{"version":3,"sources":["app-48c7d30b4f.min.js","ui/core/controls/ui/core/controls/esRouteSwitch.js","blocks/browserStorage/blocks/browserStorage/module.js","blocks/directives/blocks/directives/module.js","blocks/exception/blocks/exception/module.js","blocks/i18n/blocks/i18n/module.js","blocks/blocks/module.js","blocks/notifier/blocks/notifier/module.js","blocks/router/blocks/router/module.js","blocks/utils/blocks/utils/module.js","blocks/validators/blocks/validators/module.js","bootstrapper/bootstrapper/module.js","core/core/module.js","module.js","ui/core/ui/core/module.js","ui/features/alerts/ui/features/alerts/module.js","ui/features/blasting/ui/features/blasting/module.js","ui/features/configuration/company/blasting/ui/features/configuration/company/blasting/module.js","ui/features/configuration/company/modelling/ui/features/configuration/company/modelling/module.js","ui/features/configuration/company/monitoring/ui/features/configuration/company/monitoring/module.js","ui/features/configuration/ui/features/configuration/module.js","ui/features/configuration/system/ui/features/configuration/system/module.js","ui/features/dashboard/ui/features/dashboard/module.js","ui/features/extras/ui/features/extras/module.js","ui/features/incidentIntelligence/ui/features/incidentIntelligence/module.js","ui/features/modelling/ui/features/modelling/module.js","ui/features/monitoring/ui/features/monitoring/module.js","ui/features/reporting/ui/features/reporting/module.js","ui/features/user/ui/features/user/module.js","blocks/browserStorage/blocks/browserStorage/browserStorage.js","blocks/directives/esDataGrid/blocks/directives/esDataGrid/esDataGrid.js","blocks/directives/blocks/directives/pelAutoFocus.js","blocks/directives/blocks/directives/pelMarkModelDirtyOnBlur.js","blocks/directives/blocks/directives/pelScrollToFirstError.js","blocks/exception/blocks/exception/exceptionHandlerDecorator.js","blocks/i18n/blocks/i18n/i18n.js","blocks/notifier/blocks/notifier/notifier.js","blocks/router/blocks/router/constants.js","blocks/router/blocks/router/routehelper.js","blocks/utils/blocks/utils/utils.js","core/core/appSettings.js","core/bootstrapper/configurators/core/bootstrapper/configurators/blockUI.js","core/bootstrapper/configurators/core/bootstrapper/configurators/compile.PRODUCTION.js","core/bootstrapper/configurators/core/bootstrapper/configurators/dashboard.js","core/bootstrapper/configurators/core/bootstrapper/configurators/environment.PRODUCTION.js","core/bootstrapper/configurators/core/bootstrapper/configurators/http.js","core/bootstrapper/configurators/core/bootstrapper/configurators/httpBatch.js","core/bootstrapper/configurators/core/bootstrapper/configurators/IE9Behavior.js","core/bootstrapper/configurators/core/bootstrapper/configurators/internationalization.js","core/bootstrapper/configurators/core/bootstrapper/configurators/localStorage.js","core/bootstrapper/configurators/core/bootstrapper/configurators/notification.js","core/bootstrapper/configurators/core/bootstrapper/configurators/tooltip.js","core/bootstrapper/runners/core/bootstrapper/runners/dashboard.js","core/bootstrapper/runners/core/bootstrapper/runners/fileUploader.js","core/bootstrapper/runners/core/bootstrapper/runners/internationalization.js","core/bootstrapper/runners/core/bootstrapper/runners/kendoCultures.js","core/bootstrapper/runners/core/bootstrapper/runners/passwordExpirationValidator.js","core/bootstrapper/runners/core/bootstrapper/runners/routeHandler.js","core/constants/core/constants/app.core.mapDefaults.js","core/constants/core/constants/vendor.js","core/core/events.js","core/filters/core/filters/dateTimeFormatFilter.js","core/filters/core/filters/facilityTimezoneFilter.js","core/core/httpInterceptors.js","core/core/leafletScopeDecoration.js","core/logger/core/logger/log4jProvider.js","core/logger/core/logger/logDecorator.js","core/models/alerts/core/models/alerts/WebAlert.js","core/models/blasting/core/models/blasting/BlastModel.js","core/models/blasting/core/models/blasting/blastModelCategory.js","core/models/blasting/core/models/blasting/blastModelType.js","core/models/blasting/core/models/blasting/BlastScenario.js","core/models/blasting/core/models/blasting/blastSetup.js","core/models/blasting/core/models/blasting/DispersionModel.js","core/models/blasting/core/models/blasting/FlyrockModel.js","core/models/blasting/core/models/blasting/FumeManagementZoneModel.js","core/models/blasting/core/models/blasting/GroundVibrationModel.js","core/models/blasting/core/models/blasting/OverpressureModel.js","core/models/blasting/core/models/blasting/PathModel.js","core/models/blasting/core/models/blasting/VibrationPointOfInterestMapMarker.js","core/models/jobs/core/models/jobs/Job.js","core/models/jobs/core/models/jobs/jobCompletionStatus.js","core/models/jobs/core/models/jobs/ModellingJob.js","core/models/legends/core/models/legends/ArrowLegend.js","core/models/legends/core/models/legends/CircleLegend.js","core/models/legends/core/models/legends/Legend.js","core/models/legends/core/models/legends/legendFactory.js","core/models/legends/core/models/legends/StrokeLegend.js","core/models/mapping/core/models/mapping/Boundary.js","core/models/mapping/core/models/mapping/DataPoint.js","core/models/mapping/core/models/mapping/dataPointFactory.js","core/models/mapping/core/models/mapping/dataPointType.js","core/models/mapping/core/models/mapping/PathDataPoint.js","core/models/mapping/core/models/mapping/PlumeDataPoint.js","core/models/mapping/core/models/mapping/WindDataPoint.js","core/models/messages/core/models/messages/messageList.js","core/models/core/models/modelLoadingStatus.js","core/models/monitoring/core/models/monitoring/monitorMapFenceline.js","core/models/monitoring/core/models/monitoring/monitorMapMarker.js","core/models/monitoring/core/models/monitoring/monitorMapPath.js","core/providers/core/providers/alertDataProvider.js","core/providers/core/providers/blastingDataProvider.js","core/providers/core/providers/companyDataProvider.js","core/providers/configuration/core/providers/configuration/blastingDataProvider.js","core/providers/configuration/core/providers/configuration/gisModelDataProvider.js","core/providers/configuration/core/providers/configuration/lookupDataProvider.js","core/providers/configuration/core/providers/configuration/measurementGroupDataProvider.js","core/providers/configuration/core/providers/configuration/modellingDataProvider.js","core/providers/configuration/core/providers/configuration/monitoringDataProvider.js","core/providers/core/providers/diagnosticsDataProvider.js","core/providers/core/providers/errorThrowingDataProvider.js","core/providers/core/providers/gisModelDataProvider.js","core/providers/core/providers/incidentIntelligenceDataProvider.js","core/providers/core/providers/mappingDataProvider.js","core/providers/core/providers/monitoringDataProvider.js","core/providers/core/providers/reportsDataProvider.js","core/providers/core/providers/securityDataProvider.js","core/providers/core/providers/userDataProvider.js","core/core/requestManager.js","core/security/core/security/knownCredentials.js","core/services/core/services/alertService.js","core/services/core/services/appVersionService.js","core/services/core/services/blastingService.js","core/services/core/services/companyService.js","core/services/configuration/core/services/configuration/blastingService.js","core/services/configuration/core/services/configuration/gisModelService.js","core/services/configuration/core/services/configuration/lookupService.js","core/services/configuration/core/services/configuration/measurementGroupService.js","core/services/configuration/core/services/configuration/modellingService.js","core/services/configuration/core/services/configuration/monitoringService.js","core/services/core/services/confirmationDialog.js","core/services/core/services/dashboardService.js","core/services/core/services/dateTimeService.js","core/services/core/services/diagnosticsService.js","core/services/core/services/errorService.js","core/services/core/services/exportService.js","core/services/core/services/gisModelService.js","core/services/core/services/incidentIntelligenceService.js","core/services/core/services/locationService.js","core/services/core/services/mappingService.js","core/services/core/services/mathService.js","core/services/core/services/monitoringService.js","core/services/core/services/reportsService.js","core/services/core/services/securityService.js","core/services/core/services/settingsService.js","core/services/core/services/userService.js","core/signalR/alerts/core/signalR/alerts/alertStatusHub.js","core/signalR/alerts/core/signalR/alerts/events.js","core/signalR/alerts/core/signalR/alerts/state.js","core/signalR/core/signalR/Hub.js","core/signalR/core/signalR/hubsConnector.js","core/signalR/jobs/core/signalR/jobs/events.js","core/signalR/jobs/core/signalR/jobs/jobStatusHub.js","core/signalR/jobs/core/signalR/jobs/state.js","core/states/core/states/monitoringTimeState.js","core/core/timeZoneDateTime.js","core/validators/core/validators/esAfterDate.js","core/validators/core/validators/esAngle.js","core/validators/core/validators/esBeforeDate.js","core/validators/core/validators/esDecimal.js","core/validators/core/validators/esLatitude.js","core/validators/core/validators/esLongitude.js","core/validators/core/validators/esNoxScale.js","core/validators/core/validators/esPassword.js","core/validators/core/validators/esUnique.js","core/validators/core/validators/esValidDate.js","resources/scripts/resources/scripts/date-extensions.js","resources/scripts/resources/scripts/kendo.custom.cultures.min.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.ArrowMultiPolyLine.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.Corridor.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.EasyButtons.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.Google.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.HtmlIcon.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.ImageOverlay.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.InfluenceArcs.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.LatLngHelpers.js","resources/scripts/leaflet-extensions/resources/scripts/leaflet-extensions/L.es.MapCredits.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeaflet.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletBoundsHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletCenter.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletControlHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletData.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletDirectiveControlsHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletEventsHelpersFactory.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletGeoJsonHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletIterators.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletLabelEvents.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletLayerHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletLayers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletMapDefaults.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletMapEvents.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletMarkerEvents.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletMarkers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletMarkersHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletPathEvents.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletPaths.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletPathsHelpers.js","resources/scripts/leaflet/resources/scripts/leaflet/esLeafletWatchHelpers.js","resources/scripts/resources/scripts/number-extensions.js","routes.js","ui/core/alerts/controls/ui/core/alerts/controls/esAlertDropdownOpener.js","ui/core/alerts/controls/ui/core/alerts/controls/esAlertLevelSpinner.js","ui/core/alerts/controls/ui/core/alerts/controls/esAlerts.js","ui/core/controls/ui/core/controls/esAccordionPreventCollapse.js","ui/core/controls/ui/core/controls/esAddressLookup.js","ui/core/controls/ui/core/controls/esBusyLoading.js","ui/core/controls/ui/core/controls/esBusySaving.js","ui/core/controls/ui/core/controls/esButtonCreate.js","ui/core/controls/ui/core/controls/esButtonGroup.js","ui/core/controls/ui/core/controls/esButtonPrimary.js","ui/core/controls/ui/core/controls/esDateTimeSelector.js","ui/core/controls/ui/core/controls/esFileUploader.js","ui/core/controls/ui/core/controls/esLabelledSwitch.js","ui/core/controls/ui/core/controls/esLegend.js","ui/core/controls/ui/core/controls/esList.js","ui/core/controls/ui/core/controls/esPageBlocker.js","ui/core/controls/ui/core/controls/esPersistenceStore.js","ui/core/controls/ui/core/controls/esSetSideBarDefaultWidth.js","ui/core/controls/ui/core/controls/esTabSet.js","ui/core/controls/ui/core/controls/esTimeSlider.js","ui/core/controls/ui/core/controls/StepTicker.js","ui/core/controls/ui/core/controls/Tab.js","ui/core/ui/core/esComponentChangeHandlerFactory.js","ui/core/ui/core/esStateStore.js","ui/core/ui/core/Forbidden.js","ui/core/jobs/controls/ui/core/jobs/controls/esJobs.js","ui/core/ui/core/keyboardShortcuts.js","ui/core/layout/controls/ui/core/layout/controls/esFullScreen.js","ui/core/layout/controls/ui/core/layout/controls/esSideBar.js","ui/core/layout/controls/ui/core/layout/controls/esWindowResize.js","ui/core/layout/ui/core/layout/shell.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapCentre.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapCluster.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapCredits.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapDomainBoundaries.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapEmissionSources.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapHeatmap.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapInfluenceArcs.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapKml.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapLocationSelector.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapReady.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapResizer.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapScale.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapTemporalEvents.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapTiles.js","ui/core/mapping/controls/ui/core/mapping/controls/esMapType.js","ui/core/mapping/ui/core/mapping/mapLayerRenderer.js","ui/core/messages/controls/ui/core/messages/controls/esMessages.js","ui/core/ui/core/NotFound.js","ui/features/alerts/ui/features/alerts/ContentPanel.js","ui/features/alerts/ui/features/alerts/routes.js","ui/features/blasting/ui/features/blasting/AddScenarioContentPanel.js","ui/features/blasting/ui/features/blasting/AddScenarioLeftPanel.js","ui/features/blasting/ui/features/blasting/BlastDataMediator.js","ui/features/blasting/ui/features/blasting/BlastDataStore.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscFileUploader.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscLocation.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscMap.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscModelParameters.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscModelSelector.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscModelTypeRequired.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscName.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscPollutantConcentrationSelector.js","ui/features/blasting/controls/configuration/ui/features/blasting/controls/configuration/esbscTimeSelector.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsActualBlastTime.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsFlyrockLegend.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsModelCategorySelector.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsModelGroupingSelector.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsModelLegendToggle.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsModelParameters.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsPollutantOutline.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsTimeSelector.js","ui/features/blasting/controls/ui/features/blasting/controls/esbsVibrationPointsOfInterest.js","ui/features/blasting/ui/features/blasting/hashParser.js","ui/features/blasting/ui/features/blasting/routes.js","ui/features/blasting/ui/features/blasting/scenarioConfigurationState.js","ui/features/blasting/ui/features/blasting/ScenarioModelsActionsPanel.js","ui/features/blasting/ui/features/blasting/ScenarioModelsContentPanel.js","ui/features/blasting/ui/features/blasting/ScenarioModelsLeftPanel.js","ui/features/blasting/ui/features/blasting/scenarioModelsState.js","ui/features/blasting/ui/features/blasting/ScenarioSelectionContentPanel.js","ui/features/configuration/company/blasting/ui/features/configuration/company/blasting/routes.js","ui/features/configuration/company/blasting/scenarios/ui/features/configuration/company/blasting/scenarios/ContentPanel.js","ui/features/configuration/company/blasting/scenarios/controls/ui/features/configuration/company/blasting/scenarios/controls/esBlastScenarioForm.js","ui/features/configuration/company/blasting/scenarios/controls/ui/features/configuration/company/blasting/scenarios/controls/esBlastScenarioFormMap.js","ui/features/configuration/company/blasting/scenarios/ui/features/configuration/company/blasting/scenarios/DetailPanel.js","ui/features/configuration/company/blasting/scenarios/ui/features/configuration/company/blasting/scenarios/state.js","ui/features/configuration/company/modelling/aermet/ui/features/configuration/company/modelling/aermet/ContentPanel.js","ui/features/configuration/company/modelling/aermet/ui/features/configuration/company/modelling/aermet/store.js","ui/features/configuration/company/modelling/emissionsData/ui/features/configuration/company/modelling/emissionsData/ContentPanel.js","ui/features/configuration/company/modelling/emissionsData/ui/features/configuration/company/modelling/emissionsData/store.js","ui/features/configuration/company/modelling/models/ui/features/configuration/company/modelling/models/ContentPanel.js","ui/features/configuration/company/modelling/models/ui/features/configuration/company/modelling/models/DeleteModal.js","ui/features/configuration/company/modelling/models/ui/features/configuration/company/modelling/models/DetailPanel.js","ui/features/configuration/company/modelling/models/ui/features/configuration/company/modelling/models/state.js","ui/features/configuration/company/modelling/ui/features/configuration/company/modelling/routes.js","ui/features/configuration/company/monitoring/measurementGroups/ui/features/configuration/company/monitoring/measurementGroups/ContentPanel.js","ui/features/configuration/company/monitoring/measurementGroups/ui/features/configuration/company/monitoring/measurementGroups/DeleteModal.js","ui/features/configuration/company/monitoring/measurementGroups/ui/features/configuration/company/monitoring/measurementGroups/DetailPanel.js","ui/features/configuration/company/monitoring/measurementGroups/ui/features/configuration/company/monitoring/measurementGroups/state.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/ContentPanel.js","ui/features/configuration/company/monitoring/monitors/controls/ui/features/configuration/company/monitoring/monitors/controls/esMeasurementTypeThresholds.js","ui/features/configuration/company/monitoring/monitors/controls/ui/features/configuration/company/monitoring/monitors/controls/esMonitorVariableDisplay.js","ui/features/configuration/company/monitoring/monitors/controls/ui/features/configuration/company/monitoring/monitors/controls/esMonitorVariablePreferences.js","ui/features/configuration/company/monitoring/monitors/controls/ui/features/configuration/company/monitoring/monitors/controls/esRequireUniqueMeasurementGroupSelection.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/DataImportTab.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/DataImportTabEditPanel.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/DetailPanel.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/DetailsTab.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/MapConfigurationTab.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTab.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTabEditPanel.js","ui/features/configuration/company/monitoring/monitors/ui/features/configuration/company/monitoring/monitors/state.js","ui/features/configuration/company/monitoring/ui/features/configuration/company/monitoring/routes.js","ui/features/configuration/company/monitoring/settings/ui/features/configuration/company/monitoring/settings/ContentPanel.js","ui/features/configuration/company/monitoring/settings/controls/ui/features/configuration/company/monitoring/settings/controls/esWeatherStationConfiguration.js","ui/features/configuration/ui/features/configuration/ContentPanel.js","ui/features/configuration/controls/ui/features/configuration/controls/esAccordionConfigurationSetContainerHeight.js","ui/features/configuration/controls/ui/features/configuration/controls/esFormStateTracker.js","ui/features/configuration/ui/features/configuration/LeftPanel.js","ui/features/configuration/ui/features/configuration/routes.js","ui/features/configuration/ui/features/configuration/state.js","ui/features/configuration/system/modelling/modelRuns/ui/features/configuration/system/modelling/modelRuns/ContentPanel.js","ui/features/configuration/system/ui/features/configuration/system/routes.js","ui/features/dashboard/ui/features/dashboard/ContentPanel.js","ui/features/dashboard/controls/blasting/ui/features/dashboard/controls/blasting/esBlastScenariosDashboardWidget.js","ui/features/dashboard/controls/modelling/ui/features/dashboard/controls/modelling/esDailyModelsDashboardWidget.js","ui/features/dashboard/controls/monitoring/ui/features/dashboard/controls/monitoring/esMonitorGraphsDashboardWidget.js","ui/features/dashboard/controls/monitoring/ui/features/dashboard/controls/monitoring/esMonitorHealthDashboardWidget.js","ui/features/dashboard/ui/features/dashboard/routes.js","ui/features/dashboard/ui/features/dashboard/state.js","ui/features/extras/about/ui/features/extras/about/ContentPanel.js","ui/features/extras/help/ui/features/extras/help/ContentPanel.js","ui/features/extras/ui/features/extras/routes.js","ui/features/incidentIntelligence/artifacts/ui/features/incidentIntelligence/artifacts/ActionsPanel.js","ui/features/incidentIntelligence/artifacts/ui/features/incidentIntelligence/artifacts/ContentPanel.js","ui/features/incidentIntelligence/ui/features/incidentIntelligence/hashParser.js","ui/features/incidentIntelligence/ui/features/incidentIntelligence/routes.js","ui/features/incidentIntelligence/ui/features/incidentIntelligence/state.js","ui/features/incidentIntelligence/summary/ui/features/incidentIntelligence/summary/ActionsPanel.js","ui/features/incidentIntelligence/summary/ui/features/incidentIntelligence/summary/ContentPanel.js","ui/features/incidentIntelligence/summary/ui/features/incidentIntelligence/summary/LeftPanel.js","ui/features/incidentIntelligence/summary/ui/features/incidentIntelligence/summary/state.js","ui/features/modelling/ui/features/modelling/ActionsPanel.js","ui/features/modelling/ui/features/modelling/ContentPanel.js","ui/features/modelling/controls/ui/features/modelling/controls/esMapModels.js","ui/features/modelling/controls/ui/features/modelling/controls/esModellingDurationSelect.js","ui/features/modelling/controls/ui/features/modelling/controls/esModellingModelSelect.js","ui/features/modelling/ui/features/modelling/hashParser.js","ui/features/modelling/ui/features/modelling/LeftPanel.js","ui/features/modelling/ui/features/modelling/ModellingDataStore.js","ui/features/modelling/ui/features/modelling/modellingMediator.js","ui/features/modelling/ui/features/modelling/routes.js","ui/features/modelling/ui/features/modelling/state.js","ui/features/modelling/ui/features/modelling/timeStepCalculator.js","ui/features/monitoring/ui/features/monitoring/ActionsPanel.js","ui/features/monitoring/ui/features/monitoring/ContentPanel.js","ui/features/monitoring/controls/ui/features/monitoring/controls/esMetSummary.js","ui/features/monitoring/controls/ui/features/monitoring/controls/esMonitoringDateTimeSelector.js","ui/features/monitoring/controls/ui/features/monitoring/controls/esMonitoringPopups.js","ui/features/monitoring/controls/ui/features/monitoring/controls/esMonitoringWidget.js","ui/features/monitoring/controls/ui/features/monitoring/controls/esMonitorTypeSelectionCriteria.js","ui/features/monitoring/controls/ui/features/monitoring/controls/esSourceIdentificationPanel.js","ui/features/monitoring/ui/features/monitoring/LeftPanel.js","ui/features/monitoring/ui/features/monitoring/routes.js","ui/features/monitoring/ui/features/monitoring/state.js","ui/features/reporting/ui/features/reporting/ContentPanel.js","ui/features/reporting/reports/ui/features/reporting/reports/ProcessDataReport.js","ui/features/reporting/ui/features/reporting/routes.js","ui/features/user/profile/ui/features/user/profile/ContentPanel.js","ui/features/user/profile/ui/features/user/profile/PasswordTab.js","ui/features/user/profile/ui/features/user/profile/state.js","ui/features/user/profile/ui/features/user/profile/UserDetailsTab.js","ui/features/user/ui/features/user/routes.js","ui/features/user/settings/ui/features/user/settings/ContentPanel.js"],"names":["_extends","Object","assign","target","i","arguments","length","source","key","prototype","hasOwnProperty","call","apply","this","_objectWithoutProperties","excluded","_objectWithoutPropertiesLoose","getOwnPropertySymbols","sourceSymbolKeys","indexOf","propertyIsEnumerable","sourceKeys","keys","_typeof","obj","Symbol","iterator","constructor","_classCallCheck","instance","Constructor","TypeError","_defineProperties","props","descriptor","enumerable","configurable","writable","defineProperty","_createClass","protoProps","staticProps","_toConsumableArray","arr","_arrayWithoutHoles","_iterableToArray","_nonIterableSpread","iter","toString","Array","from","isArray","arr2","_defineProperty","value","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","_arr","_n","_d","_e","undefined","_s","_i","next","done","push","err","esRouteSwitch","$state","changeRoute","routeName","oldRoute","vm","selectedRouteName","go","onChange","newRoute","$onChanges","changes","selectedRoute","currentValue","angular","module","BootstrapConfig","_len","configurators","_key","forEach","configurator","configure","BootstrapRun","_len2","runners","_key2","run","config","$inject","$compileProvider","preAssignBindingsEnabled","browserStorage","_","webStorage","persist","storageKey","itemToPersist","validateStorageKey","storageItem","get","isEqual","add","persistBucket","bucketKey","validateBucketKey","deleteItem","remove","deleteBucket","getBucket","isString","Error","delete","factory","esDataGrid","$window","link","$scope","$element","resizeGrid","container","find","gridElement","gridRows","otherGridElements","children","not","footer","otherElementsHeight","offsetHeight","element","containerHeight","preferredHeight","paddingBottom","maxAllowedHeight","height","offset","top","Math","min","buttons","button","removeClass","$on","scope","options","grid","restrict","templateUrl","controller","esDataGridController","controllerAs","bindToController","dateTimeService","promiseTracker","activate","buildGridApi","rebuildGrid","columns","schemaAndColumns","buildSchemaAndColumns","kendoGrid","setOptions","dataSource","reader","model","define","schema","refreshData","read","getSearchCriteria","filter","col","field","map","take","skip","sort","aggregates","initGridAfterKendoGridCreated","pager","hide","$watch","selectedId","$grid","content","row","addClickHandler","dataProvider","preProcessedOptions","preProcessOptions","onDataBound","rest","kendoGridOptions","merge","getDefaultOptions","getDefaultDataSourceOptions","onDataBoundFromOptions","kendoEvent","rowCallback","sender","item","dataItem","select","event","highlightSelectedItem","concat","uid","addClass","totalPages","show","$broadcast","selectable","sortable","mode","allowUnsort","dataBound","change","resizable","reorderable","transport","queryObject","data","loadingPromise","then","success","busyLoading","addPromise","response","total","groups","serverPaging","serverSorting","serverGrouping","serverFiltering","pageSize","groupable","navigatable","scrollable","virtual","pageable","numeric","previousNext","refresh","input","filterable","extra","extend","sortBy","sorts","schemaFields","column","columnIndex","dataType","format","formats","kendo","dateTime","type","ui","dir","order","click","fieldTemplate","template","clickableCellSelector","clickableCells","every","width","isNaN","parseFloat","isFinite","fields","selector","join","on","$this","$row","closest","rowData","clickAttr","attributes","attr","name","matches","match","parseInt","clickHandler","isFunction","directive","pelAutoFocus","focus","pelMarkModelDirtyOnBlur","compiler","delegatingEventSelector","is","ngModel","currentTarget","$apply","$$lastCommittedViewValue","$dirty","$commitViewValue","compile","pelScrollToFirstError","$elem","clientWidth","clientHeight","style","opacity","visibility","display","parent","$input","decorateExceptionHandler","$provide","decorator","exceptionHandlerDecorator","$log","$injector","addJavascriptErrorsToMessageList","i18n","$timeout","messageList","title","i10n","message","update","isUnhandledJavascriptError","addFatal","unhandledJavaScriptStatusCode","fatal","error","LogRocket","captureException","status","window","addEventListener","exception","handled","mock","rethrow","i18nProvider","$translatePartialLoader","$translate","$q","routeHelper","buildUrl","url","partCount","part","substr","loadTranslationsFor","referenceUrl","resourceUrl","getResourceUrl","addPart","debug","instant","onTranslationsLoaded","state","current","loadedPromise","getTranslationsLoadedPromise","loadStates","isEmpty","loaders","when","allLoaders","values","all","templateFolder","resourceName","getResourceUrlsFromStateSettings","resourceUrls","settings","test","ensureTranslationsAreLoaded","fromState","toState","unloadStates","logReadyDebug","unloadResource","resourcePath","has","addedResources","deletePart","unloadTemplateResource","templateResourceUrl","ready","toStatePath","getStatePath","toStateResources","unloadedResources","stateName","isInPath","getParentStateName","explicitResourcesForState","explicitResourcesToUnload","includes","templateResourceUrls","getTemplateResourceUrls","loadResource","requiredResources","loadTemplateResource","resolvedPromise","refreshPromise","fromStatePath","path","requiredLoaders","requiredPath","templates","views","templateUrlValues","templateUrlValue","params","childStateName","toLowerCase","statePath","addStateChangeStartEventHandler","toParams","self","$get","provider","notifier","notificationService","moment","notify","info","warning","defaultOptions","text","delay","mouse_reset","closer","closer_hover","sticker","notifyWithDefaults","service","setHtml5Mode","$locationProvider","html5Mode","routeHelperProvider","$stateProvider","$rootScope","fnThatReturnsAPromise","prioritisedPromiseBuilder","builder","stateChangeStartPromiseBuilders","without","subscribeToStateChangeStart","fromParams","chainHandlerPromise","promise","errorFn","reject","onHandlersSuccessful","reload","$current","$reload","onHandlersFailed","ensureRootTranslationsAreLoaded","preventDefault","builders","reduce","translationsLoadedPromise","configureRoutes","routes","determinePageLayoutType","route","leftPanel","layoutType","getNavigationRoutes","chain","navigation","group","getUtils","freeze","deep","getOwnPropertyNames","propertyName","propertyValue","valueType","isFrozen","arrToObj","hashKey","hash","appSettingsProvider","appSettingsFactory","postal","coreEvents","addDisplayNameProperty","user","firstName","lastName","ensureSessionStorageHasFacilityDetails","setLoggingContext","webApiHostUri","zeusHostUri","replace","mvcHostUri","eS2VersionedApiUri","reportsAppHostUri","icpCertificate","internetSecurityNumberText","internetSecurityRegistrationLink","addToCache","session","local","getFromCache","isBrowserSessionPrimedWithFacilityDetails","site","company","alias","facility","primeSessionStorageWithFacilityDetails","companyAlias","facilityAlias","cleanupServerProvidedFacilityDetails","updateLoggingContext","id","apiKey","publish","topic","payload","channel","channelName","accessControls","set","newValue","ticketingSystemType","baseUrl","ticketsUrl","ticketingSystemTenantId","ticketUrl","ticketId","topics","accessControlsUpdated","forgetCompanyAndFacility","es1RouteName","appName","pageTitle","configureBlockUI","blockUIConfig","loadingBarConfig","autoBlock","autoInjectBodyBlock","includeSpinner","noop","configureCompileProvider","debugInfoEnabled","configureDashboard","dashboardProvider","screen","structure","rows","styleClass","constant","production","develop","configureHttp","$httpProvider","defaults","withCredentials","headers","common","post","interceptors","configureHttpBatch","httpBatchConfigProvider","appSettings","environment","signalRHostUri","setAllowedBatchEndpoint","maxBatchedRequestPerCall","configureIE9Behavior","console","log","warn","configureInternationalization","$translateProvider","$translatePartialLoaderProvider","useLoader","urlTemplate","addInterpolation","useSanitizeValueStrategy","showEmptyTranslations","translations","activityIndicator.default.label","preferredLanguage","locale","fallbackLanguage","use","culture","configureLocalStorage","defaultSettings","prefix","configureNotification","notificationServiceProvider","PNotify","styling","setDefaults","history","setStack","dir1","dir2","firstpos1","firstpos2","setDefaultStack","configureTooltips","$tooltipProvider","tooltipFactory","$compile","$document","$position","$interpolate","dashboard","$templateCache","passwordExpirationValidator","overrideDashboardEditTemplate","put","overrideWidgetEditTemplate","configureFileUploader","FileUploader","FileItem","_validationErrors","cookie","userService","settingsService","useLocale","supportedLanguages","getSupportedLanguages","getLocale","configureKendoCultures","overrideCultureVi","dayNamesShort","overrides","calendars","standard","days","namesAbbr","namesShort","overrideCultureIfExists","overrideCultureEs","dayNames","names","kendoCultures","cultures","cultureInfo","securityService","getPasswordExpirationStatus","shownNotification","daysBeforePasswordExpiration","addWarning","setPasswordExpirationConfirmed","stateReloadDecorator","decorateTransitionTo","$delegate","transitionToWithReload","to","original","transitionTo","runRouteHandler","$location","blockUI","companyService","locationService","hubsConnector","onRouteChangeStart","validateCompanyAndFacilityExist","resolve","errorHandler","createRoutingFailedErrorHandler","applySelectedCompanyFacilityDetailsToAppSettings","ianaTimeZoneId","windowsTimeZoneId","facilityCode","region","refreshUserAndAccessControls","refreshUser","heapAnalytics","heap","email","isInternal","identify","addUserProperties","Is_Internal","Region","getUserDetails","ga","username","displayName","userType","getUserType","refreshAccessControls","getAccessControls","authorizeRouteAccess","requiredAccessControl","accessControlCheck","redirectToOmnisCheck","enableEs2","allowedStates","redirectUrl","omnisHostUri","startsWith","location","connectSignalRHubs","connect","updateLastCompanyFacilityAccessed","lastCompanyFacilityRouted","detail","getInvalidRouteErrorMessage","errorCode","userId","hasTheCompanyFacilityChangedButTheRouteStayedTheSame","href","startNavigationTracker","result","getCompanyWithFacility","routeErrorHandler","stopNavigationTracker","successPromise","onRouteChangeError","handlingRouteChangeError","destination","msg","JSON","stringify","onRouteChangeSuccess","unloadPreviousPageTranslations","updateGoogleAnalyticsPageValue","page","userDescription","dimension1","dimension2","clearExitPoint","bindPageHeading","emailAddress","endsWith","blocker","instances","start","busyMessage","stop","mapConfiguredOptions","getConfiguredBaseLayer","layers","mapProvider","mapDefaults","baselayers","google","mapboxApiKey","configuredLayer","zoomControlPosition","zoomAnimation","fadeAnimation","trackResize","attributionControl","worldCopyJump","controls","visible","position","collapsed","openStreetMap","layerOptions","attribution","subdomains","layerType","gaode","baidu","mapbox","jQuery","L","d3","MG","Mousetrap","saveAs","Utm","LatLon","log4javascript","anime","getEvents","facilityTimezoneFilter","date","formatAs","timeZoneDateTime","decorateFilter","parsedDate","Date","getTime","convertDateTimeToFacilityTimeZone","httpInterceptors","errorService","appVersionService","requestInterceptor","httpConfig","responseInterceptor","retryQueue","processSuccess","appVersion","validate","responseErrorInterceptor","dfd","defer","unhandledErrorCodes","logResponse","getBatchConfig","enabled","existsInRetryQueue","processError","interceptor","request","responseError","leafletScopeDecoration","injectScopeProperty","property","leafletDirectiveDecorator","$$isolateBindings","attrName","optional","log4jProvider","disableRemoteLogging","logger","getDefaultLogger","ajaxAppender","removeAppender","enableRemoteLogging","addAppender","companyId","facilityId","configureDefaultAppender","configureAjaxAppender","defaultAppender","removeAllAppenders","BrowserConsoleAppender","setThreshold","Level","INFO","setLayout","PatternLayout","ajaxAppenderEndpoint","AjaxAppender","getHeaders","addHeader","logLog","setQuietMode","setShowStackTraces","getNullLogger","getLogger","decorateLog","logDecorator","$logDelegate","log4j","decorateLogFunction","getLoggingFn","loggingFn","args","logMessage","alertFactory","WebAlert","alertEventSourceId","level","triggerTime","sentTime","_level","previousLevel","blastModelFactory","BlastModel","modelId","modelType","modelCategory","blastModelLegends","getDataPoints","blastTimeMillis","dataPointsForBlastTime","dataPoints","modelData","createDataPointsFromModelData","createCombinedDataPoint","offsetMinutes","combinedDataPoint","layerGroup","LayerGroup","constituentDataPoints","flatten","dataPoint","addLayer","getBlastModelCategories","animated","snapshot","getBlastModelTypes","dispersion","fmz","gain","contour","flyrock","groundVibration","BlastScenario","scenarioId","scenarioAlias","models","blastTimesMillis","blastParameters","getBlastSetups","burden","stemming","DispersionModelFactory","blastModelType","blastModelCategory","mapLayerRenderer","DispersionModel","legends","windDataPoints","renderDataPoints","windData","plumeDataPoints","plumes","groupBy","renderLayer","create","FlyrockModelFactory","FlyrockModel","createPolygonPoints","faceAngleStart","faceAngleStop","backAngleStop","backAngleStart","points","angle","point","startingPoint","destinationPoint","azimuthBearingOffset","frontFaceDistanceInMetres","lat","lng","backFaceDistanceInMetres","createPolygon","color","polygon","fillOpacity","stroke","weight","flyrockBoundaries","LatLng","latitude","longitude","azimuth","boundary","sortedData","reverse","index","polygonPoints","FumeManagementZoneModelFactory","FumeManagementZoneModel","plume","GroundVibrationModelFactory","VibrationPointOfInterestMapMarker","GroundVibrationModel","renderReadings","ppvReadings","reading","thresholds","sortedThresholds","ppv","ppvThreshold","vibrationMarker","icon","divIcon","marker","renderThresholds","distanceInMetres","ppvThresholds","OverpressureModelFactory","OverpressureModel","calculateScale","referencePoint","convertToLatLng","centrePoint","x","y","metresToReferencePoint","centreLatLng","distanceTo","abs","convertToCartesian","latLngToContainerPoint","containerPointToLatLng","imageUrl","image","latLng","padding","left","right","bottom","imageEdgeLengthPixels","imageEdgeLengthKm","imageRadius","imageMetresPerPixel","mapMetresPerPixel","multiplier","imageSWLatLng","imageNELatLng","imageOverlay","latLngBounds","PathModelFactory","PathModel","primaryTrackDataPoints","primaryTrack","configMonitoringService","backgroundColor","getHtml","getMonitorTypeIcon","round","layer","iconAnchor","html","jobFactory","jobEvents","jobCompletionStatus","jobRunningStaleTimeoutMillis","jobRunningStaleTimeoutSeconds","jobQueuedStaleTimeoutMillis","jobQueuedStaleTimeoutSeconds","jobId","scheduleIsStaleCheck","cancelStaleTimeout","hasCompleted","hasFailed","timeoutMillis","hasStarted","staleCutoffMillis","isStale","lastUpdatedMillis","jobStale","isStaleTimeout","cancel","addMessage","messages","messageType","messageKey","getJobType","jobType","i18nKey","i18nResult","description","progress","completionStatus","incomplete","lastUpdatedDateTime","progressMessages","errorMessages","last","failure","isNumber","addProgressMessage","addErrorMessage","getJobCompletionStatus","calculate","jobSucceededCount","jobFailedCount","partial","ModellingJobFactory","Job","ModellingJob","requesterId","fromMillis","toMillis","toFacilityDateTimeString","createFromJobData","jobData","calculateCompletionStatus","startDate","utcFromDateTime","endDate","utcToDateTime","lastUpdated","utcLastUpdatedDateTime","modellingJob","requesterName","errors","millis","facilityTime","arrowLegendFactory","Legend","ArrowLegend","legendData","circleLegendFactory","CircleLegend","legendFactory","items","StrokeLegend","legend","legendType","strokeLegendFactory","BoundaryFactory","Boundary","bottomLeft","bottomRight","topLeft","topRight","isCoordinate","defineProperties","coord","contains","isBetween","lowerBound","upperBound","isLatitudeInBoundary","crossesAntimeridian","DataPointFactory","dataPointType","dataPointFactory","PlumeDataPoint","WindDataPoint","PathDataPoint","sourceData","wind","getDataPointTypes","PathDataPointFactory","DataPoint","timeStepData","processTimeStepData","gisPoint","timeMillis","utcEndTime","latitudeStdDev","longitudeStdDev","PlumeDataPointFactory","processConcentration","concentration","regionPoints","processRegions","regions","polygons","displayColor","gisPoints","concentrations","WindDataPointFactory","processWindDataSpeedRange","speedRange","windVectors","vector","bearing","windDirection","magnitude","windSpeed","minimumSpeed","maximumSpeed","windDataSpeedRanges","now","timestamp","count","processRecoverableErrorCountOverTime","errorMessageCount","presentDialogConfiguration","messageTimestamps","numberOfMessages","comparisonTime","earliestTime","subtract","timePeriodSeconds","isSameOrAfter","confirmationDialog","addError","addInfo","predicate","removeStale","oneDayAgo","isBefore","removeAll","filteredMessages","acc","val","getModelLoadingStatuses","pending","loading","loaded","failed","$filter","monitoringService","createMonitorMapFenceline","monitor","switches","buildFenceline","getCircle","latlng","latlngs","monitorType","isFocusedFenceline","processVariable","thresholdColour","radius","showMonitorsThatHaveExceededFirstThreshold","thresholdExceeded","hasValueExceededFirstThreshold","fencelineLocations","firstLatLng","lastLatLng","line","max","circle1","circle2","extendMonitorAttributes","showUnitsOnPopup","canAccessConfiguration","getGraphProcessVariables","getGraphVariables","esLeafletData","createMonitorMapMarker","buildMarker","buildMarkerIcon","isUnfocusedMonitor","setZIndex","isValueStale","zIndexOffset","hasDisplayableValue","getSensorValueCssClasses","cssClassList","showInHeroMode","showUnits","showValue","showIcons","hasValueFlatlined","getTextColor","renderScaledMonitor","scaledMonitor","isDiscreteReceptor","currentZoom","getZoom","wrapInsideLink","scaleFactor","textColor","iconSize","sensorValueCssClasses","buildIcon","monitorTypeIcon","buildValue","buildUnits","buildMonitorName","valueRounded","valueInDisplayUnit","numericScale","units","monitorName","showMonitorName","className","getMap","getMarkerDisplayLocation","firstFenceSegment","slice","c","a","b","monitorNames","heroMode","icons","dataValue","displayLocation","draggable","riseOnHover","createMonitorMapPath","buildPath","getPathColor","dp","graphProcessVariables","alertDataProvider","$http","getActiveWebAlerts","dismissWebAlert","alertId","getAlertsHistory","blastingDataProvider","getScenarios","getScenario","getBlastData","requestData","utcBlastTime","toISOString","getOverlays","companyDataProvider","getCompanies","getFacilityLocation","getDomainBoundaries","getModelTypes","getOverlayFilesUrl","getOverlayFiles","requestConfig","getOverlayFile","fileName","deleteOverlayFile","getValidScenarioAlias","createScenario","scenario","deleteScenario","updateActualBlastTime","actualBlastTime","postData","utcActualBlastTime","getAddOverlayUrl","gisModelDataProvider","getEmissionsDataFileUploadUrl","getExistingEmissionsDataFiles","calpuffConfigId","getModel","getAll","getOptions","getCalpuffConfigs","addPlume","plumeData","addWind","importEmissionsData","updatePlume","updateWind","deleteEmissionsDataFiles","fileNames","lookupDataProvider","getWindowsTimeZones","measurementGroupDataProvider","getAllMeasurementGroups","getMeasurementGroup","measurementGroupId","isMeasurementGroupBeingUsed","getMeasurementGroupChildCount","queryMeasurementGroups","searchCriteria","createMeasurementGroup","measurementGroup","updateMeasurementGroup","deleteMeasurementGroup","modellingDataProvider","getWrfConfiguration","runCalModelling","wrfConfigurationName","forecastDate","forecastRun","utcForecastDate","runAerModelling","upperAirMetMonitorId","surfaceMetMonitorId","fromDate","toDate","upperAirWeatherStationId","surfaceWeatherStationId","utcFromDate","utcToDate","monitoringDataProvider","linqSuccess","getMonitorType","monitorId","getMonitorTypes","getMonitor","kebabCase","getMonitors","whereVisible","parameters","getSurfaceWeatherStations","getUpperAirWeatherStations","getAllMetStations","getMonitorLocation","getMonitorDisplay","getMeasurementType","measurementTypeId","getMeasurementTypeConfigurationOptions","queryMonitors","setDefaultMetStation","createMonitor","queryMonitorMeasurementTypes","createMeasurementType","updateMonitor","updateMonitorDisplay","updateMeasurementType","diagnosticsDataProvider","getUtcLatestProcessDataEndTime","errorThrowingDataProvider","getException","getFailedResult","getIntervals","getModelDataSet","modelIds","getModellingJobs","getModelDataAvailability","getDiscreteReceptorData","fromTime","toTime","utcFromTime","utcToTime","dismissJob","dismissJobs","jobIds","jobBatchIds","getStatus","startTestJob","incidentIntelligenceDataProvider","getPathModel","ticketActivityId","getSummaryLookupValues","getTicketSummaryLocations","criteria","categoryTypes","selectedCategoryId","resolutionTypes","selectedStatuses","issueTypes","selectedTypes","mappingDataProvider","getKmlDataSet","includeFiles","ignoreFiles","getTileLayers","getMapCredits","getElevationAtPoint","getActiveTemporalEventGroups","activeAtDateTime","utcActiveAtDateTime","getMonitorsByType","getMonitorData","monitorIds","utcDateTime","getSourceAreaData","getMetSummary","getMonitorSensorData","processVariableIds","utcDateTimeEnd","getSensorDataSeries","dateTimeStart","dateTimeEnd","processVariableId","utcDateTimeStart","getMonitorDataAlarms","monitorTypes","samplingTime","utcSamplingTime","reportsDataProvider","getListOfReports","getAlertPointReports","getProcessDataReportLookupValues","reportId","getProcessDataReportColumns","processId","getProcessDataReport","startTime","endTime","postProcessDataRequest","exportProcessDataReport","queryString","securityDataProvider","cacheFactory","cache","accessControlCache","queryApiCredentials","getApiCredential","credentialId","createApiCredential","updateApiCredential","logout","cacheName","maxAge","cacheFlushInterval","deleteOnExpire","onExpire","userDataProvider","updatePassword","currentPassword","newPassword","oldPassword","password","updateUserDetails","requestManager","createQueuedRequestManager","createFetcher","fnPromise","queueName","fetch","postFetch","queue","shift","queueWasDrained","drainQueue","resolveLastFetchOnly","deferred","reason","queues","fetchCount","nextFetcher","fetcher","enqueue","onQueue","getKnownCredentials","createCredential","apiCredentialId","alertEngine","guest","jobProcessor","messageBroker","signalR","jiraServiceDesk","alertService","endpointProvider","mapAlerts","webAlertId","alertLogHistory","datum","dismissed","utcDismissedTime","utcTriggeredTime","alertDeliveryMethod","mappedQuery","mapQueryObject","getFieldMapping","defaultQueryObject","filters","convertFacilityDateTimeToLocalTimeZone","alerts","webAlert","utcSentTime","isCurrentVersion","isNoticeDisplayed","notice","blastingService","jobDataProvider","scenarios","blastScenarioSummaries","firstScenarioTime","utcFirstScenarioTime","utcLastUpdatedTime","createBlastModel","blastModel","blastWidth","blastLength","blastHeight","elevation","forwardTrajectoryScientificModel","forwardTrajectoryScientificModelDescription","windScientificModel","windScientificModelDescription","windScientificModelId","pollutant","pollutantDescription","pollutantId","modelPollutantId","pollutantScientificModel","pollutantScientificModelDescription","pollutantScientificModelId","displayUnit","displayUnitDescription","displayUnitId","initialConcentration","initialConcentrationGramsPerCubicMetre","blastSetup","chargeMass","chargeMassPerHole","holeDiameter","stemmingHeight","frontFaceKFactor","backFaceKFactor","flyrockSiteConstantKv","holeAngle","dispersalAngle","groundVibrationSiteConstantKv","groundVibrationSiteExponentKb","blastModels","keyBy","utcBlastTimes","processActiveJob","processAvailableData","availableData","processPathModelData","processDispersionModelData","processFmzModelData","createDataPoint","track","gisTrackDataTimeSteps","createDataPoints","dataSet","dataPointSource","offsetTimeMillis","millisPerMinute","activeJobForBlastModel","activeJobBatch","availableBlastModelData","companiesPromise","companies","normalisedCompanies","facilities","searchTerms","existingFacilities","matchingCompany","matchingFacility","companyWithFacility","getFacilityDetails","zoom","showModelling","showBlasting","showIncidentIntelligence","boundaries","filteredBoundaries","isSourceForModelling","isSourceForBlasting","isSourceForIncidentIntelligence","canAccessFacility","hashToNamedObjectArray","keyName","getAllScenarios","modelTypes","parse","getDefaultConcentrations","defaultConcentrations","Map","getModelOptions","modelOptions","pollutantOptions","plumeGisModelOptions","pollutantOption","modelPollutantDisplayName","modelPollutantName","modelPollutantShortName","windGisModelOptions","displayUnitOptions","windScientificModels","forwardTrajectoryModelOptions","pollutantGisModelOptions","noxScale","ppm","gramsPerCubicMetre","colour","overlayFile","size","dateModified","utcLastModifiedDateTime","isNOxPollutant","toUpperCase","scenarioData","pickBy","isSelected","forwardTrajectoryScientificModelId","isGroundVibrationSelected","pointsOfInterest","groundVibrationPois","gisModelService","getModellingOptions","pollutants","option","displayUnits","scientificModels","associatedPlumeScientificModels","generateNameForScientificModel","intervalDurationInMinutes","plumeOptions","windOptions","isPredictive","getAllModels","lookupService","timeZones","timeZone","Id","DisplayName","measurementGroupService","getMeasurementGroupsFlattened","mg","defaultOrder","measurementGroups","getMeasurementGroupsNested","byId","parents","parentId","modellingService","configurationName","utcDate","configurationMonitoringService","camelCase","monitors","availableVariables","pv","mapResults","fromConfigureProcessVariableRequest","aggregateTypeIds","aggregateTypes","aggregateTypeId","measurementTypeCategories","processVariableCategories","measurementType","toConfigureProcessVariableRequest","getGuid","guid","defaultDisplayUnitId","defaultImportUnitId","samplingRateMillis","exceedanceThresholds","mappedExceedanceThresholds","threshold","hexColor","intToHexColor","categoryId","genericMeasurementTypeCategoryId","samplingRateSeconds","hexColorToInt","hex","int","$modal","ask","body","buildDialog","onClick","contactSupport","localiseDefaultOptionsButtonText","open","backdrop","getDialogController","animation","confirmationDialogController","$modalInstance","cssClass","continue","dashboardService","getDashboard","getWidgets","accessorizeWidget","widget","widgetType","isNew","previousAccessibleWidgets","validateMajorVersion","majorVersion","isNull","isUndefined","Number","validateMinorVersion","minorVersions","isObject","mv","minorVersion","tap","minorVersionNumbers","previous","accessibleWidgetStorageKey","getStorageBucketKey","accessibleWidgets","widgets","canAccessWidget","persistWidgetList","newWidgets","accessibleWidget","buildDefaultDashboard","getDefaultColumnLayout","getDefaultNumberOfLayoutColumns","filterAccessibleWidgets","newWidget","titleTemplateUrl","version","isDefault","addTemplateUrl","updateDeviceWidgets","persistedDashboardConfiguration","updateDeviceWidget","deviceWidget","removeFromDeviceDashboard","removedWidgets","upgradeConfiguration","executeMinorVersionUpgrade","widgetConfig","minorVersionNumber","currentMinor","upgradeFunction","latestVersionOfWidget","upgradedConfig","currentMajor","_$map","split","number","_$map2","latestMajor","notifyUserAboutTroublesomeWidgets","notificationTitle","widgetNames","list","removedWidget","notificationMessage","persistDashboard","_getWidgets","dashboardLayoutStorageKey","newWidgetsAreAvailable","onUserHasViewed","supportsLayouts","accessControl","deleteDashboard","dateTimeServiceFactory","setupCultureFormats","updateCurrentCultureFormats","cultureFormats","getSelectedLanguage","dateTimeWithSeconds","hour","time","timeWithSeconds","iso","roundUpToClosestMinute","dateTimeMillis","delta","roundedEndTimeMillis","addCultureFormats","getEnFormats","is24Hour","getViFormats","hoursInDay12","get24HourFormats","diagnosticsService","getLatestProcessDataEndTime","utcLatestEndTime","$interval","addRemoveStaleMessagesAfterPeriodHandler","fiveMinutes","isOfflineError","isServerError","isUnauthorised","loginUri","getErrorMessage","errorWithStatus","_ref","statusText","stackTrace","method","captureMessage","exportService","exportPdf","postUrl","waitTimeMs","isLandscape","responseType","exportPng","intervals","interval","dateFrom","dateTo","activeJobs","activeJobsForGisModels","job","flattenModels","modelName","durationInMinutes","isQueued","latestTime","utcLatestTime","fromDateTime","toDateTime","mapDiscreteReceptorData","discreteReceptorData","mapProcessVariableData","getValue","getThresholdColour","mapValues","incidentIntelligenceService","mapResult","pathData","firstStep","firstPoint","startPoint","isForwardTrajectory","equals","lastStep","goHome","ensureCompanyExists","validCompanies","companyToSwitchTo","goToCompanyHome","companyAndFacility","isGuestUser","pageHeading","pageHeadingParameters","exitPoint","updatePageHeading","pageHeadingParams","updateExitPoint","exitState","stateParameters","i18nParameters","exit","mappingService","getKmls","sourcesKmlFileName","getEmissionSourceKml","kmls","mapBounds","LatLngBounds","bounds","minZoom","maxZoom","getElevation","isDate","MathService","floatMaxValue","floatMinValue","decimalPlaces","monitorsByType","discreteReceptor","monitorGrouping","head","selectedMeasurementGroupId","mapSourceAreaData","sourceAreaData","_sourceAreaData$proce","process","processData","mapMonitorData","monitorData","influenceArc","valueTime","processVariables","graphVariables","startDateTime","endDateTime","processResponse","valueInBaseUnit","processMonitorDataAlarms","monitorDataAlarms","processMonitorsByType","processMonitor","alarms","processAlarm","alarm","toFixed","hasAlarms","monitorTypesToRequest","capitalize","reportsService","collection","mapLegacyReport","report","isProcessDataReport","reportType","isEs2Report","uri","linkSafeName","javaScriptReports","mapJavaScriptReport","powerBiReports","mapPowerBiReport","legacyReports","reports","dataForEndTime","localDateTime","_appSettings$site","reportAlias","_appSettings$site2","accessControlPromise","mapUtcDateTimesToDateTimes","credential","mapDateTimesToUtcDateTimes","utcLastUsedTime","lastUsedTime","utcGeneratedTime","generatedTime","utcDeactivatedTime","deactivatedTime","loginUrl","lodash","supported","en","es","fr","vi","zh","lt","explicitlyAllowed","languagesExplicitlyAllowed","code","trim","setLanguage","language","getSampleDateTime","validDateRegex","dateTimeMoment","isValid","userDetails","forceRefresh","userPromise","alertStatusHub","Hub","alertEvents","onNotify","alert","onDismiss","dismiss","joinFacility","signalRHub","subscribeAlerts","leaveFacility","unsubscribeAlerts","hubName","hub","canAccess","methods","listeners","hubFactory","$logger","$","SignalRHub","HubReconnectionManager","configuration","HubLogWrapper","updateSubscribedFacility","isHubConnected","currentFacility","subscribedFacility","updateSubscription","facilityToLeave","unsubscribe","isConnectionAllowedByAccessControl","facilityToJoin","subscribedFacilityPromise","connection","connectionState","connected","onConnectionStateChanged","getConnectionStateName","oldState","newState","disconnected","reconnect","reconnectionManager","reset","connecting","reconnecting","onError","isTransient","subscription","rootPath","logging","useSharedConnection","stateChanged","queryParams","subscribe","callback","invoke","hubReconnectionManagerFactory","retryConnection","retryTimeout","getNextRetryMinutesIndex","currentRetryMinutesIndex","nextIndex","retryMinutes","minutes","writeLog","logDelegate","logPrefix","_len3","_key3","_len4","_key4","_len5","_key5","_len6","_key6","$connected$","hubs","progressUpdate","jobCompleted","jobDismissed","jobStatusHub","jobState","onJobBatchCreated","jobBatchId","getJobById","jobs","onJobBatchUpdated","progressMessage","errorMessage","onJobBatchCompleted","onJobBatchDismissed","_$remove","_$remove2","subscribeJobStatus","unsubscribeJobStatus","jobBatchCreated","jobBatchUpdated","jobBatchCompleted","jobBatchDismissed","monitoringTimeState","_previousDateTime","_dateTime","isRealTime","facilityStartOfDay","getFacilityStartOfDay","facilityEndOfDay","getFacilityEndOfDay","dateTimeHasChangedDays","previousStartOfDay","currentStartOfDay","offsetDifference","getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes","dateToOffset","getTimezoneOffset","tz","zone","utcOffset","utc","facilityDateTime","startOf","endOf","getFacilityTimeZoneOffsetDifferenceFromLocal","esAfterDate","require","attrs","$validators","afterDate","modelValue","viewValue","$isEmpty","$eval","kOptions","viewDate","parseDate","compareDateProperty","compareDate","esAngle","esBeforeDate","beforeDate","esDecimal","decimal","decimalValue","esLatitude","esLongitude","esNoxScale","validator","$attrs","ctrl","$$state","isPasswordValid","validateMinLength","validateContainsLowercaseLetter","validateContainsUppercaseLetter","validateContainsNumber","validateContainsSpecialCharacter","validateUsernamePasswordNotTheSame","unique","esUnique","esValidDate","validDate","e","amd","numberFormat","pattern","decimals",",",".","groupSize","percent","symbol","currency","abbr","months","AM","PM","patterns","d","D","F","g","G","m","M","s","t","T","u","Y","/",":","firstDay","n","ArrowMultiPolyLine","defaultArrowHeadFactor","defaultArrowHeadAngle","defaultScale","Polyline","initialize","windArrows","_this","arrowPointCollection","windArrow","arrowPoints","_getArrowPoints","arrowHeadFactor","arrowHeadAngle","scale","tail","arrowBackTick1","arrowBackTick2","corridorPlugin","Corridor","corridor","updateCallback","_updateWeight","onAdd","onRemove","off","setStyle","_getWeight","_getMetersPerPixel","centerLatLng","getCenter","pointC","pointX","latLngX","Control","EasyButtons","disable","isEnabled","DomUtil","enable","DomEvent","disableClickPropagation","_click","extraClasses","lastIndexOf","setActive","setInactive","googlePlugin","GoogleLayer","TileLayer","tileSize","errorTileUrl","continuousWorld","noWrap","mapOptions","Util","_ready","isGoogleMapsReady","asyncWait","_type","_map","_initContainer","_initMapObject","_reset","throttle","_update","_handleZoomAnim","_controlCorners","bottomright","marginBottom","_container","removeChild","getAttribution","setOpacity","setElementSize","tilePane","first","firstChild","stamp","zIndex","insertBefore","getSize","_googleCenter","maps","center","tilt","mapTypeId","MapTypeId","disableDefaultUI","keyboardShortcuts","disableDoubleClickZoom","scrollwheel","streetViewControl","styles","addListenerOnce","onReposition","_google","_checkZoomLevels","fire","mapObject","setZoom","_resize","setCenter","_center","trigger","asyncInitialize","o","googleLayer","HtmlIcon","Icon","iconUrl","shadowUrl","createIcon","document","createElement","innerHTML","_setIconStyles","createShadow","htmlIcon","ImageOverlay","baseInitialize","isDataUrl","separator","urlWithAuth","addInfluenceArcPolygon","InfluenceArcs","Polygon","arcsData","_buildArc","_arcMultiplier","_centrePoint","_arcLength","_arcColor","_arcPts","_drawArc","sigmaTheta","setLatLngs","fillColor","_popup","setContent","_getPopupContent","bindPopup","setLatLng","direction","_drawInvArc","initialBearing","finalBearing","_newcenter","_initialPoint","_finalPoint","_newFinalBearing","_newInitialBearing","_points","_extp","_deltaBearing","influenceArcs","latRadians","PI","lngRadians","_from","_to","_lat1","toRad","_lon1","_lat2","_lon2","_angle","atan2","sin","cos","toDeg","distance","_earthRadiusMeters","_brng","asin","MapCredits","addCredit","imageClick","src","addListener","stopPropagation","esLeaflet","esLeafletMapDefaults","esLeafletHelpers","esLeafletMapEvents","isDefined","mapEvents","getAvailableMapEvents","addEvents","mapId","setDirectiveControls","getMapCreationDefaults","_leafletMap","setView","tileLayerObj","tileLayer","tileLayerOptions","addTo","setTiles","zoomControl","setPosition","removeFrom","zoomsliderControl","whenReady","setMap","unresolveMap","invalidateSize","markers","paths","transclude","esLeafletController","getLeafletScope","esLeafletBoundsHelpers","createLeafletBounds","isValidBounds","southWest","northEast","controllers","shouldInitializeMapWithBounds","isUndefinedOrEmpty","centerController","leafletScope","centerModel","getDefaults","search","errorHeader","fitBounds","safeApply","autoDiscover","getBounds","_northEast","_southWest","copy","urlCenterHash","mapReady","urlHashCenter","extractCenterFromUrl","centerParam","cParam","currentScope","urlCenter","isSameCenterOnMap","settingCenterFromLeaflet","isValidCenter","locate","settingCenterFromScope","notifyCenterChangedToBounds","_leafletCenter","notifyCenterUrlHashChanged","esLeafletControlHelpers","updateLayersControl","overlays","leafletLayers","_layersControl","_controls","mustBeLoaded","layersControlMustBeVisible","removeLayer","removeControl","createLayersControl","hideOnSelector","showOnSelector","addBaseLayer","hideOverlayOnSelector","layerParams","addOverlay","addControl","atLeastOneControlItemMustBeShown","controlOptions","autoZIndex","control","Layers","leafletMap","scopeId","getUnresolvedDefer","setResolvedDefer","getDefer","setMarkers","leafletMarkers","getMarkers","setPaths","getPaths","getLayers","setLayers","getTiles","tiles","leafletTiles","leafletControl","directiveControls","getDirectiveControls","obtainEffectiveMapId","esLeafletDirectiveControlsHelpers","thingToAddName","createFn","cleanFn","_fnHeader","extender","clean","esLeafletEventsHelpersFactory","EventsHelper","rootBroadcastName","lObjectType","getAvailableEvents","genDispatchEvent","maybeMapId","eventName","logic","lObject","layerName","broadcastName","toSend","leafletEvent","leafletObject","$emit","bindEvents","events","eventBroadcast","eventsEnable","eventsDisable","splice","EsLeafletEventsHelpersFactory","esLeafletGeoJsonHelpers","esLeafletIterators","Point","validateCoords","coords","coordinates","pos","getCoords","p","getObjectArrayPath","pathStr","getObjectDotPath","arrayOfStrings","defaultTo","_default","isTruthy","mapCenter","fn","phase","$root","$$phase","$evalAsync","_errorHeader","resolvedDefer","isValidPoint","FullScreenControlPlugin","isLoaded","Fullscreen","MiniMapControlPlugin","MiniMap","AwesomeMarkersPlugin","AwesomeMarkers","equal","iconA","iconB","VectorMarkersPlugin","VectorMarkers","DomMarkersPlugin","DomMarkers","PolylineDecoratorPlugin","PolylineDecorator","decoration","decorationA","decorationB","MakiMarkersPlugin","MakiMarkers","ExtraMarkersPlugin","ExtraMarkers","LabelPlugin","Label","MarkerClusterGroup","MarkerClusterPlugin","GoogleLayerPlugin","LeafletProviderPlugin","Provider","HeatLayerPlugin","heatLayer","WebGLHeatMapLayerPlugin","WebGLHeatMap","BingLayerPlugin","BingLayer","AGSFeatureLayerPlugin","esri","featureLayer","AGSTiledMapLayerPlugin","tiledMapLayer","AGSDynamicMapLayerPlugin","dynamicMapLayer","AGSImageMapLayerPlugin","imageMapLayer","AGSClusteredLayerPlugin","clusteredFeatureLayer","YandexLayerPlugin","Yandex","GeoJSONPlugin","GeoJSON","Leaflet","DivIcon","watchOptions","doWatch","isDeep","individual","_isArrayLike","MAX_ARRAY_INDEX","_identity","_property","optimizeCb","func","context","argCount","other","accumulator","createAssigner","keysFunc","undefinedOnly","l","_isMatch","object","_keys","_matcher","_extendOwn","cb","currentKey","_hasErrors","ignoreCollection","cbName","_iterate","externalCb","internalCb","each","pow","esLeafletLabelEvents","LabelEvents","markerName","genEvents","labelEvents","scopeWatchName","label","esLeafletLayerHelpers","isValidLayerType","layerDefinition","layerTypes","mustHaveUrl","mustHaveData","mustHaveLayer","mustHaveBounds","mustHaveKey","createLayer","attrname","pluginOptions","safeAddLayer","safeRemoveLayer","loadedDefer","defers","getLayerTypes","xyz","__mapbox","geoJSON","geoJSONShape","geoJSONAwesomeMarker","pointToLayer","feature","geoJSONVectorMarker","wms","wmts","lyrs","IteratorHelper","featureGroup","here","openstreetmap","agsFeature","load","agsTiled","agsDynamic","agsImage","agsClustered","markercluster","bing","webGLHeatmap","setData","heat","HeatLayer","yandex","iip","custom","Class","isLayersControlVisible","_leafletLayers","oneVisibleLayer","newBaseLayer","newOverlayLayer","newBaseLayers","oldBaseLayers","doRefresh","hasLayer","newName","testBaseLayer","found","newOverlayLayers","oldOverlayLayers","testOverlayLayer","_loaded","scopeDefaults","keyboard","dragging","doubleClickZoom","scrollWheelZoom","touchZoom","crs","markerZoomAnimation","userDefaults","newDefaults","_getDefaults","CRS","zoomSliderControl","nominatim","server","EPSG3857","esLeafletEventsHelpers","genDispatchMapEvent","centerUrlHash","contextName","esLeafletMarkerEvents","lblHelp","MarkerEvents","handle","getLatLng","openPopup","esLeafletMarkersHelpers","esLeafletWatchHelpers","getLMarker","maybeLayerName","setLMarker","maybeAddMarkerToLayer","doIndividualWatch","FeatureGroup","addMarkers","markersToRender","oldModels","skips","pathToMarker","maybeLMarker","oldModel","updateMarker","createMarker","popupOptions","groupOptions","groupOption","addMarkerToGroup","bindTooltip","pass","addMarkerWatcher","listenMarkerEvents","seeWhatWeAlreadyHave","markerModels","oldMarkerModels","lMarkers","oldMarker","newMarker","hasLogged","doCheckOldModel","destroy","lMarkerName","deleteMarker","getNewModelsToSkip","newModels","_markersWatchOptions","maybeWatch","extendDirectiveControls","mapController","markersWatchOptions","watchMarkers","isNested","markersNested","_clean","markerToMaybeDel","_create","markersToAdd","newMarkers","oldMarkers","createLeafletIcon","iconData","markerScope","getMarkerScope","iconDataCopy","base64icon","base64shadow","Default","popupAnchor","shadowSize","closePopup","groupKey","adjustPopupPan","layerPos","_containerLeft","_containerBottom","containerPos","layerPointToContainerPoint","_adjustPan","compilePopup","_contentNode","updatePopup","innerText","textContent","reflow","offsetWidth","_updateLayout","_updatePosition","autoPan","manageOpenPopup","markerData","getMessageScope","compileMessage","manageOpenLabel","labelScope","getLabelScope","noHide","showLabel","oldMarkerData","isInitializing","iconAngle","setIconAngle","Handler","MarkerDrag","setIcon","unbindPopup","dragG","updateLabelContent","getLabel","unbindLabel","setPopupContent","updatedFocus","setZIndexOffset","markerLatLng","isCluster","markerOptions","clickable","markerDatum","Marker","groupName","isDeepWatch","markerWatchPath","clearWatch","esLeafletPathEvents","Helpers","_genDispatchPathEvent","_bindPathEvents","pathEvents","pathEventsEnable","pathEventsDisable","_getAvailablePathEvents","getAvailablePathEvents","bindPathEvents","esLeafletPathsHelpers","createPath","setPathOptions","leafletPaths","shouldWatch","watchPaths","watchPathFn","leafletPath","old","overlay","$watchCollection","newPaths","newPath","bindLabel","_convertToLeafletLatLngs","_convertToLeafletLatLng","_convertToLeafletMultiLatLngs","_getOptions","availableOptions","optionName","_updatePathOptions","updatedStyle","_isValidPolyline","pathTypes","polyline","setPath","multiPolyline","MultiPolyline","multiPolygon","MultiPolygon","rectangle","Rectangle","setBounds","circle","Circle","setRadius","circleMarker","CircleMarker","_getPathData","pathType","thingToWatchStr","initCb","maybe","watchFunctionName","unWatch","oldValue","toBrng","configureRouteAliases","$urlRouterProvider","redirectToDashboard","appRun","getRoutes","abstract","companyFacilities","esAlertDropdownOpener","openDropdown","closeDropdown","esAlertLevelSpinner","hasLevelIncreased","esAlerts","esAlertsController","refreshAlerts","alertCount","unsubscribeFromNotifications","activeAlerts","subscribeToNotifications","dismissAlert","dismissedAlerts","removeAlertFromState","goToAlertHistory","subscriptions","onAlertNotification","onAlertDismiss","isAlertDismissed","existingAlert","getAlertForSourceId","updateExistingAlert","moveAlertToFrontOfTheList","updateAlert","isNewAlert","unshift","$$hashKey","invokeMap","esAccordionPreventCollapse","preventCollapsingOpenPanelOnClick","removeHandler","accordionLinks","hasClass","configureAutoComplete","watchLocation","watchBoundaries","updateBounds","autocomplete","setAutocompleteBounds","strictBounds","_boundary","$watchGroup","locationChanged","address","locationChangedUnwatch","latLngMatch","_latLngMatch","$setDirty","places","Autocomplete","onfocus","$setTouched","place","getPlace","geometry","addressPicked","formatted_address","esBusyLoading","esPageBlocker","$target","busy","removeAttr","blockerName","blockerCount","busyTracker","active","loadingMessage","priority","terminal","esBusySaving","savingMessage","component","bindings","disabled","esButtonGroup","selected","textField","valueField","translationKey","esButtonGroupController","setSelected","containerName","$form","updateKendoDateWhenModelChanges","updateParentModelValidityWhenValidityChanges","dateString","onKendoDateChanged","$invalid","localTime","onErrorsChanged","previousErrors","currentValidatorErrorKeys","previousValidatorErrorKeys","keysRemoved","difference","$setValidity","$error","FileUploaderController","changeHandlerFactory","onChanges","getUploader","autoUpload","uploadUrl","formData","onAfterAddingFile","onFileAdded","onSuccessItem","onFileUploaded","restorePreviouslyUploadedFiles","existingFiles","uploader","existingFile","fileItem","isUploaded","isSuccess","file","lastModifiedDate","utcLastModifiedTime","changeHandler","heading","hasFirstChanged","hasChanged","allowedExtensions","extensions","validateAddedFile","validateExtension","fileNameLower","validExtension","extension","validationErrors","getValidationError","isError","validateSize","canUpload","maxSizeBytes","maxSizeMb","errorName","formattingArguments","errorKey","isValidExtension","isValidSize","upload","queuedItem","removeFromQueue","uploadedFile","isResultFileDifferentToUploadedFile","dequeueDuplicates","queued","fileUploaded","removeFile","deleteFile","required","onSwitched","esLegend","esLegendController","esList","esListController","rebindListItemsWhenTheDataSourceItemsChange","setSelectedItemStatus","filterItems","resetSelectedItemWhenIdValueChanges","selectedItem","selectItem","invokeItemSelectedFunction","invokeItemSelectedCallback","onItemSelected","previousSelectedItemId","addItem","term","filterTerm","columnDefs","j","fieldName","renderedData","defaultListOptions","isFilterable","updatePageBlocker","isActive","blockers","esPersistenceStore","deserializeItem","serializeItem","defaultModel","esPersistenceStoreController","bucket","esSetSideBarDefaultWidth","sidebarContainer","css","esTabSet","tabs","esTabSetController","esTimeSlider","addTemporalDataClassToMapWhenEnabled","resizeSliderOnPageResize","redrawDataAvailabilityWhenUpdated","redrawDataAvailabilityWhenSliderCreated","resize","timeSlider","kendoSlider","redrawDataAvailabilityLayers","modelDataAvailability","buildAvailabilityClasses","$sliderItemsContainer","$esDataAvailability","resetDataAvailabilityContainer","availabilityClasses","$sliderItems","itemCount","$items","pointIndex","$item","availabilityClass","buildDataAvailabilityIndicator","append","adjustDataAvailabilityContainerPosition","stepSize","query","modelCount","_loop","tick","modelsWithDataAtTick","sliderMin","$parent","$container","empty","appendTo","itemWidth","isFirstChild","isLastChild","indicatorWidth","marginWidth","$indicator","marginProperty","originalMarginLeft","marginLeftWithUnits","exec","firstIndicatorWidth","marginLeft","stepTooltip","onStepChanged","esTimeSliderController","StepTicker","calculateSliderMin","createTimeSlider","ticker","createStepTicker","changeTickerSpeed","tickerSpeedLabel","updateTickerWhenBoundsChange","raiseStepChangedEvent","cleanupWhenScopeDestroyed","calculateTickerSpeeds","watches","rebuildTimeSlider","isRunning","slider","smallStep","largeStep","tickPlacement","step","activeStep","calculateStepIndex","tooltip","hasTimeSliderParameters","stepCount","loop","onTick","stepIndex","stepValue","defaultSpeed","getDefaultTickerSpeedForIntervalCount","tickerSpeeds","tickerSpeedLabels","tickerSpeedIndex","floor","intervalCount","tickMillis","StepTickerFactory","updatePropertyThenRestart","shouldRestart","pause","canStart","ensureActiveStepIsValid","hasReachedFinalStep","updateActiveStep","timer","Tab","getUrl","isVisible","isDirty","isBusyLoading","esComponentChangeHandlerFactory","defaultHasChangedEvaluator","previousValue","propertySelector","fluentResult","isFirstChange","applyFilter","currentBoundValue","createThenFunction","because","hasChangedEvaluator","hasPropertyChanged","processChange","isPropertyInChangeMap","previousBoundValue","propertyChanges","esStateStore","utils","getBaseState","saving","subscribeToRouteChanges","store","toRoute","toRouteParams","$routeParams","initialStateResolver","dispatchers","unsubscribeFromRouteChanges","_state","dispatch","createDispatcher","initialStateLoader","save","init","Forbidden","esJobs","esJobsController","updateJobsWhenJobsChange","updateActiveJobCountOnJobCreated","updateActiveJobCountOnJobComplete","reloadJobsWhenFacilityChanges","newJobs","oldJobs","jobsAdded","jobsRemoved","recalculateActiveJobCount","activeJobCount","clearJob","clearCompleted","jobsToDismiss","shortcutCollection","shortcut","keyboardShortcutCollections","shortcuts","bind","unbind","action","originalCallback","stopCallback","esFullScreen","isFullScreen","$shellView","fullScreen","esSideBar","triggerResizePage","handles","maxWidth","innerWidth","minWidth","debounce","toggleClass","evt","esWindowResize","registerWindowResizeHandler","debouncedResize","registerPageLoadedHandler","debounceContentLoaded","unsubscribeMe","Shell","httpBatcher","errorThrower","alertState","showOperationsMenu","shouldShowOperationsMenu","$dropdown","updateFacilityDetails","showFacilityMenu","setupGlobalShortcuts","jobCount","showLeftPanel","classes","getClasses","getColumnClass","columnCount","menu","operations","incidentIntelligence","menuShortcutBindings","menuShortcuts","getActionMenuItems","getIncidentIntelligenceMenuItems","getConfigurationMenuItems","columnClass","calculateOperationsMenuHeight","routeState","selectedCompanyAlias","selectedFacilityAlias","currentState","flush","facilityName","globalShortcuts","monkey","balls","friday","dropdown","$new","setFilterText","$event","keyCode","filterText","filteredCompanies","filteredFacilities","blur","String","fromCharCode","resetFilterText","filterCompanies","menuItems","getMenuItemLabel","getMenuItemShortcutDescription","ticketingSystem","menuItem","dropdownMenu","isAttached","scrollHeight","innerHeight","URLSearchParams","menuClick","esMapCentre","defaultCentre","centre","esMapCentreController","fitMapToBounds","areCentresInSync","originalCentre","zoomToExtents","unwatch","_layers","firstTileLayer","eachLayer","esMapCluster","renderClusters","clusterGroup","markerClusterGroup","iconCreateFunction","cluster","getClusterIcon","getChildCount","chunkedLoading","polygonOptions","getMarkerIcon","onclick","isToggleMarker","getSelectedMarkerIcon","addLayers","clearLayers","markerColor","childCount","clusterSize","$onInit","$onDestroy","esMapCredits","esMapCreditsController","mapCredits","processCredits","mapCredit","popupFunction","textVersion","showCreditText","hasDismissedText","logoMimeType","logoData","storedTextVersion","storageBucketKey","dismissVersion","newScope","modalInstance","mapPromise","boundariesPromise","results","createToggleButtonAndAddToMap","easyButton","toggleDomainBoundaries","buildLayerGroup","lineOptions","dashArray","firstPolyline","secondPolyline","thirdPolyline","fourthPolyline","esMapEmissionSources","esMapEmissionSourcesController","loadSourcesOverlay","toggleSources","kml","hasSources","kmlLayer","KML","async","parser","DOMParser","xmlDoc","parseFromString","_addKML","esMapHeatMapController","retryCount","minOpacity","esMapInfluenceArcDirective","esMapInfluenceArcsController","leafletArcs","arcs","influenceArcPolygon","unrender","bringToBack","overlayProvider","showControls","interactive","showLayerToggleControlWhenShowControlsRequested","renderOverlaysWhenOverlaySourceChanges","isAddedToMap","layerToggleControl","renderOverlays","onKmlLayerClicked","isShowing","toggleLayerGroup","evnt","originalEvent","containerPoint","mouseEventToContainerPoint","layerPoint","containerPointToLayerPoint","layerPointToLatLng","addTargetingCssClassWhenTargeting","isTargeting","$map","targetingClassName","unregisterOutOfBoundsWatcher","addOutOfBoundsCssClassWhenOutOfBounds","outOfBoundsClassName","onMouseMoved","isInBounds","wasInBounds","moveMarkerWhenLocationChanges","toggleTargetting","shouldEnableTargetting","enableTargetting","disableTargetting","onLocationSelected","onLocationChanged","_location","esMapReady","isReady","esMapReadyController","mapTilesLoaded","isMapIdle","once","isMapReady","esMapResizer","esMapResizerController","invalidateMap","ex","debounceInvalidateMap","Scale","imperial","temporalEventGroups","leafletLayerGroups","removeLeafletGeoJsonLayerGroup","createLeafletLayerGroups","llg","eventGroup","geoJsonContentType","kmlContentType","geoJsons","fallbackContentType","temporalEvent","contentType","fallbackContent","leafletLayerGroup","geoJson","geoJsonOptions","getGeoJsonOptions","popupContent","properties","createHtmlMarker","onEachFeature","esMapTiles","esMapTilesController","tileConfigs","tileServerUrl","esMapType","isColor","esMapTypeController","mapLayer","toggleMapColours","buildArrowLayer","buildPolygonLayer","buildPathLayer","smoothFactor","windVector","createPolylineOptions","isForward","showLabels","labels","latLngs","testLatitude","testLongitude","latitudeDistance","longitudeDistance","stdDevRadius","polylineOptions","startTimeMillis","green","red","stdDevPaneName","stdDevGroup","pane","stepIncrement","timeOffsetMinutes","getColour","sign","startColour","endColour","ratio","sanitizeColour","substring","toHex","r","ceil","renderPathLayer","esMessagesController","NotFound","ContentPanel","formatMessage","defaultSentTime","setDate","getDate","setMinutes","getMinutes","operator","encoded","contentPanel","AddScenarioContentPanel","scenarioConfigurationState","AddScenarioLeftPanel","blastingConfigService","scenarioPromise","existing","hasModel","isSubmitted","savingPromise","back","allowedOverlayFileExtensions","blastDataMediatorFactory","modelLoadingStatus","onRefreshed","onJobStale","onJobCompleted","onJobDismissed","wasModelDataImported","importDataForSelectedModels","wasModelDataRemoved","removeUnselectedModelData","selectedModels","wereModelsImported","dataStore","hasImportedData","hasModelLoadedData","importDataIntoDataStore","loadData","loadBlastDataSuccess","getBlastDataResult","addBlastDataToModel","blastData","isModelSelected","wasDataImported","setModelLoadingStatus","addActiveJobToJobState","existingJob","loadBlastDataFailed","currentStatus","getModelLoadingStatus","importData","wereModelsRemoved","importedModelsAndTimes","removeData","processJobCompleted","currentLoadingStatus","hasActiveJob","doesActiveJobExist","clearStaleJobs","existingJobs","dispose","blastDataStore","blastDataStoreFactory","setHasImportedData","hasData","importedTimesForModel","hasBlastData","allDataForOffset","importedData","modelDataForOffset","allDataForTimeStep","modelDataAtTimeStep","getDataAtOffset","maxSize","validateUploadedFile","validatePotentialUpload","setValidationError","loaderPromise","files","validateOverlay","validateKmlOverlay","xmlParser","kmlValidator","hasNoLayers","overlayFiles","invalidateLocationWhenOutsideDomainBoundaries","validateSelectedLocationIsWithinBounds","isLocationOutOfBounds","isOutOfBounds","outOfBoundsValidationErrorKey","initilizeMap","loadFacilityOverlays","lookups","facilityLocation","buildLayers","vibrationLayer","createVibrationMarkerLayer","isSelectingBlastLocation","updatePollutantOptionsWhenPollutantChanges","selectedPollutant","updateAzimuthWhenValueFallsOutsideValidRange","updateElevationWhenBlastLocationChanges","locationData","oldLocationData","isElevationRequired","hasLocation","getElevationForSelectedLocation","elevationData","_locationData","isPollutantModelSelected","isOverpressureModelSelected","isPathModelSelected","isFlyrockSelected","isStemming","isBurden","validateHasSelectedModel","isValidationRequired","some","$modelValue","directiveName","editAlias","isEditingAlias","setDefaultAlias","hasAlias","updateAlias","refreshAlias","isBusy","validAlias","itemTemplate","noxComboBox","editInitialConcentration","isEditingInitialConcentration","hasInitialConcentration","refreshInitialConcentration","updateInitialConcentration","modelPollutant","libraryPollutantId","initialiseBlastTimeSelectors","nextBlastTime","estimateNextBlastTime","addAnotherBlastTimeSelector","latestBlastTime","removeBlastTimeSelector","lastBlastTime","roundUpToHalfHour","millisOverHalfHour","millisPerHalfHour","ensureBlastIsDuringDaylightHours","blastDate","hours","getHours","setHours","millisPerHour","esbsActualBlastTime","esbsActualBlastTimeController","updateVisibilityWhenScenarioChanges","updateDisplayedBlastTimeWhenActualBlastTimeChanges","isEditingBlastTime","canUpdateBlastTime","canModifyBlasting","changeBlastTime","actualBlastTimeModel","buildActualBlastTimeModel","formattedString","getDatePicker","hasFocus","timeFormat","originalBlastTime","selectedBlastTime","busySaving","datePicker","esbsFlyrockLegend","esbsFlyrockLegendController","esbsModelCategorySelector","esbsModelCategorySelectorController","updateModelTypeWhenStateChanges","updateStateWhenModelTypeChanges","selectedModelCategory","modelCategories","category","toArray","esbsModelGroupingSelector","esbsModelGroupingSelectorController","updateHasModelsForCategoryWhenCategoryChanges","hasModelsForCategory","groupingTypes","modelGroupingTypes","esbsModelLegendToggle","esbsModelLegendToggleController","toggleLegendVisible","esbsModelParameters","esbsModelParametersController","showPathParameters","hasBlastModelParameters","showPollutantParameters","showOverpressureParameters","showOverpressureBurdenParameters","showOverpressureStemmingParameters","showFlyrockParameters","showGroundVibrationParameters","duplicate","isNullOrUndefined","blastParameter","parameter","showPollutantBlastOutlineWhenBlastParametersAreValid","getBlastParametersForDisplay","updatePollutantBlastOutline","areParametersValid","showPollutantBlastOutline","hidePollutantBlastOutline","outline","arrows","polygonBounds","calculatePolygonBounds","calculateTranslationDelta","sqrt","theta","atan","azimuthRad","beta","x1","y1","x2","y2","calculateOutlinePoints","calculateArrowPoints","createArrowPoints","tip","headLength","arrowLength","headSpread","arrowHeadDelta","tipPoint1","tipPoint2","arrowLines","linePoints","offsetFromCentre","arrowLineDelta","topArrow","bottomArrow","esbsTimeSelector","esbsTimeSelectorController","createGroupsWhenScenarioChanges","updateGroupsWhenGroupingChanges","createScenarioGroups","modelGroups","createModelGroups","timeGroups","createTimeGroups","updateGroupsFromState","times","facilityDate","isLegendVisible","selectedModelGroupingType","selectedType","updateModelGroupsFromState","updateTimeGroupsFromState","grouping","selectedTimesForModel","selectedTimeMillis","selectedTimes","timesMillis","selectedModelsForTime","toggleLegend","toggleTimeSelectedForModel","setModelSelected","toggleModelSelectedForTime","getVibrationMonitors","loadAndDisplayVibrationMonitors","loadVibrationMonitors","bindMarkers","vibrationMonitor","monitorLoaders","hashParser","buildScenarioOptionsHash","configureScenarioOptionsFromHash","scenarioModelsState","parseHashString","parts","redirectTo","$match","contentPanel@app","actionsPanel@app","leftPanel@app","stateFactory","ScenarioConfigurationState","getDefaultConfigurationValue","windScientificModelOptions","pollutantScientificModelOptions","pollutantDisplayUnitOptions","forwardTrajectoryScientificModelOptions","forwardTrajectoryScientificModels","defaultPollutantDisplayUnitId","defaultPollutantScientificModelId","defaultWindScientificModel","defaultWindScientificModelId","defaultForwardTrajectoryScientificModelId","nox","defaultModelPollutantId","defaultUnit","canUpdateOverpressureModels","canUpdateFlyrockModels","canUpdateGroundvibrationModels","_results","ActionsPanel","ScenarioModelsContentPanel","BlastDataMediator","resolveMap","showBlastOriginWhenScenarioIsLoaded","updateIsAnimatedWhenModelCategoryChanges","updateVisibleModelsWhenSelectedModelsChange","destroyMediatorOnDeactivate","loadOverlays","onScenarioUpdated","existingScenario","addOverlays","mediator","showBlastOrigin","blastCentreMarker","isAnimatedModel","triggerMapResize","activeOffsetMinutes","updateVisibleModels","hadSelectedModels","hasSelectedModels","onActiveOffsetChanged","bindVisibleTimeStepDataToMap","onMediatorRefreshed","hasModelData","mapLayerDatasets","activeOffsetTooltip","ScenarioModelsLeftPanel","blastingConfigurationService","configureScenarioOptions","scenarioHash","getDefaultModelCategory","getDefaultModelGroupingType","loadScenarioModels","onConfirm","removalPromise","removeSuccess","headingKey","descKey","modalOptions","hasAnimatedModels","showBottomControls","BlastDataStore","ScenarioModelsState","domainBoundaries","isInSelectedModels","selectedBlastTimesForModel","buildModelLoadingStatusKey","modelLoadingStatuses","getMapBounds","memo","coordinate","buildModelCategory","buildModelGroupingType","simulationParameters","durationMinutes","intervalMinutes","groupingType","ScenarioSelectionContentPanel","onScenarioSelected","addScenario","scenariosState","detailPanel","updateUIWithSelectedScenario","listOptions","loadScenarios","getListOptions","esBlastScenarioForm","esBlastScenarioFormController","esBlastScenarioFormMap","esBlastScenarioFormMapController","DetailPanel","loadScenario","selectedScenario","stateFactoryResolver","ContentPanelController","runAermet","$valid","$setPristine","resetState","upperAirWeatherStationsDefaultValue","surfaceWeatherStationsDefaultValue","onUpperAirWeatherStationChanged","selectedUpperAirWeatherStationChanged","onSurfaceWeatherStationChanged","selectedSurfaceWeatherStationChanged","mapStateToVm","buildDatePicker","dateObj","onChanged","whenState","selectedUpperAirWeatherStationId","selectedSurfaceWeatherStationId","fromDateChanged","toDateChanged","lastRunDetails","runDetails","runDates","aermetStore","_monitors","surfaceWeatherStations","upperAirWeatherStations","emissionsDataUpload","emissionsDataFileUploadUrl","emissionsDataFileAdded","emissionsDataFileDeleted","existingEmissionsDataFiles","selectedCalpuffConfigId","calpuffConfigs","hasImportComplete","uploadedFiles","hasUploadedEmissionsData","canRunImport","emissionsDataImportCancelled","onSelectedCalpuffConfigChanged","selectedCalpuffConfigChanged","$delete$","uploadedFileName","$save$","resolvers","modelsState","updateUIWithSelectedModel","loadModels","onModelSelected","onAddModel","DeleteModal","openModal","$stateParams","navigateToModelsList","returnToEdit","loadDropDownData","setDropDownDataToVm","loadExistingModel","setExistingModelToVm","isPlume","isWind","autoGenerate","autoGenerateGisModel","calpuffConfigPollutantId","selectedDisplayUnit","selectedAssociatedWindScientificModel","associatedWindScientificModelId","selectedPlumeScientificModel","scientificModelId","selectedWindScientificModel","updateDefaultName","saveSuccess","getSavePlumePromise","plumeModel","defaultName","getSaveWindPromise","windModel","setModelType","resetPollutantDependentFields","displayUnitField","plumeScientificModelField","resetField","allowedOptions","funcToSetNewValue","fieldToSetToPristine","associatedWindScientificModel","deleteModal","emissionsDataStore","onEnter","onExit","gridOptions","getGridOptions","getMeasurementGroups","onSelectMeasurementGroup","addMeasurementGroup","hidden","handleDataBound","_event$sender","tbody","dataItems","view","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","isChild","isInUse","removeExisting","hasChildren","removeParent","navigateToMeasurementGroupsList","confirmRemove","loadMeasurementGroups","updateOrderWhenParentChanges","getPotentialParentMeasurementGroups","getMeasurementGroupToEdit","editGroup","child","measurementGroupDescription","measurementGroupDefaultOrder","measurementGroupParentId","measurementGroupCanHaveParent","measurementGroupsNested","getNextDefaultOrder","oldParentId","findHighestDefaultOrderRecursive","findHighestDefaultOrder","measurementGroupWithHighestDefaultOrder","onSelectMonitor","onAddMonitor","aSelectedMonitorRoute","aMeasurementTypeRoute","aDataImportRoute","detailsRoute","unitTypes","math","updateDisplayUnitText","defaultDisplayUnitName","updateBaseThreshold","baseThreshold","baseValue","thresholdColours","setInfluenceArcThreshold","validateThresholdValue","$index","thirdPartyCheck","previousThresholdValue","isThresholdValid","validateThresholdColour","uniqueColours","uniq","hasDuplicateThresholdColour","hasExistingCustomThresholdValue","influenceArcDisplayThreshold","influenceArcDisplayThresholdBaseValue","influenceArcDisplayThresholdMaxValue","thresholdType","getThresholdType","arcThresholdType","addThreshold","newThreshold","colourPalette","removeThreshold","yellow","brown","purple","selectedMeasurementGroup","getSortableOptions","removeDangerZone","addDangerZone","removeDropZone","addDropZone","$list","listId","connectWith","over","notInTheAvailableListEventHandler","reorderingInSameList","sourceList","draggingFromAvailableList","sortables","sourceModel","processVariableExistsInTargetList","out","reorderingInTheSameList","droptargetModel","received","droppingAvailableVariableIntoAnotherList","droptarget","refreshAvailableListWithAllAvailableProcessVariables","refreshAvailableProcessVariables","sortableOptions","cloneTheAvailableProcessVariables","availableProcessVariables","itemIndex","validateUniqueMeasurementGroup","DataImportTab","dataImportState","registerForStateEvents","apiCredentials","onSelectApiCredential","onCreateApiCredential","apiCredentialsDefaultValue","DataImportTabEditPanel","monitorTabs","isEdit","dataImport","loadingPromises","loadingCredentialPromise","apiCredential","forOwn","overrideAccessControls","initialiseForm","emptyGuid","requiresSecureConnection","persistApiCredential","toggleIsEnabled","_vm$accessControls","DetailsTab","detailsState","details","latlongWatches","updateMap","updateElevation","formIsReady","gcs","unwatchUtm","updateUtm","utm","updateLatLong","timeZoneDDL","monitorTypeDDL","hemisphere","configurationOptions","persistMonitor","northing","easting","latlong","toLatLonE","lon","toUtm","onMonitorTypeChanged","typeDefaultValue","timeZoneDefaultValue","monitorTemplate","monitorTypeGridOptions","valueTemplate","preferredWeatherMonitoringStationDefaultValue","MapConfigurationTab","mapConfigurationState","loadDisplay","syncDirtyStatus","isFormDirty","mapConfiguration","setSortables","displayVariables","dv","haveVariablesChanged","variableType","zip","comparer","saveDisplay","getId","getDisplayVariable","MeasurementTypesTab","measurementTypesState","registerForMeasurementTypeStateEvents","measurementTypes","onSelectMeasurementType","onCreateMeasurementType","measurementTypesDefaultValue","MeasurementTypesTabEditPanel","importMeasurementType","onCategoryChanged","showErrors","staleDataTimeoutSeconds","unitCollection","pollutantCollection","defaultAggregateTypeId","dataAvailabilityThresholds","unit","unitTypeId","onDefaultDisplayUnitChanged","unitId","onDefaultImportUnitChanged","persistMeasurementType","maxStaleDataTimeoutSeconds","pollutantDefaultValue","categoryDefaultValue","defaultDisplayUnitDefaultValue","defaultImportUnitDefaultValue","hasMonitorId","stateParams","monitorsPromise","monitorTypesPromise","windowsTimeZonesPromise","facilityLocationPromise","monitorsState","measurementGroupsState","tab","tab@app.configuration.company.monitoring.monitors.tabs","form@app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes","form@app.configuration.company.monitoring.monitors.tabs.monitor.dataImport","esWeatherStationConfiguration","esWeatherStationConfigurationController","stations","selectedStation","esAccordionConfigurationSetContainerHeight","setAccordionBodyMaxSize","$panels","$panelBody","$bottomToggle","availableHeight","bottomToggleHeight","accordionScaffoldingHeight","panel","$panel","pxToInt","maxPanelHeight","esFormStateTracker","discardChanges","unbindListeners","removeEventListener","windowUnloadListener","removeStateChangeStartEventHandler","routeChangingListener","unsavedChangesHeading","unsavedChangesHtml","returnValue","unsavedChangesText","LeftPanel","configurationState","companyNavigationGroups","getCompanyNavigationGroups","monitoringGroup","ref","annotationsGroup","isRouteSelected","modellingGroup","getCompanyRoute","groupRef","itemRef","configurationStateFactory","loadPromise","loadConfigurationNames","wrfConfigurationNames","forecastRunNames","forecastRuns","runDate","runPromise","selectedWrfConfigurationName","selectedForecastRunName","today","dashboardState","moveDashboardTitleInclude","registerForEvents","setupKeyboardShortcuts","removeDashboardTitleInclude","dashboardTitle","actionsPanel","contents","resetDashboard","dashboardCopy","dashboardResetKeyboardSequence","decorateColumnsWithCssSizingClasses","$column","unwatchDashboard","editMode","widgetFilter","navigateToScenario","widgetName","getModels","navigateToModel","modelhash","buildModelRunOptionsHash","oneDayInMinutes","linkHandlers","last24hrs","midnight","widgetDefinition","edit","editController","setContentBoundsWidth","selectedMonitorId","loadGraphs","$widgetContent","contentBounds","sampleDateTime","refreshMonitorDataTimeout","getTimeoutMillis","refreshTimeoutSeconds","getSeconds","setContentBounds","loadAvailableMonitors","availableMonitors","selectedMonitor","optionLabel","controllerName","editControllerName","onSelectedMonitorTypesChanged","selectedMonitorTypes","cancelMonitorDataAlarmsTimeout","hasSelectedMonitorTypes","loadMonitorDataAlarmsPromise","scheduleMonitorDataAlarmsTimeout","refreshTimeoutMillis","refreshMonitorDataAlarmsTimeout","loadMonitorTypes","getMonitorTypesPromise","availableMonitorTypes","isMonitorTypeSelected","toggleMonitorType","dashboardStateFactory","updateProcessDataLastReceived","localEndTime","labelKeySuffix","formattingArgs","labelKey","processDataLastReceived","actions","timeZoneService","updateViewModel","showOverlayControls","optimiseMapBounds","facilityTimeZoneStartTime","showOverControls","buildOptionsHash","configureOptionsFromHash","selectedModel","summaryState","onSummaryRouteEnter","State","ActionsPanelController","LeftPanelController","toggleStatus","toggleItem","ticket","toggleType","selectedItems","searchSummaryValues","form","getDateInLocalTimeZone","facilityTimeZoneFromDate","facilityTimeZoneToDate","ticketLocations","long","criteriaChanged","buildControls","maxDate","summaryStateFactory","createState","lookupValues","nowTime","categories","types","statuses","modellingState","ModellingMediator","timeStepCalculator","refreshWhenDateRangeChanges","refreshWhenChangingRealTimeModellingMode","refreshWhenSelectedModelsChange","watchTimeSlider","enableTimeSliderWhenSelectedModelsHaveData","isSingleTimeStep","showTimeSlider","onModelDataRefreshed","evaluateIfSelectedModelsHaveData","bindEnabledTimeStepDataToMap","onActiveTimeStepChanged","selectedInterval","activeTimeRange","calculateTimeStepRange","activeTimeStepStart","activeTimeStepEnd","modellingDataStore","getTimeStepDataForEnabledModels","renderDiscreteReceptors","getTimeStepDiscreteReceptorDataForEnabledModels","discreteReceptors","getReportUri","dataSetStartDate","dataSetEndDate","discreteReceptorDisplayOptions","alertPointReports","adjustActiveTimeStepToDataSetDateRange","updateTimeSliderParameters","isRealTimeMode","autoUpdateEnabled","currentRealTimeMode","realTimeMode","clear","intervalMillis","startMillis","endMillis","activeEndMillis","isUpdateRequired","oldSelectedModels","newModelIds","oldModelIds","disableModel","enableModel","dateRange","getDataSetDateRange","hasDataForAnySelectedModel","timeStepMillis","getTimeMillis","timeSliderStart","timeSliderEnd","timeSliderStepSize","timeSliderTooltip","hasTimeSteps","hasModellingParameters","esMapModels","toggleActiveLayers","currentDataPoints","previousDataPoints","closeTooltip","baseLayer","openTooltip","modelLayerIndex","createPane","esModellingDurationSelect","selectedDuration","availableDurations","textPrefix","esModellingDurationSelectController","updateSelectableDurationsWhenAvailableDurationsChange","formattedDurations","minutesToText","esModellingModelSelect","esModellingModelSelectController","updateModelLegendClassesAndTooltipsWhenDataSetChanges","updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges","dataSetDateWatchers","rebuildAllLegendClassesAndTooltips","unwatchLegends","rebuildLegendClassesAndTooltipForModel","isLoading","modelLegendClasses","modelLegendTooltips","toggleModel","durationFrom","durationTo","autoUpdate","hashDate","buildHashDate","modelIdList","AUTO_UPDATE","isMoment","KNOWN_DATES","knownDate","configureModelRunOptionsFromHash","leftPanelController","parsedHash","setSelectedModelDetails","setSelectedDateDetails","getClosestMatchingInterval","requestedInterval","availableIntervals","durationRanges","validModels","getIntervalModelsFoundInHash","toLocaleLowerCase","subscribeToDateChanges","subscribeToIntervalChanges","updateModelHashIfAutoUpdateChanges","updateModelHashIfSelectedModelsChange","onAutoUpdateChanged","scheduleNextAutoUpdateOfSelectedDate","lastInterval","rebaseSelectedTimeToLastInterval","nextIntervalAt","timeUntilNextIntervalMillis","seconds","autoUpdateTimeout","lastIntervalMillis","getLastIntervalMillis","i10nWarningPrefix","selectedDate","timeRange","trackModelDurationWarnings","timeStepCount","modelDurationTimeStepWarningCount","suffix","modelDurationWarning","warningClassName","recalculateModelHash","resetSelectedModels","oldInterval","updateTimePickerDropdownTimeIntervals","kendoDatePicker","rebaseSelectedTimeToIntervalBoundary","modelHash","updateModelHashUrlParameter","initialDate","onBlur","onFocus","ModellingDataStore","_dateIndex","_importedTimeSteps","_availableTimeStepDataIds","_disabledModels","_discreteReceptorValues","importDiscreteReceptorData","entries","_ref2","dateKey","importModelDataSets","modelDataSets","importTimeStepData","timeStepDataSet","temporalData","timeStepEndDate","dataPointId","addToDateIndex","addToImportedTimeSteps","addToModelDataPointIndex","itemAdded","existingDataPoint","timeStepDataId","rebuildRenderingLayers","releaseRenderingLayers","getImportedTimeStepsForModel","timeSteps","modelHasDataAt","modellingMediatorFactory","modelIdsToLoad","selectedModelIds","canRefresh","isRefreshRequired","loadDataForModels","resyncModelDataAvailability","isTimeStepIndexed","indexedTimeSteps","loadTimeRangeIfRequired","loadTimeAdjustedDataForModel","loadDataForModel","updateModelDataAvailability","latestUnindexedTimeStepMillis","oneHourBeforeToTimeMillis","availability","latestModelAvailabilityMillis","adjustedToMillis","adjustedFromMillis","adjustedOffsetMilliseconds","processDiscreteReceptorData","offsetResponseData","adjustedResponse","offsetAdjustedKey","offsetMillis","processModelDataSet","gisModels","gisModel","adjustedGisModels","availableGisModels","importedTimeSteps","setStatusForImportedTimeStepsToLoaded","addActiveJobsToJobState","setStatusToLoaded","timeStep","setModelLoadingStatusForSingleTimeStep","processModelDataSetErrors","promises$","discreteReceptor$","model$","getModelById","dataSetDateRange","isJobForCurrentDateRange","isModelStillSelected","tickStep","reloadOnSearch","modellingStateFactory","modellingStateFactoryResolver","_result","mapLocation","mappedIntervals","intervalOptionMinutes","ModellingState","clearData","dataObject","dataSetDateRangeMillis","intervalStatuses","intervalStepMillis","stepMillis","intervalStatus","modelLoadingStatusByTimeStep","getModelLoadingStatusByTimeStep","updateLoadingStatus","timeStepEndMillis","loadingStatusByTimeStep","baseDate","fromMinutes","toMinutes","isIntervalValid","baseDateMillis","fromTicks","toTicks","remainder","monitoringState","refreshTemporalEventGroups","eventGroups","sourceIdentificationDebug","hasAccessToSourceIdentification","refreshDataForAllMonitors","refreshDataForAllSourceAreas","refreshDataForMonitorType","sourceIdentification","areaSources","addIsRealTimeWatcher","dataCalls","getMonitorDataPromise","updatingPromise","renderMonitorMapMarkers","renderAreaSources","isPolling","pollingMonitorsPromise","realTimeTickTimeout","stopPollingMonitoringData","mergeResultsWithState","renderSourceAreaSources","exists","esMetSummary","esMetSummaryController","metSummaries","metSummary","metStation","storedMetStationId","getPreferredMetStationStore","changeSelectedMetStation","metStationId","esMonitoringDateTimeSelector","renameSliderStepLabels","stepContainer","siblings","steps","startOfDay","valueOf","esMonitoringDateTimeSelectorController","bindKeyboardShortcuts","startClock","generateErrorMessage","setDateTimeToNow","setDatePickerMaxDate","enableHistoricalMode","enableRealTimeMode","updateWidgetsInterval","updateDateTimeUrlParameter","debouncedTimeChanged","calculateFacilityLocalTime","updateDateTimeFromWidgetValues","getTimeSlider","fiveMinuteInterval","sixtyMinuteInterval","datePickerMax","readDateTimeFromWidgets","millisAtMorningMidnightOfSelectedDate","notifyTimeChanged","moveDateTimeBy","period","targetDate","focusTimeSlider","shortcutKeys","focusDatePicker","forwardOneDay","backwardOneDay","shortcutBindings","is24Hours","switchBackToRealTimeMode","updateWidgets","updateDatePicker","dateTimeMorningMidnight","updateTimeSlider","millisSinceMorningMidnight","digitalClockTime","esMonitoringPopups","leafletController","subscribeToLeafletMarkerClick","esMonitoringPopupsController","subscribeToLeafletClickEvents","onLeafletElementClick","leafletElementEvent","popupToClone","setGraphVariables","variables","setMapInstance","getPopup","findLast","openPopups","popup","_popupToClone$options","_leaflet_pos","closeOnClick","autoPanPadding","closeButton","autoClose","$widgetScope","popupSize","removeTracking","bringToFront","enableFocus","debouncedBringToFront","_wrapper","isClosing","enableDragAndDrop","Draggable","setCloseMethod","setResizePopupMethod","resizePopup","newContentBounds","getContentBounds","setCloneMethod","clonePopup","getCompiledElement","targetScope","buildViewModel","defaultSize","showConfigButton","estimatePopupHeight","pvRowHeight","graphHeight","paddingHeight","chromeHeight","isPortrait","compiledTemplate","popupSizes","unsubscribeFromMarkerClick","unsubscribeFromPathClick","lastOpenedPopup","pop","Set","small","medium","large","selectedProcessVariableId","mathService","loadWidget","hasChangedDays","sampleDate","currentDate","currentlySelectedDateTime","diff","onSuccess","sensorData","graphsNeedRerendering","initialLoad","selectedProcessVariable","defaultSensorId","onClickProcessVariable","graphWidth","renderSelectedSensorGraphs","onFail","sampleTime","busyLoadingSensors","ensureSensorAlwaysSelectedForLandscapeWidgets","selectedProcessVariableIds","loadSensorDataSeries","busyLoadingGraphDataSeries","renderSensorGraphs","debouncedOnClickProcessVariable","abortSingleClick","dblClickDelay","ctrlKey","onMultiSelectProcessVariable","pull","updateGraphDetails","convertDatumToFacilityDateTime","matchingThreshold","pvThresholds","defaultColor","getMinMaxThresholdValuesToShow","pvValues","MIN_SAFE_INTEGER","MAX_SAFE_INTEGER","pvValue","lower","upper","_iteratorNormalCompletion2","_didIteratorError2","_iteratorError2","_step2","_iterator2","pvThreshold","thresholdValue","graphDetails","processName","readings","processVariableName","_getMinMaxThresholdVa","baselines","baseLineValue","prevDataSeries","windowStart","windowEnd","dataSeries","isDataMissing","renderMissingData","$targetAccessor","missingText","isSingleSelectMode","selectedSensors","data_graphic","chart_type","missing_text","targetAccessor","full_width","full_height","renderTrend","hasDstAdjustment","selectedGraphs","indices","sId","findIndex","pvId","adjustedPalette","palette","animate_on_load","min_x","max_x","x_accessor","xax_format","y_accessor","yax_format","yax_count","y_extended_ticks","show_secondary_x_label","show_rollover_text","interpolate","curveMonotoneX","aggregate_rollover","missing_is_zero","colors","area","flip_area_under_y_value","mouseover","sensor","selectedDataPoint","mouseout","baseline","$baseline","instanceId","seen","toLocaleTimeString","series","selectedHighlight","renderMarkers","addWatchersToDisplaySwitches","addWatchersToSensorSwitches","mapSensorNameToSensorArcTuple","sensorType","influenceArcOverlayBySensor","getInfluenceArcsOverlayForSensor","arc","toggleInfluenceArcVisibility","getSensorTypes","watchSensorVisibilityToggle","toggleSensorVisibility","sensorTypes","monitoringStateFactory","monitoringConfigurationService","setInfluenceArcs","fencelines","fenceline","areaSourcesLayerName","areaSource","loadReports","onReportSelected","ProcessDataReport","saveFile","buildDataGrid","loadReportData","dataGrid","loadLookupValues","importLookupValues","processes","hasAllStateParams","stateParamsKeys","createDateModel","utcStartTime","lastProcessIdUsedToLoadColumns","utcTime","convertUtcToFacilityTime","redirectBackToReports","loadReportDataIfParametersSpecified","gridApi","updateGrid","revalidateStartAndEndTimeWhenParametersChange","$validate","updateStateParams","_toParams","convertFacilityDateTimeToShortISOString","buildGridColumns","timeColumn","loadingColumnsPromise","hasColumns","gridColumns","getParametersWithLocalTimes","localStartTime","notifyIfNoDataAvailable","exportReport","getReportDataAsCsv","getReportDataAsCsvPromise","saveCsvFile","csvData","textBlob","Blob","utf8EncodingHeader","utcDateTimeString","userTabs","PasswordTab","clearForm","UserDetailsTab","loadUserDetails","profile","persistUserDetails","userState","tab@app.user.profile","languages","selectedLanguage"],"mappings":"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","file":"app-48c7d30b4f.min.js","sourcesContent":["\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.browserStorage\", [\"webStorageModule\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.directives\", [\"kendo.directives\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.exception\", []);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.i18n\", []);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks\", []);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.notifier\", [\"jlareau.pnotify\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.router\", [\"ui.router\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.utils\", []);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.validators\", []);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"bootstrapper\", [\"app.core\"]);\n angular.module(\"bootstrapper\").config(BootstrapConfig).run(BootstrapRun);\n BootstrapConfig.$inject = [\"app.core.bootstrapper.configurators.stateReloadDecoratorProvider\", \"app.core.bootstrapper.configurators.IE9BehaviorProvider\", \"app.core.bootstrapper.configurators.notificationProvider\", \"app.core.bootstrapper.configurators.httpProvider\", \"app.core.bootstrapper.configurators.httpBatchProvider\", \"app.core.bootstrapper.configurators.internationalizationProvider\", \"app.core.bootstrapper.configurators.blockUIProvider\", \"app.core.bootstrapper.configurators.localStorageProvider\", \"app.core.bootstrapper.configurators.tooltipProvider\", \"app.core.bootstrapper.configurators.dashboardProvider\"];\n\n function BootstrapConfig() {\n for (var _len = arguments.length, configurators = new Array(_len), _key = 0; _key < _len; _key++) {\n configurators[_key] = arguments[_key];\n }\n\n configurators.forEach(function (configurator) {\n return configurator.configure();\n });\n }\n\n BootstrapRun.$inject = [\"app.core.bootstrapper.runners.routeHandler\", \"app.core.bootstrapper.runners.dashboard\", \"app.core.bootstrapper.runners.fileUploader\", \"app.core.bootstrapper.runners.kendoCultures\", \"app.core.bootstrapper.runners.internationalization\"];\n\n function BootstrapRun() {\n for (var _len2 = arguments.length, runners = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n runners[_key2] = arguments[_key2];\n }\n\n runners.forEach(function (run) {\n return run();\n });\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\", [\n /*\r\n * Angular modules\r\n */\n \"ngAnimate\", \"ngSanitize\", \"ngCookies\",\n /*\r\n * Our reusable cross app code modules\r\n */\n \"blocks\", \"blocks.directives\", \"blocks.exception\", \"blocks.router\", \"blocks.notifier\", \"blocks.i18n\", \"blocks.validators\", \"blocks.browserStorage\", \"blocks.utils\",\n /*\r\n * 3rd Party modules\r\n */\n \"kendo.directives\", \"ngMessages\", \"ui.router\", \"ui.validate\", \"SignalR\", \"ui.bootstrap\", \"ipCookie\", \"ajoslin.promise-tracker\", \"blockUI\", \"jcs.angular-http-batch\", \"angular-cache\", \"ngclipboard\", \"angularFileUpload\", \"angular-loading-bar\",\n /*\r\n * Angular Dashboard\r\n */\n \"adf\", \"adf.provider\",\n /*\r\n * Angular translate dependencies\r\n */\n \"pascalprecht.translate\",\n /*\r\n * Leaflet Angular directive\r\n */\n \"es-leaflet-directive\", \"app.legacy-adapter\"]).config([\"$compileProvider\", function ($compileProvider) {\n return $compileProvider.preAssignBindingsEnabled(true);\n }]);\n})();\n\n\n\"use strict\";\n\n(function () {\n 'use strict';\n\n angular.module(\"app\", [\n /*\r\n * Order is not important. Angular makes a\r\n * pass to register all of the modules listed\r\n * and then when app.dashboard tries to use app.data,\r\n * its components are available.\r\n */\n \"app.templates\",\n /*\r\n * Gulp bundled - Application Features\r\n */\n \"app.ui.features.alerts\", \"app.ui.features.blasting\", \"app.ui.features.dashboard\", \"app.ui.features.extras\", \"app.ui.features.modelling\", \"app.ui.features.monitoring\", \"app.ui.features.reporting\", \"app.ui.features.user\", \"app.ui.features.configuration.company.blasting\", \"app.ui.features.configuration.company.modelling\", \"app.ui.features.configuration.company.monitoring\", \"app.ui.features.configuration.system\",\n /*\r\n * WebPack bundled - Application Features\r\n * NOTE: add the module into App.Tests\\stubs\\webPackModules.stub.js\r\n */\n \"app.ui.features.incidentIntelligence\", // This is the new stuff\n \"app.parcel\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\", [\"app.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.alerts\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\", [\"angularFileUpload\", \"frapontillo.bootstrap-switch\", \"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration.company.blasting\", [\"app.ui.features.configuration\", \"app.ui.features.blasting\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration.company.modelling\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration.company.monitoring\", [\"ui.sortable\", \"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration\", [\"ui.bootstrap\", \"angularFileUpload\", \"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration.system\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.dashboard\", [\"ui.bootstrap\", \"app.ui.features.modelling\", \"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.extras\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\", [\"frapontillo.bootstrap-switch\", \"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.monitoring\", [\"frapontillo.bootstrap-switch\", \"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.reporting\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.user\", [\"app.ui.core\"]);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.browserStorage\").factory(\"browserStorage\", browserStorage);\n browserStorage.$inject = [\"lodash\", \"webStorage\"];\n\n function browserStorage(_, webStorage) {\n return {\n persist: persist,\n get: get,\n 'delete': deleteItem,\n persistBucket: persistBucket,\n getBucket: getBucket,\n deleteBucket: deleteBucket\n }; /////////////////////\n\n function persist(storageKey, itemToPersist) {\n validateStorageKey(storageKey);\n var storageItem = webStorage.get(storageKey) || {};\n\n if (!_.isEqual(storageItem, itemToPersist)) {\n storageItem = itemToPersist;\n webStorage.add(storageKey, storageItem);\n }\n }\n\n function persistBucket(storageKey, bucketKey, itemToPersist) {\n validateBucketKey(storageKey, bucketKey);\n var storageItem = webStorage.get(storageKey) || {};\n\n if (!_.isEqual(storageItem[bucketKey], itemToPersist)) {\n storageItem[bucketKey] = itemToPersist;\n webStorage.add(storageKey, storageItem);\n }\n }\n\n function deleteItem(storageKey) {\n validateStorageKey(storageKey);\n webStorage.remove(storageKey);\n }\n\n function deleteBucket(storageKey, bucketKey) {\n validateBucketKey(storageKey, bucketKey);\n var storageItem = webStorage.get(storageKey) || {};\n delete storageItem[bucketKey];\n webStorage.add(storageKey, storageItem);\n }\n\n function get(storageKey) {\n validateStorageKey(storageKey);\n var storageItem = webStorage.get(storageKey);\n return storageItem;\n }\n\n function getBucket(storageKey, bucketKey) {\n validateBucketKey(storageKey, bucketKey);\n var storageItem = webStorage.get(storageKey) || {};\n return storageItem[bucketKey];\n }\n\n function validateStorageKey(storageKey) {\n if (!_.isString(storageKey)) {\n throw new Error(\"The storage key must be a string with a value.\");\n }\n }\n\n function validateBucketKey(storageKey, bucketKey) {\n validateStorageKey(storageKey);\n\n if (!_.isString(bucketKey)) {\n throw new Error(\"The bucket key must be a string with a value.\");\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.directives\").directive(\"esDataGrid\", esDataGrid).controller(\"esDataGridController\", esDataGridController);\n esDataGrid.$inject = [\"$window\", \"lodash\"];\n\n function esDataGrid($window, _) {\n return {\n scope: {\n options: \"=\",\n grid: \"=?\"\n },\n restrict: \"E\",\n templateUrl: \"/App/blocks/directives/esDataGrid/esDataGrid.html\",\n controller: esDataGridController,\n controllerAs: \"vm\",\n bindToController: true,\n link: link\n };\n\n function link($scope, $element) {\n var paddingBottom = 5;\n $scope.$on(\"resizePage\", resizeGrid);\n $scope.$on(\"grid.resize\", resizeGrid);\n\n function resizeGrid() {\n var container = $element.find(\".panel\"),\n gridElement = $element.find(\".k-grid\"),\n gridRows = gridElement.find(\".k-grid-content\"),\n otherGridElements = gridElement.children().not(\".k-grid-content\"),\n footer = $element.find(\".panel-footer\");\n var otherElementsHeight = footer && footer.length && footer[0].offsetHeight || 0;\n\n _.forEach(otherGridElements, function (element) {\n otherElementsHeight += element.offsetHeight;\n });\n\n var containerHeight = container[0].offsetHeight;\n var preferredHeight = containerHeight - otherElementsHeight - paddingBottom;\n var maxAllowedHeight = angular.element($window).height() - container.offset().top - otherElementsHeight - paddingBottom;\n gridRows.height(Math.min(preferredHeight, maxAllowedHeight));\n var buttons = gridRows.find(\".k-button\");\n\n _.forEach(buttons, function (button) {\n angular.element(button).removeClass(\"k-button\");\n angular.element(button).removeClass(\"k-button-icontext\");\n });\n }\n }\n }\n\n esDataGridController.$inject = [\"$scope\", \"lodash\", \"app.core.services.dateTimeService\", \"promiseTracker\"];\n\n function esDataGridController($scope, _, dateTimeService, promiseTracker) {\n var vm = this;\n var clickableCells = [];\n var sorts = [];\n vm.busyLoading = promiseTracker();\n activate();\n\n function activate() {\n if (!vm.options.dataProvider) {\n throw new Error(\"Data provider not defined. Please bind to a function that returns a promise for a DataSourceResult.\");\n }\n\n var preProcessedOptions = preProcessOptions(vm.options);\n\n var onDataBound = preProcessedOptions.onDataBound,\n rest = _objectWithoutProperties(preProcessedOptions, [\"onDataBound\"]);\n\n vm.kendoGridOptions = angular.merge(getDefaultOptions(onDataBound), getDefaultDataSourceOptions(), rest);\n vm.grid = buildGridApi();\n initGridAfterKendoGridCreated(); ////////////////////\n // This builds an API that can be called by the consumer of the grid to force a refresh or update the\n // columns dynamically.\n\n function buildGridApi() {\n return {\n rebuildGrid: rebuildGrid,\n refreshData: refreshData,\n getSearchCriteria: getSearchCriteria\n }; //////////////////////\n // Rebuild the grid, which will also refresh the data\n\n function rebuildGrid(columns) {\n var schemaAndColumns = buildSchemaAndColumns(columns);\n var options = {\n columns: schemaAndColumns.columns\n };\n vm.kendoGrid.setOptions(options);\n vm.kendoGrid.dataSource.reader.model.define(schemaAndColumns.schema.model);\n } // Refresh the data\n\n\n function refreshData() {\n vm.kendoGrid.dataSource.read();\n }\n\n function getSearchCriteria() {\n var dataSource = vm.kendoGrid.dataSource;\n return {\n columns: vm.kendoGrid.columns.filter(function (col) {\n return col.field;\n }).map(function (col) {\n return col.field;\n }),\n take: dataSource.take(),\n skip: dataSource.skip(),\n sort: dataSource.sort(),\n filter: dataSource.filter(),\n aggregates: dataSource.aggregates()\n };\n }\n }\n\n function initGridAfterKendoGridCreated() {\n $scope.$on(\"kendoWidgetCreated\", function () {\n if (!vm.kendoGrid) {\n return;\n }\n\n vm.kendoGrid.pager.element.hide();\n $scope.$watch(function () {\n return vm.options.selectedId;\n }, function (selectedId) {\n if (selectedId) {\n return;\n }\n\n var $grid = angular.element(vm.kendoGrid.content);\n var row = $grid.find(\"tbody>tr.k-state-selected\");\n row.removeClass(\"k-state-selected\");\n });\n addClickHandler();\n });\n }\n } //////////////////////\n\n\n function getDefaultOptions(onDataBoundFromOptions) {\n var options = {\n selectable: \"single row\",\n sortable: {\n mode: \"multiple\",\n allowUnsort: true\n },\n columns: [],\n dataBound: onDataBound,\n change: onChange,\n resizable: true,\n reorderable: true\n };\n return options; ////////////////////\n\n function onChange(kendoEvent) {\n if (!vm.options.rowCallback) {\n return;\n }\n\n var grid = kendoEvent.sender;\n var item = grid.dataItem(grid.select());\n vm.options.rowCallback(item);\n }\n\n function onDataBound(event) {\n if (vm.kendoGrid.dataSource.totalPages() > 1) {\n vm.kendoGrid.pager.element.show();\n } else {\n vm.kendoGrid.pager.element.hide();\n }\n\n if (vm.options.selectedId) {\n highlightSelectedItem();\n }\n\n if (onDataBoundFromOptions) {\n onDataBoundFromOptions.call(this, event);\n }\n\n $scope.$broadcast(\"grid.resize\"); ///////////////////\n\n function highlightSelectedItem() {\n var item = vm.kendoGrid.dataSource.get(vm.options.selectedId);\n\n if (item) {\n var $grid = angular.element(vm.kendoGrid.content);\n var row = $grid.find(\"tbody>tr[data-uid=\".concat(item.uid, \"]\"));\n row.addClass(\"k-state-selected\");\n }\n }\n }\n }\n\n function getDefaultDataSourceOptions() {\n var options = {\n dataSource: {\n transport: {\n read: function read(kendoEvent) {\n var queryObject = kendoEvent.data;\n\n if (vm.options.dataProvider) {\n var loadingPromise = vm.options.dataProvider(queryObject).then(kendoEvent.success);\n vm.busyLoading.addPromise(loadingPromise);\n }\n }\n },\n sort: null,\n schema: {\n data: function data(response) {\n return response && response.data || [];\n },\n total: function total(response) {\n return response && response.total || 0;\n },\n aggregates: function aggregates(response) {\n return response && response.aggregates || [];\n },\n groups: function groups(response) {\n return response && response.groups || [];\n }\n },\n serverPaging: true,\n serverSorting: true,\n serverGrouping: false,\n serverFiltering: true,\n pageSize: 100\n },\n groupable: false,\n navigatable: true,\n scrollable: {\n virtual: false\n },\n pageable: {\n numeric: false,\n previousNext: true,\n refresh: true,\n input: true\n },\n filterable: {\n extra: false\n }\n };\n return options;\n }\n\n function preProcessOptions(options) {\n var schemaAndColumns = buildSchemaAndColumns(options.columns);\n options.columns = schemaAndColumns.columns;\n options.dataSource = _.extend({}, options.dataSource || {}, {\n schema: _extends({}, schemaAndColumns.schema, options.dataSource && options.dataSource.schema || {}),\n sort: _.sortBy(sorts, \"order\")\n });\n return options;\n }\n\n function buildSchemaAndColumns(columns) {\n var schemaFields = {};\n columns = _.map(columns, function (column, columnIndex) {\n if (column.dataType === \"datetime\") {\n column.format = \"{0:\".concat(dateTimeService.formats.kendo.dateTime, \"}\");\n column.type = \"date\";\n\n if (typeof column.filterable === \"undefined\") {\n column.filterable = {\n ui: \"datetimepicker\",\n format: \"{0:\".concat(dateTimeService.formats.kendo.dateTime, \"}\")\n };\n }\n }\n\n if (column.dataType === \"date\") {\n column.format = \"{0:\".concat(dateTimeService.formats.kendo.dateTime, \"}\");\n column.type = \"date\";\n\n if (typeof column.filterable === \"undefined\") {\n column.filterable = {\n ui: \"datepicker\",\n format: \"{0:\".concat(dateTimeService.formats.kendo.dateTime, \"}\")\n };\n }\n }\n\n if (column.dataType === \"time\") {\n column.format = \"{0:\".concat(dateTimeService.formats.kendo.dateTime, \"}\");\n column.type = \"date\";\n\n if (typeof column.filterable === \"undefined\") {\n column.filterable = {\n ui: \"timepicker\",\n format: \"{0:\".concat(dateTimeService.formats.kendo.dateTime, \"}\")\n };\n }\n } // The default filterable ui works well for the remaining data types, so we don't need to set these explicitly.\n\n\n if (column.dataType === \"number\") {\n column.type = \"number\";\n }\n\n if (column.dataType === \"boolean\") {\n column.type = \"boolean\";\n }\n\n if (column.dataType === \"string\" || typeof column.dataType === \"undefined\") {\n column.type = \"string\";\n }\n\n if (column.sort) {\n sorts.push({\n field: column.field,\n dir: column.sort.dir,\n order: column.sort.order\n });\n } // NOTE: Order is important here! The click handler below must be the last item since the above are fixed once the template is set.\n\n\n if (column.click) {\n var fieldTemplate = column.template || column.format ? \"#= kendo.format('\".concat(column.format, \"', \").concat(column.field, \")#\") : \"#=\".concat(column.field, \"#\");\n var clickableCellSelector = \"data-click-\".concat(columnIndex);\n clickableCells.push(\"[\".concat(clickableCellSelector, \"]\"));\n column.template = \"\").concat(fieldTemplate, \"\");\n }\n\n if (column.field && column.type) {\n schemaFields[column.field] = {\n type: column.type\n };\n }\n\n return column;\n }); // Add a slack column that does not have a fixed width to fill out the remainder of the grid width.\n // If this is not added resizing will not function correctly if all columns are set to fixed width as they will be implicitly (incorrectly) converted to variable width.\n // If only some of the columns are set then they will not be visible on smaller screen resolutions.\n // If every column does not have a width then we are assuming the user has opted for variable widths.\n\n if (columns.every(function (column) {\n return column.width && !isNaN(parseFloat(column.width)) && isFinite(column.width);\n })) {\n columns.push({});\n }\n\n var schema = {\n model: {\n fields: schemaFields\n }\n };\n return {\n columns: columns,\n schema: schema\n };\n }\n\n function addClickHandler() {\n if (!clickableCells.length) {\n return;\n }\n\n var selector = clickableCells.join(\", \");\n var $grid = angular.element(vm.kendoGrid.content); // Note: DO NOT change this to an arrow function, it changes the scope of `this` and breaks.\n\n $grid.on(\"click\", selector, function () {\n // Find the data record\n var $this = angular.element(this);\n var $row = $this.closest(\"tr\");\n var rowData = vm.kendoGrid.dataItem($row); // Lookup the function from the parent scope\n\n var clickAttr = _.find(this.attributes, function (attr) {\n return attr.name.indexOf(\"data-click-\") === 0;\n });\n\n if (!clickAttr) {\n return;\n }\n\n var matches = clickAttr.name.match(/data-click-(\\d+)/);\n var columnIndex = parseInt(matches[1], 10);\n var column = vm.kendoGrid.columns[columnIndex];\n var clickHandler = column.click;\n\n if (clickHandler && _.isFunction(clickHandler)) {\n clickHandler(rowData);\n }\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.directives\").directive(\"pelAutoFocus\", pelAutoFocus);\n pelAutoFocus.$inject = [];\n\n function pelAutoFocus() {\n return {\n restrict: \"A\",\n link: link\n };\n\n function link($scope, $element) {\n $element[0].focus();\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.directives\").directive(\"pelMarkModelDirtyOnBlur\", pelMarkModelDirtyOnBlur);\n pelMarkModelDirtyOnBlur.$inject = [];\n\n function pelMarkModelDirtyOnBlur() {\n var directive = {\n restrict: \"A\",\n compile: compiler\n };\n return directive;\n\n function compiler() {\n return function ($scope, $element) {\n var delegatingEventSelector = $element.is(\"input\") || $element.is(\"select\") ? \"\" : \"input, select\";\n $element.on(\"blur\", delegatingEventSelector, function (event) {\n var ngModel = angular.element(event.currentTarget).data(\"$ngModelController\");\n\n if (ngModel) {\n $scope.$apply(function () {\n ngModel.$$lastCommittedViewValue = ngModel.$$lastCommittedViewValue + \" \";\n ngModel.$dirty = true;\n ngModel.$commitViewValue();\n });\n }\n });\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.directives\").directive(\"pelScrollToFirstError\", pelScrollToFirstError);\n pelScrollToFirstError.$inject = [];\n /* istanbul ignore next */\n\n function pelScrollToFirstError() {\n return {\n restrict: \"A\",\n link: link\n };\n /* istanbul ignore next */\n\n function link($scope, $elem) {\n $elem.on(\"click\", function () {\n var $input = $elem.closest(\"form\").find(\"input.ng-invalid,textarea.ng-invalid,select.ng-invalid\").filter(\":first\");\n focus($input);\n });\n\n function focus($element) {\n if (!$element || !$element.length) {\n return;\n }\n\n var element = $element[0];\n\n if (element.clientWidth !== 0 && element.clientHeight !== 0 && element.style.opacity !== 0 && element.style.visibility !== \"hidden\" && element.style.display !== \"none\") {\n $element.focus();\n return;\n }\n\n focus($element.parent());\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.exception\").config(decorateExceptionHandler);\n decorateExceptionHandler.$inject = [\"$provide\"];\n\n function decorateExceptionHandler($provide) {\n $provide.decorator(\"$exceptionHandler\", exceptionHandlerDecorator);\n }\n\n exceptionHandlerDecorator.$inject = [\"$log\", \"$injector\", \"$window\"];\n\n function exceptionHandlerDecorator($log, $injector, $window) {\n var unhandledJavaScriptStatusCode = -999;\n var i18n, messageList, message, title, $timeout;\n\n var isUnhandledJavascriptError = function isUnhandledJavascriptError(error) {\n return error.type === \"fatal\" && error.status === unhandledJavaScriptStatusCode;\n };\n\n window.addEventListener(\"error\", addJavascriptErrorsToMessageList);\n return function (exception) {\n if (exception.handled) {\n return;\n }\n\n addJavascriptErrorsToMessageList({\n message: exception.message,\n error: exception\n });\n\n if (angular.mock && exception.rethrow) {\n throw exception;\n }\n }; ////////////////////////\n\n function addJavascriptErrorsToMessageList(event) {\n // these messages are 'fatal' in that they can prevent the application from running correctly but\n // refreshing the page for a javascript error will not result in any benefit to the user\n if (!i18n) {\n // Injector is used to get dependency because injecting these dependencies directly will result into circular dependency.\n i18n = $injector.get(\"i18n\");\n $timeout = $injector.get(\"$timeout\");\n messageList = $injector.get(\"app.core.models.messages.messageList\");\n title = i18n.i10n(\"errors.javascript.exception.title\");\n message = i18n.i10n(\"errors.javascript.exception.message\");\n }\n\n $timeout(function () {\n messageList.update(isUnhandledJavascriptError) || messageList.addFatal(title, message, unhandledJavaScriptStatusCode);\n });\n\n if (event) {\n $log.fatal(event.message, event.error);\n $window.LogRocket && $window.LogRocket.captureException(event.error);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.i18n\", [\"blocks.router\"]).provider(\"i18n\", i18nProvider);\n i18nProvider.$inject = [];\n\n function i18nProvider() {\n var self = this;\n self.settings = {};\n self.$get = i18n;\n i18n.$inject = [\"$translatePartialLoader\", \"$translate\", \"$state\", \"$q\", \"$log\", \"routeHelper\", \"lodash\"];\n\n function i18n($translatePartialLoader, $translate, $state, $q, $log, routeHelper, _) {\n var loaders = {};\n var addedResources = [];\n var resolvedPromise = $q.when(true);\n routeHelper.addStateChangeStartEventHandler(function (event, toState, toParams, fromState) {\n return ensureTranslationsAreLoaded(fromState, toState);\n }, 99999); // make this the last step\n\n return {\n i10n: $translate.instant,\n // e.g. i10n(`resourceKey`) -> returns the localized value.\n loadTranslationsFor: loadTranslationsFor,\n // e.g. for example usage see -> app/core/services/jobService.js\n onTranslationsLoaded: onTranslationsLoaded,\n // used by blocks.router -> routeHelper.js\n unloadStates: unloadStates // used by bootstrapper in the $stateChangeSuccess event\n\n }; ///////////////\n\n function buildUrl() {\n var url = [];\n var partCount = arguments.length;\n\n for (var i = 0; i < partCount; i++) {\n var part = i < 0 || arguments.length <= i ? undefined : arguments[i]; // If this isn't the first part, and it STARTS with a slash, then strip it off\n\n if (i > 0 && part[0] === \"/\") {\n part = part.substr(1);\n } // If this isn't the last part, and it ENDS with a slash, then strip it off.\n\n\n if (i < partCount - 1 && part[part.length - 1] === \"/\") {\n part = part.substr(0, part.length - 1);\n }\n\n url.push(part);\n }\n\n return url.join(\"/\");\n }\n\n function loadTranslationsFor(referenceUrl) {\n var resourceUrl = getResourceUrl(referenceUrl);\n $translatePartialLoader.addPart(resourceUrl);\n return $translate.refresh().then(function () {\n $log.debug(\"loaded: \" + referenceUrl);\n return $translate.instant;\n });\n }\n\n function onTranslationsLoaded(state) {\n if (!state) {\n state = $state.current;\n }\n\n var loadedPromise = getTranslationsLoadedPromise(state);\n return loadedPromise.then(function () {\n return $translate.instant; // note: this promise can be accessed in the controller constructor as i10n [see: admin.js]\n });\n }\n\n function getTranslationsLoadedPromise(state) {\n if (state) {\n return loadStates(null, state);\n }\n\n if (_.isEmpty(loaders)) {\n return $q.when(true);\n }\n\n var allLoaders = _.values(loaders);\n\n return $q.all(allLoaders);\n } /// The reference url can have a .html suffix (for template urls) or not.\n\n\n function getResourceUrl(referenceUrl) {\n if (!referenceUrl) {\n return null;\n }\n\n var matches; // If the referenceUrl DOES NOT end with .html\n\n if (referenceUrl.indexOf(\".html\", referenceUrl.length - \".html\".length) === -1) {\n matches = referenceUrl.match(/(.+(?=\\/))(?:\\/)(.*)/); // Using this as an example: app/ui/monitoring/app.ui.monitoring.ContentPanel\n // matches[1]: (app/ui/monitoring/)\n // matches[2]: (app.ui.monitoring.ContentPanel)\n } else {\n matches = referenceUrl.match(/(.+(?=\\/))(?:\\/)(.*(?=.html))/); // Using this as an example: app/ui/monitoring/ContentPanel.html\n // matches[1]: (app/ui/monitoring/)\n // matches[2]: (ContentPanel)\n }\n\n var templateFolder = matches[1];\n var resourceName = matches[2]; // Now we can compose the resource path: \"i18n/app/ui/monitoring/i18n/app.ui.monitoring.ContentPanel\".\n // The `i18n` at the start forces the correct resource to be loaded via the InternationalisationController.\n\n return buildUrl(\"i18n\", templateFolder, \"i18n\", resourceName);\n }\n\n function getResourceUrlsFromStateSettings(state) {\n var resourceUrls = [];\n\n if (!(state && state.settings && state.settings.i18n)) {\n return resourceUrls;\n }\n\n resourceUrls = state.settings.i18n;\n\n if (_.isString(resourceUrls)) {\n resourceUrls = [resourceUrls];\n }\n\n return resourceUrls.map(function (url) {\n if (url === null || url === undefined || !_.isString(url)) {\n return null;\n } // This regex tests if the url starts with /i18n/ or i18n/\n\n\n return /^[\\/]?i18n\\//i.test(url) ? url : buildUrl(\"i18n\", url);\n });\n }\n\n function ensureTranslationsAreLoaded(fromState, toState) {\n return loadStates(fromState, toState);\n }\n\n function unloadStates(fromState, toState) {\n var ready = $q.when(true);\n\n if (!fromState) {\n return ready;\n }\n\n var toStatePath = toState && toState.name && getStatePath(toState.name) || [];\n var toStateResources = getResourceUrlsFromStateSettings(toState);\n var unloadedResources = false;\n\n for (var stateName = fromState.name; stateName !== null; stateName = getParentStateName(stateName)) {\n // Unload up to the part where resources are no longer common. e.g. if you are navigating via the following states:\n // From - agent.college.enrolments\n // To - agent.college.offers\n //\n // Then we only want to unload the \"enrolments\" resources\n if (isInPath(toStatePath, stateName)) {\n break;\n }\n\n var state = stateName === fromState.name ? fromState : $state.get(stateName);\n\n if (!state) {\n continue;\n }\n\n unloadedResources = true; // Unload explicitly defined resources that are no longer required\n\n var explicitResourcesForState = getResourceUrlsFromStateSettings(state);\n\n var explicitResourcesToUnload = _.filter(explicitResourcesForState, function (url) {\n return !_.includes(toStateResources, url);\n });\n\n _.forEach(explicitResourcesToUnload, unloadResource); // Now check for a resource corresponding to all templates\n\n\n var templateResourceUrls = getTemplateResourceUrls(state);\n\n _.forEach(templateResourceUrls, unloadTemplateResource);\n }\n\n if (unloadedResources) {\n ready = $translate.refresh();\n ready.then(logReadyDebug);\n }\n\n return ready;\n\n function logReadyDebug() {\n $log.debug(\"finished unloading translation files...\");\n }\n\n function unloadResource(resourcePath) {\n //// Don`t bother if the resource is null or hasn`t been loaded\n if (!(resourcePath && _.has(loaders, resourcePath))) {\n return;\n } // this line was added for the following scenario. we have a route called /add\n // it loads in a language file corresponding with a details.html template.\n // we then move to a route called /edit\n // it loads in a language file corresponding to the same details.html template - as both routes\n // are based on the same template.\n // usually we unload language files associated with templates from the previous route\n // but this time we want to keep it loaded as it's the same and required.\n\n\n if (!addedResources.length) {\n return;\n }\n\n $translatePartialLoader.deletePart(resourcePath, false);\n delete loaders[resourcePath];\n $log.debug(\"unloading: \" + resourcePath);\n }\n\n function unloadTemplateResource(templateResourceUrl) {\n unloadResource(getResourceUrl(templateResourceUrl));\n }\n }\n\n function loadStates(fromState, toState) {\n if (!toState) {\n return resolvedPromise;\n }\n\n addedResources = [];\n var requiredResources = [];\n var refreshPromise;\n var fromStatePath = fromState && fromState.name && getStatePath(fromState.name) || []; // Load resources for this state as well as parent states\n\n for (var stateName = toState.name; stateName !== null; stateName = getParentStateName(stateName)) {\n // These states are already loaded by the parent path\n if (isInPath(fromStatePath, stateName)) {\n break;\n }\n\n var state = stateName === toState.name ? toState : $state.get(stateName);\n\n if (!state) {\n continue;\n } // Check for explicitly defined resources\n\n\n var resourceUrls = getResourceUrlsFromStateSettings(state);\n\n _.forEach(resourceUrls, loadResource); // Now check for a resource corresponding to all templates\n\n\n var templateResourceUrls = getTemplateResourceUrls(state);\n\n _.forEach(templateResourceUrls, loadTemplateResource);\n }\n\n if (addedResources.length) {\n // If we have requested any resources, then we return a new promise which will resolve when these\n // resources have been loaded.\n refreshPromise = $translate.refresh();\n\n _.forEach(addedResources, function (path) {\n loaders[path] = refreshPromise;\n });\n } else if (requiredResources.length) {\n // If no new resources have been requested, but there are resources which are required, then we return\n // a new promise which resolves when ALL of the required resource loaders are resolved.\n var requiredLoaders = _.map(requiredResources, function (requiredPath) {\n return _.has(loaders, requiredPath) && loaders[requiredPath] || resolvedPromise;\n });\n\n refreshPromise = $q.all(requiredLoaders);\n } else {\n // If there's nothing to load, well...\n refreshPromise = resolvedPromise;\n }\n\n if (refreshPromise !== resolvedPromise) {\n refreshPromise.then(function () {\n $log.debug(\"finished loaded translation files...\");\n });\n }\n\n return refreshPromise;\n\n function loadResource(resourcePath) {\n requiredResources.push(resourcePath); // Don`t reload the resources if they`re already loading/loaded\n\n if (!resourcePath || _.has(loaders, resourcePath)) {\n return;\n }\n\n $translatePartialLoader.addPart(resourcePath);\n addedResources.push(resourcePath);\n $log.debug(\"loading: \" + resourcePath);\n }\n\n function loadTemplateResource(templateResourceUrl) {\n loadResource(getResourceUrl(templateResourceUrl));\n }\n }\n\n function getTemplateResourceUrls(state) {\n var templateUrl;\n var templates = [];\n\n if (state.views) {\n var templateUrlValues = _.map(state.views, \"templateUrl\");\n\n _.forEach(templateUrlValues, function (templateUrlValue) {\n if (_.isFunction(templateUrlValue)) {\n templateUrl = templateUrlValue(state.params);\n templates.push(templateUrl);\n } else {\n // string\n templates.push(templateUrlValue);\n }\n });\n } else {\n if (_.isFunction(state.templateUrl)) {\n templateUrl = state.templateUrl(state.params);\n } else {\n templateUrl = state.templateUrl;\n }\n\n templates.push(templateUrl);\n }\n\n return templates;\n }\n\n function getParentStateName(childStateName) {\n var matches = childStateName.match(/(.+)\\./);\n return matches && matches.length ? matches[1] : null;\n } // Breaks up a state path such as \"modelling.job.dashboard\" into [\"modelling\", \"job\", \"dashboard\"];\n\n\n function getStatePath(stateName) {\n return _.map(stateName.match(/[^.]+/g), function (path) {\n return path.toLowerCase();\n });\n } // Finds out if the given path (e.g. [\"modelling\", \"job\", \"dashboard\"]) contains the supplied path (e.g. \"modelling.job\")\n\n\n function isInPath(path, stateName) {\n var statePath = getStatePath(stateName);\n\n if (statePath.length > path.length) {\n return false;\n }\n\n for (var i = 0; i < statePath.length; i++) {\n if (path[i] !== statePath[i]) {\n return false;\n }\n }\n\n return true;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.notifier\").factory(\"notifier\", notifier);\n notifier.$inject = [\"notificationService\", \"moment\"];\n\n function notifier(notificationService, moment) {\n var service = {\n error: error,\n info: info,\n success: success,\n warning: warning\n };\n return service; /////////////////////\n\n function error(message, title) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {\n hide: false\n };\n message += \"\".concat(moment().format(\"DD MMM YYYY hh:mm:ss A\"), \"\");\n return notify(message, title, \"error\", options);\n }\n\n function info(message, title) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return notify(message, title, \"info\", options);\n }\n\n function success(message, title) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return notify(message, title, \"success\", options);\n }\n\n function warning(message, title) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return notify(message, title, \"notice\", options);\n }\n\n function notify(message, title, type, options) {\n /* eslint-disable camelcase */\n var defaultOptions = {\n title: title,\n text: message,\n type: type,\n hide: true,\n delay: 4000,\n mouse_reset: false,\n buttons: {\n closer: true,\n closer_hover: false,\n sticker: false\n }\n };\n /* eslint-enable camelcase */\n\n return notificationService.notifyWithDefaults(angular.extend(defaultOptions, options));\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.router\");\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.router\").provider(\"routeHelper\", routeHelperProvider).config(setHtml5Mode);\n setHtml5Mode.$inject = [\"$locationProvider\"];\n\n function setHtml5Mode($locationProvider) {\n $locationProvider.html5Mode(true);\n } // This angular provider allows us to `carry` an angular.module.config() provider object into the angular.module.run() cycle of the lifecycle.\n\n\n routeHelperProvider.$inject = [\"$stateProvider\"];\n\n function routeHelperProvider($stateProvider) {\n this.$get = [\"$rootScope\", \"$state\", \"$q\", \"$translate\", \"lodash\", routeHelper];\n\n function routeHelper($rootScope, $state, $q, $translate, _) {\n var routes = [];\n var stateChangeStartPromiseBuilders = [];\n var translationsLoadedPromise;\n subscribeToStateChangeStart();\n return {\n configureRoutes: configureRoutes,\n getNavigationRoutes: getNavigationRoutes,\n addStateChangeStartEventHandler: addStateChangeStartEventHandler\n }; //////////////////\n // Call this method to add logic in the $stateChangeStart event handler.\n // If the promise returned is successful, the next event handler in the chain is executed (if one exists).\n // If the promise returned is rejected, the rejection function you provide is executed with the $state details.\n // When all event handlers pass the $stateChangeStart event is successful and the pipeline continues to $stateChangeSuccess.\n\n function addStateChangeStartEventHandler(fnThatReturnsAPromise) {\n var order = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var prioritisedPromiseBuilder = {\n builder: fnThatReturnsAPromise,\n order: order\n };\n stateChangeStartPromiseBuilders.push(prioritisedPromiseBuilder);\n stateChangeStartPromiseBuilders = _.sortBy(stateChangeStartPromiseBuilders, function (item) {\n return item.order;\n });\n return function () {\n stateChangeStartPromiseBuilders = _.without(stateChangeStartPromiseBuilders, prioritisedPromiseBuilder);\n };\n }\n\n function subscribeToStateChangeStart() {\n $rootScope.$on(\"$stateChangeStart\", function (event, toState, toParams, fromState, fromParams) {\n // allow the event to pass through untouched if we don't have any logic to execute.\n if (!stateChangeStartPromiseBuilders || !stateChangeStartPromiseBuilders.length) {\n return;\n } // we have to prevent a stack overflow by continuously returning to the /oops page\n\n\n if (toState.state === \"not-found\") {\n return ensureRootTranslationsAreLoaded();\n } // pause the progression of the route...\n\n\n event.preventDefault();\n return ensureRootTranslationsAreLoaded().then(function () {\n // progress through the event handlers, bailing out when an event handler rejection occurs\n // if all event handlers successful, continue the state/route change pipeline.\n var builders = _.map(stateChangeStartPromiseBuilders, \"builder\");\n\n _.reduce(builders, chainHandlerPromise, null).then(onHandlersSuccessful, onHandlersFailed);\n });\n\n function chainHandlerPromise(promise, builder) {\n if (!promise) {\n return builder(event, toState, toParams, fromState, fromParams);\n }\n\n return promise.then(function () {\n return builder(event, toState, toParams, fromState, fromParams);\n }, function (errorFn) {\n return _.isFunction(errorFn) && errorFn(event, toState, toParams, fromState, fromParams) || $q.reject(null);\n });\n }\n\n function onHandlersSuccessful() {\n var reload = $state.$current.data && $state.$current.data.$reload;\n $state.go(toState.name, toParams, {\n notify: false,\n reload: reload\n }).then(function () {\n $rootScope.$broadcast(\"$stateChangeSuccess\", toState, toParams, fromState, fromParams);\n });\n }\n\n function onHandlersFailed() {// rejection happens here.\n }\n });\n }\n\n function ensureRootTranslationsAreLoaded() {\n return translationsLoadedPromise || (translationsLoadedPromise = $translate.refresh());\n }\n\n function configureRoutes(routes) {\n routes.forEach(function (route) {\n $stateProvider.state(route.state, route);\n determinePageLayoutType(route);\n });\n\n function determinePageLayoutType(route) {\n if (route.views && (route.views.leftPanel || route.views[\"leftPanel@app\"])) {\n route.data = angular.extend(route.data || {}, {\n layoutType: \"split\"\n });\n }\n }\n }\n\n function getNavigationRoutes() {\n if (routes && routes.length) {\n return routes;\n }\n\n routes = _.chain($state.get()).filter(function (state) {\n return state.settings && state.settings.navigation && state.settings.navigation.group && state.settings.navigation.group === \"application\";\n }).sortBy(function (state) {\n return state.settings.navigation.order ? state.settings.navigation.order : 1000;\n }).value();\n return routes;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n(function () {\n \"use strict\";\n\n angular.module(\"blocks.utils\").factory(\"utils\", getUtils);\n getUtils.$inject = [\"lodash\"];\n\n function getUtils(_) {\n return {\n freeze: freeze,\n arrToObj: arrToObj\n }; ////////////////////\n\n function freeze(obj) {\n var deep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n if (deep) {\n Object.getOwnPropertyNames(obj).forEach(function (propertyName) {\n var propertyValue = obj[propertyName];\n\n if (propertyValue === null || propertyValue === undefined) {\n return;\n }\n\n var valueType = _typeof(propertyValue);\n\n if (valueType !== \"object\" && valueType !== \"function\") {\n return;\n }\n\n if (Object.isFrozen(propertyValue)) {\n return;\n }\n\n freeze(propertyValue);\n });\n }\n\n Object.freeze(obj);\n return obj;\n } // Use this function to use an immutable array in an ng-repeat loop.\n //\n // ng-repeat wants to adorn array elements with a $$hashKey property which isn't possible when using esStateStore\n // which freezes the state (including arrays). ng-repeat can loop through an object literal, treating the object keys as the $$hashKey.\n\n\n function arrToObj(arr) {\n var hashKey = 0;\n return _.reduce(arr, function (hash, value) {\n hash[hashKey++] = value;\n return hash;\n }, {});\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.appSettings\", appSettingsProvider);\n appSettingsProvider.$inject = [];\n\n function appSettingsProvider() {\n var self = this;\n self.settings = {\n appName: \"Envirosuite\",\n pageTitle: \"\",\n user: {},\n site: {\n company: {},\n facility: {}\n }\n };\n self.$get = appSettingsFactory;\n appSettingsFactory.$inject = [\"$timeout\", \"$log\", \"webStorage\", \"postal\", \"app.core.events\"];\n\n function appSettingsFactory($timeout, $log, webStorage, postal, coreEvents) {\n var channel = postal.channel(coreEvents.channelName);\n var accessControls = {};\n var user = {};\n Object.defineProperty(self.settings.site.company, \"alias\", {\n get: function get() {\n return getFromCache(\"company-alias\");\n },\n set: function set(newValue) {\n return addToCache(\"company-alias\", newValue);\n },\n enumerable: true\n });\n Object.defineProperty(self.settings.site.facility, \"es1RouteName\", {\n get: function get() {\n return getFromCache(\"es1-route-name\");\n },\n set: function set(newValue) {\n return addToCache(\"es1-route-name\", newValue);\n },\n enumerable: true\n });\n Object.defineProperty(self.settings.site.facility, \"alias\", {\n get: function get() {\n return getFromCache(\"facility-alias\");\n },\n set: function set(newValue) {\n addToCache(\"facility-alias\", newValue);\n\n if (newValue) {\n updateLoggingContext();\n }\n },\n enumerable: true\n });\n Object.defineProperty(self.settings.site.facility, \"ticketingSystem\", {\n get: function get() {\n if (self.settings.site.facility.ticketingSystemType === \"d522663f-75c2-4f7d-ba8d-81b90f93382a\") {\n var name = \"JIRA Service Desk\";\n var baseUrl = \"https://envirosuite.atlassian.net\";\n var ticketsUrl = \"\".concat(baseUrl, \"/projects/\").concat(self.settings.site.facility.ticketingSystemTenantId, \"/queues\");\n return {\n name: name,\n baseUrl: baseUrl,\n ticketsUrl: ticketsUrl,\n ticketUrl: function ticketUrl(ticketId) {\n return \"\".concat(baseUrl, \"/browse/\").concat(ticketId);\n }\n };\n }\n },\n enumerable: true\n });\n Object.defineProperty(self.settings.site, \"accessControls\", {\n get: function get() {\n return accessControls;\n },\n set: function set(newValue) {\n accessControls = newValue;\n publish(coreEvents.topics.accessControlsUpdated, accessControls);\n }\n });\n Object.defineProperty(self.settings, \"user\", {\n get: function get() {\n return user;\n },\n set: function set(newValue) {\n if (user !== newValue) {\n user = newValue;\n addDisplayNameProperty();\n }\n }\n });\n\n self.settings.forgetCompanyAndFacility = function () {\n self.settings.site.company.alias = null;\n self.settings.site.facility.es1RouteName = null;\n self.settings.site.facility.alias = null;\n };\n\n function addDisplayNameProperty() {\n Object.defineProperty(self.settings.user, \"displayName\", {\n get: function get() {\n return user.firstName && user.lastName ? \"\".concat(user.firstName, \" \").concat(user.lastName) : \"\";\n }\n });\n }\n\n activate();\n\n function activate() {\n ensureSessionStorageHasFacilityDetails();\n $log.setLoggingContext(self.settings.webApiHostUri + \"log\", null, null, \"9B088CF9-C8BA-4F66-A462-7B1454BBA53C\" // KnownCredentials.Guest\n );\n self.settings.user = {\n firstName: self.settings.firstName,\n lastName: self.settings.lastName\n }; // ensure the web api url ends with a slash\n\n self.settings.zeusHostUri = self.settings.zeusHostUri && self.settings.zeusHostUri.replace(/\\/?$/, \"/\");\n self.settings.mvcHostUri = self.settings.mvcHostUri && self.settings.mvcHostUri.replace(/\\/?$/, \"/\");\n self.settings.webApiHostUri = self.settings.webApiHostUri && self.settings.webApiHostUri.replace(/\\/?$/, \"/\");\n self.settings.eS2VersionedApiUri = self.settings.eS2VersionedApiUri && self.settings.eS2VersionedApiUri.replace(/\\/?$/, \"/\");\n self.settings.reportsAppHostUri = self.settings.reportsAppHostUri && self.settings.reportsAppHostUri.replace(/\\/?$/, \"/\"); // transform icp registration configs\n\n self.settings.icpCertificate = self.settings[\"china-IcpCertificate\"];\n self.settings.internetSecurityNumberText = self.settings[\"china-InternetSecurityNumberText\"];\n self.settings.internetSecurityRegistrationLink = self.settings[\"china-InternetSecurityNumber\"] ? \"http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=\".concat(self.settings[\"china-InternetSecurityNumber\"]) : null;\n }\n\n return self.settings; ////////////////\n\n function addToCache(key, value) {\n webStorage.session.add(key, value);\n webStorage.local.add(key, value);\n }\n\n function getFromCache(key) {\n var value = webStorage.session.get(key);\n\n if (value === undefined || value === null) {\n value = webStorage.local.get(key);\n }\n\n return value;\n }\n\n function ensureSessionStorageHasFacilityDetails() {\n if (!isBrowserSessionPrimedWithFacilityDetails()) {\n // default the user to the first company/alias available to them.\n primeSessionStorageWithFacilityDetails();\n } // otherwise we use the company/facility stored in session previously (before hard-refresh)\n // see: routeHandler.js to see how the company/facility provided via the url route is used to override these session storage values.\n\n\n cleanupServerProvidedFacilityDetails(); /////////////\n\n function isBrowserSessionPrimedWithFacilityDetails() {\n return self.settings.site.company.alias && self.settings.site.facility.alias;\n }\n\n function primeSessionStorageWithFacilityDetails() {\n self.settings.site.company.alias = self.settings.companyAlias;\n self.settings.site.facility.alias = self.settings.facilityAlias;\n }\n\n function cleanupServerProvidedFacilityDetails() {\n delete self.settings.facilityAlias;\n delete self.settings.companyAlias;\n }\n }\n\n function updateLoggingContext() {\n if (!(self.settings.site.company.id && self.settings.site.facility.id)) {\n return;\n }\n\n $log.setLoggingContext(self.settings.webApiHostUri + \"log\", self.settings.site.company.id, self.settings.site.facility.id, self.settings.apiKey);\n }\n\n function publish(topic, payload) {\n $timeout(function () {\n return channel.publish(topic, payload);\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.blockUI\", configureBlockUI);\n configureBlockUI.$inject = [\"blockUIConfig\", \"cfpLoadingBarProvider\"];\n\n function configureBlockUI(blockUIConfig, loadingBarConfig) {\n this.configure = function () {\n blockUIConfig.autoBlock = false;\n blockUIConfig.autoInjectBodyBlock = false;\n blockUIConfig.delay = 150;\n blockUIConfig.templateUrl = \"App/ui/core/layout/blockUI.html\";\n loadingBarConfig.includeSpinner = false;\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").config(configureCompileProvider);\n configureCompileProvider.$inject = [\"$compileProvider\"];\n\n function configureCompileProvider($compileProvider) {\n // See: https://docs.angularjs.org/guide/production\n $compileProvider.debugInfoEnabled(false);\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.dashboard\", configureDashboard);\n configureDashboard.$inject = [\"dashboardProvider\"];\n\n function configureDashboard(dashboardProvider) {\n this.configure = function () {\n if (screen.width < 992) {\n dashboardProvider.structure(\"100\", {\n rows: [{\n columns: [{\n styleClass: \"col-md-12\"\n }]\n }]\n });\n } else {\n dashboardProvider.structure(\"50-50\", {\n rows: [{\n columns: [{\n styleClass: \"col-md-6\"\n }, {\n styleClass: \"col-md-6\"\n }]\n }]\n }).structure(\"40-60\", {\n rows: [{\n columns: [{\n styleClass: \"col-md-4\"\n }, {\n styleClass: \"col-md-8\"\n }]\n }]\n }).structure(\"25-50-25\", {\n rows: [{\n columns: [{\n styleClass: \"col-md-3\"\n }, {\n styleClass: \"col-md-6\"\n }, {\n styleClass: \"col-md-3\"\n }]\n }]\n }).structure(\"33-33-33\", {\n rows: [{\n columns: [{\n styleClass: \"col-md-4\"\n }, {\n styleClass: \"col-md-4\"\n }, {\n styleClass: \"col-md-4\"\n }]\n }]\n });\n }\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").constant(\"environment\", {\n production: true,\n develop: false\n });\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.http\", configureHttp);\n configureHttp.$inject = [\"$httpProvider\"];\n\n function configureHttp($httpProvider) {\n this.configure = function () {\n $httpProvider.defaults.withCredentials = true; // this is needed to get cookies sent across the wire.\n\n /* eslint-disable dot-notation */\n\n $httpProvider.defaults.headers.common[\"Content-Type\"] = \"application/json\"; // used by post and put - telling the server that we're sending json content.\n\n $httpProvider.defaults.headers.post[\"Accept\"] = \"application/json, text/plain\";\n /* eslint-enable dot-notation */\n\n $httpProvider.interceptors.push(\"app.core.httpInterceptors\");\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.httpBatch\", configureHttpBatch);\n configureHttpBatch.$inject = [\"httpBatchConfigProvider\", \"app.core.appSettingsProvider\", \"environment\"];\n\n function configureHttpBatch(httpBatchConfigProvider, appSettings, environment) {\n this.configure = function () {\n // note: this is a workaround for when browser-sync strips the http:// from out appSettings objects when proxying to our real-url.\n if (appSettings.settings.webApiHostUri.indexOf(\"//\") === 0) {\n appSettings.settings.webApiHostUri = \"http:\".concat(appSettings.settings.webApiHostUri);\n appSettings.settings.signalRHostUri = \"http:\".concat(appSettings.settings.signalRHostUri);\n } // ensure the webApiHostUri has a backslash on it\n\n\n appSettings.settings.webApiHostUri = appSettings.settings.webApiHostUri.replace(/\\/?$/, \"/\");\n\n if (environment.production) {\n //http://www.jonsamwell.com/batching-http-requests-in-angular/\n httpBatchConfigProvider.setAllowedBatchEndpoint(appSettings.settings.webApiHostUri, appSettings.settings.webApiHostUri + \"batch\", {\n maxBatchedRequestPerCall: 20\n });\n }\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.IE9Behavior\", configureIE9Behavior);\n\n function configureIE9Behavior() {\n this.configure = function () {\n if (!(window.console && console.log)) {\n console = {\n log: function log() {},\n debug: function debug() {},\n info: function info() {},\n warn: function warn() {},\n error: function error() {}\n };\n }\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.internationalization\", configureInternationalization);\n configureInternationalization.$inject = [\"$translateProvider\", \"$translatePartialLoaderProvider\", \"app.core.appSettingsProvider\", \"moment\", \"kendo\"];\n\n function configureInternationalization($translateProvider, $translatePartialLoaderProvider, appSettingsProvider, moment, kendo) {\n this.configure = function () {\n $translateProvider.useLoader(\"$translatePartialLoader\", {\n urlTemplate: \"{part}.{lang}.json\"\n });\n $translatePartialLoaderProvider.addPart(\"i18n/app/i18n/shared\");\n $translatePartialLoaderProvider.addPart(\"i18n/app/ui/core/i18n/notFound\");\n $translatePartialLoaderProvider.addPart(\"i18n/app/ui/core/i18n/forbidden\");\n $translateProvider.addInterpolation(\"$translateMessageFormatInterpolation\"); // null: does not sanitize and allows bad html (like )\n // sanitize: sanitizes HTML in the translation text using $sanitize\n // escape: escapes HTML in the translation\n // sanitizeParameters: sanitizes HTML in the values of the interpolation parameters using $sanitize\n // escapeParameters: escapes HTML in the values of the interpolation parameters\n // sce: wraps HTML in $sce.trustAsHtml(value)\n // sceParameters: wraps HTML in the values of the interpolation parameters in $sce.trustAsHtml(value)\n\n $translateProvider.useSanitizeValueStrategy(\"escapeParameters\"); // adding in some static translations needed to indicate that other translations are loading... :)\n\n if (!appSettingsProvider.settings.showEmptyTranslations) {\n $translateProvider.translations(\"en\", {\n 'activityIndicator.default.label': \"Please wait ...\"\n });\n $translateProvider.translations(\"es\", {\n 'activityIndicator.default.label': \"Por favor espere ...\"\n });\n $translateProvider.translations(\"fr\", {\n 'activityIndicator.default.label': \"S'il vous pla\\xEEt, attendez ...\"\n });\n $translateProvider.translations(\"vi\", {\n 'activityIndicator.default.label': \"Xin vui l\\xF2ng ch\\u1EDD ...\"\n });\n $translateProvider.translations(\"zh\", {\n 'activityIndicator.default.label': \"\\u8BF7\\u7A0D\\u5019...\"\n });\n $translateProvider.translations(\"lt\", {\n 'activityIndicator.default.label': \"Pra\\u0161au palauk...\"\n });\n }\n\n $translateProvider.preferredLanguage(appSettingsProvider.settings.locale);\n $translateProvider.fallbackLanguage(\"en\");\n $translateProvider.use(appSettingsProvider.settings.locale);\n var locale = appSettingsProvider.settings.locale;\n kendo.culture(locale);\n moment.locale(locale.toLowerCase());\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.localStorage\", configureLocalStorage);\n configureLocalStorage.$inject = [\"defaultSettings\"];\n\n function configureLocalStorage(defaultSettings) {\n this.configure = function () {\n defaultSettings.prefix = \"es.\";\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.notification\", configureNotification);\n configureNotification.$inject = [\"notificationServiceProvider\", \"PNotify\"];\n\n function configureNotification(notificationServiceProvider, PNotify) {\n this.configure = function () {\n PNotify.defaults.styling = \"bootstrap3\";\n notificationServiceProvider.setDefaults({\n delay: 8000,\n hide: true,\n buttons: {\n closer: false,\n sticker: false\n },\n history: {\n history: false\n }\n }).setStack(\"top_right\", \"stack-topright\", {\n dir1: \"down\",\n dir2: \"left\",\n firstpos1: 100,\n firstpos2: 30\n }).setDefaultStack(\"top_right\");\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.tooltip\", configureTooltips);\n /* istanbul ignore next */\n\n configureTooltips.$inject = [\"$tooltipProvider\"];\n\n function configureTooltips($tooltipProvider) {\n this.configure = function () {\n var tooltipFactory = $tooltipProvider.$get[$tooltipProvider.$get.length - 1]; // decorate the tooltip getter\n\n $tooltipProvider.$get = [\"$window\", \"$compile\", \"$timeout\", \"$document\", \"$position\", \"$interpolate\", \"$rootScope\", function ($window, $compile, $timeout, $document, $position, $interpolate, $rootScope) {\n // for touch devices, don't return tooltips\n if (\"ontouchstart\" in $window) {\n return function () {\n return {\n compile: function compile() {}\n };\n };\n } else {\n // run the default behavior\n return tooltipFactory($window, $compile, $timeout, $document, $position, $interpolate, $rootScope);\n }\n }];\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n//TODO: 12/01/2016 - Ben - This is a hack to overwrite the provided dashboard edit template until the library provides an override point like all the other templates.\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.bootstrapper.runners.dashboard\", dashboard);\n dashboard.$inject = [\"$templateCache\", \"app.core.bootstrapper.runners.passwordExpirationValidator\"];\n /* istanbul ignore next */\n\n function dashboard($templateCache, passwordExpirationValidator) {\n passwordExpirationValidator();\n return function () {\n overrideDashboardEditTemplate();\n overrideWidgetEditTemplate();\n };\n\n function overrideDashboardEditTemplate() {\n $templateCache.put(\"../src/templates/dashboard-edit.html\", \"\\n
\\n \\n

{{ 'adf.dashboard.actions.layout.modal.heading' | translate }}

\\n
\\n
\\n
\\n
\\n
\\n \\n\\n
\\n
\\n
\\n
\\n
\\n \\n
\\n \");\n }\n\n function overrideWidgetEditTemplate() {\n $templateCache.put(\"../src/templates/widget-edit.html\", \"\\n
\\n \\n

{{ widget.name | translate }}

\\n
\\n
\\n
\\n
\\n \\n \\n
\\n
\\n
\\n \\n
\\n
\\n
\\n \\n \\n
\\n \");\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.bootstrapper.runners.fileUploader\", configureFileUploader);\n configureFileUploader.$inject = [\"FileUploader\"];\n /* istanbul ignore next */\n\n function configureFileUploader(FileUploader) {\n return function () {\n // Adds a `validationErrors` property to the FileItem class on the file uploaders\n Object.defineProperty(FileUploader.FileItem.prototype, \"validationErrors\", {\n get: function get() {\n this._validationErrors = this._validationErrors || {};\n return this._validationErrors;\n },\n set: function set(value) {\n this._validationErrors = value;\n }\n });\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.bootstrapper.runners.internationalization\", configure);\n configure.$inject = [\"ipCookie\", \"$window\", \"$translate\", \"app.core.appSettings\", \"app.core.services.userService\", \"app.core.services.settingsService\", \"moment\", \"kendo\"];\n\n function configure(cookie, $window, $translate, appSettings, userService, settingsService, moment, kendo) {\n var fallbackLanguage = \"en\";\n var supportedLanguages = settingsService.getSupportedLanguages();\n\n function useLocale(locale) {\n $translate.use(locale);\n kendo.culture(locale);\n moment.locale(locale.toLowerCase());\n }\n\n return function () {\n userService.getLocale().then(function (locale) {\n return useLocale(supportedLanguages.hasOwnProperty(locale) ? locale : fallbackLanguage);\n }).catch(function () {\n return useLocale(fallbackLanguage);\n });\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.bootstrapper.runners.kendoCultures\", configureKendoCultures);\n configureKendoCultures.$inject = [\"$window\", \"lodash\"];\n /* istanbul ignore next */\n\n function configureKendoCultures($window, _) {\n return function () {\n overrideCultureVi();\n overrideCultureEs();\n }; ////////////////////\n\n function overrideCultureVi() {\n // According to Vianna, there's not really a three-letter abbreviation for the days of the week, so\n // we use the same abbreviations for both namesAbbr and namesShort.\n var dayNamesShort = [\"CN\", \"TH\", \"TB\", \"TT\", \"TN\", \"TS\", \"TB\"];\n var overrides = {\n calendars: {\n standard: {\n days: {\n namesAbbr: dayNamesShort,\n namesShort: dayNamesShort\n }\n }\n }\n };\n overrideCultureIfExists(overrides, \"vi\", \"vi-VN\");\n }\n\n function overrideCultureEs() {\n // Abbreviations from Fernando - wanted to override the 'X' for Miércoles with another 'M'.\n var dayNamesShort = [\"D\", \"L\", \"M\", \"M\", \"J\", \"V\", \"S\"]; // Also override the day names since it seems to fix an encoding issue for 'Miércoles'.\n\n var dayNames = [\"Domingo\", \"Lunes\", \"Martes\", \"Mi\\xE9rcoles\", \"Jueves\", \"Viernes\", \"S\\xE1bado\"];\n var overrides = {\n calendars: {\n standard: {\n days: {\n names: dayNames,\n namesAbbr: dayNamesShort,\n namesShort: dayNamesShort\n }\n }\n }\n };\n overrideCultureIfExists(overrides, \"es\", \"es-ES\");\n }\n\n function overrideCultureIfExists(overrides) {\n var kendoCultures = $window.kendo.cultures;\n\n for (var _len = arguments.length, cultures = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n cultures[_key - 1] = arguments[_key];\n }\n\n _.forEach(cultures, function (culture) {\n var cultureInfo = kendoCultures[culture];\n\n if (cultureInfo) {\n _.merge(cultureInfo, overrides);\n }\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.bootstrapper.runners.passwordExpirationValidator\", passwordExpirationValidator);\n passwordExpirationValidator.$inject = [\"app.core.services.securityService\", \"i18n\", \"app.core.models.messages.messageList\"];\n /* istanbul ignore next */\n\n function passwordExpirationValidator(securityService, i18n, messageList) {\n return function () {\n securityService.getPasswordExpirationStatus().then(function (data) {\n if (!data.shownNotification && data.daysBeforePasswordExpiration && data.daysBeforePasswordExpiration <= 7) {\n messageList.addWarning(i18n.i10n(\"passwordExpirationValidator.notification.title\"), i18n.i10n(\"passwordExpirationValidator.notification.message\", {\n daysBeforePasswordExpiration: data.daysBeforePasswordExpiration\n }), 200);\n securityService.setPasswordExpirationConfirmed();\n }\n });\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.bootstrapper.configurators.stateReloadDecorator\", stateReloadDecorator).service(\"app.core.bootstrapper.runners.routeHandler\", runRouteHandler);\n stateReloadDecorator.$inject = [\"$provide\", \"lodash\"];\n\n function stateReloadDecorator($provide, _) {\n this.configure = function configure() {\n $provide.decorator(\"$state\", decorateTransitionTo);\n decorateTransitionTo.$inject = [\"$delegate\"];\n\n function decorateTransitionTo($delegate) {\n var original = $delegate.transitionTo;\n $delegate.transitionTo = transitionToWithReload;\n\n function transitionToWithReload(to, toParams, options) {\n var $state = this;\n $state.$current.data = _.extend($state.$current.data || {}, {\n $reload: options.reload\n });\n return original(to, toParams, options);\n }\n\n return $delegate;\n }\n };\n\n this.$get = angular.noop;\n }\n\n runRouteHandler.$inject = [\"$rootScope\", \"$window\", \"$q\", \"$log\", \"$state\", \"$location\", \"lodash\", \"blockUI\", \"routeHelper\", \"i18n\", \"app.core.appSettings\", \"app.core.services.userService\", \"app.core.services.companyService\", \"app.core.services.securityService\", \"app.core.services.locationService\", \"app.core.signalR.hubsConnector\"];\n\n function runRouteHandler($rootScope, $window, $q, $log, $state, $location, _, blockUI, routeHelper, i18n, appSettings, userService, companyService, securityService, locationService, hubsConnector) {\n return function () {\n var successPromise = $q.when(null);\n var busyMessage = i18n.i10n(\"activityIndicator.default.label\");\n var handlingRouteChangeError = false;\n var lastCompanyFacilityRouted = null; // keep track of the last company/facility selected so we can route to different error pages under different conditions.\n\n onRouteChangeStart();\n onRouteChangeSuccess();\n onRouteChangeError(); ////////////////////////////////\n\n function onRouteChangeStart() {\n routeHelper.addStateChangeStartEventHandler(function (event, toState, toParams) {\n startNavigationTracker();\n\n if (toState.name === \"not-found\" || toState.name === \"forbidden\") {\n return $q.when({\n result: \"not-found\"\n });\n }\n\n var companyAlias = toParams.companyAlias || appSettings.site.company.alias;\n var facilityAlias = toParams.facilityAlias || appSettings.site.facility.alias;\n\n if (companyAlias && facilityAlias) {\n return companyService.getCompanyWithFacility(companyAlias, facilityAlias).then(validateCompanyAndFacilityExist).then(applySelectedCompanyFacilityDetailsToAppSettings).then(refreshUserAndAccessControls).then(redirectToOmnisCheck).then(authorizeRouteAccess).then(updateLastCompanyFacilityAccessed).then(connectSignalRHubs).catch(function (routeErrorHandler) {\n stopNavigationTracker();\n\n if (routeErrorHandler) {\n return $q.reject(routeErrorHandler);\n } // otherwise try and send them to dashboard\n\n\n $state.go(\"app.dashboard\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }, {\n reload: true\n });\n return $q.reject({});\n });\n }\n\n return successPromise; ////////////////////\n\n function validateCompanyAndFacilityExist(company) {\n return $q(function (resolve, reject) {\n if (!company || !company.facility) {\n var errorHandler = createRoutingFailedErrorHandler(\"not-found\", \"no facility access\");\n reject(errorHandler);\n } else {\n resolve(company);\n }\n });\n }\n\n function applySelectedCompanyFacilityDetailsToAppSettings(company) {\n appSettings.site.company.id = company.id;\n appSettings.site.company.alias = company.alias;\n appSettings.site.facility.id = company.facility.id;\n appSettings.site.facility.alias = company.facility.alias;\n appSettings.site.facility.es1RouteName = company.facility.es1RouteName;\n appSettings.site.facility.ianaTimeZoneId = company.facility.ianaTimeZoneId;\n appSettings.site.facility.windowsTimeZoneId = company.facility.windowsTimeZoneId;\n appSettings.site.facility.ticketingSystemType = company.facility.ticketingSystemType;\n appSettings.site.facility.ticketingSystemTenantId = company.facility.ticketingSystemTenantId;\n appSettings.site.facility.facilityCode = company.facility.facilityCode;\n appSettings.site.facility.region = company.facility.region;\n return $q.when(company);\n }\n\n function refreshUserAndAccessControls(company) {\n return $q.all([refreshUser(), refreshAccessControls()]).then(function () {\n return company;\n });\n\n function refreshUser() {\n return userService.getUserDetails().then(function (user) {\n appSettings.user = user;\n $window.ga && $window.ga(\"set\", \"userId\", user.username);\n $window.LogRocket && window.LogRocket.identify(\"\".concat(user.displayName, \" (\").concat(user.username, \")\"), {\n email: user.email && user.email.toLowerCase() || \"\",\n userType: getUserType()\n });\n heapAnalytics(user);\n });\n\n function heapAnalytics(user) {\n if (!$window.heap) {\n return;\n }\n\n if (!user || !user.id || !user.email) {\n return;\n }\n\n var isInternal = user.email.indexOf(\"@envirosuite\") !== -1;\n $window.heap.identify(user.id);\n $window.heap.addUserProperties({\n 'Is_Internal': isInternal,\n 'Region': appSettings.site.facility.region\n });\n }\n }\n\n function refreshAccessControls() {\n return securityService.getAccessControls(company.id, company.facility.id).then(function (accessControls) {\n appSettings.site.accessControls = accessControls;\n });\n }\n }\n\n function authorizeRouteAccess(company) {\n return $q(function (resolve, reject) {\n if (!toState.data || !toState.data.requiredAccessControl) {\n // only check routes set up for checking\n resolve(company);\n return;\n }\n\n var requiredAccessControl = toState.data.requiredAccessControl;\n var accessControlCheck = appSettings.site.accessControls[requiredAccessControl];\n\n if (accessControlCheck) {\n resolve(company);\n } else {\n var errorHandler = createRoutingFailedErrorHandler(\"forbidden\", \"failed access control check\");\n reject(errorHandler);\n }\n });\n }\n\n function redirectToOmnisCheck(company) {\n return $q(function (resolve, reject) {\n var enableEs2 = appSettings.site.accessControls[\"app.es2\"];\n var state = toState.state;\n var allowedStates = [\"app.dashboard\", \"app.reporting\"];\n\n if (enableEs2) {\n return resolve(company);\n }\n\n if (allowedStates.includes(state)) {\n return resolve(company);\n }\n\n var redirectUrl = appSettings.omnisHostUri;\n\n if (state.startsWith(\"app.monitoring\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/monitoring/real-time\");\n } else if (state.startsWith(\"app.modelling.trajectory\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/trajectories\");\n } else if (state.startsWith(\"app.modelling\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/modelling\");\n } else if (state.startsWith(\"app.alerts\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/alerts\");\n } else if (state.startsWith(\"app.incidentIntelligence\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/incident-intelligence\");\n } else if (state.startsWith(\"app.configuration.company.modelling.models\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/configuration/modelling/models\");\n } else if (state.startsWith(\"app.configuration.company.monitoring.monitors\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/configuration/monitoring/monitors\");\n } else if (state.startsWith(\"app.configuration.company.monitoring.measurementGroups\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/configuration/monitoring/measurement-groups\");\n } else if (state.startsWith(\"app.configuration.company.annotations.monitorPollutants\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/configuration/annotations/pollutant\");\n } else if (state.startsWith(\"app.configuration\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/configuration\");\n } else if (state.startsWith(\"app.user.profile\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/user/profile/details\");\n } else if (state.startsWith(\"app.user.settings\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/user/profile/settings\");\n } else if (state.startsWith(\"app.about\")) {\n redirectUrl = redirectUrl + \"/\".concat(companyAlias, \"/\").concat(facilityAlias, \"/user/profile/about\");\n }\n\n $window.location.replace(redirectUrl);\n });\n }\n\n function connectSignalRHubs(company) {\n return hubsConnector.connect().then(function () {\n return company;\n });\n }\n\n function updateLastCompanyFacilityAccessed(company) {\n lastCompanyFacilityRouted = {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n };\n return $q.when(company);\n }\n\n function createRoutingFailedErrorHandler(route, detail) {\n return function errorHandler(event, toState, toParams) {\n if (hasTheCompanyFacilityChangedButTheRouteStayedTheSame()) {\n $state.go(\"app.dashboard\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }, {\n reload: true\n });\n return;\n }\n\n $state.go(route, toParams, {\n notify: false\n }).then(function () {\n $rootScope.$broadcast(\"$stateChangeSuccess\", toState, toParams);\n var url = $state.href(toState, toParams);\n\n if (route === \"not-found\") {\n $log.error(getInvalidRouteErrorMessage(\"404\", url));\n $location.url(url);\n return;\n }\n\n if (route === \"forbidden\") {\n $log.error(getInvalidRouteErrorMessage(\"403\", url));\n return;\n }\n });\n return $q.reject({\n status: route,\n detail: detail\n });\n };\n\n function getInvalidRouteErrorMessage(errorCode, url) {\n return \"\".concat(errorCode, \" trying to access \").concat(url, \" with userId - \").concat(appSettings.userId, \" and apiKey - \").concat(appSettings.apiKey, \" and company/facility - [\").concat(companyAlias, \"/\").concat(facilityAlias, \"]\");\n }\n\n function hasTheCompanyFacilityChangedButTheRouteStayedTheSame() {\n return lastCompanyFacilityRouted !== null && (lastCompanyFacilityRouted.companyAlias !== companyAlias || lastCompanyFacilityRouted.facilityAlias !== facilityAlias);\n }\n }\n });\n }\n\n function onRouteChangeError() {\n // Route cancellation:\n // On routing error, go to the dashboard.\n // Provide an exit clause if it tries to do it twice.\n $rootScope.$on(\"$stateChangeError\", function (event, toState, toParams, fromState, fromParams, error) {\n stopNavigationTracker();\n\n if (handlingRouteChangeError) {\n return;\n }\n\n handlingRouteChangeError = true;\n var destination = toState !== null ? \"\".concat(toState.name, \" - \").concat($state.href(toState, toParams)) : \"unknown target\";\n var msg = \"Error routing to \".concat(destination, \". \").concat(error && JSON.stringify(error.message) || \"\");\n $log.error(msg, toState);\n $state.go(\"app.dashboard\");\n });\n }\n\n function onRouteChangeSuccess() {\n $rootScope.$on(\"$stateChangeSuccess\", function (event, toState, toParams, fromState) {\n handlingRouteChangeError = false;\n locationService.clearExitPoint();\n unloadPreviousPageTranslations(fromState, toState).then(function () {\n updateGoogleAnalyticsPageValue(toState.name);\n locationService.bindPageHeading();\n }).finally(function () {\n stopNavigationTracker();\n });\n });\n\n function unloadPreviousPageTranslations(fromState, toState) {\n return i18n.unloadStates(fromState, toState);\n }\n\n function updateGoogleAnalyticsPageValue(stateName) {\n var page = $location.path();\n var userDescription = \"\".concat(appSettings.user.displayName, \" (\").concat(appSettings.user.username, \")\");\n\n if ($window.ga) {\n $window.ga(\"send\", \"pageview\", {\n page: page,\n title: stateName,\n dimension1: getUserType(),\n dimension2: userDescription\n });\n $window.ga(\"send\", \"event\", \"user-tracking\", userDescription, page);\n }\n }\n }\n\n function getUserType() {\n var emailAddress = appSettings.user.email && appSettings.user.email.toLowerCase() || \"\";\n return _.endsWith(emailAddress, \"envirosuite.com\") ? \"internal\" : \"customer\";\n }\n\n function startNavigationTracker() {\n var blocker = blockUI.instances.get(\"full-page\");\n blocker.start(busyMessage);\n }\n\n function stopNavigationTracker() {\n var blocker = blockUI.instances.get(\"full-page\");\n blocker.stop();\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n var mapDefaults = {\n settings: {\n zoomControlPosition: \"topright\",\n zoomAnimation: true,\n fadeAnimation: false,\n trackResize: false,\n attributionControl: false,\n worldCopyJump: true,\n controls: {\n layers: {\n visible: false,\n position: \"topright\",\n collapsed: true\n }\n }\n },\n baselayers: {\n openStreetMap: {\n name: \"Open Street Map\",\n type: \"openstreetmap\",\n url: \"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\",\n layerOptions: {\n attribution: \"© OpenStreetMap\",\n subdomains: [\"a\", \"b\", \"c\"]\n }\n },\n google: {\n name: \"Google Hybrid\",\n layerType: \"HYBRID\",\n type: \"google\"\n },\n gaode: {\n name: \"Gaode\",\n type: \"gaode\",\n url: \"http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}\",\n layerOptions: {\n attribution: \"© \\u9AD8\\u5FB7\\u5730\\u56FE\",\n subdomains: [\"1\", \"2\", \"3\", \"4\"]\n }\n },\n baidu: {\n name: \"Baidu\",\n type: \"baidu\",\n url: \"http://online{s}.map.bdimg.com/tile/?qt=vtile&x={x}&y={y}&z={z}&styles=pl&scaler=1&udt=20190929\",\n layerOptions: {\n attribution: \"© \\u767E\\u5EA6\",\n subdomains: [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]\n }\n },\n mapbox: {\n name: \"Mapbox\",\n type: \"mapbox\",\n url: \"https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/{z}/{x}/{y}\",\n layerOptions: {\n style: \"mapbox://styles/mapbox/satellite-v9\",\n attribution: \"\\xA9 Mapbox \\xA9 OpenStreetMap\"\n }\n }\n }\n };\n angular.module(\"app.core\").factory(\"app.core.mapDefaults\", mapConfiguredOptions);\n mapConfiguredOptions.$inject = [\"app.core.appSettings\"];\n\n function mapConfiguredOptions(appSettings) {\n var configuredLayer = getConfiguredBaseLayer();\n return {\n settings: mapDefaults.settings,\n baselayers: configuredLayer\n };\n\n function getConfiguredBaseLayer() {\n var layers = {};\n layers[appSettings.mapProvider] = mapDefaults.baselayers[appSettings.mapProvider] || mapDefaults.baselayers.google;\n\n if (appSettings.mapProvider === \"mapbox\") {\n layers[appSettings.mapProvider].apiKey = appSettings.mapboxApiKey;\n }\n\n return layers;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n /* eslint-disable no-undef */\n\n\n angular.module(\"app.core\").constant(\"jQuery\", jQuery).constant(\"moment\", moment).constant(\"kendo\", kendo).constant(\"leafletLib\", L).constant(\"d3\", d3).constant(\"MG\", MG).constant(\"Mousetrap\", Mousetrap).constant(\"FileSaver\", saveAs).constant(\"Utm\", Utm).constant(\"LatLon\", LatLon).constant(\"log4javascript\", log4javascript).constant(\"PNotify\", PNotify).constant(\"google\", window.google).constant(\"d3\", d3).constant(\"anime\", anime);\n /* eslint-enable no-undef */\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.events\", getEvents());\n\n function getEvents() {\n return {\n channelName: \"app.core\",\n topics: {\n accessControlsUpdated: \"accessControls.updated\"\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").filter(\"dateTimeFormat\", facilityTimezoneFilter);\n facilityTimezoneFilter.$inject = [\"app.core.services.dateTimeService\", \"lodash\"];\n\n function facilityTimezoneFilter(dateTimeService, _) {\n return function (date, format) {\n format = format || \"dateTimeWithSeconds\";\n\n if (!_.has(dateTimeService.formatAs, format)) {\n return date;\n } else {\n return dateTimeService.formatAs[format](date);\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").filter(\"facilityTimezone\", facilityTimezoneFilter);\n facilityTimezoneFilter.$inject = [\"app.core.datetime.timeZoneDateTime\"];\n\n function facilityTimezoneFilter(timeZoneDateTime) {\n function decorateFilter(input) {\n var parsedDate = new Date(input);\n\n if (isNaN(parsedDate.getTime())) {\n return input;\n }\n\n return timeZoneDateTime.convertDateTimeToFacilityTimeZone(parsedDate);\n }\n\n return decorateFilter;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.httpInterceptors\", httpInterceptors);\n httpInterceptors.$inject = [\"lodash\", \"httpBatchConfig\", \"$injector\", \"$log\", \"$q\", \"app.core.appSettings\", \"$timeout\", \"app.core.errorService\", \"app.core.appVersionService\"];\n\n function httpInterceptors(_, httpBatchConfigProvider, $injector, $log, $q, appSettings, $timeout, errorService, appVersionService) {\n var unhandledErrorCodes = [0, 500];\n var retryQueue = {};\n var interceptor = {\n request: requestInterceptor,\n response: responseInterceptor,\n responseError: responseErrorInterceptor\n };\n return interceptor; /////////////////////\n\n function requestInterceptor(httpConfig) {\n httpConfig.headers[\"Authorization\"] = \"Token \".concat(appSettings.apiKey);\n httpConfig.headers[\"PEL-Company-Alias\"] = appSettings.site.company.alias;\n httpConfig.headers[\"PEL-Facility-Alias\"] = appSettings.site.facility.alias;\n return httpConfig;\n }\n\n function responseInterceptor(response) {\n delete retryQueue[response.config.url];\n errorService.processSuccess(response);\n var appVersion = response.headers()[\"pel-app-version\"] || appSettings.appVersion;\n appVersionService.validate(appVersion);\n return response;\n }\n\n function responseErrorInterceptor(response) {\n var dfd = $q.defer();\n dfd.reject(response);\n\n if (_.includes(unhandledErrorCodes, response.status)) {\n if (/.*(batch[\\/]?)$/.test(response.config.url)) {\n $log.error(\"A http batch request failed; turning off http batch requests. Perform a hard-refresh to re-enable.\");\n errorService.logResponse(response); // we don't want the usual error handling to occur here so we just log the response.\n\n httpBatchConfigProvider.getBatchConfig(appSettings.webApiHostUri).enabled = false;\n return dfd.promise;\n } else {\n var existsInRetryQueue = retryQueue[response.config.url];\n\n if (!existsInRetryQueue) {\n retryQueue[response.config.url] = response;\n return $injector.get(\"$http\")(response.config);\n }\n\n delete retryQueue[response.config.url];\n }\n } // We have a bad state, but we want to give the developer a chance to handle it first. Run this on a later execution loop.\n // Effectively a last ditch catchall in case the developer forgets to handle their errors.\n\n\n $timeout(function () {\n if (!response.handled) {\n errorService.processError(response);\n }\n }, 1000);\n return dfd.promise;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.leafletScopeDecoration\", leafletScopeDecoration);\n leafletScopeDecoration.$inject = [\"$provide\"];\n\n function leafletScopeDecoration($provide) {\n this.injectScopeProperty = function (property, attr) {\n $provide.decorator(\"leafletDirective\", leafletDirectiveDecorator);\n leafletDirectiveDecorator.$inject = [\"$delegate\"];\n\n function leafletDirectiveDecorator($delegate) {\n var directive = $delegate[0]; //http://www.ipreferjim.com/2014/11/decorating-directives-with-isolate-scope-in-angular-1-3/\n\n directive.$$isolateBindings[property] = {\n attrName: attr,\n mode: \"=\",\n optional: true\n };\n return $delegate;\n }\n };\n\n this.$get = angular.noop;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"log4j\", log4jProvider);\n log4jProvider.$inject = [\"log4javascript\"];\n\n function log4jProvider(log4javascript) {\n var self = this;\n var defaultAppender = null;\n var ajaxAppender = null;\n var ajaxAppenderEndpoint = null;\n log4javascript.logLog.setQuietMode(true);\n log4javascript.setShowStackTraces(true);\n self.logger = log4javascript.getNullLogger();\n self.$get = [function () {\n return {\n getLogger: function getLogger() {\n return self.logger;\n },\n setLoggingContext: setLoggingContext,\n disableRemoteLogging: disableRemoteLogging,\n enableRemoteLogging: enableRemoteLogging\n };\n }];\n\n function disableRemoteLogging() {\n var logger = log4javascript.getDefaultLogger();\n\n if (ajaxAppender !== null) {\n logger.removeAppender(ajaxAppender);\n }\n }\n\n function enableRemoteLogging() {\n var logger = log4javascript.getDefaultLogger();\n\n if (ajaxAppender !== null) {\n logger.addAppender(ajaxAppender);\n }\n }\n\n function setLoggingContext(webApiHostUri, companyId, facilityId, apiKey) {\n var logger = log4javascript.getDefaultLogger();\n configureDefaultAppender(logger);\n configureAjaxAppender(logger, webApiHostUri, companyId, facilityId, apiKey);\n return self.logger = logger;\n }\n\n function configureDefaultAppender(logger) {\n if (defaultAppender) {\n return;\n }\n\n logger.removeAllAppenders();\n defaultAppender = new log4javascript.BrowserConsoleAppender();\n defaultAppender.setThreshold(log4javascript.Level.INFO);\n defaultAppender.setLayout(new log4javascript.PatternLayout(\"%d{HH:mm:ss,SSS} %-5p - %m{1}\"));\n logger.addAppender(defaultAppender);\n }\n\n function configureAjaxAppender(logger, webApiHostUri, companyId, facilityId, apiKey) {\n if (webApiHostUri !== ajaxAppenderEndpoint) {\n if (ajaxAppender !== null) {\n logger.removeAppender(ajaxAppender);\n }\n\n ajaxAppender = new log4javascript.AjaxAppender(webApiHostUri, true);\n ajaxAppender.setThreshold(log4javascript.Level.INFO); //logger.addAppender(ajaxAppender);\n\n ajaxAppenderEndpoint = webApiHostUri;\n }\n\n ajaxAppender.getHeaders().length = 0;\n ajaxAppender.addHeader(\"Authorization\", \"Token \".concat(apiKey));\n ajaxAppender.addHeader(\"PEL-Company-Id\", companyId);\n ajaxAppender.addHeader(\"PEL-Facility-Id\", facilityId);\n return ajaxAppender;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").config(decorateLog);\n decorateLog.$inject = [\"$provide\"];\n\n function decorateLog($provide) {\n $provide.decorator(\"$log\", logDecorator);\n }\n\n logDecorator.$inject = [\"$delegate\", \"log4j\"];\n\n function logDecorator($logDelegate, log4j) {\n // copies of original functions.\n var fatal = $logDelegate.fatal;\n var error = $logDelegate.error;\n var warn = $logDelegate.warn;\n var info = $logDelegate.info;\n var log = $logDelegate.log; // decorating the original log functions.\n\n $logDelegate.fatal = decorateLogFunction(function (logger) {\n return logger.fatal;\n }, fatal);\n $logDelegate.error = decorateLogFunction(function (logger) {\n return logger.error;\n }, error);\n $logDelegate.warn = decorateLogFunction(function (logger) {\n return logger.warn;\n }, warn);\n $logDelegate.info = decorateLogFunction(function (logger) {\n return logger.info;\n }, info);\n $logDelegate.log = decorateLogFunction(function (logger) {\n return logger.info;\n }, log); // Temporary hack to quiet down the leaflet directive logging\n // $logDelegate.debug = decorateLogFunction(logger => logger.debug, log);\n\n $logDelegate.debug = function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n if (!(args && args.length)) {\n return;\n }\n\n var logMessage = args[0];\n\n if (logMessage && typeof logMessage === \"string\" && logMessage.indexOf(\"leafletDirective\") === 0) {\n return;\n }\n\n var logger = log4j.getLogger();\n logger.debug.apply(logger, args);\n };\n\n $logDelegate.setLoggingContext = log4j.setLoggingContext;\n\n function decorateLogFunction(getLoggingFn) {\n return function () {\n var logger = log4j.getLogger();\n var loggingFn = getLoggingFn(logger);\n\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n loggingFn.apply(logger, args);\n };\n }\n\n return $logDelegate;\n }\n})();\n\n\n\"use strict\";\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.alerts.WebAlert\", alertFactory);\n alertFactory.$inject = [];\n\n function alertFactory() {\n return (\n /*#__PURE__*/\n function () {\n function WebAlert(id, alertEventSourceId, name, message, level, triggerTime, sentTime) {\n _classCallCheck(this, WebAlert);\n\n this.id = id;\n this.alertEventSourceId = alertEventSourceId;\n this.name = name;\n this.message = message;\n this.level = level;\n this.triggerTime = triggerTime;\n this.sentTime = sentTime;\n }\n\n _createClass(WebAlert, [{\n key: \"level\",\n get: function get() {\n return this._level;\n },\n set: function set(level) {\n if (this._level === level) {\n return;\n }\n\n this.previousLevel = this._level;\n this._level = level;\n }\n }, {\n key: \"hasLevelIncreased\",\n get: function get() {\n return this.previousLevel === undefined || this.level > this.previousLevel;\n }\n }, {\n key: \"hasLevelDecreased\",\n get: function get() {\n return this.previousLevel !== undefined && this.level < this.previousLevel;\n }\n }]);\n\n return WebAlert;\n }()\n );\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.BlastModel\", blastModelFactory);\n blastModelFactory.$inject = [\"lodash\", \"leafletLib\"];\n\n function blastModelFactory(_, L) {\n function BlastModel(modelId, modelType, modelCategory, blastModelLegends) {\n var self = this;\n this.id = modelId;\n this.modelType = modelType;\n this.modelCategory = modelCategory;\n this.blastModelLegends = blastModelLegends;\n var data = {};\n var dataPoints = {};\n Object.defineProperty(this, \"data\", {\n get: function get() {\n return data;\n }\n });\n this.getDataPoints = getDataPoints;\n this.createDataPointsFromModelData = createDataPointsFromModelData; ////////////////////\n\n function getDataPoints(blastTimeMillis, map) {\n var dataPointsForBlastTime = _.has(dataPoints, blastTimeMillis) && dataPoints[blastTimeMillis] || null;\n\n if (dataPointsForBlastTime) {\n return dataPointsForBlastTime;\n }\n\n var modelData = self.data[blastTimeMillis];\n dataPointsForBlastTime = self.createDataPointsFromModelData(modelData, map); // Snapshot models only have one data point, but when it gets imported into the store, it needs to\n // pretend its part of a series of timestep data points.\n\n if (!_.isArray(dataPointsForBlastTime)) {\n dataPointsForBlastTime = [dataPointsForBlastTime];\n }\n\n return dataPoints[blastTimeMillis] = dataPointsForBlastTime;\n }\n\n function createDataPointsFromModelData() {\n throw new Error(\"createDataPointsFromModelData has not been implemented.\");\n }\n }\n\n BlastModel.prototype.createCombinedDataPoint = function (offsetMinutes) {\n var combinedDataPoint = {\n offsetMinutes: offsetMinutes,\n layerGroup: new L.LayerGroup()\n };\n\n for (var _len = arguments.length, constituentDataPoints = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n constituentDataPoints[_key - 1] = arguments[_key];\n }\n\n _.flatten(constituentDataPoints).forEach(function (dataPoint) {\n return combinedDataPoint.layerGroup.addLayer(dataPoint.layerGroup);\n });\n\n return combinedDataPoint;\n };\n\n return BlastModel;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.blasting.blastModelCategory\", getBlastModelCategories());\n\n function getBlastModelCategories() {\n // Maps front-end model types to the equivalent back-end enum value.\n return {\n animated: \"animated\",\n snapshot: \"snapshot\"\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.blasting.blastModelType\", getBlastModelTypes());\n\n function getBlastModelTypes() {\n // Maps front-end model types to the equivalent back-end enum value.\n return {\n path: \"path\",\n dispersion: \"dispersion\",\n fmz: \"fumeManagementZone\",\n gain: \"overpressureGain\",\n contour: \"overpressureContour\",\n flyrock: \"flyrock\",\n groundVibration: \"groundVibration\"\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.blasting.BlastScenario\", BlastScenario);\n\n function BlastScenario(scenarioId, scenarioAlias, name) {\n this.id = scenarioId;\n this.alias = scenarioAlias;\n this.name = name;\n this.models = [];\n this.blastTimesMillis = [];\n this.blastParameters = null;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.blasting.blastSetup\", getBlastSetups());\n\n function getBlastSetups() {\n return {\n burden: \"burden\",\n stemming: \"stemming\"\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.DispersionModel\", DispersionModelFactory);\n DispersionModelFactory.$inject = [\"lodash\", \"app.core.models.blasting.BlastModel\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastModelCategory\", \"app.ui.core.mapping.mapLayerRenderer\"];\n\n function DispersionModelFactory(_, BlastModel, blastModelType, blastModelCategory, mapLayerRenderer) {\n function DispersionModel(modelId, legends) {\n BlastModel.call(this, modelId, blastModelType.dispersion, blastModelCategory.animated, legends);\n this.createDataPointsFromModelData = createDataPointsFromModelData;\n }\n\n DispersionModel.prototype = Object.create(BlastModel.prototype);\n return DispersionModel; ////////////////////\n\n function createDataPointsFromModelData(modelData) {\n var self = this; // Dispersion blasts contain plume and wind data, but when these get imported into the data store,\n // we need to represent them as a single data point.\n\n var windDataPoints = renderDataPoints(modelData.windData);\n var plumeDataPoints = renderDataPoints(modelData.plumes);\n return _.chain(windDataPoints.concat(plumeDataPoints)).groupBy(\"offsetMinutes\").map(function (dataPoints, offsetMinutes) {\n return self.createCombinedDataPoint(offsetMinutes, dataPoints);\n }).value();\n }\n\n function renderDataPoints(dataPoints) {\n if (!dataPoints) {\n return [];\n }\n\n dataPoints.forEach(function (dataPoint) {\n mapLayerRenderer.renderLayer(dataPoint);\n delete dataPoint.data;\n });\n return dataPoints;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.FlyrockModel\", FlyrockModelFactory);\n FlyrockModelFactory.$inject = [\"leafletLib\", \"lodash\", \"i18n\", \"app.core.models.blasting.BlastModel\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastModelCategory\"];\n\n function FlyrockModelFactory(L, _, i18n, BlastModel, blastModelType, blastModelCategory) {\n function FlyrockModel(modelId, legends) {\n BlastModel.call(this, modelId, blastModelType.flyrock, blastModelCategory.snapshot, legends);\n this.createDataPointsFromModelData = createDataPointsFromModelData;\n }\n\n FlyrockModel.prototype = Object.create(BlastModel.prototype);\n return FlyrockModel; ////////////////////\n\n function createDataPointsFromModelData(modelData) {\n var flyrockBoundaries = modelData.flyrockBoundaries;\n var startingPoint = new L.LatLng(modelData.location.latitude, modelData.location.longitude);\n var layerGroup = new L.LayerGroup();\n var azimuthBearingOffset = modelData.azimuth - 90; //calculate the points for the polygons\n\n _.map(flyrockBoundaries, function (boundary) {\n return boundary.points = createPolygonPoints(boundary);\n }); // the sort order is important here to get it to render correctly on the screen.\n\n\n var sortedData = _.sortBy(flyrockBoundaries, \"frontFaceDistanceInMetres\").reverse();\n\n _.map(sortedData, function (boundary, index) {\n var polygonPoints = [];\n polygonPoints.push(boundary.points);\n\n if (index < sortedData.length - 1) {\n polygonPoints.push(sortedData[index + 1].points);\n }\n\n createPolygon(polygonPoints, boundary.color);\n });\n\n return {\n offsetMinutes: 0,\n layerGroup: layerGroup\n };\n\n function createPolygonPoints(values) {\n var faceAngleStart = 45;\n var faceAngleStop = 135;\n var backAngleStop = 315;\n var backAngleStart = 225;\n var points = [];\n\n for (var angle = faceAngleStart; angle < faceAngleStop; angle++) {\n var point = startingPoint.destinationPoint(angle + azimuthBearingOffset, values.frontFaceDistanceInMetres);\n points.push([point.lat, point.lng]);\n }\n\n for (var _angle = backAngleStart; _angle < backAngleStop; _angle++) {\n var _point = startingPoint.destinationPoint(_angle + azimuthBearingOffset, values.backFaceDistanceInMetres);\n\n points.push([_point.lat, _point.lng]);\n }\n\n return points;\n }\n\n function createPolygon(path, color) {\n var polygon = L.polygon(path, {\n color: color,\n fillOpacity: 0.3,\n stroke: true,\n weight: 1,\n opacity: 0.4\n });\n layerGroup.addLayer(polygon);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.FumeManagementZoneModel\", FumeManagementZoneModelFactory);\n FumeManagementZoneModelFactory.$inject = [\"app.core.models.blasting.BlastModel\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastModelCategory\", \"app.ui.core.mapping.mapLayerRenderer\"];\n\n function FumeManagementZoneModelFactory(BlastModel, blastModelType, blastModelCategory, mapLayerRenderer) {\n function FumeManagementZoneModel(modelId, legends) {\n BlastModel.call(this, modelId, blastModelType.fmz, blastModelCategory.snapshot, legends);\n this.createDataPointsFromModelData = createDataPointsFromModelData;\n }\n\n FumeManagementZoneModel.prototype = Object.create(BlastModel.prototype);\n return FumeManagementZoneModel; ////////////////////\n\n function createDataPointsFromModelData(modelData) {\n var dataPoint = modelData.plume;\n mapLayerRenderer.renderLayer(dataPoint);\n delete dataPoint.data;\n return dataPoint;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.GroundVibrationModel\", GroundVibrationModelFactory);\n GroundVibrationModelFactory.$inject = [\"leafletLib\", \"lodash\", \"i18n\", \"app.core.models.blasting.BlastModel\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastModelCategory\", \"app.core.models.blasting.VibrationPointOfInterestMapMarker\"];\n\n function GroundVibrationModelFactory(L, _, i18n, BlastModel, blastModelType, blastModelCategory, VibrationPointOfInterestMapMarker) {\n function GroundVibrationModel(modelId, legends) {\n BlastModel.call(this, modelId, blastModelType.groundVibration, blastModelCategory.snapshot, legends);\n this.createDataPointsFromModelData = createDataPointsFromModelData;\n }\n\n GroundVibrationModel.prototype = Object.create(BlastModel.prototype);\n return GroundVibrationModel; ////////////////////\n\n function createDataPointsFromModelData(modelData) {\n var ppvThresholds = modelData.ppvThresholds,\n ppvReadings = modelData.ppvReadings;\n var layerGroup = new L.LayerGroup();\n\n var sortedThresholds = _.sortBy(ppvThresholds, \"distanceInMetres\").reverse();\n\n renderThresholds();\n renderReadings();\n return {\n offsetMinutes: 0,\n layerGroup: layerGroup\n };\n\n function renderReadings() {\n _.forEach(ppvReadings, function (reading) {\n var thresholds = sortedThresholds.filter(function (ppv) {\n return ppv.ppvThreshold <= reading.value;\n });\n var color = thresholds && thresholds.length ? thresholds[thresholds.length - 1].color : \"white\";\n var vibrationMarker = new VibrationPointOfInterestMapMarker(reading.location, reading.value, color);\n var icon = L.divIcon(vibrationMarker.icon);\n layerGroup.addLayer(L.marker([reading.location.latitude, reading.location.longitude], {\n icon: icon\n }));\n });\n }\n\n function renderThresholds() {\n var startingPoint = new L.LatLng(modelData.location.latitude, modelData.location.longitude); //calculate the points for the polygons\n\n _.forEach(sortedThresholds, function (boundary) {\n return boundary.points = createPolygonPoints(startingPoint, boundary);\n });\n\n _.forEach(sortedThresholds, function (boundary, index) {\n var polygonPoints = [];\n polygonPoints.push(boundary.points);\n\n if (index < sortedThresholds.length - 1) {\n polygonPoints.push(sortedThresholds[index + 1].points);\n }\n\n createPolygon(polygonPoints, boundary.color);\n });\n\n function createPolygon(path, color) {\n var polygon = L.polygon(path, {\n color: color,\n fillOpacity: 0.3,\n stroke: true,\n weight: 1,\n opacity: 0.4\n });\n layerGroup.addLayer(polygon);\n }\n\n function createPolygonPoints(startingPoint, values) {\n var points = [];\n\n for (var angle = 0; angle < 360; angle++) {\n var point = startingPoint.destinationPoint(angle, values.distanceInMetres);\n points.push([point.lat, point.lng]);\n }\n\n return points;\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.OverpressureModel\", OverpressureModelFactory);\n OverpressureModelFactory.$inject = [\"leafletLib\", \"app.core.models.blasting.BlastModel\", \"app.core.models.blasting.blastModelCategory\"];\n\n function OverpressureModelFactory(L, BlastModel, blastModelCategory) {\n function OverpressureModel(modelId, modelType, legends) {\n BlastModel.call(this, modelId, modelType, blastModelCategory.snapshot, legends);\n this.createDataPointsFromModelData = createDataPointsFromModelData;\n }\n\n OverpressureModel.prototype = Object.create(BlastModel.prototype);\n return OverpressureModel; ////////////////////\n\n function createDataPointsFromModelData(modelData, map) {\n //todo kmcdonald 2015-08-19 add a mimetype field to the model returned by the service\n var imageUrl = \"data:image/png;base64,\".concat(modelData.image);\n var layerGroup = new L.LayerGroup();\n var centreLatLng = L.latLng(modelData.latitude, modelData.longitude);\n var centrePoint = convertToCartesian(centreLatLng); // This is the number of pixels to crop off each edge of the raw Terrock image so that\n // what we are left with is simply the \"data\" part of the image overlay.\n\n var padding = {\n top: 10,\n left: 47,\n right: 5,\n bottom: 42\n }; // The data part of the image is 468px square, which represents a 20 KM square area.\n\n var imageEdgeLengthPixels = 468;\n var imageEdgeLengthKm = 20;\n var imageRadius = imageEdgeLengthPixels / 2;\n var imageMetresPerPixel = 1000 / (imageEdgeLengthPixels / imageEdgeLengthKm);\n var mapMetresPerPixel = calculateScale();\n var multiplier = Math.abs(imageMetresPerPixel / mapMetresPerPixel);\n var top = centrePoint.y - (imageRadius + padding.top) * multiplier;\n var left = centrePoint.x - (imageRadius + padding.left) * multiplier;\n var bottom = centrePoint.y + (imageRadius + padding.bottom) * multiplier;\n var right = centrePoint.x + (imageRadius + padding.right) * multiplier;\n var imageSWLatLng = convertToLatLng(L.point(left, bottom));\n var imageNELatLng = convertToLatLng(L.point(right, top));\n layerGroup.addLayer(L.imageOverlay(imageUrl, L.latLngBounds(imageSWLatLng, imageNELatLng), {\n opacity: 0.15\n }));\n delete modelData.image;\n return {\n offsetMinutes: 0,\n layerGroup: layerGroup\n };\n\n function calculateScale() {\n var referencePoint = convertToLatLng([centrePoint.x + 1000, centrePoint.y]);\n var metresToReferencePoint = centreLatLng.distanceTo(referencePoint);\n return Math.abs(metresToReferencePoint) / 1000;\n }\n\n function convertToCartesian(point) {\n return map.latLngToContainerPoint(point);\n }\n\n function convertToLatLng(point) {\n return map.containerPointToLatLng(point);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.PathModel\", PathModelFactory);\n PathModelFactory.$inject = [\"app.core.models.blasting.BlastModel\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastModelCategory\", \"app.ui.core.mapping.mapLayerRenderer\"];\n\n function PathModelFactory(BlastModel, blastModelType, blastModelCategory, mapLayerRenderer) {\n function PathModel(modelId, legends) {\n BlastModel.call(this, modelId, blastModelType.path, blastModelCategory.snapshot, legends);\n this.createDataPointsFromModelData = createDataPointsFromModelData;\n }\n\n PathModel.prototype = Object.create(BlastModel.prototype);\n return PathModel; ////////////////////\n\n function createDataPointsFromModelData(modelData) {\n // Path models contain one track.\n var primaryTrackDataPoints = renderDataPoints(modelData.primaryTrack);\n return this.createCombinedDataPoint(0, primaryTrackDataPoints);\n }\n\n function renderDataPoints(dataPoint) {\n mapLayerRenderer.renderLayer(dataPoint);\n delete dataPoint.data;\n return dataPoint;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.blasting.VibrationPointOfInterestMapMarker\", factory);\n factory.$inject = [\"app.core.services.configuration.monitoringService\"];\n\n function factory(configMonitoringService) {\n function VibrationPointOfInterestMapMarker(location, value, backgroundColor) {\n this.lat = location.latitude;\n this.lng = location.longitude;\n this.layer = \"VibrationPOILayer\";\n this.icon = {\n iconAnchor: [-11, 11],\n html: getHtml(),\n type: \"div\"\n };\n this.location = location;\n\n function getHtml() {\n var icon = configMonitoringService.getMonitorTypeIcon(\"vibrationMonitor\");\n\n if (value) {\n return \"\\n
\\n
\\n \\n
\\n
\").concat(Math.round(value * 100) / 100, \" PPV mm/s
\\n
\\n \");\n }\n\n return \"\");\n }\n }\n\n return VibrationPointOfInterestMapMarker;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.jobs.Job\", jobFactory);\n jobFactory.$inject = [\"$timeout\", \"$log\", \"i18n\", \"lodash\", \"postal\", \"app.core.appSettings\", \"app.core.signalR.jobs.events\", \"app.core.models.jobs.jobCompletionStatus\"];\n\n function jobFactory($timeout, $log, i18n, _, postal, appSettings, jobEvents, jobCompletionStatus) {\n var jobRunningStaleTimeoutMillis = (appSettings.jobRunningStaleTimeoutSeconds || 60) * 1000;\n var jobQueuedStaleTimeoutMillis = (appSettings.jobQueuedStaleTimeoutSeconds || 300) * 1000;\n return function Job(jobId) {\n var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"Unknown job\";\n var description = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n var progress = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n var completionStatus = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : jobCompletionStatus.incomplete;\n var lastUpdatedDateTime = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;\n var self = this;\n var channel = postal.channel(jobEvents.channelName);\n var lastUpdatedMillis = (lastUpdatedDateTime || new Date()).getTime();\n var isStale = false;\n var isStaleTimeout = null;\n self.jobId = jobId;\n self.name = name;\n self.description = description;\n var progressMessages = [];\n var errorMessages = [];\n Object.defineProperty(self, \"progressMessages\", {\n get: function get() {\n return progressMessages;\n }\n });\n Object.defineProperty(self, \"errorMessages\", {\n get: function get() {\n return errorMessages;\n }\n });\n Object.defineProperty(self, \"lastMessage\", {\n get: function get() {\n return self.hasFailed ? _.last(errorMessages) : _.last(progressMessages);\n }\n });\n Object.defineProperty(self, \"hasCompleted\", {\n get: function get() {\n return completionStatus !== jobCompletionStatus.incomplete;\n }\n });\n Object.defineProperty(self, \"hasFailed\", {\n get: function get() {\n return completionStatus === jobCompletionStatus.failure;\n }\n });\n Object.defineProperty(self, \"hasStarted\", {\n get: function get() {\n return _.isNumber(self.progress);\n }\n });\n Object.defineProperty(self, \"hasErrors\", {\n get: function get() {\n return errorMessages.length > 0;\n }\n });\n Object.defineProperty(self, \"isQueued\", {\n get: function get() {\n return !self.hasStarted;\n }\n });\n Object.defineProperty(self, \"isRunning\", {\n get: function get() {\n return self.hasStarted && !self.hasCompleted;\n }\n });\n Object.defineProperty(self, \"isStale\", {\n get: function get() {\n return isStale;\n }\n });\n Object.defineProperty(self, \"progress\", {\n get: function get() {\n return progress;\n },\n set: function set(value) {\n if (progress === value) {\n return;\n }\n\n progress = value;\n lastUpdatedMillis = new Date().getTime();\n scheduleIsStaleCheck();\n }\n });\n Object.defineProperty(self, \"completionStatus\", {\n get: function get() {\n return completionStatus;\n },\n set: function set(value) {\n if (completionStatus === value) {\n return;\n }\n\n completionStatus = value;\n cancelStaleTimeout();\n\n if (value === jobCompletionStatus.incomplete) {\n scheduleIsStaleCheck();\n }\n }\n });\n\n self.getJobType = function () {\n return \"job\";\n };\n\n self.addProgressMessage = function (messageKey) {\n return addMessage(progressMessages, \"progress\", messageKey);\n };\n\n self.addErrorMessage = function (messageKey) {\n return addMessage(errorMessages, \"error\", messageKey);\n };\n\n activate(); ////////////////////\n\n function activate() {\n scheduleIsStaleCheck();\n }\n\n function scheduleIsStaleCheck() {\n cancelStaleTimeout();\n\n if (self.hasCompleted || self.hasFailed) {\n return;\n }\n\n var timeoutMillis = self.hasStarted ? jobRunningStaleTimeoutMillis : jobQueuedStaleTimeoutMillis;\n var staleCutoffMillis = new Date().getTime() - timeoutMillis;\n isStale = lastUpdatedMillis <= staleCutoffMillis;\n\n if (isStale) {\n // signalR is down before starting the job, we can already publish the stale event directly (instead of waiting the timeout).\n channel.publish(jobEvents.topics.jobStale, self);\n } else {\n // we will send the notification in a few minutes, to let a chance for the job to finish processing\n isStaleTimeout = $timeout(function () {\n isStale = true;\n channel.publish(jobEvents.topics.jobStale, self);\n }, timeoutMillis);\n }\n }\n\n function cancelStaleTimeout() {\n if (isStaleTimeout) {\n $timeout.cancel(isStaleTimeout);\n }\n\n if (self.hasCompleted || self.hasFailed) {\n isStale = false;\n }\n }\n\n function addMessage(messages, messageType, messageKey) {\n if (!messageKey) {\n return;\n }\n\n var message = i10n(self.getJobType(), messageType, messageKey);\n messages.push(message);\n }\n\n function i10n(jobType, messageType, key) {\n if (!key) {\n return null;\n }\n\n var i18nKey = \"app.core.models.jobs.\".concat(jobType, \".\").concat(messageType, \".\").concat(key);\n var i18nResult = i18n.i10n(i18nKey);\n\n if (i18nResult !== i18nKey) {\n return i18nResult;\n }\n\n $log.error(\"Untranslated job status \".concat(messageType, \" message detected: \").concat(key));\n return key;\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.jobs.jobCompletionStatus\", getJobCompletionStatus());\n\n function getJobCompletionStatus() {\n var jobCompletionStatus = {\n incomplete: \"incomplete\",\n success: \"success\",\n partial: \"partialSuccess\",\n failure: \"failure\"\n };\n return angular.extend(jobCompletionStatus, {\n calculate: calculate\n }); ////////////////////\n\n function calculate(jobSucceededCount, jobFailedCount) {\n if (jobFailedCount) {\n return jobSucceededCount ? jobCompletionStatus.partial : jobCompletionStatus.failure;\n }\n\n return jobCompletionStatus.success;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.jobs.ModellingJob\", ModellingJobFactory);\n ModellingJobFactory.$inject = [\"app.core.models.jobs.Job\", \"app.core.services.dateTimeService\", \"app.core.datetime.timeZoneDateTime\", \"app.core.models.jobs.jobCompletionStatus\"];\n\n function ModellingJobFactory(Job, dateTimeService, timeZoneDateTime, jobCompletionStatus) {\n function ModellingJob(jobId, requesterId, fromMillis, toMillis) {\n var name = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : \"Unknown job\";\n var progress = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;\n var completionStatus = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : jobCompletionStatus.incomplete;\n var lastUpdatedDateTime = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;\n var description = \"\".concat(toFacilityDateTimeString(fromMillis), \" - \").concat(toFacilityDateTimeString(toMillis));\n Job.call(this, jobId, name, description, progress, completionStatus, lastUpdatedDateTime);\n\n this.getJobType = function () {\n return \"modellingJob\";\n };\n\n this.requesterId = requesterId;\n this.fromMillis = fromMillis;\n this.toMillis = toMillis;\n }\n\n ModellingJob.prototype = Object.create(Job.prototype);\n ModellingJob.createFromJobData = createFromJobData;\n return ModellingJob; ////////////////////\n\n function createFromJobData(jobData) {\n var startDate = new Date(jobData.utcFromDateTime);\n var endDate = new Date(jobData.utcToDateTime);\n var lastUpdated = jobData.utcLastUpdatedDateTime ? new Date(jobData.utcLastUpdatedDateTime) : null;\n var progress = parseInt(jobData.progress) || null;\n var completionStatus = calculateCompletionStatus();\n var modellingJob = new ModellingJob(jobData.id, jobData.requesterId, startDate.getTime(), endDate.getTime(), jobData.requesterName, progress, completionStatus, lastUpdated);\n\n if (jobData.errors) {\n jobData.errors.forEach(modellingJob.addErrorMessage);\n }\n\n return modellingJob; ////////////////////\n\n function calculateCompletionStatus() {\n if (!jobData.hasCompleted) {\n return jobCompletionStatus.incomplete;\n }\n\n if (jobData.jobFailedCount) {\n return jobData.jobSucceededCount ? jobCompletionStatus.partial : jobCompletionStatus.failure;\n }\n\n return jobCompletionStatus.success;\n }\n }\n\n function toFacilityDateTimeString(millis) {\n var date = new Date(millis);\n var facilityTime = timeZoneDateTime.convertDateTimeToFacilityTimeZone(date);\n return dateTimeService.formatAs.dateTime(facilityTime);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.legends.ArrowLegend\", arrowLegendFactory);\n arrowLegendFactory.$inject = [\"app.core.models.legends.Legend\"];\n\n function arrowLegendFactory(Legend) {\n var template = \"/App/ui/core/controls/esArrowLegend.html\";\n\n function ArrowLegend(legendData) {\n Legend.call(this, legendData, template);\n }\n\n ArrowLegend.prototype = Object.create(Legend.prototype);\n return ArrowLegend;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.legends.CircleLegend\", circleLegendFactory);\n circleLegendFactory.$inject = [\"app.core.models.legends.Legend\"];\n\n function circleLegendFactory(Legend) {\n var template = \"/App/ui/core/controls/esCircleLegend.html\";\n\n function CircleLegend(legendData) {\n Legend.call(this, legendData, template);\n }\n\n CircleLegend.prototype = Object.create(Legend.prototype);\n return CircleLegend;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.legends.Legend\", legendFactory);\n legendFactory.$inject = [];\n\n function legendFactory() {\n function Legend(legendData, template) {\n this.title = legendData.title;\n this.description = legendData.description;\n this.items = legendData.items;\n this.template = template;\n }\n\n return Legend;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.legends.legendFactory\", legendFactory);\n legendFactory.$inject = [\"app.core.models.legends.ArrowLegend\", \"app.core.models.legends.CircleLegend\", \"app.core.models.legends.StrokeLegend\"];\n\n function legendFactory(ArrowLegend, CircleLegend, StrokeLegend) {\n return {\n create: create\n }; ////////////////////\n\n function create(legend) {\n if (!legend) {\n throw new Error(\"You must supply the legend.\");\n }\n\n switch (legend.legendType) {\n case \"wind\":\n return new ArrowLegend(legend);\n\n case \"path\":\n return new StrokeLegend(legend);\n\n default:\n return new CircleLegend(legend);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.legends.StrokeLegend\", strokeLegendFactory);\n strokeLegendFactory.$inject = [\"app.core.models.legends.Legend\"];\n\n function strokeLegendFactory(Legend) {\n var template = \"/App/ui/core/controls/esStrokeLegend.html\";\n\n function StrokeLegend(legendData) {\n Legend.call(this, legendData, template);\n }\n\n StrokeLegend.prototype = Object.create(Legend.prototype);\n return StrokeLegend;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.mapping.Boundary\", BoundaryFactory);\n BoundaryFactory.$inject = [];\n\n function BoundaryFactory() {\n function Boundary(bottomLeft, bottomRight, topLeft, topRight) {\n if (!(bottomLeft && bottomRight && topLeft && topRight)) {\n throw new Error(\"You must provide four coordinates for a boundary.\");\n }\n\n if (!(isCoordinate(bottomLeft) && isCoordinate(bottomRight) && isCoordinate(topLeft) && isCoordinate(topRight))) {\n throw new Error(\"all coordinates must each have a latitude and longitude property.\");\n }\n\n Object.defineProperties(this, {\n bottomLeft: {\n get: function get() {\n return bottomLeft;\n }\n },\n bottomRight: {\n get: function get() {\n return bottomRight;\n }\n },\n topLeft: {\n get: function get() {\n return topLeft;\n }\n },\n topRight: {\n get: function get() {\n return topRight;\n }\n }\n });\n }\n\n function isCoordinate(coord) {\n return coord.hasOwnProperty(\"latitude\") && coord.hasOwnProperty(\"longitude\");\n }\n\n Boundary.prototype.contains = function (latitude, longitude) {\n var bottomLeft = this.bottomLeft;\n var topRight = this.topRight;\n var isLatitudeInBoundary = isBetween(latitude, bottomLeft.latitude, topRight.latitude);\n\n if (!isLatitudeInBoundary) {\n return false;\n }\n\n var crossesAntimeridian = bottomLeft.longitude > topRight.longitude;\n return crossesAntimeridian ? isBetween(longitude, bottomLeft.longitude, 180) || isBetween(longitude, -180, topRight.longitude) : isBetween(longitude, bottomLeft.longitude, topRight.longitude);\n\n function isBetween(value, lowerBound, upperBound) {\n return value >= lowerBound && value <= upperBound;\n }\n };\n\n return Boundary;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.mapping.DataPoint\", DataPointFactory);\n DataPointFactory.$inject = [\"lodash\"];\n\n function DataPointFactory(_) {\n return function DataPoint(dataPointType, data) {\n this.data = data;\n var isEmpty = !_.find(data, {\n isEmpty: false\n });\n Object.defineProperties(this, {\n type: {\n get: function get() {\n return dataPointType;\n }\n },\n isEmpty: {\n get: function get() {\n return isEmpty;\n }\n }\n });\n };\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.mapping.dataPointFactory\", dataPointFactory);\n dataPointFactory.$inject = [\"lodash\", \"app.core.models.mapping.dataPointType\", \"app.core.models.mapping.PlumeDataPoint\", \"app.core.models.mapping.WindDataPoint\", \"app.core.models.mapping.PathDataPoint\"];\n\n function dataPointFactory(_, dataPointType, PlumeDataPoint, WindDataPoint, PathDataPoint) {\n return {\n create: create\n }; ////////////////////\n\n function create(type, sourceData) {\n if (!_.isString(type)) {\n throw new Error(\"You must specify the data point type.\");\n }\n\n switch (type.toLowerCase()) {\n case dataPointType.plume:\n return new PlumeDataPoint(sourceData);\n\n case dataPointType.wind:\n return new WindDataPoint(sourceData);\n\n case dataPointType.path:\n return new PathDataPoint(sourceData);\n }\n\n throw new Error(\"Unknown data point type: \".concat(type));\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.mapping.dataPointType\", getDataPointTypes());\n\n function getDataPointTypes() {\n return {\n plume: \"plume\",\n wind: \"wind\",\n path: \"path\"\n };\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.mapping.PathDataPoint\", PathDataPointFactory);\n PathDataPointFactory.$inject = [\"lodash\", \"app.core.models.mapping.DataPoint\", \"app.core.models.mapping.dataPointType\"];\n\n function PathDataPointFactory(_, DataPoint, dataPointType) {\n function PathDataPoint(timeStepData) {\n DataPoint.call(this, dataPointType.path, processTimeStepData(timeStepData));\n }\n\n PathDataPoint.prototype = Object.create(DataPoint.prototype);\n return PathDataPoint; ////////////////////\n\n function processTimeStepData(timeStepData) {\n return _.chain(timeStepData).map(function (point) {\n var gisPoint = point.gisPoint;\n var dataPoint = {\n latitude: gisPoint.latitude,\n longitude: gisPoint.longitude,\n timeMillis: new Date(point.utcEndTime).getTime()\n };\n\n if (point.latitudeStdDev && point.longitudeStdDev) {\n return _extends({\n latitudeStdDev: point.latitudeStdDev,\n longitudeStdDev: point.longitudeStdDev\n }, dataPoint);\n }\n\n return dataPoint;\n }).sortBy(\"timeMillis\").value();\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.mapping.PlumeDataPoint\", PlumeDataPointFactory);\n PlumeDataPointFactory.$inject = [\"app.core.models.mapping.DataPoint\", \"app.core.models.mapping.dataPointType\"];\n\n function PlumeDataPointFactory(DataPoint, dataPointType) {\n function PlumeDataPoint(timeStepData) {\n DataPoint.call(this, dataPointType.plume, processTimeStepData(timeStepData));\n }\n\n PlumeDataPoint.prototype = Object.create(DataPoint.prototype);\n return PlumeDataPoint; ////////////////////\n\n function processTimeStepData(timeStepData) {\n return timeStepData.concentrations.map(processConcentration); ////////////////////\n\n function processConcentration(concentration) {\n var regionPoints = processRegions(concentration.regions);\n return {\n polygons: regionPoints,\n isEmpty: !regionPoints.length,\n color: concentration.displayColor,\n value: concentration.value\n };\n }\n\n function processRegions(regions) {\n return regions.map(function (region) {\n return region.gisPoints.map(function (point) {\n return {\n lat: point.latitude,\n lng: point.longitude\n };\n });\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.mapping.WindDataPoint\", WindDataPointFactory);\n WindDataPointFactory.$inject = [\"app.core.models.mapping.DataPoint\", \"app.core.models.mapping.dataPointType\"];\n\n function WindDataPointFactory(DataPoint, dataPointType) {\n function WindDataPoint(timeStepData) {\n DataPoint.call(this, dataPointType.wind, processTimeStepData(timeStepData));\n }\n\n WindDataPoint.prototype = Object.create(DataPoint.prototype);\n return WindDataPoint; ////////////////////\n\n function processTimeStepData(timeStepData) {\n return timeStepData.windDataSpeedRanges.map(processWindDataSpeedRange); ////////////////////\n\n function processWindDataSpeedRange(speedRange) {\n var windVectors = speedRange.windVectors.map(function (vector) {\n return {\n lat: vector.latitude,\n lng: vector.longitude,\n bearing: vector.windDirection,\n magnitude: vector.windSpeed\n };\n });\n return {\n windVectors: windVectors,\n color: speedRange.displayColor,\n minimumSpeed: speedRange.minimumSpeed,\n maximumSpeed: speedRange.maximumSpeed,\n isEmpty: !windVectors.length\n };\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.messages.messageList\", factory);\n factory.$inject = [\"$injector\", \"$rootScope\", \"$window\", \"lodash\", \"moment\", \"app.core.datetime.timeZoneDateTime\"];\n\n function factory($injector, $scope, $window, _, moment, timeZoneDateTime) {\n var messages = [];\n var confirmationDialog;\n var presentDialogConfiguration = {\n numberOfMessages: 10,\n timePeriodSeconds: 300,\n // five minutes\n messageTimestamps: []\n };\n return {\n addFatal: function addFatal(title, message, status) {\n return addMessage(\"fatal\", title, message, status);\n },\n addError: function addError(title, message, status) {\n var msg = addMessage(\"error\", title, message, status);\n\n if (status >= 500) {\n presentDialogConfiguration.messageTimestamps.push(msg.timestamp);\n processRecoverableErrorCountOverTime();\n }\n },\n addWarning: function addWarning(title, message, status) {\n return addMessage(\"warning\", title, message, status);\n },\n addInfo: function addInfo(title, message, status) {\n return addMessage(\"info\", title, message, status);\n },\n remove: function remove(predicate) {\n _.remove(messages, predicate);\n },\n removeStale: function removeStale() {\n var oneDayAgo = now().subtract(1, \"days\");\n\n _.remove(messages, function (message) {\n return message.timestamp.isBefore(oneDayAgo);\n });\n },\n removeAll: function removeAll() {\n messages = [];\n },\n update: function update(predicate) {\n var message = _.find(messages, predicate);\n\n if (!message) {\n return false;\n }\n\n message.count++;\n\n if (message.type === \"error\" && message.status >= 500) {\n presentDialogConfiguration.messageTimestamps.push(now());\n processRecoverableErrorCountOverTime();\n }\n\n return true;\n },\n all: function all() {\n return messages;\n },\n count: function count() {\n var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"all\";\n var filteredMessages = type === \"all\" ? messages : _.filter(messages, {\n type: type\n });\n return _.reduce(filteredMessages, function (acc, val) {\n return acc + val.count;\n }, 0);\n }\n }; ////////////////////\n\n function now() {\n return moment(timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date()));\n }\n\n function addMessage(type, title, message, status) {\n var item = {\n type: type,\n status: status,\n title: title,\n message: message,\n timestamp: now(),\n count: 1\n };\n messages.push(item);\n return item;\n }\n\n function processRecoverableErrorCountOverTime() {\n var errorMessageCount = presentDialogConfiguration.messageTimestamps.length;\n\n if (errorMessageCount >= presentDialogConfiguration.numberOfMessages) {\n var comparisonTime = presentDialogConfiguration.messageTimestamps[errorMessageCount - presentDialogConfiguration.numberOfMessages];\n var earliestTime = now().subtract(presentDialogConfiguration.timePeriodSeconds, \"seconds\");\n\n if (comparisonTime.isSameOrAfter(earliestTime)) {\n confirmationDialog = confirmationDialog || $injector.get(\"confirmationDialog\");\n confirmationDialog.error();\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.models.modelLoadingStatus\", getModelLoadingStatuses());\n\n function getModelLoadingStatuses() {\n return {\n pending: \"pending\",\n loading: \"loading\",\n loaded: \"loaded\",\n failed: \"failed\"\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.monitoring.createMonitorMapFenceline\", factory);\n factory.$inject = [\"$filter\", \"lodash\", \"$q\", \"app.core.services.monitoringService\"];\n\n function factory($filter, _, $q, monitoringService) {\n function createMonitorMapFenceline(monitor, switches) {\n extendMonitorAttributes();\n return buildFenceline(); ////////////////////\n\n function buildFenceline() {\n var processVariable = monitor.processVariable;\n var showMonitorsThatHaveExceededFirstThreshold = switches.thresholdExceeded;\n var isFocusedFenceline = processVariable && (!showMonitorsThatHaveExceededFirstThreshold || processVariable.hasValueExceededFirstThreshold);\n var latlngs = monitor.fencelineLocations.map(function (location) {\n return {\n lat: location.latitude,\n lng: location.longitude\n };\n });\n var firstLatLng = {\n lat: monitor.fencelineLocations[0].latitude,\n lng: monitor.fencelineLocations[0].longitude\n };\n var last = monitor.fencelineLocations.length - 1;\n var lastLatLng = {\n lat: monitor.fencelineLocations[last].latitude,\n lng: monitor.fencelineLocations[last].longitude\n };\n var line = {\n id: \"fenceline_\".concat(monitor.name.replace(/\\s/g, \"\").toLowerCase()),\n monitor: monitor,\n filter: \"fenceline\",\n latlngs: latlngs,\n lat: _.max(latlngs, function (monitor) {\n return monitor.lat;\n }).lat,\n lng: _.min(latlngs, function (monitor) {\n return monitor.lng;\n }).lng,\n type: \"polyline\",\n layer: monitor.monitorType,\n color: isFocusedFenceline ? monitor.processVariable.thresholdColour : \"#111\",\n weight: isFocusedFenceline ? 4 : 2\n };\n var circle1 = getCircle(firstLatLng, \"one\");\n var circle2 = getCircle(lastLatLng, \"two\");\n\n function getCircle(latlng, prefix) {\n return {\n id: \"fenceline_\".concat(prefix, \"_\").concat(monitor.id.replace(/[\\s\\-\\d]/g, \"\").toLowerCase()),\n monitor: monitor,\n filter: \"fenceline\",\n latlngs: latlng,\n lat: latlng.lat,\n lng: latlng.lng,\n type: \"circleMarker\",\n layer: monitor.monitorType,\n color: isFocusedFenceline ? monitor.processVariable.thresholdColour : \"#111\",\n radius: isFocusedFenceline ? 4 : 2,\n weight: isFocusedFenceline ? 4 : 2\n };\n }\n\n return [circle1, line, circle2];\n }\n\n function extendMonitorAttributes() {\n monitor.showUnitsOnPopup = true;\n monitor.canAccessConfiguration = true;\n\n monitor.getGraphProcessVariables = function () {\n return monitoringService.getGraphVariables(monitor.id);\n };\n }\n }\n\n return createMonitorMapFenceline;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.monitoring.createMonitorMapMarker\", factory);\n factory.$inject = [\"$filter\", \"app.core.services.configuration.monitoringService\", \"app.core.services.monitoringService\", \"app.core.appSettings\", \"esLeafletData\"];\n\n function factory($filter, configMonitoringService, monitoringService, appSettings, esLeafletData) {\n var scaleFactor = 1.5;\n\n function createMonitorMapMarker(monitor, switches, link) {\n extendMonitorAttributes();\n return buildMarker(); ////////////////////\n\n function buildMarker() {\n var showMonitorName = switches.monitorNames;\n var showUnits = switches.units;\n var showMonitorsThatHaveExceededFirstThreshold = switches.thresholdExceeded;\n var showInHeroMode = switches.heroMode;\n var showIcons = switches.icons;\n var showValue = switches.dataValue;\n var displayLocation = getMarkerDisplayLocation(monitor);\n var marker = {\n monitor: monitor,\n filter: \"marker\",\n title: monitor.name,\n lat: displayLocation.latitude,\n lng: displayLocation.longitude,\n focus: false,\n draggable: false,\n riseOnHover: true,\n layer: monitor.monitorType,\n type: monitor.monitorType,\n link: link,\n zIndexOffset: 0\n };\n marker.icon = buildMarkerIcon();\n return marker; ////////////////////\n\n function buildMarkerIcon() {\n var isDiscreteReceptor = marker.type === \"discreteReceptor\";\n var processVariable = marker.monitor.processVariable;\n var monitorTypeIcon = configMonitoringService.getMonitorTypeIcon(marker.type);\n\n if (isUnfocusedMonitor()) {\n return {\n type: \"div\",\n className: \"unfocused-monitor-container\",\n html: \"
\"\n };\n }\n\n setZIndex();\n var backgroundColor = processVariable.thresholdColour;\n var textColor = getTextColor(processVariable);\n var sensorValueCssClasses = getSensorValueCssClasses(processVariable);\n var scaledMonitor = {\n type: \"div\",\n className: \"dots-on-a-plane\",\n html: \"
\")\n };\n esLeafletData.getMap(\"map-canvas\").then(function (map) {\n renderScaledMonitor(map, scaledMonitor, isDiscreteReceptor);\n map.on(\"zoomend\", function () {\n return renderScaledMonitor(map, scaledMonitor, isDiscreteReceptor);\n });\n });\n return scaledMonitor; ////////////////////\n\n function isUnfocusedMonitor() {\n return !processVariable || showMonitorsThatHaveExceededFirstThreshold && !processVariable.hasValueExceededFirstThreshold;\n }\n\n function setZIndex() {\n if (processVariable) {\n if (processVariable.hasValueExceededFirstThreshold && !processVariable.isValueStale) {\n marker.zIndexOffset = 9999; // any threshold exceedances show on top\n } else if (!processVariable.hasDisplayableValue) {\n marker.zIndexOffset = 500; // then stale data monitors\n } else {\n marker.zIndexOffset = 9998; // then green monitors\n }\n } else {\n marker.zIndexOffset = 0; // unfocused etc.\n }\n }\n\n function getSensorValueCssClasses(processVariable) {\n var cssClassList = [\"sensor-value\"];\n\n if (showInHeroMode) {\n cssClassList.push(\"hero-mode\");\n }\n\n if (showUnits) {\n cssClassList.push(\"show-units\");\n }\n\n if (processVariable.hasDisplayableValue) {\n cssClassList.push(\"has-displayable-value\");\n }\n\n if (processVariable.hasDisplayableValue && showValue) {\n cssClassList.push(\"show-value\");\n }\n\n if (showIcons) {\n cssClassList.push(\"show-icons\");\n }\n\n if (processVariable.hasValueFlatlined) {\n cssClassList.push(\"flatlined\");\n }\n\n return cssClassList.join(\" \");\n }\n\n function getTextColor(processVariable) {\n return processVariable.hasDisplayableValue ? \"#fff\" : \"#444\";\n }\n\n function renderScaledMonitor(map, scaledMonitor, isDiscreteReceptor) {\n var currentZoom = map.getZoom();\n\n if (currentZoom >= 10 && !isDiscreteReceptor) {\n scaledMonitor.iconAnchor = [-11, 11];\n scaledMonitor.html = link ? wrapInsideLink(getHtml()) : getHtml();\n } else {\n var radius = Math.round(currentZoom * scaleFactor);\n var html = \"
\");\n scaledMonitor.iconSize = [radius, radius];\n delete scaledMonitor.iconAnchor;\n scaledMonitor.html = link ? wrapInsideLink(html) : html;\n }\n }\n\n function wrapInsideLink(html) {\n return \"\").concat(html, \"\");\n }\n\n function getHtml() {\n return \"\\n
\\n
\\n \").concat(buildIcon(monitorTypeIcon), \"\\n \").concat(buildValue(processVariable), \"\\n \").concat(buildUnits(processVariable), \"\\n
\\n \").concat(buildMonitorName(), \"\\n
\\n \");\n }\n\n function buildIcon() {\n return \"\");\n }\n\n function buildValue(processVariable) {\n var valueRounded = $filter(\"number\")(processVariable.valueInDisplayUnit, processVariable.numericScale);\n return \"\".concat(valueRounded, \"\");\n }\n\n function buildUnits(processVariable) {\n return \"\".concat(processVariable.units, \"\");\n }\n\n function buildMonitorName() {\n var monitorName = showMonitorName ? marker.title : null;\n return monitorName && monitorName.length ? \"
\".concat(monitorName, \"
\") : \"\";\n }\n }\n\n function getMarkerDisplayLocation(monitor) {\n // Apply special handling for placement of marker\n if (monitor.fencelineLocations && monitor.fencelineLocations.length > 1) {\n // If the marker is for a fenceline, position marker at the center of the first two fenceline points.\n var firstFenceSegment = monitor.fencelineLocations.slice(0, 2);\n var latitude = firstFenceSegment.map(function (c) {\n return c.latitude;\n }).reduce(function (a, b) {\n return a + b;\n }, 0) / 2;\n var longitude = firstFenceSegment.map(function (c) {\n return c.longitude;\n }).reduce(function (a, b) {\n return a + b;\n }, 0) / 2;\n return {\n latitude: latitude,\n longitude: longitude\n };\n }\n\n return {\n latitude: monitor.latitude,\n longitude: monitor.longitude\n };\n }\n }\n\n function extendMonitorAttributes() {\n monitor.showUnitsOnPopup = true;\n monitor.canAccessConfiguration = true;\n\n monitor.getGraphProcessVariables = function () {\n return monitoringService.getGraphVariables(monitor.id);\n };\n }\n }\n\n return createMonitorMapMarker;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.models.monitoring.createMonitorMapPath\", factory);\n factory.$inject = [\"$filter\", \"lodash\", \"$q\"];\n\n function factory($filter, _, $q) {\n function createMonitorMapPath(monitor, options) {\n extendMonitorAttributes();\n return buildPath(); ////////////////////\n\n function buildPath() {\n return {\n id: \"path_\".concat(monitor.id.replace(/[\\s\\-\\d]/g, \"\").toLowerCase()),\n monitor: monitor,\n filter: options.layer,\n title: monitor.name,\n latlngs: monitor.latlngs,\n focus: false,\n draggable: false,\n riseOnHover: true,\n lat: _.max(monitor.latlngs, function (monitor) {\n return monitor.lat;\n }).lat,\n lng: _.min(monitor.latlngs, function (monitor) {\n return monitor.lng;\n }).lng,\n type: \"polygon\",\n layer: options.layer,\n color: getPathColor(),\n weight: 1,\n fillOpacity: 0.5\n };\n }\n\n function getPathColor() {\n if (!monitor.dataPoints) {\n return null;\n }\n\n var dataPoint = monitor.dataPoints && monitor.dataPoints.find(function (dp) {\n return dp.valueInDisplayUnit !== null;\n });\n return dataPoint && dataPoint.thresholdColour || _.get(monitor, \"dataPoints[0].thresholdColour\", null);\n }\n\n function extendMonitorAttributes() {\n monitor.showUnitsOnPopup = options.showUnitsOnPopup;\n\n monitor.getGraphProcessVariables = function () {\n return $q.resolve(options.graphProcessVariables);\n };\n\n monitor.canAccessConfiguration = options.canAccessConfiguration;\n }\n }\n\n return createMonitorMapPath;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.alertDataProvider\", alertDataProvider);\n alertDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function alertDataProvider($http, appSettings) {\n return {\n getActiveWebAlerts: getActiveWebAlerts,\n dismissWebAlert: dismissWebAlert,\n getAlertsHistory: getAlertsHistory\n }; //////////////\n\n function buildUrl(url) {\n return appSettings.webApiHostUri + url;\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getActiveWebAlerts() {\n var url = buildUrl(\"alerts/web/active\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function dismissWebAlert(alertId) {\n var url = buildUrl(\"alerts/web/dismiss/\".concat(alertId));\n return $http.delete(url).then(success).catch(angular.noop);\n }\n\n function getAlertsHistory(queryObject) {\n var url = buildUrl(\"alerts/history\");\n return $http.post(url, queryObject).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.blastingDataProvider\", blastingDataProvider);\n blastingDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function blastingDataProvider($http, appSettings) {\n return {\n getScenarios: getScenarios,\n getScenario: getScenario,\n getBlastData: getBlastData,\n getOverlays: getOverlays\n }; /////////////\n\n function buildUrl(url) {\n return \"\".concat(appSettings.webApiHostUri, \"blasting/scenarios/\").concat(url);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getScenarios(queryObject) {\n var url = buildUrl(\"\");\n return $http.post(url, queryObject).then(success).catch(angular.noop);\n }\n\n function getScenario(scenarioAlias) {\n var url = buildUrl(\"\".concat(scenarioAlias));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getBlastData(scenarioAlias, modelType, blastTimeMillis) {\n var url = buildUrl(\"\".concat(scenarioAlias, \"/\").concat(modelType));\n var requestData = {\n params: {\n utcBlastTime: new Date(blastTimeMillis).toISOString()\n }\n };\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getOverlays(scenarioId) {\n var url = buildUrl(\"\".concat(scenarioId, \"/overlays\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.providers.companyDataProvider\", companyDataProvider);\n companyDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function companyDataProvider($http, appSettings) {\n return {\n getCompanies: getCompanies,\n getFacilityLocation: getFacilityLocation,\n getDomainBoundaries: getDomainBoundaries\n }; ////////////////////\n\n function buildUrl(path) {\n return \"\".concat(appSettings.webApiHostUri).concat(path);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getCompanies(apiKey) {\n var url = buildUrl(\"companies?apiKey=\".concat(apiKey));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getFacilityLocation() {\n var url = buildUrl(\"facility/location\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getDomainBoundaries() {\n var url = buildUrl(\"facility/boundaries\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.configuration.blastingDataProvider\", blastingDataProvider);\n blastingDataProvider.$inject = [\"$http\", \"$q\", \"app.core.appSettings\"];\n\n function blastingDataProvider($http, $q, appSettings) {\n return {\n getScenario: function getScenario() {\n return $q.when({});\n },\n getValidScenarioAlias: getValidScenarioAlias,\n getModelTypes: getModelTypes,\n getAddOverlayUrl: getOverlayFilesUrl,\n getOverlayFiles: getOverlayFiles,\n deleteOverlayFile: deleteOverlayFile,\n createScenario: createScenario,\n getOverlayFile: getOverlayFile,\n deleteScenario: deleteScenario,\n updateActualBlastTime: updateActualBlastTime\n }; //////////////\n\n function buildUrl(path) {\n return \"\".concat(appSettings.webApiHostUri, \"configuration/blasting/scenarios/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getModelTypes() {\n var url = \"\".concat(appSettings.webApiHostUri, \"configuration/blasting/model-types\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getOverlayFilesUrl() {\n return buildUrl(\"overlays\");\n }\n\n function getOverlayFiles(scenarioId) {\n var requestConfig = {\n params: {\n scenarioId: scenarioId || null\n }\n };\n var url = getOverlayFilesUrl();\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function getOverlayFile(fileName) {\n var url = buildUrl(\"overlay\");\n var requestConfig = {\n params: {\n fileName: fileName\n }\n };\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function deleteOverlayFile(scenarioId, fileName) {\n var requestConfig = {\n params: {\n scenarioId: scenarioId || null,\n fileName: fileName\n }\n };\n var url = getOverlayFilesUrl(scenarioId);\n return $http.delete(url, requestConfig).catch(angular.noop);\n }\n\n function getValidScenarioAlias(alias) {\n var requestConfig = {\n params: {\n alias: alias || null\n }\n };\n var url = buildUrl(\"valid-alias\");\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function createScenario(scenario) {\n var url = buildUrl(\"\");\n return $http.post(url, scenario).then(success).catch(angular.noop);\n }\n\n function deleteScenario(scenarioAlias) {\n var url = buildUrl(scenarioAlias);\n return $http.delete(url).then(success).catch(angular.noop);\n }\n\n function updateActualBlastTime(scenarioAlias, actualBlastTime) {\n var postData = {\n utcActualBlastTime: actualBlastTime.toISOString()\n };\n var url = buildUrl(\"\".concat(scenarioAlias, \"/blast-time\"));\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.configuration.gisModelDataProvider\", gisModelDataProvider);\n gisModelDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function gisModelDataProvider($http, appSettings) {\n return {\n getEmissionsDataFileUploadUrl: getEmissionsDataFileUploadUrl,\n getExistingEmissionsDataFiles: getExistingEmissionsDataFiles,\n getAll: getAll,\n getModel: getModel,\n getOptions: getOptions,\n getCalpuffConfigs: getCalpuffConfigs,\n remove: remove,\n addPlume: addPlume,\n addWind: addWind,\n importEmissionsData: importEmissionsData,\n updatePlume: updatePlume,\n updateWind: updateWind,\n deleteEmissionsDataFiles: deleteEmissionsDataFiles\n }; ////////////////\n\n function buildUrl(path) {\n return \"\".concat(appSettings.webApiHostUri, \"configuration/gis-models/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getEmissionsDataFileUploadUrl() {\n return buildUrl(\"emissions-data-file\");\n } // HTTP GETs\n\n\n function getExistingEmissionsDataFiles(calpuffConfigId) {\n var url = buildUrl(\"emissions-data-file\");\n var requestData = {\n params: {\n calpuffConfigId: calpuffConfigId\n }\n };\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getModel(modelId) {\n var url = buildUrl(\"\".concat(modelId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getAll() {\n var url = buildUrl(\"\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getOptions() {\n var url = buildUrl(\"options\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getCalpuffConfigs() {\n var url = buildUrl(\"calpuff-configs\");\n return $http.get(url).then(success).catch(angular.noop);\n } // HTTP POSTS\n\n\n function addPlume(plumeData) {\n var url = buildUrl(\"plume\");\n return $http.post(url, plumeData).then(success).catch(angular.noop);\n }\n\n function addWind(windData) {\n var url = buildUrl(\"wind\");\n return $http.post(url, windData).then(success).catch(angular.noop);\n }\n\n function importEmissionsData(calpuffConfigId) {\n var url = buildUrl(\"import-emissions-data\");\n return $http.post(url, {\n calpuffConfigId: calpuffConfigId\n }).then(success).catch(angular.noop);\n } // HTTP PUTs\n\n\n function updatePlume(plumeData) {\n var url = buildUrl(\"plume\");\n return $http.put(url, plumeData).then(success).catch(angular.noop);\n }\n\n function updateWind(windData) {\n var url = buildUrl(\"wind\");\n return $http.put(url, windData).then(success).catch(angular.noop);\n } // HTTP DELETEs\n\n\n function remove(modelId) {\n var url = buildUrl(\"\".concat(modelId));\n return $http.delete(url).then(success).catch(angular.noop);\n }\n\n function deleteEmissionsDataFiles(calpuffConfigId, fileNames) {\n var requestData = {\n params: {\n calpuffConfigId: calpuffConfigId,\n fileNames: fileNames\n }\n };\n var url = buildUrl(\"emissions-data-files\");\n return $http.delete(url, requestData).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.configuration.legacyLookupDataProvider\", lookupDataProvider);\n lookupDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function lookupDataProvider($http, appSettings) {\n return {\n getWindowsTimeZones: getWindowsTimeZones\n }; ////////////////\n\n function buildUrl() {\n var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n return \"\".concat(appSettings.webApiHostUri, \"configuration/lookup/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n } // HTTP GETs\n\n\n function getWindowsTimeZones() {\n var url = buildUrl(\"windows-timezones\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.configuration.measurementGroupDataProvider\", measurementGroupDataProvider);\n measurementGroupDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function measurementGroupDataProvider($http, appSettings) {\n return {\n getAllMeasurementGroups: getAllMeasurementGroups,\n queryMeasurementGroups: queryMeasurementGroups,\n getMeasurementGroup: getMeasurementGroup,\n isMeasurementGroupBeingUsed: isMeasurementGroupBeingUsed,\n getMeasurementGroupChildCount: getMeasurementGroupChildCount,\n createMeasurementGroup: createMeasurementGroup,\n updateMeasurementGroup: updateMeasurementGroup,\n deleteMeasurementGroup: deleteMeasurementGroup\n }; ////////////////\n\n function buildUrl() {\n var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n return \"\".concat(appSettings.webApiHostUri, \"configuration/monitoring/measurement-groups/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n } // HTTP GETs\n\n\n function getAllMeasurementGroups() {\n var url = buildUrl();\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMeasurementGroup(measurementGroupId) {\n var url = buildUrl(\"\".concat(measurementGroupId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function isMeasurementGroupBeingUsed(measurementGroupId) {\n var url = buildUrl(\"\".concat(measurementGroupId, \"/is-in-use\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMeasurementGroupChildCount(measurementGroupId) {\n var url = buildUrl(\"\".concat(measurementGroupId, \"/child-count\"));\n return $http.get(url).then(success).catch(angular.noop);\n } // HTTP POSTs\n\n\n function queryMeasurementGroups(searchCriteria) {\n var url = buildUrl(\"query\");\n return $http.post(url, searchCriteria).then(success).catch(angular.noop);\n }\n\n function createMeasurementGroup(measurementGroup) {\n var url = buildUrl();\n return $http.post(url, measurementGroup).then(success).catch(angular.noop);\n } // HTTP PUTs\n\n\n function updateMeasurementGroup(measurementGroup) {\n var url = buildUrl();\n return $http.put(url, measurementGroup).then(success).catch(angular.noop);\n } // HTTP DELETEs\n\n\n function deleteMeasurementGroup(measurementGroupId) {\n var url = buildUrl(\"\".concat(measurementGroupId));\n return $http.delete(url).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.configuration.modellingDataProvider\", modellingDataProvider);\n modellingDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function modellingDataProvider($http, appSettings) {\n return {\n getWrfConfiguration: getWrfConfiguration,\n runCalModelling: runCalModelling,\n runAerModelling: runAerModelling\n }; ////////////////\n\n function buildUrl(path) {\n return \"\".concat(appSettings.webApiHostUri, \"configuration/modelling/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n } // HTTP GETs\n\n\n function getWrfConfiguration() {\n var url = buildUrl(\"wrf-configuration\");\n return $http.get(url).then(success);\n } // HTTP POSTS\n\n\n function runCalModelling(wrfConfigurationName, forecastDate, forecastRun) {\n var url = buildUrl(\"run-calmodelling\");\n var payload = {\n wrfConfigurationName: wrfConfigurationName,\n utcForecastDate: forecastDate,\n // no toISOString(); the date must be formatted without a time\n forecastRun: forecastRun\n };\n return $http.post(url, payload).then(success);\n }\n\n function runAerModelling(upperAirMetMonitorId, surfaceMetMonitorId, fromDate, toDate) {\n var url = buildUrl(\"run-aermodelling\");\n var payload = {\n upperAirWeatherStationId: upperAirMetMonitorId,\n surfaceWeatherStationId: surfaceMetMonitorId,\n utcFromDate: fromDate.toISOString(),\n utcToDate: toDate.toISOString()\n };\n return $http.post(url, payload).then(success);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.configuration.monitoringDataProvider\", monitoringDataProvider);\n monitoringDataProvider.$inject = [\"$http\", \"lodash\", \"app.core.appSettings\"];\n\n function monitoringDataProvider($http, _, appSettings) {\n return {\n getMonitors: getMonitors,\n getUpperAirWeatherStations: getUpperAirWeatherStations,\n getSurfaceWeatherStations: getSurfaceWeatherStations,\n getMonitorType: getMonitorType,\n getMonitorTypes: getMonitorTypes,\n getMonitor: getMonitor,\n getMonitorLocation: getMonitorLocation,\n getMonitorDisplay: getMonitorDisplay,\n queryMonitors: queryMonitors,\n getAllMetStations: getAllMetStations,\n setDefaultMetStation: setDefaultMetStation,\n updateMonitorDisplay: updateMonitorDisplay,\n createMonitor: createMonitor,\n updateMonitor: updateMonitor,\n getMeasurementType: getMeasurementType,\n getMeasurementTypeConfigurationOptions: getMeasurementTypeConfigurationOptions,\n queryMonitorMeasurementTypes: queryMonitorMeasurementTypes,\n createMeasurementType: createMeasurementType,\n updateMeasurementType: updateMeasurementType\n }; ////////////////\n\n function buildUrl() {\n var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n return \"\".concat(appSettings.webApiHostUri, \"configuration/monitoring/monitors/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function linqSuccess(response) {\n return response.data.data.data;\n } // HTTP GETs\n\n\n function getMonitorType(monitorId) {\n var url = buildUrl(\"\".concat(monitorId, \"/monitor-type\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitorTypes() {\n var url = \"\".concat(appSettings.webApiHostUri, \"configuration/monitoring/monitor-types\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitor(monitorType, monitorId) {\n var url = buildUrl(\"\".concat(_.kebabCase(monitorType), \"/\").concat(monitorId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitors(whereVisible) {\n var url = buildUrl(\"\");\n var parameters = {\n params: {\n whereVisible: whereVisible\n }\n };\n return $http.get(url, parameters).then(success).catch(angular.noop);\n }\n\n function getSurfaceWeatherStations() {\n var url = buildUrl(\"surface-weather-stations\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getUpperAirWeatherStations() {\n var url = buildUrl(\"upper-air-weather-stations\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getAllMetStations() {\n var url = buildUrl(\"met-stations\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitorLocation(monitorId) {\n var url = buildUrl(\"\".concat(monitorId, \"/location\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitorDisplay(monitorId) {\n var url = buildUrl(\"\".concat(monitorId, \"/display\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMeasurementType(measurementTypeId) {\n var url = buildUrl(\"measurement-types/\".concat(measurementTypeId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMeasurementTypeConfigurationOptions() {\n var url = buildUrl(\"measurement-types/options\");\n return $http.get(url).then(success).catch(angular.noop);\n } // HTTP POSTs\n\n\n function queryMonitors(searchCriteria) {\n var url = buildUrl(\"query\");\n return $http.post(url, searchCriteria).then(success).catch(angular.noop);\n }\n\n function setDefaultMetStation(monitorId) {\n var url = buildUrl(\"\".concat(monitorId, \"/default-met-station\"));\n return $http.post(url).then(success).catch(angular.noop);\n }\n\n function createMonitor(monitorType, payload) {\n var url = buildUrl(\"\".concat(_.kebabCase(monitorType)));\n return $http.post(url, payload).then(success).catch(angular.noop);\n }\n\n function queryMonitorMeasurementTypes(monitorId, searchCriteria) {\n var url = buildUrl(\"measurement-types/query?monitorId=\".concat(monitorId));\n return $http.post(url, searchCriteria).then(linqSuccess).catch(angular.noop);\n }\n\n function createMeasurementType(payload) {\n var url = buildUrl(\"measurement-types\");\n return $http.post(url, payload).then(success).catch(angular.noop);\n } // HTTP PUTs\n\n\n function updateMonitor(monitorType, payload) {\n var url = buildUrl(\"\".concat(_.kebabCase(monitorType)));\n return $http.put(url, payload).then(success).catch(angular.noop);\n }\n\n function updateMonitorDisplay(monitorId, payload) {\n var url = buildUrl(\"\".concat(monitorId, \"/display\"));\n return $http.put(url, payload).then(success).catch(angular.noop);\n }\n\n function updateMeasurementType(payload) {\n var url = buildUrl(\"measurement-types\");\n return $http.put(url, payload).then(success).catch(angular.noop);\n } // HTTP DELETEs\n\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.diagnosticsDataProvider\", diagnosticsDataProvider);\n diagnosticsDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function diagnosticsDataProvider($http, appSettings) {\n return {\n getUtcLatestProcessDataEndTime: getUtcLatestProcessDataEndTime\n }; //////////////\n\n function buildUrl(url) {\n return appSettings.webApiHostUri + url;\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getUtcLatestProcessDataEndTime() {\n var url = buildUrl(\"diagnostics/latest-process-data-time\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.providers.errorThrowingDataProvider\", errorThrowingDataProvider);\n errorThrowingDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function errorThrowingDataProvider($http, appSettings) {\n return {\n getException: getException,\n getFailedResult: getFailedResult\n }; /////////////\n\n function getException() {\n var webApiHostUri = appSettings.webApiHostUri;\n var url = \"\".concat(webApiHostUri, \"error/exception\");\n return $http.get(url);\n }\n\n function getFailedResult() {\n var webApiHostUri = appSettings.webApiHostUri;\n var url = \"\".concat(webApiHostUri, \"error/failed-result\");\n return $http.get(url);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.gisModelDataProvider\", gisModelDataProvider);\n gisModelDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function gisModelDataProvider($http, appSettings) {\n return {\n getIntervals: getIntervals,\n getModelDataSet: getModelDataSet,\n getModellingJobs: getModellingJobs,\n getModelDataAvailability: getModelDataAvailability,\n getDiscreteReceptorData: getDiscreteReceptorData,\n dismissJob: dismissJob,\n dismissJobs: dismissJobs,\n getStatus: getStatus,\n startTestJob: startTestJob\n };\n\n function buildUrl(url) {\n return appSettings.webApiHostUri + url;\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getIntervals() {\n var url = buildUrl(\"gis-models/intervals\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getModelDataSet(modelIds, startDate, endDate) {\n var postData = {\n modelIds: modelIds,\n utcFromDate: startDate.toISOString(),\n utcToDate: endDate.toISOString()\n };\n var url = buildUrl(\"gis-models/model-data\");\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n\n function getModellingJobs() {\n var url = buildUrl(\"jobs/modelling\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getModelDataAvailability(modelId) {\n var url = buildUrl(\"gis-models/model-data-availability/\".concat(modelId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getDiscreteReceptorData(modelId, fromTime, toTime) {\n var postData = {\n modelId: modelId,\n utcFromTime: fromTime.toISOString(),\n utcToTime: toTime.toISOString()\n };\n var url = buildUrl(\"gis-models/discrete-receptor-data\");\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n\n function dismissJob(jobId) {\n var url = buildUrl(\"jobs/modelling/\".concat(jobId));\n return $http.delete(url);\n }\n\n function dismissJobs(jobIds) {\n var url = buildUrl(\"jobs/modelling/delete\");\n var postData = {\n jobBatchIds: jobIds\n };\n return $http.post(url, postData);\n }\n\n function getStatus(jobId) {\n var url = buildUrl(\"jobs/modelling/\".concat(jobId, \"/status\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function startTestJob() {\n var url = buildUrl(\"jobs/modelling/test\");\n var postData = {};\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.incidentIntelligenceDataProvider\", incidentIntelligenceDataProvider);\n incidentIntelligenceDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function incidentIntelligenceDataProvider($http, appSettings) {\n return {\n getPathModel: getPathModel,\n getSummaryLookupValues: getSummaryLookupValues,\n getTicketSummaryLocations: getTicketSummaryLocations\n }; /////////////\n\n function buildUrl(url) {\n return \"\".concat(appSettings.webApiHostUri, \"incident-intelligence/\").concat(url);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getPathModel(ticketId, ticketActivityId) {\n var url = buildUrl(\"ticket/\".concat(ticketId, \"/path-model/\").concat(ticketActivityId));\n var requestData = {\n params: {\n ticketId: ticketId,\n ticketActivityId: ticketActivityId\n }\n };\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getSummaryLookupValues() {\n var url = buildUrl(\"tickets/summary-lookup-values\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getTicketSummaryLocations(criteria) {\n var payload = {\n params: {\n categoryTypes: [criteria.selectedCategoryId],\n resolutionTypes: criteria.selectedStatuses,\n issueTypes: criteria.selectedTypes,\n utcFromTime: criteria.fromDate.toISOString(),\n utcToTime: criteria.toDate.toISOString()\n }\n };\n var url = buildUrl(\"tickets/summary-locations\");\n return $http.get(url, payload).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.mappingDataProvider\", mappingDataProvider);\n mappingDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function mappingDataProvider($http, appSettings) {\n return {\n getKmlDataSet: getKmlDataSet,\n getTileLayers: getTileLayers,\n getMapCredits: getMapCredits,\n getElevationAtPoint: getElevationAtPoint,\n getActiveTemporalEventGroups: getActiveTemporalEventGroups\n };\n\n function buildUrl(url) {\n return appSettings.webApiHostUri + url;\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getKmlDataSet(includeFiles, ignoreFiles) {\n var url = buildUrl(\"map/kml-files\");\n var requestConfig = {\n params: {\n includeFiles: includeFiles,\n ignoreFiles: ignoreFiles\n }\n };\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function getTileLayers() {\n var url = buildUrl(\"map/tile-layers\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMapCredits() {\n var url = buildUrl(\"map/credits\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getElevationAtPoint(latitude, longitude) {\n var url = buildUrl(\"map/elevation\");\n var requestConfig = {\n params: {\n longitude: longitude,\n latitude: latitude\n }\n };\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function getActiveTemporalEventGroups(activeAtDateTime) {\n var requestConfig = {\n params: {\n utcActiveAtDateTime: activeAtDateTime.toISOString()\n }\n };\n var url = buildUrl(\"temporal-events/active-event-groups\");\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.monitoringDataProvider\", monitoringDataProvider);\n monitoringDataProvider.$inject = [\"$http\", \"lodash\", \"app.core.appSettings\"];\n\n function monitoringDataProvider($http, _, appSettings) {\n return {\n getMonitorsByType: getMonitorsByType,\n getMonitorData: getMonitorData,\n getMetSummary: getMetSummary,\n getGraphVariables: getGraphVariables,\n getMonitorSensorData: getMonitorSensorData,\n getSensorDataSeries: getSensorDataSeries,\n getMonitorTypes: getMonitorTypes,\n getMonitorDataAlarms: getMonitorDataAlarms,\n getSourceAreaData: getSourceAreaData\n }; ////////////////////\n\n function buildUrl(template) {\n return \"\".concat(appSettings.webApiHostUri).concat(template);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getMonitorsByType() {\n var url = buildUrl(\"monitoring/monitors-by-type\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitorData(monitorIds, measurementGroupId, dateTime) {\n var postData = {\n monitorIds: monitorIds,\n measurementGroupId: measurementGroupId,\n utcDateTime: dateTime.toISOString()\n };\n var url = buildUrl(\"monitoring/monitor-data\");\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n\n function getSourceAreaData(dateTime) {\n var requestData = {\n params: {\n utcDateTime: dateTime.toISOString()\n }\n };\n var url = buildUrl(\"monitoring/source-areas-data\");\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getMetSummary(dateTime) {\n var requestData = {\n params: {\n utcDateTime: dateTime.toISOString()\n }\n };\n var url = buildUrl(\"monitoring/met-summaries\");\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getGraphVariables(monitorId) {\n var requestData = {\n params: {\n monitorId: monitorId\n }\n };\n var url = buildUrl(\"monitoring/graph-variables\");\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getMonitorSensorData(monitorId, processVariableIds, dateTime) {\n var requestData = {\n params: {\n monitorId: monitorId,\n processVariableIds: processVariableIds,\n utcDateTimeEnd: dateTime.toISOString()\n }\n };\n var url = buildUrl(\"monitoring/graph-data\");\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getSensorDataSeries(dateTimeStart, dateTimeEnd, processVariableId) {\n var requestData = {\n params: {\n processVariableId: processVariableId,\n utcDateTimeStart: dateTimeStart.toISOString(),\n utcDateTimeEnd: dateTimeEnd.toISOString()\n }\n };\n var url = buildUrl(\"monitoring/process-variable-trend\");\n return $http.get(url, requestData).then(success).catch(angular.noop);\n }\n\n function getMonitorTypes() {\n var url = buildUrl(\"monitoring/monitor-types\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getMonitorDataAlarms(monitorTypes) {\n var samplingTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var postData = {\n monitorTypes: monitorTypes,\n utcSamplingTime: samplingTime.toISOString()\n };\n var url = buildUrl(\"monitoring/monitor-data/alarms\");\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.reportsDataProvider\", reportsDataProvider);\n reportsDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function reportsDataProvider($http, appSettings) {\n return {\n getListOfReports: getListOfReports,\n getAlertPointReports: getAlertPointReports,\n getProcessDataReportLookupValues: getProcessDataReportLookupValues,\n getProcessDataReportColumns: getProcessDataReportColumns,\n getProcessDataReport: getProcessDataReport,\n exportProcessDataReport: exportProcessDataReport\n }; //////////////\n\n function buildUrl(url) {\n return \"\".concat(appSettings.webApiHostUri, \"reports/\").concat(url);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getListOfReports() {\n var url = buildUrl(\"\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getAlertPointReports() {\n var url = buildUrl(\"alert-points\");\n return $http.get(url).then(success);\n }\n\n function getProcessDataReportLookupValues(reportId) {\n var url = buildUrl(\"process-data/\".concat(reportId, \"/lookup-values\"));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getProcessDataReportColumns(processId) {\n var url = buildUrl(\"process-data/columns?processId=\".concat(processId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getProcessDataReport(processId, startTime, endTime, searchCriteria) {\n var path = \"process-data\";\n return postProcessDataRequest(path, processId, startTime, endTime, searchCriteria);\n }\n\n function exportProcessDataReport(processId, startTime, endTime, searchCriteria) {\n var path = \"process-data/export\";\n return postProcessDataRequest(path, processId, startTime, endTime, searchCriteria);\n }\n\n function postProcessDataRequest(path, processId, startTime, endTime, searchCriteria) {\n var queryString = \"processId=\".concat(processId, \"&utcStartTime=\").concat(startTime.toISOString(), \"&utcEndTime=\").concat(endTime.toISOString());\n var url = buildUrl(\"\".concat(path, \"?\").concat(queryString));\n return $http.post(url, searchCriteria).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").service(\"app.core.providers.securityDataProvider\", securityDataProvider);\n securityDataProvider.$inject = [\"$http\", \"app.core.appSettings\", \"CacheFactory\"];\n\n function securityDataProvider($http, appSettings, cacheFactory) {\n var cacheName = \"accessControlCache\";\n var accessControlCache = cacheFactory.get(cacheName);\n\n if (!accessControlCache) {\n accessControlCache = cacheFactory(cacheName, {\n maxAge: 5 * 60 * 1000,\n // Items added to this cache expire after 5 minutes\n cacheFlushInterval: 60 * 60 * 1000,\n // This cache will clear itself every hour\n deleteOnExpire: \"aggressive\",\n // Items will be deleted from this cache when they expire\n onExpire: function onExpire(url) {\n $http.get(url).then(function (response) {\n accessControlCache.put(url, response.data);\n });\n }\n });\n }\n\n return {\n getAccessControls: getAccessControls,\n queryApiCredentials: queryApiCredentials,\n getApiCredential: getApiCredential,\n createApiCredential: createApiCredential,\n updateApiCredential: updateApiCredential,\n getPasswordExpirationStatus: getPasswordExpirationStatus,\n setPasswordExpirationConfirmed: setPasswordExpirationConfirmed,\n logout: logout\n }; /////////////\n\n function buildUrl() {\n var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n return \"\".concat(appSettings.webApiHostUri, \"security/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function linqSuccess(response) {\n return response.data.data.data;\n }\n\n function getAccessControls(companyId, facilityId) {\n var url = buildUrl(\"access-controls?companyId=\".concat(companyId, \"&facilityId=\").concat(facilityId));\n return $http.get(url, {\n cache: accessControlCache\n }).then(success).catch(angular.noop);\n }\n\n function queryApiCredentials(monitorId, searchCriteria) {\n var url = buildUrl(\"monitor/api-credentials/\".concat(monitorId, \"/query\"));\n return $http.post(url, searchCriteria).then(linqSuccess).catch(angular.noop);\n }\n\n function getApiCredential(credentialId) {\n var url = buildUrl(\"monitor/api-credentials/\".concat(credentialId));\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function createApiCredential(payload) {\n var url = buildUrl(\"monitor/api-credentials\");\n return $http.post(url, payload).then(success).catch(angular.noop);\n }\n\n function updateApiCredential(payload) {\n var url = buildUrl(\"monitor/api-credentials\");\n return $http.put(url, payload).then(success).catch(angular.noop);\n }\n\n function getPasswordExpirationStatus() {\n var url = \"\".concat(appSettings.webApiHostUri, \"user/passwordExpirationStatus\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function setPasswordExpirationConfirmed() {\n var url = \"\".concat(appSettings.webApiHostUri, \"user/setPasswordExpirationConfirmation\");\n return $http.post(url).then(success).catch(angular.noop);\n }\n\n function logout() {\n var url = buildUrl(\"logout\");\n return $http.post(url).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.providers.userDataProvider\", userDataProvider);\n userDataProvider.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function userDataProvider($http, appSettings) {\n return {\n getUserDetails: getUserDetails,\n getLocale: getLocale,\n updatePassword: updatePassword,\n updateUserDetails: updateUserDetails\n }; ////////////////\n\n function buildUrl(path) {\n return \"\".concat(appSettings.webApiHostUri, \"user/\").concat(path);\n }\n\n function success(response) {\n return response.data.data;\n } // HTTP GETs\n\n\n function getUserDetails() {\n var url = buildUrl(\"\");\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getLocale() {\n var url = buildUrl(\"locale\");\n return $http.get(url).then(success).catch(angular.noop);\n } // HTTP POSTS\n\n\n function updatePassword(username, currentPassword, newPassword) {\n var url = \"\".concat(appSettings.webApiHostUri, \"security/authenticate-new-password\");\n var postData = {\n username: username,\n oldPassword: currentPassword,\n password: newPassword\n };\n return $http.post(url, postData).then(success).catch(angular.noop);\n } // HTTP PUTS\n\n\n function updateUserDetails(payload) {\n var url = buildUrl(\"details\");\n return $http.put(url, payload).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.requestManager\", requestManager);\n requestManager.$inject = [\"$q\", \"$log\"];\n\n function requestManager($q, $log) {\n return createQueuedRequestManager();\n\n function createQueuedRequestManager() {\n var queues = {};\n\n function createFetcher(fnPromise, queueName, options) {\n var queue = queues[queueName] || (queues[queueName] = []);\n var deferred = $q.defer();\n var fetcher = {\n fetch: fetch,\n cancel: cancel,\n promise: deferred.promise\n };\n queue.push(fetcher);\n\n if (queue.length === 1) {\n $log.debug(\"fetching first request - \".concat(queueName, \" - \").concat(queue.length));\n fetcher.fetch();\n }\n\n return fetcher; ////////////////////\n\n function fetch() {\n fnPromise().then(postFetch, cancel);\n\n function postFetch(result) {\n queue.shift(); // remove the in-flight fetcher.\n\n var queueWasDrained = drainQueue();\n\n if (queueWasDrained && options.resolveLastFetchOnly) {\n $log.debug(\"request rejected - \".concat(queueName, \" - \").concat(queue.length)); // The package was actually fetched successfully, but since the options are configured to\n // only resolve the last fetch, we reject with a reason to say that the request expired.\n\n deferred.reject({\n reason: \"expired\",\n result: result\n });\n return;\n }\n\n $log.debug(\"request resolved - \".concat(queueName, \" - \").concat(queue.length));\n deferred.resolve(result);\n }\n }\n\n function cancel() {\n deferred.reject({\n reason: \"cancelled\",\n result: {}\n });\n }\n\n function drainQueue() {\n if (queue.length === 0) {\n delete queues[queueName];\n return false; // didn't do anything\n } // cancel backlog of requests except for the last one\n\n\n while (queue.length > 1) {\n var fetchCount = queue.length;\n var nextFetcher = queue.shift();\n $log.debug(\"cancelling - \".concat(queueName, \" - fetcher \").concat(fetchCount));\n nextFetcher.cancel();\n } // fetch latest pending request\n\n\n $log.debug(\"fetching request - \".concat(queueName, \" - \").concat(queue.length));\n queue[0].fetch();\n return true; // queue was drained\n }\n }\n\n return {\n enqueue: function enqueue(fnPromise) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n resolveLastFetchOnly: true\n };\n return {\n onQueue: function onQueue(queueName) {\n var fetcher = createFetcher(fnPromise, queueName, options);\n return fetcher.promise;\n }\n };\n }\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.security.knownCredentials\", getKnownCredentials());\n\n function getKnownCredentials() {\n return {\n alertEngine: createCredential(\"c33c0b79-6517-44f2-98bb-ad183eeb698d\", \"Alert Engine\", \"1c9b737d-b933-436f-97be-2c7946b2913d\"),\n guest: createCredential(\"d2d8c870-72a3-4dfb-bcc9-da64dc035f96\", \"Guest\", \"9b088cf9-c8ba-4f66-a462-7b1454bba53c\"),\n jobProcessor: createCredential(\"3bafdca3-4585-49a1-8ec4-547aca1db123\", \"Job Processor\", \"37d6157d-d8c4-4e45-919c-643beefafbb1\"),\n messageBroker: createCredential(\"f89c2a6a-46e2-4e0d-b17d-0d9bd4339b0e\", \"Message Broker\", \"b95fbe53-c5b9-4ad7-badc-4aee4b7c6ad9\"),\n signalR: createCredential(\"60f3fc47-7a75-4790-98f5-50b5717a5f97\", \"SignalR\", \"17a3c141-5541-40ff-adfe-0c3c9d257471\"),\n jiraServiceDesk: createCredential(\"2c15ab74-5d7b-4bbe-96f1-c6b54ef3b456\", \"Jira Service Desk\", \"47472d9a-5582-4dea-92f5-957e28a882eb\")\n };\n\n function createCredential(apiCredentialId, name, apiKey) {\n return {\n apiCredentialId: apiCredentialId,\n name: name,\n apiKey: apiKey\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.alertService\", alertService);\n alertService.$inject = [\"app.core.providers.alertDataProvider\", \"app.core.models.alerts.WebAlert\", \"lodash\", \"app.core.datetime.timeZoneDateTime\"];\n\n function alertService(endpointProvider, WebAlert, _, timeZoneDateTime) {\n return {\n getActiveWebAlerts: getActiveWebAlerts,\n dismissWebAlert: dismissWebAlert,\n getAlertsHistory: getAlertsHistory\n }; //////////////\n\n function getActiveWebAlerts() {\n return endpointProvider.getActiveWebAlerts().then(mapAlerts);\n }\n\n function dismissWebAlert(webAlertId) {\n return endpointProvider.dismissWebAlert(webAlertId);\n }\n\n function getAlertsHistory(queryObject) {\n var mappedQuery = queryObject && mapQueryObject(queryObject);\n return endpointProvider.getAlertsHistory(mappedQuery).then(success);\n\n function success(response) {\n response.data = _.map(response.alertLogHistory, function (datum) {\n return {\n dismissed: datum.utcDismissedTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(datum.utcDismissedTime)) : null,\n sentTime: timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(datum.utcTriggeredTime)),\n type: datum.alertDeliveryMethod,\n description: datum.description,\n message: datum.message\n };\n });\n return response;\n }\n }\n\n function mapQueryObject(queryObject) {\n var defaultQueryObject = {\n group: [],\n sort: [],\n filter: {\n filters: []\n }\n };\n defaultQueryObject.group = _.map(queryObject.group, function (group) {\n return {\n value: group.field === \"sentTime\" ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(group.value) : group.value,\n field: getFieldMapping(group.field)\n };\n });\n defaultQueryObject.sort = _.map(queryObject.sort, function (sort) {\n return {\n value: sort.field === \"sentTime\" ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(sort.value) : sort.value,\n field: getFieldMapping(sort.field)\n };\n });\n defaultQueryObject.filter.filters = _.map(queryObject.filter && queryObject.filter.filters, function (filter) {\n return {\n value: filter.field === \"sentTime\" ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(filter.value) : filter.value,\n field: getFieldMapping(filter.field)\n };\n });\n angular.merge(queryObject, defaultQueryObject);\n return queryObject;\n\n function getFieldMapping(field) {\n var fields = {\n dismissed: \"UtcDismissedTime\",\n sentTime: \"UtcTriggeredTime\",\n type: \"AlertDeliveryMethod\",\n description: \"Description\",\n message: \"Message\"\n };\n return _.get(fields, field);\n }\n }\n\n function mapAlerts(alerts) {\n if (!(alerts && alerts.length)) {\n return [];\n }\n\n return alerts.map(function (webAlert) {\n var triggerTime = new Date(webAlert.utcTriggeredTime);\n var sentTime = new Date(webAlert.utcSentTime);\n return new WebAlert(webAlert.id, webAlert.alertEventSourceId, webAlert.name, webAlert.message, webAlert.level, triggerTime, sentTime);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.appVersionService\", appVersionService);\n appVersionService.$inject = [\"$log\", \"$injector\", \"notifier\", \"app.core.appSettings\", \"log4j\"];\n\n function appVersionService($log, $injector, notifier, appSettings, log4j) {\n var notice, i18n;\n var service = {\n validate: validate\n };\n return service; /////////////////////\n\n function validate(appVersion) {\n var isCurrentVersion = appSettings.appVersion === appVersion;\n var isNoticeDisplayed = notice && notice.state !== \"closed\";\n\n if (isCurrentVersion || isNoticeDisplayed) {\n return;\n } // Injector was used to get dependency because injecting i18n directly will result into circular dependency.\n\n\n if (!i18n) {\n i18n = $injector.get(\"i18n\");\n }\n\n $log.info(\"EnviroSuite Application needs refreshing. Actual version: '\".concat(appSettings.appVersion, \"', expected version: '\").concat(appVersion, \"'.\"));\n var msg = i18n.i10n(\"version.message\");\n var title = i18n.i10n(\"version.title\");\n\n if (msg !== \"version.message\" && title !== \"version.title\") {\n notice = notifier.warning(msg, title, {\n hide: false\n });\n } // disable the remote logging from the logger to avoid bombing the server with irrelevant log messages\n\n\n log4j.disableRemoteLogging();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.blastingService\", blastingService);\n blastingService.$inject = [\"lodash\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.dateTimeService\", \"app.core.providers.blastingDataProvider\", \"app.core.providers.gisModelDataProvider\", \"app.core.models.jobs.ModellingJob\", \"app.core.models.mapping.dataPointType\", \"app.core.models.mapping.dataPointFactory\", \"app.core.models.legends.legendFactory\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.BlastScenario\", // Blast Models\n \"app.core.models.blasting.DispersionModel\", \"app.core.models.blasting.FumeManagementZoneModel\", \"app.core.models.blasting.PathModel\", \"app.core.models.blasting.OverpressureModel\", \"app.core.models.blasting.FlyrockModel\", \"app.core.models.blasting.GroundVibrationModel\"];\n\n function blastingService(_, timeZoneDateTime, dateTimeService, endpointProvider, jobDataProvider, ModellingJob, dataPointType, dataPointFactory, legendFactory, blastModelType, BlastScenario, DispersionModel, FumeManagementZoneModel, PathModel, OverpressureModel, FlyrockModel, GroundVibrationModel) {\n var millisPerMinute = 60 * 1000;\n return {\n getScenarios: getScenarios,\n getScenario: getScenario,\n getBlastData: getBlastData,\n getOverlays: getOverlays,\n dismissJob: jobDataProvider.dismissJob,\n getStatus: jobDataProvider.getStatus\n }; ////////////////////\n\n function getScenarios() {\n var queryObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var mappedQuery = mapQueryObject(queryObject);\n return endpointProvider.getScenarios(mappedQuery).then(function (scenarios) {\n scenarios.data = _.map(scenarios.blastScenarioSummaries, function (scenario) {\n return {\n alias: scenario.alias,\n name: scenario.name,\n actualBlastTime: scenario.utcActualBlastTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(scenario.utcActualBlastTime)) : null,\n firstScenarioTime: scenario.utcFirstScenarioTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(scenario.utcFirstScenarioTime)) : null,\n lastUpdated: timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(scenario.utcLastUpdatedTime))\n };\n });\n return scenarios;\n }).catch(function (result) {\n throw new Error(result);\n });\n }\n\n function mapQueryObject(queryObject) {\n var defaultQueryObject = {\n group: [],\n sort: [],\n filter: {\n filters: []\n }\n };\n\n if (!queryObject) {\n return defaultQueryObject;\n }\n\n defaultQueryObject.group = _.map(queryObject.group, function (group) {\n return {\n value: group.field === \"lastUpdated\" ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(group.value) : group.value,\n field: getFieldMapping(group.field)\n };\n });\n defaultQueryObject.sort = _.map(queryObject.sort, function (sort) {\n return {\n value: sort.field === \"lastUpdated\" ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(sort.value) : sort.value,\n field: getFieldMapping(sort.field)\n };\n });\n defaultQueryObject.filter.filters = _.map(queryObject.filter && queryObject.filter.filters, function (filter) {\n return {\n value: filter.field === \"lastUpdated\" ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(filter.value) : filter.value,\n field: getFieldMapping(filter.field)\n };\n });\n angular.merge(queryObject, defaultQueryObject);\n return queryObject;\n\n function getFieldMapping(field) {\n var fields = {\n alias: \"Alias\",\n name: \"Name\",\n lastUpdated: \"UtcLastUpdatedTime\"\n };\n return _.get(fields, field);\n }\n }\n\n function getScenario(scenarioAlias) {\n return endpointProvider.getScenario(scenarioAlias).then(function (result) {\n var scenario = new BlastScenario(result.id, scenarioAlias, result.name);\n scenario.blastParameters = {\n latitude: result.latitude,\n longitude: result.longitude,\n blastWidth: result.width,\n blastLength: result.length,\n blastHeight: result.height,\n azimuth: result.azimuth,\n elevation: result.elevation,\n forwardTrajectoryScientificModel: result.forwardTrajectoryScientificModelDescription,\n windScientificModel: result.windScientificModelDescription,\n windScientificModelId: result.windScientificModelId,\n pollutant: result.pollutantDescription,\n pollutantId: result.modelPollutantId,\n pollutantScientificModel: result.pollutantScientificModelDescription,\n pollutantScientificModelId: result.pollutantScientificModelId,\n displayUnit: result.displayUnitDescription,\n displayUnitId: result.displayUnitId,\n initialConcentration: result.initialConcentrationGramsPerCubicMetre,\n blastSetup: result.blastSetup,\n chargeMass: result.chargeMass,\n chargeMassPerHole: result.chargeMassPerHole,\n holeDiameter: result.holeDiameter,\n burden: result.burden,\n stemmingHeight: result.stemmingHeight,\n frontFaceKFactor: result.frontFaceKFactor,\n backFaceKFactor: result.backFaceKFactor,\n flyrockSiteConstantKv: result.flyrockSiteConstantKv,\n holeAngle: result.holeAngle,\n dispersalAngle: result.dispersalAngle,\n groundVibrationSiteConstantKv: result.groundVibrationSiteConstantKv,\n groundVibrationSiteExponentKb: result.groundVibrationSiteExponentKb\n };\n scenario.models = _.chain(result.blastModels).map(createBlastModel).keyBy(\"id\").value();\n scenario.blastTimesMillis = result.utcBlastTimes.map(function (utcBlastTime) {\n return new Date(utcBlastTime).getTime();\n });\n scenario.actualBlastTime = result.utcActualBlastTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(result.utcActualBlastTime)) : null;\n return scenario;\n }); ////////////////////\n\n function createBlastModel(blastModel) {\n var legends = blastModel.legends.map(legendFactory.create);\n\n switch (blastModel.modelType) {\n case blastModelType.path:\n return new PathModel(blastModel.id, legends);\n\n case blastModelType.dispersion:\n return new DispersionModel(blastModel.id, legends);\n\n case blastModelType.fmz:\n return new FumeManagementZoneModel(blastModel.id, legends);\n\n case blastModelType.gain:\n return new OverpressureModel(blastModel.id, blastModelType.gain, legends);\n\n case blastModelType.contour:\n return new OverpressureModel(blastModel.id, blastModelType.contour, legends);\n\n case blastModelType.flyrock:\n return new FlyrockModel(blastModel.id, legends);\n\n case blastModelType.groundVibration:\n return new GroundVibrationModel(blastModel.id, legends);\n }\n\n throw new Error(\"Unsupported model type: \".concat(blastModel.modelType));\n }\n }\n\n function getBlastData(scenarioAlias, modelType, blastTimeMillis) {\n return endpointProvider.getBlastData(scenarioAlias, modelType, blastTimeMillis).then(function (result) {\n return {\n activeJobForBlastModel: processActiveJob(result.activeJobBatch),\n availableBlastModelData: processAvailableData(result.modelData)\n };\n }); ////////////////////\n\n function processActiveJob(jobData) {\n return jobData ? ModellingJob.createFromJobData(jobData) : null;\n }\n\n function processAvailableData(availableData) {\n if (!availableData) {\n return null;\n }\n\n switch (modelType) {\n case blastModelType.path:\n return processPathModelData(availableData);\n\n case blastModelType.dispersion:\n return processDispersionModelData(availableData);\n\n case blastModelType.fmz:\n return processFmzModelData(availableData);\n // No processing needed?\n\n case blastModelType.gain:\n case blastModelType.contour:\n case blastModelType.flyrock:\n case blastModelType.groundVibration:\n return availableData;\n }\n\n throw new Error(\"Processing of \".concat(modelType, \" model data is currently not supported.\"));\n }\n\n function processPathModelData(availableData) {\n return {\n primaryTrack: createDataPoint(availableData.primaryTrack)\n }; ////////////////////\n\n function createDataPoint(track) {\n return dataPointFactory.create(dataPointType.path, track.gisTrackDataTimeSteps);\n }\n }\n\n function processDispersionModelData(availableData) {\n return {\n plumes: createDataPoints(dataPointType.plume, availableData.plumes),\n windData: createDataPoints(dataPointType.wind, availableData.windData)\n }; ////////////////////\n\n function createDataPoints(type, dataSet) {\n return dataSet.data.map(function (dataPointSource) {\n var dataPoint = dataPointFactory.create(type, dataPointSource);\n var offsetTimeMillis = new Date(dataPointSource.utcEndTime).getTime();\n dataPoint.offsetMinutes = (offsetTimeMillis - blastTimeMillis) / millisPerMinute;\n return dataPoint;\n });\n }\n }\n\n function processFmzModelData(availableData) {\n return {\n plume: createDataPoint(availableData.plumes)\n }; ////////////////////\n\n function createDataPoint(dataSet) {\n // FMZ data looks like a dispersion with only a single time step. So even though the data is\n // an array, it should only contain a single element.\n if (dataSet.data.length !== 1) {\n throw new Error(\"Unexpected data encountered when processing an FMZ model. Expected 1 data point, received \".concat(dataSet.data.length, \".\"));\n }\n\n var dataPointSource = dataSet.data[0];\n var dataPoint = dataPointFactory.create(dataPointType.plume, dataPointSource);\n dataPoint.offsetMinutes = 0;\n return dataPoint;\n }\n }\n }\n\n function getOverlays(scenarioId) {\n return endpointProvider.getOverlays(scenarioId);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n angular.module(\"app.core\").factory(\"app.core.services.companyService\", companyService);\n companyService.$inject = [\"lodash\", \"app.core.appSettings\", \"app.core.providers.companyDataProvider\", \"app.core.models.mapping.Boundary\"];\n\n function companyService(_, appSettings, companyDataProvider, Boundary) {\n var companiesPromise;\n return {\n getCompanies: getCompanies,\n getCompanyWithFacility: getCompanyWithFacility,\n getFacilityDetails: getFacilityDetails,\n getFacilityLocation: getFacilityLocation,\n getDomainBoundaries: getDomainBoundaries,\n canAccessFacility: canAccessFacility\n }; ////////////////////\n\n function getCompanies(options) {\n options = angular.extend({\n refresh: false\n }, options || {});\n\n if (companiesPromise && !options.refresh) {\n return companiesPromise;\n }\n\n companiesPromise = companyDataProvider.getCompanies(appSettings.apiKey).then(function (companies) {\n var normalisedCompanies = {};\n\n _.forEach(companies, function (company) {\n var facilities = _.map(company.facilities, function (facility) {\n return angular.extend({}, facility, {\n companyId: company.id,\n es1RouteName: facility.es1RouteName,\n searchTerms: \"\".concat(company.name, \" \").concat(company.alias, \" \").concat(facility.name, \" \").concat(facility.alias)\n });\n });\n\n delete company.es1RouteName;\n\n if (!_.has(normalisedCompanies, company.alias)) {\n normalisedCompanies[company.alias] = angular.extend({}, company, {\n facilities: facilities\n });\n } else {\n var existingFacilities = normalisedCompanies[company.alias].facilities;\n normalisedCompanies[company.alias] = angular.extend({}, normalisedCompanies[company.alias], {\n facilities: [].concat(_toConsumableArray(existingFacilities), _toConsumableArray(facilities))\n });\n }\n });\n\n return _.values(normalisedCompanies);\n });\n return companiesPromise;\n }\n\n function getCompanyWithFacility(companyAlias, facilityAlias) {\n return getCompanies().then(function (companies) {\n return _.chain(companies).filter(matchingCompany).map(function (company) {\n var facility = _.find(company.facilities, matchingFacility);\n\n if (!facility) {\n return null;\n }\n\n var companyWithFacility = _extends({}, company, {\n facility: facility,\n // Cater for the normalisation process where facilities from one company may have\n // been merged with the facilities from another company.\n id: facility.companyId\n });\n\n delete companyWithFacility.facilities;\n return companyWithFacility;\n }).find(function (company) {\n return company && company.facility;\n }).value();\n }); ////////////////////\n\n function matchingCompany(company) {\n return companyAlias && company.alias.toLowerCase() === companyAlias.toLowerCase();\n }\n\n function matchingFacility(facility) {\n return facilityAlias && facility.alias.toLowerCase() === facilityAlias.toLowerCase();\n }\n }\n\n function getFacilityDetails(companyAlias, facilityAlias) {\n return getCompanyWithFacility(companyAlias, facilityAlias).then(function (company) {\n return company && company.facility;\n });\n }\n\n function getFacilityLocation() {\n return companyDataProvider.getFacilityLocation().then(function (location) {\n return {\n lat: location.latitude,\n lng: location.longitude,\n zoom: location.zoom\n };\n });\n }\n\n function getDomainBoundaries(showModelling, showBlasting, showIncidentIntelligence) {\n return companyDataProvider.getDomainBoundaries().then(function (boundaries) {\n var filteredBoundaries = boundaries.filter(function (boundary) {\n return showModelling && boundary.isSourceForModelling || showBlasting && boundary.isSourceForBlasting || showIncidentIntelligence && boundary.isSourceForIncidentIntelligence;\n });\n return filteredBoundaries.map(function (boundary) {\n return new Boundary(boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight);\n });\n });\n }\n\n function canAccessFacility(companyAlias, facilityAlias) {\n return getCompanyWithFacility(companyAlias, facilityAlias).then(function (company) {\n return company != null && company.facility != null;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.configuration.blastingService\", blastingService);\n blastingService.$inject = [\"lodash\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastSetup\", \"app.core.providers.configuration.blastingDataProvider\", \"app.core.providers.configuration.gisModelDataProvider\"]; //TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\n\n /* istanbul ignore next */\n\n function blastingService(_, blastModelType, blastSetup, blastingDataProvider, gisModelDataProvider) {\n return {\n getAllScenarios: getAllScenarios,\n getScenario: getScenario,\n deleteScenario: deleteScenario,\n updateActualBlastTime: updateActualBlastTime,\n getModelTypes: getModelTypes,\n getModelOptions: getModelOptions,\n getAddOverlayUrl: getAddOverlayUrl,\n getOverlayFiles: getOverlayFiles,\n deleteOverlayFile: deleteOverlayFile,\n isNOxPollutant: isNOxPollutant,\n getValidScenarioAlias: getValidScenarioAlias,\n createScenario: createScenario,\n getOverlayFile: getOverlayFile\n }; ////////////\n\n function hashToNamedObjectArray() {\n var keyName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"id\";\n return function (hash) {\n return _.chain(hash).map(function (name, id) {\n return _defineProperty({\n name: name\n }, keyName, id);\n }).sortBy(\"name\").value();\n };\n }\n\n function getAllScenarios() {\n return blastingDataProvider.getAllScenarios().then(hashToNamedObjectArray(\"scenarioId\"));\n }\n\n function getScenario(scenarioAlias) {\n return blastingDataProvider.getScenario(scenarioAlias);\n }\n\n function deleteScenario(scenarioAlias) {\n return blastingDataProvider.deleteScenario(scenarioAlias);\n }\n\n function updateActualBlastTime(scenarioAlias, actualBlastTime) {\n return blastingDataProvider.updateActualBlastTime(scenarioAlias, actualBlastTime);\n }\n\n function getModelTypes() {\n return blastingDataProvider.getModelTypes().then(function (modelTypes) {\n _.map(modelTypes, function (config, key, source) {\n source[key] = config && JSON.parse(config);\n });\n\n return modelTypes;\n });\n }\n\n function getDefaultConcentrations() {\n var defaultConcentrations = new Map(); // Total Suspended Particulates (TSP)\n\n defaultConcentrations.set(\"B8382C5A-AC52-4E67-93CA-755BF38F0295\", 0.054); // Particulate Matter 10 µm (PM10)\n\n defaultConcentrations.set(\"106C9CC9-5C5E-4758-B384-1340DC93D578\", 0.054);\n return defaultConcentrations;\n }\n\n function getModelOptions() {\n return gisModelDataProvider.getOptions().then(function (modelOptions) {\n var pollutantOptions = modelOptions.plumeGisModelOptions.pollutantOptions.map(function (pollutantOption) {\n pollutantOption.modelPollutantDisplayName = \"\".concat(pollutantOption.modelPollutantName, \" (\").concat(pollutantOption.modelPollutantShortName, \")\");\n return pollutantOption;\n });\n return {\n windGisModelOptions: {\n displayUnitOptions: modelOptions.windGisModelOptions.displayUnitOptions,\n windScientificModels: modelOptions.windGisModelOptions.windScientificModels.filter(function (model) {\n return model.isSourceForBlasting;\n })\n },\n forwardTrajectoryModelOptions: modelOptions.forwardTrajectoryModelOptions,\n pollutantGisModelOptions: {\n pollutantOptions: pollutantOptions,\n defaultConcentrations: getDefaultConcentrations(),\n noxScale: [//https://www.dnrm.qld.gov.au/__data/assets/pdf_file/0010/212500/qld-guidance-note-20-mgmt-oxides-nitrogen.pdf\n {\n level: 0,\n ppm: 2,\n gramsPerCubicMetre: 3.8e-3,\n description: \"Level 0 - No fume\",\n colour: \"#F4DED9\"\n }, {\n level: 1,\n ppm: 4,\n gramsPerCubicMetre: 7.5e-3,\n description: \"Level 1 - Fume\",\n colour: \"#F4DBAA\"\n }, {\n level: 2,\n ppm: 7,\n gramsPerCubicMetre: 1.32e-2,\n description: \"Level 2 - Minor yellow / orange fume\",\n colour: \"#EDA04F\"\n }, {\n level: 3,\n ppm: 17,\n gramsPerCubicMetre: 3.2e-2,\n description: \"Level 3 - Moderate orange fume\",\n colour: \"#E87511\"\n }, {\n level: 4,\n ppm: 70,\n gramsPerCubicMetre: 1.316e-1,\n description: \"Level 4 - Significant orange fume\",\n colour: \"#B55400\"\n }, {\n level: 5,\n ppm: 500,\n gramsPerCubicMetre: 0.94,\n description: \"Level 5 - Major red / purple fume\",\n colour: \"#633A11\"\n }]\n }\n };\n });\n }\n\n function getAddOverlayUrl(scenarioId) {\n return blastingDataProvider.getAddOverlayUrl(scenarioId);\n }\n\n function getOverlayFiles(scenarioId) {\n return blastingDataProvider.getOverlayFiles(scenarioId).then(function (response) {\n return _.map(response, function (overlayFile) {\n // See: https://github.com/nervgh/angular-file-upload/issues/211\n return {\n name: overlayFile.name,\n size: overlayFile.length,\n dateModified: new Date(overlayFile.utcLastModifiedDateTime),\n type: overlayFile.type\n };\n });\n });\n }\n\n function deleteOverlayFile(scenarioId, fileName) {\n return blastingDataProvider.deleteOverlayFile(scenarioId, fileName);\n }\n\n function getOverlayFile(fileName) {\n return blastingDataProvider.getOverlayFile(fileName);\n }\n\n function isNOxPollutant(pollutantId) {\n return pollutantId && pollutantId.toUpperCase() === \"B183985A-F356-4204-87E7-246A95EC3315\";\n }\n\n function getValidScenarioAlias(alias) {\n return blastingDataProvider.getValidScenarioAlias(alias);\n }\n\n function createScenario(scenarioData) {\n var scenario = {\n name: scenarioData.name,\n alias: scenarioData.alias,\n latitude: scenarioData.latitude,\n longitude: scenarioData.longitude,\n utcBlastTimes: scenarioData.blastTimesMillis.map(function (blastTimeMillis) {\n return new Date(blastTimeMillis).toISOString();\n }),\n modelTypes: _.chain(scenarioData.models).pickBy(function (isSelected) {\n return isSelected;\n }).map(function (isSelected, modelType) {\n return blastModelType[modelType];\n }).value(),\n // Path and pollutant model properties\n height: scenarioData.blastHeight,\n windScientificModelId: scenarioData.windScientificModelId,\n // Pollutant and overpressure model properties\n azimuth: scenarioData.azimuth,\n elevation: scenarioData.elevation,\n // Path model specific properties\n forwardTrajectoryScientificModelId: scenarioData.forwardTrajectoryScientificModelId,\n // Pollutant model specific properties\n modelPollutantId: scenarioData.modelPollutantId,\n pollutantScientificModelId: scenarioData.pollutantScientificModelId,\n displayUnitId: scenarioData.displayUnitId,\n initialConcentrationGramsPerCubicMetre: scenarioData.initialConcentration,\n length: scenarioData.blastLength,\n width: scenarioData.blastWidth,\n // Overpressure model specific properties\n blastSetup: scenarioData.blastSetup,\n holeDiameter: scenarioData.holeDiameter,\n frontFaceKFactor: scenarioData.frontFaceKFactor,\n backFaceKFactor: scenarioData.backFaceKFactor,\n chargeMass: scenarioData.chargeMass,\n // Flyrock\n holeAngle: scenarioData.holeAngle,\n dispersalAngle: scenarioData.dispersalAngle,\n flyrockSiteConstantKv: scenarioData.flyrockSiteConstantKv,\n // Overpressure & Flyrock properties\n burden: scenarioData.burden,\n stemmingHeight: scenarioData.stemmingHeight,\n // Ground Vibration\n chargeMassPerHole: scenarioData.chargeMassPerHole,\n groundVibrationSiteConstantKv: scenarioData.groundVibrationSiteConstantKv,\n groundVibrationSiteExponentKb: scenarioData.groundVibrationSiteExponentKb\n };\n\n if (scenarioData.isGroundVibrationSelected) {\n scenario.pointsOfInterest = scenarioData.groundVibrationPois;\n }\n\n if (scenarioData.blastSetup === blastSetup.stemming) {\n scenario.backFaceKFactor = scenario.frontFaceKFactor;\n }\n\n return blastingDataProvider.createScenario(scenario);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.configuration.gisModelService\", gisModelService);\n gisModelService.$inject = [\"lodash\", \"i18n\", \"app.core.providers.configuration.gisModelDataProvider\"];\n\n function gisModelService(_, i18n, gisModelDataProvider) {\n var service = {\n getEmissionsDataFileUploadUrl: gisModelDataProvider.getEmissionsDataFileUploadUrl,\n getExistingEmissionsDataFiles: gisModelDataProvider.getExistingEmissionsDataFiles,\n getAll: getAllModels,\n get: gisModelDataProvider.getModel,\n getOptions: getModellingOptions,\n getCalpuffConfigs: gisModelDataProvider.getCalpuffConfigs,\n remove: gisModelDataProvider.remove,\n addPlume: gisModelDataProvider.addPlume,\n addWind: gisModelDataProvider.addWind,\n importEmissionsData: gisModelDataProvider.importEmissionsData,\n updatePlume: updatePlume,\n updateWind: updateWind,\n deleteEmissionsDataFiles: gisModelDataProvider.deleteEmissionsDataFiles\n };\n return service; ////////////////////\n\n function getModellingOptions() {\n return gisModelDataProvider.getOptions().then(function (options) {\n var pollutants = _.chain(options.plumeGisModelOptions.pollutantOptions).map(function (option) {\n return {\n modelPollutantId: option.modelPollutantId,\n modelPollutantName: option.modelPollutantName,\n modelPollutantShortName: option.modelPollutantShortName,\n modelPollutantDisplayName: option.modelPollutantShortName ? \"\".concat(option.modelPollutantName, \" (\").concat(option.modelPollutantShortName, \")\") : option.modelPollutantName,\n displayUnits: option.displayUnitOptions,\n scientificModels: _.sortBy(option.associatedPlumeScientificModels, \"name\")\n };\n }).sortBy(\"modelPollutantName\").value();\n\n var windScientificModels = _.chain(options.windGisModelOptions.windScientificModels.filter(function (model) {\n return model.isSourceForModelling;\n })).map(function (windScientificModel) {\n return {\n name: generateNameForScientificModel(windScientificModel),\n id: windScientificModel.id,\n intervalDurationInMinutes: windScientificModel.intervalDurationInMinutes\n };\n }).sortBy(\"name\").value();\n\n return {\n plumeOptions: {\n pollutants: pollutants,\n windScientificModels: windScientificModels\n },\n windOptions: {\n displayUnits: options.windGisModelOptions.displayUnitOptions,\n scientificModels: windScientificModels\n }\n };\n });\n }\n\n function generateNameForScientificModel(windScientificModel) {\n var i10n = function i10n(key) {\n return i18n.i10n(\"app.core.services.configuration.gisModelService.scientificModelName.\".concat(key));\n };\n\n return \"\".concat(windScientificModel.name, \" - \").concat(windScientificModel.intervalDurationInMinutes, \" \").concat(i10n(\"minutes\"), \" - \").concat(i10n(windScientificModel.isPredictive ? \"predictive\" : \"historical\"));\n }\n\n function getAllModels() {\n return gisModelDataProvider.getAll().then(hashToNamedObjectArray(\"modelId\"));\n }\n\n function hashToNamedObjectArray() {\n var keyName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"id\";\n return function (hash) {\n return _.chain(hash).map(function (name, id) {\n return _defineProperty({\n name: name\n }, keyName, id);\n }).sortBy(\"name\").value();\n };\n }\n\n function updatePlume(plumeData) {\n return gisModelDataProvider.updatePlume(plumeData).then(function () {\n return plumeData.id;\n });\n }\n\n function updateWind(windData) {\n return gisModelDataProvider.updateWind(windData).then(function () {\n return windData.id;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.configuration.legacyLookupService\", lookupService);\n lookupService.$inject = [\"lodash\", \"app.core.providers.configuration.legacyLookupDataProvider\"];\n\n function lookupService(_, lookupDataProvider) {\n return {\n getWindowsTimeZones: getWindowsTimeZones\n }; //////////////////\n\n function getWindowsTimeZones() {\n return lookupDataProvider.getWindowsTimeZones().then(function (timeZones) {\n return _.map(timeZones, function (timeZone) {\n return {\n id: timeZone.Id,\n description: timeZone.DisplayName\n };\n });\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.configuration.measurementGroupService\", measurementGroupService);\n measurementGroupService.$inject = [\"lodash\", \"app.core.providers.configuration.measurementGroupDataProvider\"];\n\n function measurementGroupService(_, measurementGroupDataProvider) {\n return {\n getMeasurementGroupsFlattened: getMeasurementGroupsFlattened,\n getMeasurementGroupsNested: getMeasurementGroupsNested,\n queryMeasurementGroups: measurementGroupDataProvider.queryMeasurementGroups,\n getMeasurementGroup: measurementGroupDataProvider.getMeasurementGroup,\n createMeasurementGroup: measurementGroupDataProvider.createMeasurementGroup,\n updateMeasurementGroup: updateMeasurementGroup,\n isMeasurementGroupBeingUsed: measurementGroupDataProvider.isMeasurementGroupBeingUsed,\n getMeasurementGroupChildCount: getMeasurementGroupChildCount,\n deleteMeasurementGroup: measurementGroupDataProvider.deleteMeasurementGroup\n };\n\n function getMeasurementGroupsFlattened() {\n var sortBy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (mg) {\n return mg.defaultOrder;\n };\n return measurementGroupDataProvider.getAllMeasurementGroups().then(function (measurementGroups) {\n return _.sortBy(measurementGroups, sortBy);\n });\n }\n\n function getMeasurementGroupsNested() {\n var sortBy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (mg) {\n return mg.defaultOrder;\n };\n return measurementGroupDataProvider.getAllMeasurementGroups().then(function (measurementGroups) {\n var byId = _.reduce(measurementGroups, function (map, mg) {\n return map.set(mg.id, mg);\n }, new Map());\n\n var parents = [];\n\n _.forEach(measurementGroups, function (mg) {\n if (!mg.parentId) {\n parents.push(mg);\n } else {\n var parent = byId.get(mg.parentId);\n parent.children = parent.children && [].concat(_toConsumableArray(parent.children), [mg]) || [mg];\n }\n });\n\n _.forEach(parents, function (parent) {\n if (parent.children) {\n parent.children = _.sortBy(parent.children, sortBy);\n }\n });\n\n return _.sortBy(parents, sortBy);\n });\n }\n\n function updateMeasurementGroup(measurementGroup) {\n return measurementGroupDataProvider.updateMeasurementGroup(measurementGroup).then(function () {\n return measurementGroup.id;\n });\n }\n\n function getMeasurementGroupChildCount() {\n return measurementGroupDataProvider.getMeasurementGroupChildCount();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.configuration.modellingService\", modellingService);\n modellingService.$inject = [\"app.core.providers.configuration.modellingDataProvider\", \"app.core.services.dateTimeService\"];\n\n function modellingService(modellingDataProvider, dateTimeService) {\n var service = {\n getWrfConfiguration: modellingDataProvider.getWrfConfiguration,\n runCalModelling: runCalModelling,\n runAerModelling: modellingDataProvider.runAerModelling\n }; ////////////\n\n function runCalModelling(configurationName, forecastDate, forecastRun) {\n if (!configurationName) {\n throw new Error(\"configurationName is not defined\");\n }\n\n if (!forecastRun) {\n throw new Error(\"forecastRun is not defined\");\n }\n\n forecastDate = dateTimeService.formatAs.utcDate(forecastDate || new Date());\n return modellingDataProvider.runCalModelling(configurationName, forecastDate, forecastRun);\n }\n\n return service;\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.configuration.monitoringService\", configurationMonitoringService);\n configurationMonitoringService.$inject = [\"lodash\", \"app.core.providers.configuration.monitoringDataProvider\"];\n\n function configurationMonitoringService(_, monitoringDataProvider) {\n var service = {\n // monitors\n getMonitorType: getMonitorType,\n getMonitorTypes: getMonitorTypes,\n getMonitorTypeIcon: getMonitorTypeIcon,\n getMonitor: monitoringDataProvider.getMonitor,\n getMonitors: getMonitors,\n getUpperAirWeatherStations: getUpperAirWeatherStations,\n getSurfaceWeatherStations: getSurfaceWeatherStations,\n getMonitorDisplay: getMonitorDisplay,\n getMonitorLocation: monitoringDataProvider.getMonitorLocation,\n queryMonitors: queryMonitors,\n updateMonitorDisplay: monitoringDataProvider.updateMonitorDisplay,\n setDefaultMetStation: monitoringDataProvider.setDefaultMetStation,\n getAllMetStations: monitoringDataProvider.getAllMetStations,\n createMonitor: monitoringDataProvider.createMonitor,\n updateMonitor: updateMonitor,\n // measurement types\n getMeasurementType: getMeasurementType,\n getMeasurementTypeConfigurationOptions: getMeasurementTypeConfigurationOptions,\n queryMonitorMeasurementTypes: monitoringDataProvider.queryMonitorMeasurementTypes,\n createMeasurementType: createMeasurementType,\n updateMeasurementType: updateMeasurementType,\n genericMeasurementTypeCategoryId: 4 // see Enum.cs -> VariableDataType\n\n };\n return service; ////////////\n\n function getMonitorType(monitorId) {\n return monitoringDataProvider.getMonitorType(monitorId).then(_.camelCase);\n }\n\n function getMonitorTypes() {\n // eg. response -> { type: `ambientMonitor`, name: `Ambient Monitor`, icon: `circle thin` }\n return monitoringDataProvider.getMonitorTypes().then(function (monitorTypes) {\n return _.map(hashToNamedObjectArray(\"type\")(monitorTypes), function (monitorType) {\n monitorType.icon = service.getMonitorTypeIcon(monitorType.type);\n return monitorType;\n });\n });\n }\n\n function getMonitorTypeIcon(monitorType) {\n switch (monitorType) {\n case \"ambientMonitor\":\n return \"icon icons8-air-quality-filled\";\n\n case \"noiseMonitor\":\n return \"icon icons8-headphones-filled\";\n\n case \"surfaceWeatherStation\":\n return \"icon icons8-wind-gauge-filled\";\n\n case \"upperAirWeatherStation\":\n return \"icon icons8-wind-gauge-filled\";\n\n case \"surfaceWaterMonitor\":\n return \"icon icons8-water-filled\";\n\n case \"groundWaterMonitor\":\n return \"icon icons8-piping-filled\";\n\n case \"soilMonitor\":\n return \"icon icons8-sprout-filled\";\n\n case \"discreteReceptor\":\n return \"fa fa-cube\";\n\n case \"vibrationMonitor\":\n return \"fa fa-bullseye\";\n }\n }\n\n function getMonitors(whereVisible) {\n return monitoringDataProvider.getMonitors(whereVisible).then(hashToNamedObjectArray(\"monitorId\"));\n }\n\n function getUpperAirWeatherStations() {\n return monitoringDataProvider.getUpperAirWeatherStations().then(function (monitors) {\n return _.map(monitors, function (monitor) {\n return {\n name: monitor.name,\n id: monitor.id\n };\n });\n });\n }\n\n function getSurfaceWeatherStations() {\n return monitoringDataProvider.getSurfaceWeatherStations().then(function (monitors) {\n return _.map(monitors, function (monitor) {\n return {\n name: monitor.name,\n id: monitor.id\n };\n });\n });\n }\n\n function getMonitorDisplay(monitorId) {\n return monitoringDataProvider.getMonitorDisplay(monitorId).then(function (result) {\n _.forEach(result.availableVariables, function (pv) {\n return pv.measurementGroupId = null;\n });\n\n return result;\n });\n }\n\n function queryMonitors(searchCriteria) {\n return monitoringDataProvider.queryMonitors(searchCriteria).then(mapResults);\n\n function mapResults(result) {\n result.data = _.map(result.data, function (monitor) {\n monitor.type = _.camelCase(monitor.type);\n monitor.icon = service.getMonitorTypeIcon(monitor.type);\n return monitor;\n });\n return result;\n }\n }\n\n function updateMonitor(monitorType, monitor) {\n return monitoringDataProvider.updateMonitor(monitorType, monitor).then(function () {\n return monitor.id;\n });\n }\n\n function getMeasurementType(measurementTypeId) {\n return monitoringDataProvider.getMeasurementType(measurementTypeId).then(function (result) {\n return fromConfigureProcessVariableRequest(result);\n });\n }\n\n function getMeasurementTypeConfigurationOptions() {\n return monitoringDataProvider.getMeasurementTypeConfigurationOptions().then(function (result) {\n var aggregateTypeIds = _.keys(result.aggregateTypes);\n\n var aggregateTypes = _.map(aggregateTypeIds, function (aggregateTypeId) {\n return {\n type: parseInt(aggregateTypeId),\n name: result.aggregateTypes[aggregateTypeId]\n };\n });\n\n return {\n aggregateTypes: aggregateTypes,\n units: result.units,\n pollutants: result.pollutants,\n measurementTypeCategories: result.processVariableCategories\n };\n });\n }\n\n function updateMeasurementType(measurementType) {\n var payload = toConfigureProcessVariableRequest(measurementType);\n return monitoringDataProvider.updateMeasurementType(payload).then(function () {\n return payload.processVariable.id;\n });\n }\n\n function createMeasurementType(measurementType) {\n var payload = toConfigureProcessVariableRequest(measurementType);\n return monitoringDataProvider.createMeasurementType(payload).then(function (result) {\n return result;\n });\n }\n\n function hashToNamedObjectArray() {\n var keyName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"id\";\n return function (hash) {\n return _.chain(hash).map(function (name, id) {\n return _defineProperty({\n name: name\n }, keyName, id);\n }).sortBy(\"name\").value();\n };\n }\n\n function fromConfigureProcessVariableRequest(result) {\n var pollutantId = result.pollutantId,\n defaultDisplayUnitId = result.defaultDisplayUnitId,\n defaultImportUnitId = result.defaultImportUnitId,\n dataType = result.dataType,\n samplingRateMillis = result.samplingRateMillis,\n exceedanceThresholds = result.exceedanceThresholds,\n rest = _objectWithoutProperties(result, [\"pollutantId\", \"defaultDisplayUnitId\", \"defaultImportUnitId\", \"dataType\", \"samplingRateMillis\", \"exceedanceThresholds\"]);\n\n var mappedExceedanceThresholds = exceedanceThresholds.map(function (threshold) {\n var color = threshold.color,\n rest = _objectWithoutProperties(threshold, [\"color\"]);\n\n return _extends({}, rest, {\n hexColor: intToHexColor(color)\n });\n });\n return _extends({}, rest, {\n exceedanceThresholds: mappedExceedanceThresholds,\n pollutantId: getGuid(pollutantId),\n defaultDisplayUnitId: getGuid(defaultDisplayUnitId),\n defaultImportUnitId: getGuid(defaultImportUnitId),\n categoryId: dataType || service.genericMeasurementTypeCategoryId,\n samplingRateSeconds: samplingRateMillis / 1000\n });\n\n function getGuid(guid) {\n return guid === \"00000000-0000-0000-0000-000000000000\" ? null : guid;\n }\n }\n\n function toConfigureProcessVariableRequest(measurementType) {\n var monitorId = measurementType.monitorId,\n samplingRateSeconds = measurementType.samplingRateSeconds,\n categoryId = measurementType.categoryId,\n exceedanceThresholds = measurementType.exceedanceThresholds,\n rest = _objectWithoutProperties(measurementType, [\"monitorId\", \"samplingRateSeconds\", \"categoryId\", \"exceedanceThresholds\"]);\n\n var mappedExceedanceThresholds = exceedanceThresholds.map(function (threshold) {\n var hexColor = threshold.hexColor,\n rest = _objectWithoutProperties(threshold, [\"hexColor\"]);\n\n return _extends({}, rest, {\n color: hexColorToInt(hexColor)\n });\n });\n return {\n processVariable: _extends({}, rest, {\n exceedanceThresholds: mappedExceedanceThresholds,\n samplingRateMillis: samplingRateSeconds * 1000,\n dataType: categoryId,\n processId: monitorId\n })\n };\n }\n\n function hexColorToInt(hex) {\n return parseInt(hex.substr(1), 16);\n }\n\n function intToHexColor(int) {\n /* eslint-disable no-bitwise */\n return \"#\" + (int >>> 0).toString(16).slice(-6);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"confirmationDialog\", confirmationDialog);\n confirmationDialog.$inject = [\"$modal\", \"i18n\", \"lodash\"];\n\n function confirmationDialog($modal, i18n, _) {\n var defaultOptions = {\n buttons: {\n cancel: {\n cssClass: \"btn-default\",\n text: \"buttons.cancel\"\n },\n 'continue': {\n text: \"buttons.continue\"\n }\n }\n };\n return {\n ask: ask,\n notify: notify,\n error: error\n };\n\n function ask(title, body) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return buildDialog(title, body, options, \"/App/core/services/confirmationDialog.html\");\n }\n\n function notify(title, body) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return buildDialog(title, body, options, \"/App/core/services/notifyDialog.html\");\n }\n\n function error() {\n var buttons = {\n reload: {\n text: i18n.i10n(\"buttons.reload\"),\n onClick: function onClick() {\n return window.location.reload(true);\n }\n },\n contactSupport: {\n text: i18n.i10n(\"buttons.support\"),\n onClick: function onClick() {\n return window.location.href = \"mailto:cms@envirosuite.com?subject=Envirosuite Application Errors\";\n }\n }\n };\n return buildDialog(i18n.i10n(\"errors.fatal.title\"), i18n.i10n(\"errors.fatal.message\"), {\n buttons: buttons\n }, \"/App/core/services/errorDialog.html\");\n }\n\n function buildDialog(title, body, options, templateUrl) {\n localiseDefaultOptionsButtonText();\n return $modal.open({\n templateUrl: templateUrl,\n backdrop: true,\n controller: getDialogController(title, body, Object.assign({}, defaultOptions, options)),\n size: \"md\",\n animation: false\n }).result; //////////////////\n\n function localiseDefaultOptionsButtonText() {\n _.forEach(defaultOptions.buttons, function (value) {\n value.text = i18n.i10n(value.text);\n });\n }\n }\n\n function getDialogController(title, body, options) {\n confirmationDialogController.$inject = [\"$scope\", \"$modalInstance\"];\n\n function confirmationDialogController($scope, $modalInstance) {\n $scope.title = title;\n $scope.body = body;\n $scope.$modalInstance = $modalInstance;\n $scope.options = options;\n }\n\n return confirmationDialogController;\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.dashboardService\", dashboardService);\n dashboardService.$inject = [\"$log\", \"$state\", \"browserStorage\", \"lodash\", \"notifier\", \"app.core.appSettings\", \"i18n\", \"dashboard\"];\n\n function dashboardService($log, $state, browserStorage, _, notifier, appSettings, i18n, dashboard) {\n var dashboardLayoutStorageKey = \"dashboard-layout\";\n var accessibleWidgetStorageKey = \"dashboard-widgets\";\n return {\n getDashboard: getDashboard,\n persistDashboard: persistDashboard,\n deleteDashboard: deleteDashboard,\n canAccessWidget: canAccessWidget\n }; //////////////\n\n function getDashboard() {\n var _getWidgets = getWidgets(),\n accessibleWidgets = _getWidgets.accessibleWidgets,\n newWidgets = _getWidgets.newWidgets;\n\n var persistedDashboardConfiguration = browserStorage.getBucket(dashboardLayoutStorageKey, getStorageBucketKey());\n\n if (!persistedDashboardConfiguration) {\n return _.assign(buildDefaultDashboard(), {\n supportsLayouts: getDefaultNumberOfLayoutColumns() > 1\n });\n }\n\n updateDeviceWidgets(persistedDashboardConfiguration);\n\n if (newWidgets.length) {\n persistedDashboardConfiguration.newWidgetsAreAvailable = {\n onUserHasViewed: function onUserHasViewed() {\n delete persistedDashboardConfiguration.newWidgetsAreAvailable;\n persistWidgetList(accessibleWidgets);\n }\n };\n }\n\n return _.assign(persistedDashboardConfiguration, {\n supportsLayouts: getDefaultNumberOfLayoutColumns() > 1\n }); //////////////\n\n function getWidgets() {\n var previousAccessibleWidgets = browserStorage.getBucket(accessibleWidgetStorageKey, getStorageBucketKey()) || [];\n\n var accessibleWidgets = _.chain(dashboard.widgets).map(accessorizeWidget).filter(canAccessWidget).forEach(validate).value();\n\n if (!previousAccessibleWidgets.length) {\n // first time this dashboard has been accessed\n persistWidgetList(accessibleWidgets);\n }\n\n return {\n accessibleWidgets: accessibleWidgets,\n newWidgets: _.filter(accessibleWidgets, function (accessibleWidget) {\n return accessibleWidget.isNew;\n })\n }; //////////////\n\n function accessorizeWidget(widget, widgetType) {\n widget.type = widgetType;\n widget.isNew = previousAccessibleWidgets.length && !_.find(previousAccessibleWidgets, function (type) {\n return widget.type === type;\n });\n widget.onClick = widget.route ? function () {\n return $state.go(widget.route, {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n dateTime: $state.params.dateTime\n });\n } : angular.noop;\n return widget;\n }\n\n function validate(widget) {\n validateMajorVersion();\n validateMinorVersion(); ///////////\n\n function validateMajorVersion() {\n var majorVersion = widget.majorVersion;\n\n if (_.isNull(majorVersion) || _.isUndefined(majorVersion)) {\n widget.majorVersion = 1;\n } else {\n if (Number(majorVersion) !== parseInt(majorVersion) || parseInt(majorVersion, 10) < 1) {\n throw new Error(\"The '\".concat(widget.type, \"' widget must have an integer major version greater than or equal to 1\"));\n }\n\n widget.majorVersion = parseInt(majorVersion, 10);\n }\n }\n\n function validateMinorVersion() {\n var minorVersions = widget.minorVersions;\n\n if (!_.isObject(minorVersions) || _.isEmpty(minorVersions)) {\n return;\n }\n\n _.chain(_.keys(minorVersions)).map(function (mv) {\n var minorVersion = parseInt(mv, 10);\n\n if (_.isNaN(minorVersion)) {\n throw new Error(\"The minor version key '\".concat(mv, \"' must be parsable to an integer\"));\n }\n\n return minorVersion;\n }).sortBy(function (minorVersion) {\n return minorVersion;\n }).tap(function (minorVersions) {\n return widget.minorVersionNumbers = minorVersions;\n }).reduce(function (previous, current) {\n if (previous + 1 !== current) {\n throw new Error(\"The minor version is not the next in sequence - prev: \".concat(previous, \" current: \").concat(current));\n }\n\n if (!_.isFunction(minorVersions[current])) {\n throw new Error(\"The minor version upgrader must be a function.\");\n }\n\n return current;\n }, 0).value();\n }\n }\n }\n\n function buildDefaultDashboard() {\n return {\n isDefault: true,\n titleTemplateUrl: \"/App/ui/features/dashboard/DashboardActions.html\",\n addTemplateUrl: \"/App/ui/features/dashboard/WidgetAdd.html\",\n structure: \"default\",\n rows: [{\n columns: getDefaultColumnLayout()\n }]\n }; ////////////////////\n\n function getDefaultColumnLayout() {\n if (getDefaultNumberOfLayoutColumns() === 1) {\n return [{\n styleClass: \"col-md-12\",\n widgets: filterAccessibleWidgets()\n }];\n } else {\n return [{\n styleClass: \"col-md-6\",\n widgets: filterAccessibleWidgets(function (widget, index) {\n return index % 2 === 0;\n })\n }, {\n styleClass: \"col-md-6\",\n widgets: filterAccessibleWidgets(function (widget, index) {\n return index % 2 !== 0;\n })\n }];\n }\n }\n\n function filterAccessibleWidgets() {\n var filter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {\n return true;\n };\n return _.chain(accessibleWidgets).filter(filter).map(newWidget).value(); ////////////\n\n function newWidget(widget) {\n return {\n type: widget.type,\n config: {},\n titleTemplateUrl: \"/App/ui/features/dashboard/WidgetHeader.html\",\n version: \"1.0\"\n };\n }\n }\n }\n\n function updateDeviceWidgets(persistedDashboardConfiguration) {\n var removedWidgets = [];\n\n _.forEach(persistedDashboardConfiguration.rows, function (row) {\n _.forEach(row.columns, function (column) {\n column.widgets = _.chain(column.widgets).map(updateDeviceWidget).filter(function (widget) {\n return widget;\n }).value();\n });\n });\n\n persistDashboard(persistedDashboardConfiguration);\n\n if (removedWidgets.length) {\n notifyUserAboutTroublesomeWidgets(removedWidgets);\n } //////////////\n\n\n function updateDeviceWidget(deviceWidget) {\n var latestVersionOfWidget = _.find(accessibleWidgets, {\n type: deviceWidget.type\n });\n\n if (!latestVersionOfWidget) {\n // the widget is no longer accessible\n return removeFromDeviceDashboard();\n }\n\n deviceWidget.version = deviceWidget.version || \"1.0\";\n\n var _$map = _.map(deviceWidget.version.split(\".\"), function (number) {\n return parseInt(number);\n }),\n _$map2 = _slicedToArray(_$map, 2),\n currentMajor = _$map2[0],\n currentMinor = _$map2[1];\n\n var latestMajor = latestVersionOfWidget.majorVersion;\n return latestMajor === currentMajor && upgradeConfiguration() || removeFromDeviceDashboard(); ///////////\n\n function removeFromDeviceDashboard() {\n $log.info(\"The '\".concat(deviceWidget.type, \"' was removed.
Widget Details:
\").concat(JSON.stringify(deviceWidget)));\n removedWidgets = [].concat(_toConsumableArray(removedWidgets), [deviceWidget]);\n }\n\n function upgradeConfiguration() {\n try {\n deviceWidget.config = _.reduce(latestVersionOfWidget.minorVersionNumbers, executeMinorVersionUpgrade, deviceWidget.config);\n return deviceWidget;\n } catch (error) {\n return null;\n } ///////////\n\n\n function executeMinorVersionUpgrade(widgetConfig, minorVersionNumber) {\n if (minorVersionNumber <= currentMinor) {\n return widgetConfig;\n }\n\n try {\n var upgradeFunction = latestVersionOfWidget.minorVersions[minorVersionNumber];\n var upgradedConfig = upgradeFunction(widgetConfig);\n deviceWidget.version = \"\".concat(currentMajor, \".\").concat(minorVersionNumber);\n return upgradedConfig;\n } catch (error) {\n $log.error(\"The '\".concat(widgetConfig.type, \"' widget failed the upgrade path.
Initial version: \").concat(currentMajor, \".\").concat(currentMinor, \"
Failed minor version upgrader: \").concat(minorVersionNumber, \"
error: \").concat(error));\n removeFromDeviceDashboard();\n throw error;\n }\n }\n }\n }\n\n function notifyUserAboutTroublesomeWidgets(removedWidgets) {\n var notificationTitle = i18n.i10n(\"adf.notifications.widgetRemoval.title\");\n\n var widgetNames = _.reduce(removedWidgets, function (list, removedWidget) {\n return \"\".concat(list, \"
  • \").concat(i18n.i10n(removedWidget.type), \"
  • \");\n }, \"\");\n\n var notificationMessage = i18n.i10n(\"adf.notifications.widgetRemoval.message\", {\n widgetNames: widgetNames\n });\n notifier.info(notificationMessage, notificationTitle);\n }\n }\n }\n\n function canAccessWidget(widget) {\n return _.reduce(widget.accessControls, function (result, accessControl) {\n return result && appSettings.site.accessControls[accessControl];\n }, true);\n }\n\n function persistDashboard(model) {\n delete model.isDefault;\n browserStorage.persistBucket(dashboardLayoutStorageKey, getStorageBucketKey(), model);\n }\n\n function persistWidgetList(accessibleWidgets) {\n browserStorage.persistBucket(accessibleWidgetStorageKey, getStorageBucketKey(), _.map(accessibleWidgets, function (accessibleWidget) {\n return accessibleWidget.type;\n }));\n }\n\n function deleteDashboard() {\n browserStorage.deleteBucket(dashboardLayoutStorageKey, getStorageBucketKey());\n }\n\n function getStorageBucketKey() {\n return \"\".concat(appSettings.site.facility.alias, \"-\").concat(appSettings.userId);\n }\n\n function getDefaultNumberOfLayoutColumns() {\n return screen.width >= 992 ? 2 : 1;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").provider(\"app.core.services.dateTimeService\", dateTimeService);\n dateTimeService.$inject = [\"lodash\"];\n\n function dateTimeService(_) {\n this.$get = dateTimeServiceFactory; ////////////////////\n\n dateTimeServiceFactory.$inject = [\"$filter\", \"app.core.services.settingsService\"];\n\n function dateTimeServiceFactory($filter, settingsService) {\n var millisPerMinute = 1000 * 60;\n var cultureFormats = {};\n var service = {\n roundUpToClosestMinute: roundUpToClosestMinute\n };\n activate();\n return service; ////////////////////\n\n function activate() {\n setupCultureFormats();\n updateCurrentCultureFormats(cultureFormats.default);\n settingsService.getSelectedLanguage().then(function (culture) {\n culture = culture.toLowerCase();\n var formats = cultureFormats[culture]; // Cater for a more generic version of the language, e.g. let `en-AU` fallback to `en`\n\n if (!formats) {\n var match = culture.match(/[^-]+/);\n\n if (match && match.length) {\n formats = cultureFormats[match[0]];\n }\n }\n\n if (formats && service.formats !== formats) {\n updateCurrentCultureFormats(formats);\n }\n });\n }\n\n function updateCurrentCultureFormats(formats) {\n service.formats = formats;\n service.formatAs = {\n date: date,\n utcDate: utcDate,\n dateTime: dateTime,\n dateTimeWithSeconds: dateTimeWithSeconds,\n hour: hour,\n time: time,\n timeWithSeconds: timeWithSeconds,\n iso: iso\n }; ////////////////////\n\n function date(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.date);\n }\n\n function utcDate(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.utcDate);\n }\n\n function dateTime(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.dateTime);\n }\n\n function dateTimeWithSeconds(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.dateTimeWithSeconds);\n }\n\n function hour(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.hour);\n }\n\n function time(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.time);\n }\n\n function timeWithSeconds(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.timeWithSeconds);\n }\n\n function iso(dateTime) {\n return $filter(\"date\")(dateTime, formats.angular.iso);\n }\n }\n\n function roundUpToClosestMinute(dateTime) {\n var dateTimeMillis = dateTime.getTime();\n var delta = dateTimeMillis % millisPerMinute;\n\n if (delta === 0) {\n return dateTime;\n }\n\n var roundedEndTimeMillis = dateTimeMillis + millisPerMinute - delta;\n return new Date(roundedEndTimeMillis);\n }\n\n function setupCultureFormats() {\n addCultureFormats(getEnFormats(), \"default\", \"en\");\n addCultureFormats(getViFormats(), \"vi\");\n addCultureFormats(get24HourFormats(), \"fr\");\n addCultureFormats(get24HourFormats(), \"es\"); ////////////////////\n\n function addCultureFormats(formats) {\n for (var _len = arguments.length, cultures = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n cultures[_key - 1] = arguments[_key];\n }\n\n _.forEach(cultures, function (culture) {\n return cultureFormats[culture.toLowerCase()] = formats;\n });\n }\n\n function getEnFormats() {\n return {\n is24Hour: false,\n angular: {\n date: \"dd MMM yyyy\",\n utcDate: \"yyyy-MM-dd'Z'\",\n dateTime: \"dd MMM yyyy hh:mm a\",\n dateTimeWithSeconds: \"dd MMM yyyy hh:mm:ss a\",\n hour: \"hh\",\n time: \"hh:mm a\",\n timeWithSeconds: \"hh:mm:ss a\",\n iso: \"yyyy-MM-ddTHH:mm\" // ISO8601\n\n },\n moment: {\n date: \"DD MMM YYYY\",\n utcDate: \"YYYY-MM-DD[Z]\",\n dateTime: \"DD MMM YYYY hh:mm A\",\n dateTimeWithSeconds: \"DD MMM YYYY hh:mm:ss A\",\n hour: \"hh\",\n time: \"hh:mm A\",\n timeWithSeconds: \"hh:mm:ss A\",\n iso: \"YYYY-MM-DDTHH:mm\" // ISO8601\n\n },\n kendo: {\n date: \"dd MMM yyyy\",\n utcDate: \"yyyy-MM-dd'Z'\",\n dateTime: \"dd MMM yyyy hh:mm tt\",\n dateTimeWithSeconds: \"dd MMM yyyy hh:mm:ss tt\",\n hour: \"hh\",\n time: \"hh:mm tt\",\n timeWithSeconds: \"hh:mm:ss tt\",\n iso: \"yyyy-MMM-ddTHH:mm\" // ISO8601\n\n }\n };\n }\n\n function getViFormats() {\n // According to Vianna, the Vietnamese don't really do \"12 hour\" time, so we always\n // use the 24 hour times below (even for 'hoursInDay12').\n return {\n is24Hour: true,\n angular: {\n date: \"dd/MM/yyyy\",\n utcDate: \"yyyy-MM-dd'Z'\",\n dateTime: \"dd/MM/yyyy HH:mm\",\n dateTimeWithSeconds: \"dd/MM/yyyy HH:mm:ss\",\n hoursInDay12: \"HH\",\n time: \"HH:mm\",\n timeWithSeconds: \"HH:mm:ss\",\n iso: \"yyyy-MM-ddTHH:mm\" // ISO8601\n\n },\n moment: {\n date: \"DD/MM/YYYY\",\n utcDate: \"YYYY-MM-DD[Z]\",\n dateTime: \"DD/MM/YYYY HH:mm\",\n dateTimeWithSeconds: \"DD/MM/YYYY HH:mm:ss\",\n hour: \"HH\",\n time: \"HH:mm\",\n timeWithSeconds: \"HH:mm:ss\",\n iso: \"YYYY-MM-DDTHH:mm\" // ISO8601\n\n },\n kendo: {\n date: \"dd/MM/yyyy\",\n utcDate: \"yyyy-MM-dd'Z'\",\n dateTime: \"dd/MM/yyyy HH:mm\",\n dateTimeWithSeconds: \"dd/MM/yyyy HH:mm:ss\",\n hour: \"HH\",\n time: \"HH:mm\",\n timeWithSeconds: \"HH:mm:ss\",\n iso: \"yyyy-MMM-ddTHH:mm\" // ISO8601\n\n }\n };\n }\n\n function get24HourFormats() {\n return {\n is24Hour: true,\n angular: {\n date: \"dd MMM yyyy\",\n utcDate: \"yyyy-MM-dd'Z'\",\n dateTime: \"dd MMM yyyy HH:mm\",\n dateTimeWithSeconds: \"dd MMM yyyy HH:mm:ss\",\n hour: \"HH\",\n time: \"HH:mm a\",\n timeWithSeconds: \"HH:mm:ss\",\n iso: \"yyyy-MM-ddTHH:mm\" // ISO8601\n\n },\n moment: {\n date: \"DD MMM YYYY\",\n utcDate: \"YYYY-MM-DD[Z]\",\n dateTime: \"DD MMM YYYY HH:mm\",\n dateTimeWithSeconds: \"DD MMM YYYY HH:mm:ss\",\n hour: \"HH\",\n time: \"HH:mm\",\n timeWithSeconds: \"HH:mm:ss\",\n iso: \"YYYY-MM-DDTHH:mm\" // ISO8601\n\n },\n kendo: {\n date: \"dd MMM yyyy\",\n utcDate: \"yyyy-MM-dd'Z'\",\n dateTime: \"dd MMM yyyy HH:mm\",\n dateTimeWithSeconds: \"dd MMM yyyy HH:mm:ss\",\n hour: \"HH\",\n time: \"HH:mm\",\n timeWithSeconds: \"HH:mm:ss\",\n iso: \"yyyy-MMM-ddTHH:mm\" // ISO8601\n\n }\n };\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.diagnosticsService\", diagnosticsService);\n diagnosticsService.$inject = [\"app.core.providers.diagnosticsDataProvider\"];\n\n function diagnosticsService(diagnosticsDataProvider) {\n return {\n getLatestProcessDataEndTime: getLatestProcessDataEndTime\n }; ////////////////////\n\n function getLatestProcessDataEndTime() {\n return diagnosticsDataProvider.getUtcLatestProcessDataEndTime().then(function (utcLatestEndTime) {\n return utcLatestEndTime && new Date(utcLatestEndTime);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.errorService\", errorService);\n errorService.$inject = [\"$log\", \"notifier\", \"$interval\", \"$window\", \"$injector\", \"lodash\", \"moment\", \"app.core.appSettings\", \"app.core.models.messages.messageList\"];\n\n function errorService($log, notifier, $interval, $window, $injector, _, moment, appSettings, messageList) {\n var i18n;\n\n var isOfflineError = function isOfflineError(error) {\n return error.status === 0;\n };\n\n var isUnauthorised = function isUnauthorised(error) {\n return error.status === 401;\n };\n\n var isServerError = function isServerError(error) {\n return error.status === 500;\n };\n\n addRemoveStaleMessagesAfterPeriodHandler();\n return {\n processSuccess: processSuccess,\n processError: processError,\n logResponse: logResponse\n }; /////////////////////\n\n function addRemoveStaleMessagesAfterPeriodHandler() {\n var fiveMinutes = 1000 * 60 * 5;\n $interval(messageList.removeStale, fiveMinutes);\n }\n\n function processSuccess() {\n messageList.remove(isOfflineError);\n }\n\n function processError(response) {\n if (!i18n) {\n i18n = $injector.get(\"i18n\");\n } // offline\n\n\n if (isOfflineError(response) || isNaN(response.status)) {\n var title = i18n.i10n(\"errors.server.inaccessible.title\");\n var message = i18n.i10n(\"errors.server.inaccessible.message\");\n var status = 0;\n messageList.update(isOfflineError) || messageList.addFatal(title, message, status);\n } // unexpected server error\n else if (isServerError(response)) {\n var _title = i18n.i10n(\"errors.server.exception.title\");\n\n var _message = i18n.i10n(\"errors.server.exception.message\");\n\n messageList.update(isServerError) || messageList.addError(_title, _message, response.status);\n } // unauthorised\n else if (isUnauthorised(response)) {\n appSettings.forgetCompanyAndFacility();\n $window.location.href = appSettings.loginUri;\n } // unhandled\n else {\n var getErrorMessage = function getErrorMessage() {\n if (response.data && _.isArray(response.data.messages) && response.data.messages.length) {\n var messages = _.map(response.data.messages, \"content\");\n\n return messages.join(\"
    \");\n }\n\n return i18n.i10n(\"errors.server.error.message\");\n };\n\n var _title2 = i18n.i10n(\"errors.server.error.title\");\n\n var errorWithStatus = function errorWithStatus(_ref) {\n var status = _ref.status;\n return status === response.status;\n };\n\n messageList.update(errorWithStatus) || messageList.addError(_title2, getErrorMessage(), response.status);\n }\n\n response.handled = true;\n logResponse(response);\n }\n\n function logResponse(response) {\n try {\n var statusText = response.statusText || \"HTTP request status was not set.\";\n\n if (response.data !== null && typeof response.data === \"object\") {\n response.data.stackTrace = response.data.stackTrace && response.data.stackTrace.replace(\"\\r\\n\", \"\\n\");\n }\n\n var error = \"Unable to complete request:\\n\\\"\".concat(response.config.method, \" \").concat(response.config.url, \"\\\" | \").concat(response.status, \" (\").concat(statusText, \")\\n Request Headers:\\n\").concat(JSON.stringify(response.config.headers, null, 4), \"\\n Request Data:\\n\").concat(JSON.stringify(response.config.data, null, 4), \"\\n Response:\\n\").concat(JSON.stringify(response.data, null, 4), \"\\n\");\n $log.fatal(error);\n $window.LogRocket && window.LogRocket.track(\"on-screen-error\");\n $window.LogRocket && window.LogRocket.captureMessage(error);\n } catch (exception) {\n $log.fatal(exception);\n $window.LogRocket && window.LogRocket.captureException(exception);\n $window.LogRocket && window.LogRocket.track(\"on-screen-error\");\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.exportService\", exportService);\n exportService.$inject = [\"$http\", \"app.core.appSettings\"];\n\n function exportService($http, appSettings) {\n return {\n exportPdf: exportPdf,\n exportPng: exportPng\n }; ////////////\n\n function success(response) {\n return response;\n }\n\n function buildUrl(path) {\n return \"\".concat(appSettings.webApiHostUri, \"export/\").concat(path);\n }\n /*\r\n options:\r\n waitTimeMs - how long to wait before a screenshot gets taken\r\n waitForSelector - selector to wait for.\r\n selectorTimeOutMs - time to wait for selector before assuming the process failed.\r\n isLandscape\r\n */\n\n\n function exportPdf(url, options) {\n var postUrl = buildUrl(\"pdf\");\n var postData = {\n url: url,\n waitTimeMs: 1000,\n isLandscape: true\n };\n postData = _extends({}, postData, options);\n return $http.post(postUrl, postData, {\n responseType: \"blob\"\n }).then(success).catch(angular.noop);\n }\n /*\r\n options are:\r\n waitTimeMs - how long to wait before a screenshot gets taken\r\n waitForSelector - selector to wait for.\r\n selectorTimeOutMs - time to wait for selector before assuming the process failed.\r\n */\n\n\n function exportPng(url, options) {\n var postUrl = buildUrl(\"png\");\n var postData = {\n url: url,\n waitTimeMs: 1000\n };\n postData = _extends({}, postData, options);\n return $http.post(postUrl, postData, {\n responseType: \"blob\"\n }).then(success).catch(angular.noop);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.gisModelService\", gisModelService);\n gisModelService.$inject = [\"lodash\", \"$q\", \"app.core.providers.gisModelDataProvider\", \"app.core.models.jobs.ModellingJob\", \"app.core.models.legends.legendFactory\"];\n\n function gisModelService(_, $q, gisModelDataProvider, ModellingJob, legendFactory) {\n return {\n getIntervals: getIntervals,\n getModelDataSet: getModelDataSet,\n getAllModels: getAllModels,\n getModellingJobs: getModellingJobs,\n getModelDataAvailability: getModelDataAvailability,\n getDiscreteReceptorData: getDiscreteReceptorData,\n dismissJob: gisModelDataProvider.dismissJob,\n dismissJobs: gisModelDataProvider.dismissJobs,\n getStatus: gisModelDataProvider.getStatus,\n startTestJob: gisModelDataProvider.startTestJob\n };\n\n function getIntervals() {\n return gisModelDataProvider.getIntervals().then(function (intervals) {\n _.forEach(intervals, function (interval) {\n _.forEach(interval.models, function (model) {\n model.isSelected = false;\n model.legend = legendFactory.create(model.legend);\n });\n });\n\n return intervals;\n });\n }\n\n function getModelDataSet(models, dateFrom, dateTo) {\n return gisModelDataProvider.getModelDataSet(models, dateFrom, dateTo).then(function (result) {\n var response = result;\n var activeJobs = {};\n\n _.forEach(response.activeJobsForGisModels, function (job, modelId) {\n activeJobs[modelId] = ModellingJob.createFromJobData(job);\n });\n\n response.activeJobsForGisModels = activeJobs;\n return response;\n });\n }\n\n function getAllModels() {\n return getIntervals().then(function (intervals) {\n return _.chain(intervals).map(flattenModels).flatten().value();\n });\n }\n\n function flattenModels(interval) {\n return _.map(interval.models, function (model) {\n return {\n modelId: model.modelId,\n name: model.modelName,\n durationInMinutes: interval.durationInMinutes\n };\n });\n }\n\n function getModellingJobs() {\n return gisModelDataProvider.getModellingJobs().then(function (result) {\n return _.chain(result).map(function (job) {\n return ModellingJob.createFromJobData(job);\n }).sortBy(function (job) {\n if (job.hasCompleted) {\n return job.fromMillis;\n } else if (job.isQueued) {\n return 0;\n }\n\n return 0 - job.progress;\n }).value();\n });\n }\n\n function getModelDataAvailability(modelId) {\n if (!modelId) {\n throw new Error(\"modelId is not defined\");\n }\n\n return gisModelDataProvider.getModelDataAvailability(modelId).then(function (result) {\n return {\n latestTime: new Date(result.utcLatestTime)\n };\n });\n }\n\n function getDiscreteReceptorData(modelId, fromDateTime, toDateTime) {\n if (!modelId) {\n throw new Error(\"modelId is not defined\");\n }\n\n return gisModelDataProvider.getDiscreteReceptorData(modelId, fromDateTime, toDateTime).then(function (data) {\n return data && _.mapValues(data, function (item) {\n return item.map(mapDiscreteReceptorData);\n });\n }); ///////////////////\n\n function mapDiscreteReceptorData(discreteReceptorData) {\n var monitor = discreteReceptorData.monitor,\n processVariable = discreteReceptorData.processVariable;\n return {\n id: monitor.id,\n name: monitor.name,\n latitude: monitor.latitude,\n longitude: monitor.longitude,\n monitorType: monitor.monitorType && _.camelCase(monitor.monitorType) || null,\n processVariable: mapProcessVariableData(processVariable),\n modelId: modelId\n };\n }\n\n function mapProcessVariableData(processVariable) {\n if (!processVariable) {\n return null;\n }\n\n var result = {\n id: processVariable.id,\n name: processVariable.name,\n valueInDisplayUnit: getValue(processVariable),\n isValueStale: processVariable.isValueStale,\n hasValueFlatlined: processVariable.hasValueFlatlined,\n thresholdColour: getThresholdColour(processVariable),\n hasValueExceededFirstThreshold: processVariable.hasValueExceededFirstThreshold,\n units: processVariable.units,\n displayName: processVariable.displayName\n };\n result.hasDisplayableValue = !!(result.units && !result.isValueStale && _.isNumber(result.valueInDisplayUnit));\n return result; ////////////////////\n\n function getValue(processVariable) {\n if (!processVariable || processVariable.isValueStale || isNaN(processVariable.valueInDisplayUnit)) {\n return null;\n }\n\n return processVariable.valueInDisplayUnit;\n }\n\n function getThresholdColour(processVariable) {\n if (!processVariable || processVariable.isValueStale || processVariable.valueInDisplayUnit === null) {\n return \"rgb(204, 204, 204)\";\n }\n\n return processVariable.thresholdColour;\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.incidentIntelligenceService\", incidentIntelligenceService);\n incidentIntelligenceService.$inject = [\"$q\", \"leafletLib\", \"app.core.models.mapping.dataPointType\", \"app.core.models.mapping.dataPointFactory\", \"app.core.providers.incidentIntelligenceDataProvider\"];\n\n function incidentIntelligenceService($q, L, dataPointType, dataPointFactory, dataProvider) {\n return {\n getPathModel: getPathModel,\n getSummaryLookupValues: dataProvider.getSummaryLookupValues,\n getTicketSummaryLocations: dataProvider.getTicketSummaryLocations\n }; ////////////////////\n\n function getPathModel(ticketId, ticketActivityId) {\n return dataProvider.getPathModel(ticketId, ticketActivityId).then(mapResult);\n\n function mapResult(pathData) {\n var result = {\n primaryTrack: createDataPoint(pathData.primaryTrack)\n };\n var firstStep = result.primaryTrack.data.length && result.primaryTrack.data[0];\n\n if (!firstStep) {\n return $q.when(result);\n }\n\n var firstPoint = new L.LatLng(firstStep.latitude, firstStep.longitude);\n var startPoint = new L.LatLng(pathData.startPoint.latitude, pathData.startPoint.longitude);\n result.isForwardTrajectory = firstPoint.equals(startPoint);\n var lastStep = result.primaryTrack.data[result.primaryTrack.data.length - 1];\n result.startTime = result.isForwardTrajectory ? new Date(firstStep.timeMillis) : new Date(lastStep.timeMillis);\n return $q.when(result); ////////////////////\n\n function createDataPoint(track) {\n var dataPoint = dataPointFactory.create(dataPointType.path, track.gisTrackDataTimeSteps);\n return dataPoint;\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.locationService\", locationService);\n locationService.$inject = [\"$q\", \"$window\", \"$state\", \"$log\", \"lodash\", \"i18n\", \"app.core.appSettings\", \"app.core.services.companyService\", \"app.core.services.securityService\"];\n\n function locationService($q, $window, $state, $log, _, i18n, appSettings, companyService, securityService) {\n var pageHeading, pageHeadingParameters;\n var exitPoint = {};\n var service = {\n bindPageHeading: function bindPageHeading() {\n pageHeading = i18n.i10n(\"\".concat($state.$current.name, \".route.heading\"), pageHeadingParameters || {});\n },\n updatePageHeading: function updatePageHeading() {\n var pageHeadingParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n pageHeadingParameters = pageHeadingParams;\n service.bindPageHeading();\n },\n updateExitPoint: function updateExitPoint(exitState, stateParameters, i18nParameters) {\n exitPoint = {\n exit: function exit() {\n return $state.go(exitState, stateParameters);\n },\n text: i18n.i10n(\"\".concat($state.$current.name, \".route.exitText\"), i18nParameters)\n };\n $log.debug(\"setting exit point - \".concat(exitState, \" : \").concat(exitPoint.text));\n },\n clearExitPoint: function clearExitPoint() {\n return exitPoint = null;\n },\n\n get pageHeading() {\n return pageHeading;\n },\n\n get exitPoint() {\n return exitPoint;\n },\n\n goHome: goHome,\n logout: logout\n };\n return service; //////////\n\n function goHome() {\n var companyAlias = appSettings.site.company.alias;\n var facilityAlias = appSettings.site.facility.alias;\n\n if (appSettings.isGuestUser) {\n return logout();\n }\n\n companyService.getCompanies({\n refresh: true\n }).then(ensureCompanyExists).then(goToCompanyHome).catch(logout);\n\n function ensureCompanyExists(validCompanies) {\n return $q(function (resolve, reject) {\n companyService.canAccessFacility(companyAlias, facilityAlias).then(function (canAccessFacility) {\n if (canAccessFacility) {\n return resolve({\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n\n var companyToSwitchTo = _.find(validCompanies, function (company) {\n return company.facilities.length;\n });\n\n if (companyToSwitchTo) {\n return resolve({\n companyAlias: companyToSwitchTo.alias,\n facilityAlias: companyToSwitchTo.facilities[0].alias\n });\n }\n\n reject();\n });\n });\n }\n\n function goToCompanyHome(companyAndFacility) {\n $state.go(\"app.dashboard\", companyAndFacility, {\n reload: true\n });\n }\n }\n\n function logout() {\n return securityService.logout();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.mappingService\", mappingService);\n mappingService.$inject = [\"lodash\", \"app.core.providers.mappingDataProvider\", \"app.core.appSettings\", \"leafletLib\"];\n var sourcesKmlFileName = \"sources.kml\";\n\n function mappingService(_, endpointProvider, appSettings, L) {\n return {\n getKmls: getKmls,\n getEmissionSourceKml: getEmissionSourceKml,\n getTileLayers: getTileLayers,\n getMapCredits: getMapCredits,\n getElevation: getElevation,\n getActiveTemporalEventGroups: getActiveTemporalEventGroups\n };\n\n function getKmls() {\n return endpointProvider.getKmlDataSet(null, [sourcesKmlFileName]);\n }\n\n function getEmissionSourceKml() {\n return endpointProvider.getKmlDataSet([sourcesKmlFileName], null).then(function (kmls) {\n return kmls.length === 1 ? kmls[0] : null;\n });\n }\n\n function getTileLayers() {\n return endpointProvider.getTileLayers().then(function (data) {\n return _.map(data, function (config) {\n var mapBounds = new L.LatLngBounds(new L.LatLng(config.bounds[1], config.bounds[0]), new L.LatLng(config.bounds[3], config.bounds[2]));\n return {\n minZoom: config.minZoom,\n maxZoom: config.maxZoom,\n bounds: mapBounds,\n opacity: config.opacity,\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n facilityCode: appSettings.site.facility.facilityCode,\n name: config.name\n };\n });\n });\n }\n\n function getMapCredits() {\n return endpointProvider.getMapCredits();\n }\n\n function getElevation(latitude, longitude) {\n return endpointProvider.getElevationAtPoint(latitude, longitude);\n }\n\n function getActiveTemporalEventGroups(activeAtDateTime) {\n if (!_.isDate(activeAtDateTime)) {\n throw new Error(\"The activeAtDateTime must be a Date.\");\n }\n\n return endpointProvider.getActiveTemporalEventGroups(activeAtDateTime);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n(function () {\n \"use strict\";\n\n var module = angular.module(\"app.core\");\n\n var MathService =\n /*#__PURE__*/\n function () {\n function MathService() {\n _classCallCheck(this, MathService);\n\n this.floatMaxValue = 3.4e+38;\n this.floatMinValue = -this.floatMaxValue; //corresponds to ProcessVariableThresholdEntityConverter.MinBaseThresholdValue\n } // this function rounds a number to at-most the provided number of decimal places.\n //\n // e.g. 2 decimal places\n //\n // 10 -> 10\n // 10.1 -> 10.1\n // 10.12 -> 10.12\n // 10.005 -> 10.01\n // 10.1234 -> 10.12\n\n\n _createClass(MathService, [{\n key: \"round\",\n value: function round(number) {\n var decimalPlaces = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n return +(Math.round(\"\".concat(number, \"e+\").concat(decimalPlaces)) + \"e-\".concat(decimalPlaces));\n }\n }]);\n\n return MathService;\n }();\n\n MathService.$inject = [];\n module.service(\"app.core.services.mathService\", MathService);\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.monitoringService\", monitoringService);\n monitoringService.$inject = [\"$q\", \"lodash\", \"app.core.requestManager\", \"app.core.providers.monitoringDataProvider\", \"app.core.services.dateTimeService\", \"app.core.services.configuration.monitoringService\"];\n\n function monitoringService($q, _, requestManager, endpointProvider, dateTimeService, configurationMonitoringService) {\n return {\n getMonitorsByType: getMonitorsByType,\n getMetSummary: getMetSummary,\n getMonitorData: getMonitorData,\n getMonitorSensorData: getMonitorSensorData,\n getSensorDataSeries: getSensorDataSeries,\n getGraphVariables: getGraphVariables,\n getMonitorTypes: getMonitorTypes,\n getMonitorDataAlarms: getMonitorDataAlarms,\n getSourceAreaData: getSourceAreaData\n };\n\n function getMonitorsByType() {\n return endpointProvider.getMonitorsByType().then(function (monitorsByType) {\n // For now, we don't want discrete receptors to show up in ES2, so we'll just pretend they don't exist...\n delete monitorsByType.discreteReceptor;\n\n _.forEach(monitorsByType, function (monitorGrouping, monitorType) {\n if (monitorGrouping.measurementGroups && monitorGrouping.measurementGroups.length > 1) {\n monitorGrouping.measurementGroups = _.chain(monitorGrouping.measurementGroups).filter(function (mg) {\n return !mg.parentId;\n }).sortBy(function (mg) {\n return mg.defaultOrder;\n }).value();\n }\n\n var measurementGroup = _.head(monitorGrouping.measurementGroups);\n\n monitorsByType[monitorType].selectedMeasurementGroupId = measurementGroup ? measurementGroup.id : null;\n monitorsByType[monitorType].icon = configurationMonitoringService.getMonitorTypeIcon(monitorType);\n });\n\n return monitorsByType;\n });\n }\n\n function getMetSummary(dateTime) {\n dateTime = dateTime || new Date();\n return requestManager.enqueue(function () {\n return endpointProvider.getMetSummary(dateTime);\n }).onQueue(getMetSummary.name);\n }\n\n function getSourceAreaData(dateTime) {\n dateTime = dateTime || new Date();\n return requestManager.enqueue(function () {\n return endpointProvider.getSourceAreaData(dateTime).then(function (processData) {\n return processData.map(mapSourceAreaData);\n });\n }).onQueue(\"\".concat(getSourceAreaData.name));\n\n function mapSourceAreaData(sourceAreaData) {\n var _sourceAreaData$proce = sourceAreaData.process,\n id = _sourceAreaData$proce.id,\n name = _sourceAreaData$proce.name,\n points = _sourceAreaData$proce.points,\n dataPoints = sourceAreaData.dataPoints;\n return {\n id: id,\n name: name,\n dataPoints: dataPoints.map(mapProcessVariableData),\n latlngs: _.map(points, function (point) {\n return {\n lat: point.latitude,\n lng: point.longitude\n };\n })\n };\n }\n }\n\n function getMonitorData(monitorIds, measurementGroupId, dateTime) {\n if (!_.isArray(monitorIds)) {\n throw new Error(\"monitorIds is not defined\");\n }\n\n dateTime = dateTime || new Date();\n return requestManager.enqueue(function () {\n return endpointProvider.getMonitorData(monitorIds, measurementGroupId, dateTime).then(function (monitorData) {\n return monitorData.map(mapMonitorData);\n });\n }).onQueue(\"\".concat(getMonitorData.name, \"-\").concat(measurementGroupId)); ///////////////////\n\n function mapMonitorData(monitorData) {\n var monitor = monitorData.monitor;\n return {\n id: monitor.id,\n name: monitor.name,\n latitude: monitor.latitude,\n longitude: monitor.longitude,\n monitorType: monitor.monitorType && _.camelCase(monitor.monitorType) || null,\n processVariable: mapProcessVariableData(monitorData.processVariable),\n influenceArc: monitorData.influenceArc,\n fencelineLocations: monitor.fencelineLocations\n };\n }\n }\n\n function mapProcessVariableData(processVariable) {\n if (!processVariable) {\n return null;\n }\n\n var result = {\n id: processVariable.id,\n name: processVariable.name,\n valueInDisplayUnit: getValue(processVariable),\n valueTime: dateTimeService.roundUpToClosestMinute(new Date(processVariable.utcDateTimeEnd)),\n isValueStale: processVariable.isValueStale,\n hasValueFlatlined: processVariable.hasValueFlatlined,\n thresholdColour: getThresholdColour(processVariable),\n hasValueExceededFirstThreshold: processVariable.hasValueExceededFirstThreshold,\n units: processVariable.units,\n displayName: processVariable.displayName,\n numericScale: processVariable.numericScale\n };\n result.hasDisplayableValue = !!(result.units && !result.isValueStale && _.isNumber(result.valueInDisplayUnit));\n return result; /////////////\n\n function getValue(processVariable) {\n if (!processVariable || processVariable.isValueStale || isNaN(processVariable.valueInDisplayUnit)) {\n return null;\n }\n\n return processVariable.valueInDisplayUnit;\n }\n\n function getThresholdColour(processVariable) {\n if (!processVariable || processVariable.isValueStale || processVariable.valueInDisplayUnit === null) {\n return \"rgb(204, 204, 204)\";\n }\n\n return processVariable.thresholdColour;\n }\n }\n\n function getGraphVariables(monitorId) {\n return endpointProvider.getGraphVariables(monitorId);\n }\n\n function getMonitorSensorData(monitorId, processVariables, dateTime) {\n return endpointProvider.getMonitorSensorData(monitorId, processVariables, dateTime).then(function (graphVariables) {\n return graphVariables.map(mapProcessVariableData);\n });\n }\n\n function getSensorDataSeries(startDateTime, endDateTime, processVariableId) {\n return endpointProvider.getSensorDataSeries(startDateTime, endDateTime, processVariableId).then(processResponse);\n\n function processResponse(dataSet) {\n dataSet.values = dataSet.values.map(function (value) {\n return {\n valueInDisplayUnit: value.valueInDisplayUnit,\n valueInBaseUnit: value.valueInBaseUnit,\n date: dateTimeService.roundUpToClosestMinute(new Date(value.utcDateTimeEnd))\n };\n });\n return dataSet;\n }\n }\n\n function getMonitorTypes() {\n return endpointProvider.getMonitorTypes().then(function (monitorTypes) {\n return monitorTypes.map(_.camelCase);\n });\n }\n\n function getMonitorDataAlarms() {\n var monitorTypes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var samplingTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n if (!(_.isArray(monitorTypes) && monitorTypes.length)) {\n return $q.reject(\"No monitor types specified.\");\n }\n\n var monitorTypesToRequest = monitorTypes.map(_.capitalize);\n return endpointProvider.getMonitorDataAlarms(monitorTypesToRequest, samplingTime).then(processMonitorDataAlarms); ////////////////////\n\n function processMonitorDataAlarms(monitorDataAlarms) {\n var monitorsByType = _.chain(monitorDataAlarms).groupBy(function (alarm) {\n return alarm.monitorType;\n }).map(processMonitorsByType).value();\n\n _.forEach(monitorTypes, function (monitorType) {\n var hasAlarms = _.find(monitorsByType, {\n monitorType: monitorType\n });\n\n if (!hasAlarms) {\n monitorsByType.push({\n monitorType: monitorType,\n monitors: []\n });\n }\n });\n\n return monitorsByType; ////////////////////\n\n function processMonitorsByType(monitors, monitorType) {\n return {\n monitorType: _.camelCase(monitorType),\n monitors: _.map(monitors, processMonitor)\n };\n }\n\n function processMonitor(monitor) {\n return {\n id: monitor.monitorId,\n name: monitor.monitorName,\n alarms: _.map(monitor.monitorData, processAlarm)\n };\n }\n\n function processAlarm(alarm) {\n return {\n id: alarm.id,\n name: alarm.displayName || alarm.name,\n isStale: alarm.isValueStale,\n valueInDisplayUnit: alarm.valueInDisplayUnit && alarm.valueInDisplayUnit.toFixed(1) || null,\n units: alarm.units,\n thresholdColour: alarm.thresholdColour\n };\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.reportsService\", reportsService);\n reportsService.$inject = [\"lodash\", \"app.core.appSettings\", \"app.core.providers.reportsDataProvider\", \"app.core.datetime.timeZoneDateTime\"];\n\n function reportsService(_, appSettings, dataProvider, timeZoneDateTime) {\n return {\n getListOfReports: getListOfReports,\n getAlertPointReports: getAlertPointReports,\n getProcessDataReportLookupValues: dataProvider.getProcessDataReportLookupValues,\n getProcessDataReportColumns: dataProvider.getProcessDataReportColumns,\n getProcessDataReport: getProcessDataReport,\n exportProcessDataReport: exportProcessDataReport\n }; //////////////\n\n function getListOfReports() {\n return dataProvider.getListOfReports().then(function (collection) {\n var javaScriptReports = _.map(collection.javaScriptReports, mapJavaScriptReport);\n\n var powerBiReports = _.map(collection.powerBiReports, mapPowerBiReport);\n\n var legacyReports = _.chain(collection.legacyReports).filter(function (report) {\n return report.name;\n }).map(mapLegacyReport).value();\n\n return javaScriptReports.concat(powerBiReports).concat(legacyReports); ////////////////////\n\n function mapLegacyReport(report) {\n // TODO: mcross (2016/07/01) - consider making this data driven\n var isProcessDataReport = report.reportType === \"ProcessReport\";\n\n if (isProcessDataReport) {\n report.isEs2Report = true;\n report.uri = \"app.reporting.processData\";\n report.params = {\n reportId: report.id\n };\n } else {\n var linkSafeName = report.name.replace(/\\s+/g, \"_\");\n report.uri = \"\".concat(appSettings.mvcHostUri).concat(appSettings.site.facility.es1RouteName, \"/Reports/_\").concat(linkSafeName);\n }\n\n return report;\n }\n });\n }\n\n function getAlertPointReports() {\n return dataProvider.getAlertPointReports().then(function (reports) {\n return reports && reports.map(function (report) {\n return mapJavaScriptReport(report);\n });\n }).catch(function (response) {\n response.handled = true;\n return null;\n });\n }\n\n function getProcessDataReport(processId, startTime, endTime, searchCriteria) {\n return dataProvider.getProcessDataReport(processId, startTime, endTime, searchCriteria).then(function (report) {\n _.forEach(report.data, function (dataForEndTime) {\n // Dates are returned as a string; we need to convert these to an actual date so that\n // kendo can render them properly.\n var localDateTime = new Date(dataForEndTime.key);\n dataForEndTime.key = timeZoneDateTime.convertDateTimeToFacilityTimeZone(localDateTime); // The data points themselves are returned unrounded; to maintain consistency with the old process\n // data report, we need to round the figures to 1 decimal place.\n\n _.forEach(dataForEndTime.valueInDisplayUnit, function (value, processVariableId) {\n // Use bitwise shift-left to cast to an int (see: http://stackoverflow.com/a/7343175/127497)\n dataForEndTime[processVariableId] = (value * 10 << 0) * 0.1; // eslint-disable-line no-bitwise\n });\n });\n\n return report;\n });\n }\n\n function exportProcessDataReport(processId, startTime, endTime, searchCriteria) {\n return dataProvider.exportProcessDataReport(processId, startTime, endTime, searchCriteria);\n } ////////////////////\n\n\n function mapPowerBiReport(report) {\n var _appSettings$site = appSettings.site,\n company = _appSettings$site.company,\n facility = _appSettings$site.facility;\n report.uri = \"\".concat(appSettings.reportsAppHostUri).concat(company.alias, \"/\").concat(facility.alias, \"/\").concat(report.reportAlias);\n return report;\n }\n\n function mapJavaScriptReport(report) {\n var _appSettings$site2 = appSettings.site,\n company = _appSettings$site2.company,\n facility = _appSettings$site2.facility;\n report.uri = \"\".concat(appSettings.reportsAppHostUri).concat(company.alias, \"/\").concat(facility.alias, \"/\").concat(report.reportAlias);\n return report;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.securityService\", securityService);\n securityService.$inject = [\"$window\", \"lodash\", \"app.core.appSettings\", \"app.core.providers.securityDataProvider\"];\n\n function securityService($window, _, appSettings, securityDataProvider) {\n var accessControlPromise;\n return {\n getAccessControls: getAccessControls,\n queryApiCredentials: queryApiCredentials,\n getApiCredential: getApiCredential,\n createApiCredential: createApiCredential,\n updateApiCredential: updateApiCredential,\n getPasswordExpirationStatus: getPasswordExpirationStatus,\n setPasswordExpirationConfirmed: setPasswordExpirationConfirmed,\n logout: logout\n };\n\n function getAccessControls(companyId, facilityId) {\n accessControlPromise = securityDataProvider.getAccessControls(companyId, facilityId).then(function (response) {\n return response;\n });\n return accessControlPromise;\n }\n\n function queryApiCredentials(monitorId, searchCriteria) {\n return securityDataProvider.queryApiCredentials(monitorId, searchCriteria).then(function (result) {\n result.data = _.map(result.data, mapUtcDateTimesToDateTimes);\n return result;\n });\n }\n\n function getApiCredential(credentialId) {\n return securityDataProvider.getApiCredential(credentialId).then(mapUtcDateTimesToDateTimes);\n }\n\n function createApiCredential(credential) {\n return securityDataProvider.createApiCredential(mapDateTimesToUtcDateTimes(credential));\n }\n\n function updateApiCredential(credential) {\n return securityDataProvider.updateApiCredential(mapDateTimesToUtcDateTimes(credential)).then(function () {\n return credential.id;\n });\n }\n\n function getPasswordExpirationStatus() {\n return securityDataProvider.getPasswordExpirationStatus();\n }\n\n function setPasswordExpirationConfirmed() {\n return securityDataProvider.setPasswordExpirationConfirmed();\n }\n\n function mapDateTimesToUtcDateTimes(credential) {\n credential.utcLastUsedTime = credential.lastUsedTime && credential.lastUsedTime.toISOString();\n credential.utcGeneratedTime = credential.generatedTime && credential.generatedTime.toISOString();\n credential.utcDeactivatedTime = credential.deactivatedTime && credential.deactivatedTime.toISOString();\n delete credential.lastUsedTime;\n delete credential.generatedTime;\n delete credential.deactivatedTime;\n return credential;\n }\n\n function mapUtcDateTimesToDateTimes(credential) {\n credential.lastUsedTime = credential.utcLastUsedTime !== null ? new Date(credential.utcLastUsedTime) : null;\n credential.generatedTime = credential.utcGeneratedTime !== null ? new Date(credential.utcGeneratedTime) : null;\n credential.deactivatedTime = credential.utcDeactivatedTime !== null ? new Date(credential.utcDeactivatedTime) : null;\n delete credential.utcLastUsedTime;\n delete credential.utcGeneratedTime;\n delete credential.utcDeactivatedTime;\n return credential;\n }\n\n function logout() {\n return securityDataProvider.logout().then(function (loginUrl) {\n appSettings.forgetCompanyAndFacility();\n $window.location.href = loginUrl;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.settingsService\", settingsService);\n settingsService.$inject = [\"ipCookie\", \"lodash\", \"$q\", \"$state\", \"app.core.appSettings\", \"moment\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.userService\"];\n\n function settingsService(cookie, lodash, $q, $state, appSettings, moment, timeZoneDateTime, userService) {\n var validDateRegex = /(\\d{4})-(\\d{2})-(\\d{2})(T(\\d{2}):(\\d{2})){0,1}$/; // i.e. YYYY-MM-DDTHH:mm\n\n return {\n getSupportedLanguages: getSupportedLanguages,\n setLanguage: setLanguage,\n getSelectedLanguage: getSelectedLanguage,\n getSampleDateTime: getSampleDateTime\n };\n\n function getSupportedLanguages() {\n var supported = {\n 'en': \"English\",\n 'es': \"Espa\\xF1ol\",\n 'fr': \"Fran\\xE7ais\",\n 'vi': \"Ti\\u1EBFng Vi\\u1EC7t\",\n 'zh': \"\\u4E2D\\u6587\",\n 'lt': \"Lietuvis\"\n };\n var explicitlyAllowed = (appSettings.languagesExplicitlyAllowed || \"\").split(\",\").filter(function (code) {\n return code !== \"\";\n }).map(function (code) {\n return code.trim().toLowerCase();\n }); // Either an explicit set of allowed languages is supplied, or we allow all supported\n\n if (explicitlyAllowed.length === 0) {\n return supported;\n } else {\n return lodash.pickBy(supported, function (value, key) {\n return explicitlyAllowed.indexOf(key) !== -1;\n });\n }\n }\n\n function getSelectedLanguage() {\n return userService.getLocale();\n }\n\n function setLanguage(language) {\n return userService.getUserDetails().then(function (user) {\n user.locale = language;\n return userService.updateUserDetails(user);\n });\n }\n\n function getSampleDateTime() {\n if (!$state.params.dateTime) {\n return new Date();\n }\n\n if ($state.params.dateTime.match(validDateRegex)) {\n var dateTimeMoment = moment($state.params.dateTime);\n\n if (dateTimeMoment.isValid()) {\n return timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(dateTimeMoment.toDate());\n }\n }\n\n throw new Error(\"The dateTime query parameter must be a valid date and time of the format: YYYY-MM-DDTHH:mm\");\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.services.userService\", userService);\n userService.$inject = [\"app.core.providers.userDataProvider\", \"app.core.appSettings\"];\n\n function userService(userDataProvider, appSettings) {\n var userPromise;\n return {\n getUserDetails: getUserDetails,\n updatePassword: userDataProvider.updatePassword,\n updateUserDetails: updateUserDetails,\n getLocale: getLocale\n };\n\n function updateUserDetails(userDetails) {\n return userDataProvider.updateUserDetails(userDetails).then(function () {\n appSettings.user = userDetails;\n });\n }\n\n function getUserDetails() {\n var forceRefresh = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n if (userPromise && !forceRefresh) {\n return userPromise;\n }\n\n return userPromise = userDataProvider.getUserDetails();\n }\n\n function getLocale() {\n return userDataProvider.getLocale();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.signalR.alerts.alertStatusHub\", alertStatusHub);\n alertStatusHub.$inject = [\"$timeout\", \"postal\", \"app.core.appSettings\", \"app.core.signalR.Hub\", \"app.core.models.alerts.WebAlert\", \"app.core.signalR.alerts.events\"];\n\n function alertStatusHub($timeout, postal, appSettings, Hub, WebAlert, alertEvents) {\n var hubName = \"alertStatusHub\";\n var channel = postal.channel(alertEvents.channelName);\n var hub = new Hub({\n hubName: hubName,\n canAccess: function canAccess(accessControls) {\n return accessControls[\"app.alerts\"];\n },\n methods: [\"subscribeAlerts\", \"unsubscribeAlerts\"],\n listeners: {\n notify: onNotify,\n dismiss: onDismiss\n },\n joinFacility: joinFacility,\n leaveFacility: leaveFacility\n });\n return {\n name: hubName,\n connect: hub.connect\n };\n\n function onNotify(alert) {\n alert = new WebAlert(alert.id, alert.alertEventSourceId, alert.name, alert.message, alert.level, new Date(alert.utcTriggeredTime), new Date(alert.utcSentTime));\n publish(alertEvents.topics.notify, alert);\n }\n\n function onDismiss(alertId) {\n publish(alertEvents.topics.dismiss, alertId);\n }\n\n function publish(topic, payload) {\n $timeout(function () {\n return channel.publish(topic, payload);\n });\n }\n\n function joinFacility(signalRHub, facility) {\n return signalRHub.subscribeAlerts(facility, appSettings.userId);\n }\n\n function leaveFacility(signalRHub, facility) {\n return signalRHub.unsubscribeAlerts(facility, appSettings.userId);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.signalR.alerts.events\", getEvents());\n\n function getEvents() {\n return {\n channelName: \"app.core.signalR.alerts\",\n topics: {\n notify: \"notify\",\n dismiss: \"dismiss\"\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.signalR.alerts.state\", {\n alerts: []\n });\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.signalR.Hub\", hubFactory).factory(\"app.core.signalR.HubReconnectionManager\", hubReconnectionManagerFactory);\n hubFactory.$inject = [\"$log\", \"$q\", \"jQuery\", \"lodash\", \"postal\", \"Hub\", \"app.core.signalR.HubReconnectionManager\", \"app.core.appSettings\", \"app.core.events\"];\n\n function hubFactory($logger, $q, $, _, postal, SignalRHub, HubReconnectionManager, appSettings, coreEvents) {\n return function Hub(configuration) {\n var hub, subscription;\n var subscribedFacility = null;\n var subscribedFacilityPromise = $q.when(true);\n var $log;\n var reconnectionManager = null;\n activate(); ///////////////////\n\n function activate() {\n if (configuration === null || configuration === undefined) {\n throw new Error(\"The hub configuration options must be provided.\");\n }\n\n if (configuration.hubName === null || configuration.hubName === undefined) {\n throw new Error(\"The hub configuration `hubName` must be provided.\");\n }\n\n if (configuration.canAccess && !_.isFunction(configuration.canAccess)) {\n throw new Error(\"The hub configuration `canAccess` must be a function.\");\n }\n\n configuration.canAccess = configuration.canAccess || function () {\n return false;\n };\n\n $log = new HubLogWrapper($logger, configuration.hubName);\n }\n\n this.connect = function () {\n if (subscription || hub) {\n return;\n }\n\n $log.debug(\"Connecting: \".concat(configuration.hubName));\n hub = new SignalRHub(configuration.hubName, {\n name: configuration.hubName,\n rootPath: appSettings.signalRHostUri,\n logging: false,\n useSharedConnection: true,\n stateChanged: onConnectionStateChanged,\n errorHandler: onError,\n methods: configuration.methods || [],\n listeners: configuration.listeners || {},\n queryParams: {\n apiKey: appSettings.apiKey\n }\n });\n subscription = postal.subscribe({\n channel: coreEvents.channelName,\n topic: coreEvents.topics.accessControlsUpdated,\n callback: updateSubscribedFacility\n });\n };\n\n this.invoke = function (method) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n if (hub === null || hub === undefined || !_.isFunction(hub[method])) {\n throw new Error(\"The hub method is not available.\");\n }\n\n hub.promise.then(function () {\n hub[method].apply(hub, args);\n });\n }; /////////////////////\n\n\n function updateSubscribedFacility() {\n if (!isHubConnected()) {\n return;\n }\n\n var currentFacility = appSettings.site.facility.alias.toLowerCase();\n\n if (subscribedFacility === currentFacility) {\n return;\n }\n\n var updateSubscription = function updateSubscription() {\n return $q(function (resolve) {\n var facilityToLeave = subscribedFacility;\n var unsubscribe = $q.when(!facilityToLeave || configuration.leaveFacility(hub, facilityToLeave));\n unsubscribe.then(function () {\n if (facilityToLeave) {\n $log.debug(\"Left facility \".concat(facilityToLeave));\n }\n\n if (!isConnectionAllowedByAccessControl()) {\n subscribedFacility = null;\n resolve();\n } else {\n var facilityToJoin = currentFacility;\n configuration.joinFacility(hub, facilityToJoin).then(function () {\n $log.debug(\"Joined facility \".concat(facilityToJoin));\n subscribedFacility = currentFacility;\n resolve();\n });\n }\n });\n });\n };\n\n subscribedFacilityPromise = subscribedFacilityPromise.then(updateSubscription);\n }\n\n function isHubConnected() {\n if (hub === null || hub === undefined) {\n return false;\n }\n\n return hub.connection.state === $.signalR.connectionState.connected;\n }\n\n function isConnectionAllowedByAccessControl() {\n try {\n return configuration.canAccess(appSettings.site.accessControls) || false;\n } catch (error) {\n return false;\n }\n }\n\n function onConnectionStateChanged(connectionState) {\n $log.debug(\"State changed from '\".concat(getConnectionStateName(connectionState.oldState), \"' to '\").concat(getConnectionStateName(connectionState.newState), \"'.\"));\n\n if (connectionState.newState === $.signalR.connectionState.disconnected) {\n // The only time that a hub connection goes directly from connected to disconnected is when it is explicitly closed\n // (e.g. the app is being torn down). In these cases, we don't want to reconnect.\n if (connectionState.oldState === $.signalR.connectionState.connected) {\n return;\n }\n\n reconnect();\n } else if (connectionState.newState === $.signalR.connectionState.connected) {\n if (reconnectionManager !== null) {\n reconnectionManager.reset();\n }\n\n updateSubscribedFacility();\n }\n }\n\n function reconnect() {\n if (reconnectionManager === null) {\n reconnectionManager = new HubReconnectionManager(hub);\n }\n\n reconnectionManager.reconnect();\n }\n\n function getConnectionStateName(state) {\n switch (state) {\n case $.signalR.connectionState.connecting:\n return \"Connecting\";\n\n case $.signalR.connectionState.connected:\n return \"Connected\";\n\n case $.signalR.connectionState.reconnecting:\n return \"Reconnecting\";\n\n case $.signalR.connectionState.disconnected:\n return \"Disconnected\";\n }\n\n throw new Error(\"Unknown SignalR state: \".concat(state));\n }\n\n function onError(error) {\n if (error.data) {\n $log.error(\" Data - \".concat(error.data && JSON.stringify(error.data)));\n }\n\n if (error.message) {\n var isTransient = /(websocket\\sclosed)|(No\\stransport\\scould\\sbe\\sinitialized\\ssuccessfully)/i.test(error.message);\n\n if (isTransient) {\n $log.warn(\" Message - \".concat(error.message));\n } else {\n $log.error(\" Message - \".concat(error.message), error);\n }\n }\n\n if (!isHubConnected()) {\n reconnect();\n }\n }\n };\n }\n\n hubReconnectionManagerFactory.$inject = [\"$log\", \"$timeout\"];\n\n function hubReconnectionManagerFactory($logger, $timeout) {\n return function HubReconnectionManager(hub) {\n if (hub === null) {\n throw new Error(\"You must provide the hub when creating a reconnection manager.\");\n }\n\n var millisPerMinute = 60 * 1000;\n var $log = new HubLogWrapper($logger, hub.name);\n var retryMinutes = [1, 2, 5, 10];\n var currentRetryMinutesIndex = null;\n var retryTimeout; ////////////////////\n\n this.reconnect = function () {\n currentRetryMinutesIndex = getNextRetryMinutesIndex();\n var minutes = retryMinutes[currentRetryMinutesIndex];\n $log.debug(\"Retrying connection in \".concat(minutes, \" min\"));\n retryTimeout = $timeout(retryConnection, minutes * millisPerMinute);\n };\n\n function retryConnection() {\n retryTimeout = null;\n $log.debug(\"Attempting to reconnect\");\n hub.connect();\n }\n\n function getNextRetryMinutesIndex() {\n if (currentRetryMinutesIndex === null) {\n return 0;\n }\n\n var nextIndex = currentRetryMinutesIndex + 1;\n return nextIndex < retryMinutes.length ? nextIndex : currentRetryMinutesIndex;\n }\n\n this.reset = function () {\n currentRetryMinutesIndex = null;\n\n if (retryTimeout) {\n $timeout.cancel(retryTimeout);\n retryTimeout = null;\n }\n };\n };\n } // Simple wrapper to prefix each log message with the hub that it originated from.\n // istanbul ignore next\n\n\n function HubLogWrapper($log, hubName) {\n var logPrefix = \"SignalR Hub - \".concat(hubName);\n\n function writeLog(logDelegate, messages) {\n logDelegate.apply(this, [logPrefix].concat(messages));\n }\n\n this.log = function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n return writeLog($log.log, args);\n };\n\n this.debug = function () {\n for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n\n return writeLog($log.debug, args);\n };\n\n this.info = function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n\n return writeLog($log.info, args);\n };\n\n this.warn = function () {\n for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {\n args[_key5] = arguments[_key5];\n }\n\n return writeLog($log.warn, args);\n };\n\n this.error = function () {\n for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n\n return writeLog($log.error, args);\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.signalR.hubsConnector\", hubsConnector);\n hubsConnector.$inject = [\"$q\", \"$log\", \"lodash\", \"app.core.signalR.jobs.jobStatusHub\", \"app.core.signalR.alerts.alertStatusHub\"];\n\n function hubsConnector($q, $log, _) {\n for (var _len = arguments.length, hubs = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {\n hubs[_key - 3] = arguments[_key];\n }\n\n var $connected$;\n return {\n connect: connect\n }; ////////////////////\n\n function connect() {\n if ($connected$) {\n return $connected$;\n }\n\n _.forEach(hubs, function (hub) {\n $log.debug(\"Connecting to signalR hub: \".concat(hub.name));\n hub.connect();\n });\n\n return $connected$ = $q.when(true);\n }\n }\n})();\n\n\n\"use strict\";\n\n//TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.signalR.jobs.events\", getEvents());\n\n function getEvents() {\n return {\n channelName: \"app.core.signalR.jobs\",\n topics: {\n progressUpdate: \"progressUpdate\",\n jobStale: \"jobStale\",\n jobCompleted: \"jobCompleted\",\n jobDismissed: \"jobDismissed\"\n }\n };\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.signalR.jobs.jobStatusHub\", jobStatusHub);\n jobStatusHub.$inject = [\"$log\", \"$timeout\", \"postal\", \"lodash\", \"app.core.appSettings\", \"app.core.signalR.Hub\", \"app.core.models.jobs.ModellingJob\", \"app.core.models.jobs.jobCompletionStatus\", \"app.core.signalR.jobs.events\", \"app.core.signalR.jobs.state\"];\n\n function jobStatusHub($log, $timeout, postal, _, appSettings, Hub, ModellingJob, jobCompletionStatus, jobEvents, jobState) {\n var hubName = \"jobStatusHub\";\n var channel = postal.channel(jobEvents.channelName);\n var hub = new Hub({\n hubName: hubName,\n canAccess: function canAccess() {\n return true;\n },\n methods: [\"subscribeJobStatus\", \"unsubscribeJobStatus\"],\n listeners: {\n jobBatchCreated: onJobBatchCreated,\n jobBatchUpdated: onJobBatchUpdated,\n jobBatchCompleted: onJobBatchCompleted,\n jobBatchDismissed: onJobBatchDismissed\n },\n joinFacility: joinFacility,\n leaveFacility: leaveFacility\n });\n return {\n name: hubName,\n connect: hub.connect\n }; ///////////////////\n\n function onJobBatchCreated(jobBatchId, requesterId, modelName, utcFromDateTime, utcToDateTime) {\n var job = getJobById(jobBatchId);\n\n if (job) {\n return;\n }\n\n var fromMillis = new Date(utcFromDateTime).getTime();\n var toMillis = new Date(utcToDateTime).getTime();\n job = new ModellingJob(jobBatchId, requesterId, fromMillis, toMillis, modelName);\n jobState.jobs.push(job);\n }\n\n function onJobBatchUpdated(jobBatchId, progress, progressMessage, errorMessage) {\n var job = getJobById(jobBatchId);\n\n if (!job) {\n return;\n }\n\n if (!job.hasStarted || job.progress < progress) {\n job.progress = parseInt(progress) || null;\n }\n\n job.addProgressMessage(progressMessage);\n job.addErrorMessage(errorMessage);\n publish(jobEvents.topics.progressUpdate, job);\n }\n\n function onJobBatchCompleted(jobBatchId, jobSucceededCount, jobFailedCount) {\n var completionStatus = jobCompletionStatus.calculate(jobSucceededCount, jobFailedCount);\n $log.debug(\"Job \".concat(jobBatchId, \" completed with \").concat(jobSucceededCount, \" successful and \").concat(jobFailedCount, \" failed constituents (overall status: \").concat(completionStatus, \").\"));\n var job = getJobById(jobBatchId);\n\n if (!job) {\n return;\n }\n\n job.progress = 100; // cater for duplicate events which we seem to be getting now for some reason.\n\n if (completionStatus !== job.completionStatus) {\n job.completionStatus = completionStatus;\n publish(jobEvents.topics.jobCompleted, job);\n }\n }\n\n function onJobBatchDismissed(jobId) {\n var _$remove = _.remove(jobState.jobs, {\n jobId: jobId\n }),\n _$remove2 = _slicedToArray(_$remove, 1),\n job = _$remove2[0];\n\n if (job) {\n publish(jobEvents.topics.jobDismissed, job);\n }\n }\n\n function joinFacility(signalRHub, facility) {\n return signalRHub.subscribeJobStatus(facility, appSettings.userId);\n }\n\n function leaveFacility(signalRHub, facility) {\n return signalRHub.unsubscribeJobStatus(facility, appSettings.userId);\n }\n\n function getJobById(jobId) {\n return _.find(jobState.jobs, {\n jobId: jobId\n });\n }\n\n function publish(topic, job) {\n $timeout(function () {\n return channel.publish(topic, job);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").value(\"app.core.signalR.jobs.state\", {\n jobs: []\n });\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.states.monitoringTimeState\", monitoringTimeState);\n monitoringTimeState.$inject = [\"app.core.datetime.timeZoneDateTime\"];\n\n function monitoringTimeState(timeZoneDateTime) {\n var _dateTime = null;\n\n var _previousDateTime;\n\n var model = {\n isRealTime: false\n };\n Object.defineProperty(model, \"dateTime\", {\n get: function get() {\n return _dateTime;\n },\n set: function set(newValue) {\n _previousDateTime = _dateTime;\n _dateTime = newValue;\n },\n enumerable: true,\n configurable: true\n });\n\n model.facilityStartOfDay = function () {\n return timeZoneDateTime.getFacilityStartOfDay(_dateTime);\n };\n\n model.facilityEndOfDay = function () {\n return timeZoneDateTime.getFacilityEndOfDay(_dateTime);\n };\n\n model.dateTimeHasChangedDays = function () {\n if (!_previousDateTime || !_dateTime) {\n return false;\n }\n\n var previousStartOfDay = timeZoneDateTime.getFacilityStartOfDay(_previousDateTime);\n var currentStartOfDay = timeZoneDateTime.getFacilityStartOfDay(_dateTime);\n return previousStartOfDay.getTime() !== currentStartOfDay.getTime();\n };\n\n return model;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").factory(\"app.core.datetime.timeZoneDateTime\", timeZoneDateTime);\n timeZoneDateTime.$inject = [\"app.core.appSettings\", \"moment\", \"lodash\"];\n\n function timeZoneDateTime(appSettings, moment, _) {\n var service = {\n getFacilityTimeZoneOffsetDifferenceFromLocal: getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes,\n convertDateTimeToFacilityTimeZone: convertDateTimeToFacilityTimeZone,\n convertFacilityDateTimeToLocalTimeZone: convertFacilityDateTimeToLocalTimeZone,\n getFacilityStartOfDay: getFacilityStartOfDay,\n getFacilityEndOfDay: getFacilityEndOfDay\n };\n return service; //////////////\n\n /*\r\n * e.g. 10 am in AEST (e.g. Brisbane) will give back 8am AWST (e.g. Perth) time.\r\n * e.g. 11am in AEDT (e.g. Sydney) will give back 8am AWST (e.g. Perth) time.\r\n */\n\n function convertDateTimeToFacilityTimeZone(localDateTime) {\n if (!localDateTime) {\n return null;\n }\n\n var offsetDifference = getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes(localDateTime);\n return moment(localDateTime).add(offsetDifference, \"minute\").toDate();\n }\n\n function getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes(dateToOffset) {\n if (!_.isDate(dateToOffset)) {\n throw new Error(\"A date must be supplied to get the offset. This is to cater for daylight savings time.\");\n }\n\n if (!appSettings.site.facility.ianaTimeZoneId) {\n // just use local time if not timezone is configured\n return 0;\n }\n\n return dateToOffset.getTimezoneOffset() - moment.tz.zone(appSettings.site.facility.ianaTimeZoneId).utcOffset(moment(dateToOffset).utc());\n }\n /*\r\n * e.g. 8am AWST (e.g. Perth) will give back 10am in AEST (e.g. Brisbane).\r\n * e.g. 8am AWST (e.g. Perth) will give back 11am in AEDT (e.g. Sydney).\r\n */\n\n\n function convertFacilityDateTimeToLocalTimeZone(facilityDateTime) {\n if (!facilityDateTime) {\n return null;\n }\n\n var offsetDifference = getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes(facilityDateTime);\n return moment(facilityDateTime).add(-offsetDifference, \"minute\").toDate();\n } // Given a local browser Date(); it offsets to the facility timezone before returning the midnight start of day.\n\n\n function getFacilityStartOfDay(localDateTime) {\n if (!localDateTime) {\n return null;\n } // e.g. it's 1am +10, November 2nd in Brisbane; the facility timezone is +8 (e.g. Western Australia)\n\n\n var facilityTime = convertDateTimeToFacilityTimeZone(localDateTime); // // returns 11pm +10, November 1st.\n\n return moment(facilityTime).startOf(\"day\").toDate(); // 00:00:00 +10, November 1st\n } // Given a local browser Date(); it offsets to the facility timezone before return the midnight end of day.\n\n\n function getFacilityEndOfDay(localDateTime) {\n if (!localDateTime) {\n return null;\n } // e.g. it's 1am +10, November 2nd in Brisbane; the facility timezone is +8 (e.g. Western Australia)\n\n\n var facilityTime = convertDateTimeToFacilityTimeZone(localDateTime); // returns 11pm +10 November 1st.\n\n return moment(facilityTime).endOf(\"day\").toDate(); // 23:59:59 +10 November 1st\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esAfterDate\", esAfterDate);\n esAfterDate.$inject = [\"kendo\", \"app.core.services.dateTimeService\"];\n\n function esAfterDate(kendo, dateTimeService) {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.afterDate = function (modelValue, viewValue) {\n if (ngModel.$isEmpty(viewValue)) {\n return true;\n }\n\n var options = $scope.$eval(attrs.kOptions);\n var format = options && options.format && [options.format] || [dateTimeService.formats.kendo.dateTime, dateTimeService.formats.kendo.date];\n var viewDate = kendo.parseDate(viewValue, format);\n\n if (!viewDate) {\n return true;\n }\n\n var compareDateProperty = attrs.esAfterDate;\n var compareDate = $scope.$eval(compareDateProperty);\n return !compareDate || viewDate > compareDate;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esAngle\", esAngle);\n esAngle.$inject = [];\n\n function esAngle() {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.angle = function (modelValue) {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n var angle = parseInt(modelValue);\n return angle >= -360 && angle <= 360;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esBeforeDate\", esBeforeDate);\n esBeforeDate.$inject = [\"kendo\", \"app.core.services.dateTimeService\"];\n\n function esBeforeDate(kendo, dateTimeService) {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.beforeDate = function (modelValue, viewValue) {\n if (ngModel.$isEmpty(viewValue)) {\n return true;\n }\n\n var options = $scope.$eval(attrs.kOptions);\n var format = options && options.format && [options.format] || [dateTimeService.formats.kendo.dateTime, dateTimeService.formats.kendo.date];\n var viewDate = kendo.parseDate(viewValue, format);\n\n if (!viewDate) {\n return true;\n }\n\n var compareDateProperty = attrs.esBeforeDate;\n var compareDate = $scope.$eval(compareDateProperty);\n return !compareDate || viewDate < compareDate;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esDecimal\", esDecimal);\n esDecimal.$inject = [];\n\n function esDecimal() {\n return {\n require: \"ngModel\",\n scope: {\n decimalPlaces: \"=esDecimal\"\n },\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.decimal = function (modelValue) {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n if (isNaN(Number(modelValue))) {\n return false;\n }\n\n var decimalPlaces = parseInt($scope.decimalPlaces);\n decimalPlaces = isNaN(decimalPlaces) ? 2 : decimalPlaces;\n var decimalValue = parseFloat(modelValue);\n return parseFloat(decimalValue.toFixed(decimalPlaces)) === decimalValue;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esLatitude\", esLatitude);\n esLatitude.$inject = [];\n\n function esLatitude() {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.latitude = function (modelValue) {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n var latitude = parseFloat(modelValue);\n return latitude >= -90 && latitude <= 90;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esLongitude\", esLongitude);\n esLongitude.$inject = [];\n\n function esLongitude() {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.longitude = function (modelValue) {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n var longitude = parseFloat(modelValue);\n return longitude >= -180 && longitude <= 180;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esNoxScale\", esNoxScale);\n esNoxScale.$inject = [];\n\n function esNoxScale() {\n return {\n require: \"ngModel\",\n scope: {},\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.noxScale = function (modelValue) {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n if (isNaN(Number(modelValue))) {\n return false;\n }\n\n var decimalValue = parseFloat(modelValue);\n var isValid = parseFloat(decimalValue.toFixed(6)) === decimalValue && decimalValue > 0;\n return isValid;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esPassword\", validator);\n validator.$inject = [\"app.core.services.userService\"];\n\n function validator(appSettings) {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, $attrs, ctrl) {\n ctrl.$validators.password = function (modelValue) {\n if (modelValue === null || modelValue === undefined) {\n return true;\n }\n\n var username = appSettings.getUserDetails().$$state.value.username;\n var isPasswordValid = validateMinLength(modelValue) && validateContainsLowercaseLetter(modelValue) && validateContainsUppercaseLetter(modelValue) && validateContainsNumber(modelValue) && validateContainsSpecialCharacter(modelValue) && validateUsernamePasswordNotTheSame(username, modelValue);\n return isPasswordValid;\n };\n }\n };\n }\n\n function validateMinLength(password) {\n return password.length >= 14;\n }\n\n function validateContainsLowercaseLetter(password) {\n return /[a-z]/.test(password);\n }\n\n function validateContainsUppercaseLetter(password) {\n return /[A-Z]/.test(password);\n }\n\n function validateContainsSpecialCharacter(password) {\n return /[\\s!'\"`#$%&*+-./\\\\:;<=>?@^_{}|~\\[\\]]/.test(password);\n }\n\n function validateContainsNumber(password) {\n return /\\d/.test(password);\n }\n\n function validateUsernamePasswordNotTheSame(username, password) {\n return !password.toUpperCase().includes(username.toUpperCase());\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esUnique\", validator);\n validator.$inject = [];\n\n function validator() {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, $attrs, ngModel) {\n ngModel.$validators.unique = function (modelValue) {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n var collection = $scope.$eval($attrs.esUnique);\n\n if (!(collection && collection.length)) {\n return true;\n }\n\n var matches = collection.filter(function (value) {\n return value === modelValue;\n });\n return matches.length === 1;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").directive(\"esValidDate\", esValidDate);\n esValidDate.$inject = [\"kendo\", \"app.core.services.dateTimeService\"];\n\n function esValidDate(kendo, dateTimeService) {\n return {\n require: \"ngModel\",\n link: function link($scope, $element, attrs, ngModel) {\n ngModel.$validators.validDate = function (modelValue, viewValue) {\n if (ngModel.$isEmpty(viewValue)) {\n return true;\n }\n\n var options = $scope.$eval(attrs.kOptions);\n var format = options && options.format && [options.format] || [dateTimeService.formats.kendo.dateTime, dateTimeService.formats.kendo.date];\n return kendo.parseDate(viewValue, format) !== null;\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\nDate.equals = function (left, right) {\n if ((left === undefined || left === null) && (right === undefined || right === null)) {\n return true;\n }\n\n if (!(left instanceof Date && right instanceof Date)) {\n return false;\n }\n\n return left.getTime() === right.getTime();\n};\n\n\n\"use strict\";\n\n/**\r\n * Kendo UI v2019.1.220 (http://www.telerik.com/kendo-ui)\r\n * Copyright 2019 Progress Software Corporation and/or one of its subsidiaries or affiliates. All rights reserved.\r\n *\r\n * Kendo UI commercial licenses may be obtained at\r\n * http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\r\n * If you do not own a commercial license, this file shall be governed by the trial license terms.\r\n *\r\n * NOTE:\r\n *\r\n * This file was manually built by copy/pasting the files from the CDN -\r\n * e.g.\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.en.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.en-AU.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.es.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.fr.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.vi.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.zh.min.js\r\n *\r\n * NOTE:\r\n * This file has been extensively alterd to adjust special charactures from none english\r\n * alphabets to work with ES. The function layout remains identical to the CDN files but\r\n * contains formatting for readability. Updating with files listed above will loose these changes.\r\n */\n!function (e) {\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\n}(function () {\n !function (e, y) {\n kendo.cultures.en = {\n name: \"en\",\n numberFormat: {\n pattern: [\"-n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n percent: {\n pattern: [\"-n %\", \"n %\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"%\"\n },\n currency: {\n name: \"\",\n abbr: \"\",\n pattern: [\"($n)\", \"$n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"$\"\n }\n },\n calendars: {\n standard: {\n days: {\n names: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\n namesAbbr: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n namesShort: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\n },\n months: {\n names: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\n namesAbbr: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n },\n AM: [\"AM\", \"am\", \"AM\"],\n PM: [\"PM\", \"pm\", \"PM\"],\n patterns: {\n d: \"M/d/yyyy\",\n D: \"dddd, MMMM d, yyyy\",\n F: \"dddd, MMMM d, yyyy h:mm:ss tt\",\n g: \"M/d/yyyy h:mm tt\",\n G: \"M/d/yyyy h:mm:ss tt\",\n m: \"MMMM d\",\n M: \"MMMM d\",\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\n t: \"h:mm tt\",\n T: \"h:mm:ss tt\",\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\n y: \"MMMM yyyy\",\n Y: \"MMMM yyyy\"\n },\n \"/\": \"/\",\n \":\": \":\",\n firstDay: 0\n }\n }\n };\n }(this);\n});\n!function (e) {\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\n}(function () {\n !function (e, y) {\n kendo.cultures[\"en-AU\"] = {\n name: \"en-AU\",\n numberFormat: {\n pattern: [\"-n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n percent: {\n pattern: [\"-n%\", \"n%\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"%\"\n },\n currency: {\n name: \"Australian Dollar\",\n abbr: \"AUD\",\n pattern: [\"-$n\", \"$n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"$\"\n }\n },\n calendars: {\n standard: {\n days: {\n names: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\n namesAbbr: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n namesShort: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\n },\n months: {\n names: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\n namesAbbr: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n },\n AM: [\"AM\", \"am\", \"AM\"],\n PM: [\"PM\", \"pm\", \"PM\"],\n patterns: {\n d: \"d/MM/yyyy\",\n D: \"dddd, d MMMM yyyy\",\n F: \"dddd, d MMMM yyyy h:mm:ss tt\",\n g: \"d/MM/yyyy h:mm tt\",\n G: \"d/MM/yyyy h:mm:ss tt\",\n m: \"d MMMM\",\n M: \"d MMMM\",\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\n t: \"h:mm tt\",\n T: \"h:mm:ss tt\",\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\n y: \"MMMM yyyy\",\n Y: \"MMMM yyyy\"\n },\n \"/\": \"/\",\n \":\": \":\",\n firstDay: 1\n }\n }\n };\n }(this);\n});\n!function (e) {\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\n}(function () {\n !function (e, d) {\n kendo.cultures.es = {\n name: \"es\",\n numberFormat: {\n pattern: [\"-n\"],\n decimals: 2,\n \",\": \".\",\n \".\": \",\",\n groupSize: [3],\n percent: {\n pattern: [\"-n %\", \"n %\"],\n decimals: 2,\n \",\": \".\",\n \".\": \",\",\n groupSize: [3],\n symbol: \"%\"\n },\n currency: {\n name: \"\",\n abbr: \"\",\n pattern: [\"-n $\", \"n $\"],\n decimals: 2,\n \",\": \".\",\n \".\": \",\",\n groupSize: [3],\n symbol: \"€\"\n }\n },\n calendars: {\n standard: {\n days: {\n names: [\"domingo\", \"lunes\", \"martes\", \"miércoles\", \"jueves\", \"viernes\", \"sábado\"],\n namesAbbr: [\"do.\", \"lu.\", \"ma.\", \"mi.\", \"ju.\", \"vi.\", \"sá.\"],\n namesShort: [\"D\", \"L\", \"M\", \"X\", \"J\", \"V\", \"S\"]\n },\n months: {\n names: [\"enero\", \"febrero\", \"marzo\", \"abril\", \"mayo\", \"junio\", \"julio\", \"agosto\", \"septiembre\", \"octubre\", \"noviembre\", \"diciembre\"],\n namesAbbr: [\"ene.\", \"feb.\", \"mar.\", \"abr.\", \"may.\", \"jun.\", \"jul.\", \"ago.\", \"sep.\", \"oct.\", \"nov.\", \"dic.\"]\n },\n AM: [\"\"],\n PM: [\"\"],\n patterns: {\n d: \"dd/MM/yyyy\",\n D: \"dddd, d' de 'MMMM' de 'yyyy\",\n F: \"dddd, d' de 'MMMM' de 'yyyy H:mm:ss\",\n g: \"dd/MM/yyyy H:mm\",\n G: \"dd/MM/yyyy H:mm:ss\",\n m: \"d 'de' MMMM\",\n M: \"d 'de' MMMM\",\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\n t: \"H:mm\",\n T: \"H:mm:ss\",\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\n y: \"MMMM' de 'yyyy\",\n Y: \"MMMM' de 'yyyy\"\n },\n \"/\": \"/\",\n \":\": \":\",\n firstDay: 1\n }\n }\n };\n }(this);\n});\n!function (e) {\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\n}(function () {\n !function (e, d) {\n kendo.cultures.fr = {\n name: \"fr\",\n numberFormat: {\n pattern: [\"-n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n percent: {\n pattern: [\"-n %\", \"n %\"],\n decimals: 2,\n \",\": \"Â \",\n \".\": \",\",\n groupSize: [3],\n symbol: \"%\"\n },\n currency: {\n name: \"\",\n abbr: \"\",\n pattern: [\"-n $\", \"n $\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"€\"\n }\n },\n calendars: {\n standard: {\n days: {\n names: [\"dimanche\", \"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\", \"samedi\"],\n namesAbbr: [\"dim.\", \"lun.\", \"mar.\", \"mer.\", \"jeu.\", \"ven.\", \"sam.\"],\n namesShort: [\"di\", \"lu\", \"ma\", \"me\", \"je\", \"ve\", \"sa\"]\n },\n months: {\n names: [\"janvier\", \"février\", \"mars\", \"avril\", \"mai\", \"juin\", \"juillet\", \"août\", \"septembre\", \"octobre\", \"novembre\", \"décembre\"],\n namesAbbr: [\"janv.\", \"févr.\", \"mars\", \"avr.\", \"mai\", \"juin\", \"juil.\", \"août\", \"sept.\", \"oct.\", \"nov.\", \"déc.\"]\n },\n AM: [\"\"],\n PM: [\"\"],\n patterns: {\n d: \"dd/MM/yyyy\",\n D: \"dddd d MMMM yyyy\",\n F: \"dddd d MMMM yyyy HH:mm:ss\",\n g: \"dd/MM/yyyy HH:mm\",\n G: \"dd/MM/yyyy HH:mm:ss\",\n m: \"d MMMM\",\n M: \"d MMMM\",\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\n t: \"HH:mm\",\n T: \"HH:mm:ss\",\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\n y: \"MMMM yyyy\",\n Y: \"MMMM yyyy\"\n },\n \"/\": \"/\",\n \":\": \":\",\n firstDay: 1\n }\n }\n };\n }(this);\n});\n!function (n) {\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], n) : n();\n}(function () {\n !function (n, a) {\n kendo.cultures.vi = {\n name: \"vi\",\n numberFormat: {\n pattern: [\"-n\"],\n decimals: 2,\n \",\": \".\",\n \".\": \",\",\n groupSize: [3],\n percent: {\n pattern: [\"-n%\", \"n%\"],\n decimals: 2,\n \",\": \".\",\n \".\": \",\",\n groupSize: [3],\n symbol: \"%\"\n },\n currency: {\n name: \"\",\n abbr: \"\",\n pattern: [\"-n $\", \"n $\"],\n decimals: 2,\n \",\": \".\",\n \".\": \",\",\n groupSize: [3],\n symbol: \"₫\"\n }\n },\n calendars: {\n standard: {\n days: {\n names: [\"Chủ nhật\", \"Thứ hai\", \"Thứ ba\", \"Thứ tư\", \"Thứ năm\", \"Thứ sáu\", \"Ngày thứ bảy\"],\n namesAbbr: [\"CN\", \"T2\", \"T3\", \"T4\", \"T5\", \"T6\", \"T7\"],\n namesShort: [\"C\", \"H\", \"B\", \"T\", \"N\", \"S\", \"B\"]\n },\n months: {\n names: [\"Tháng Giêng\", \"Tháng hai\", \"Tháng Ba\", \"Tháng tư\", \"Có thể\", \"Tháng sáu\", \"Tháng bảy\", \"Tháng Tám\", \"Tháng Chín\", \"Tháng Mười\", \"Tháng mười một\", \"Tháng mười hai\"],\n namesAbbr: [\"Thg1\", \"Thg2\", \"Thg3\", \"Thg4\", \"Thg5\", \"Thg6\", \"Thg7\", \"Thg8\", \"Thg9\", \"Thg10\", \"Thg11\", \"Thg12\"]\n },\n AM: [\"SA\", \"sa\", \"SA\"],\n PM: [\"CH\", \"ch\", \"CH\"],\n patterns: {\n d: \"dd/MM/yyyy\",\n D: \"dd MMMM yyyy\",\n F: \"dd MMMM yyyy h:mm:ss tt\",\n g: \"dd/MM/yyyy h:mm tt\",\n G: \"dd/MM/yyyy h:mm:ss tt\",\n m: \"dd MMMM\",\n M: \"dd MMMM\",\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\n t: \"h:mm tt\",\n T: \"h:mm:ss tt\",\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\n y: \"MMMM yyyy\",\n Y: \"MMMM yyyy\"\n },\n \"/\": \"/\",\n \":\": \":\",\n firstDay: 1\n }\n }\n };\n }(this);\n});\n!function (y) {\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], y) : y();\n}(function () {\n !function (y, n) {\n kendo.cultures.zh = {\n name: \"zh\",\n numberFormat: {\n pattern: [\"-n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n percent: {\n pattern: [\"-n%\", \"n%\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"%\"\n },\n currency: {\n name: \"\",\n abbr: \"\",\n pattern: [\"$-n\", \"$n\"],\n decimals: 2,\n \",\": \",\",\n \".\": \".\",\n groupSize: [3],\n symbol: \"¥\"\n }\n },\n calendars: {\n standard: {\n days: {\n names: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"],\n namesAbbr: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"],\n namesShort: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"]\n },\n months: {\n names: [\"一月\", \"二月\", \"游行\", \"四月\", \"可以\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"],\n namesAbbr: [\"1月\", \"2月\", \"3月\", \"4月\", \"5月\", \"6月\", \"7月\", \"8月\", \"9月\", \"10月\", \"11月\", \"12月\"]\n },\n AM: [\"上午。\", \"上午。\", \"上午。\"],\n PM: [\"下午。\", \"下午。\", \"下午。\"],\n patterns: {\n d: \"yyyy/M/d\",\n D: \"yyyy'年'M'月'd'日'\",\n F: \"yyyy'年'M'月'd'日' H:mm:ss\",\n g: \"yyyy/M/d H:mm\",\n G: \"yyyy/M/d H:mm:ss\",\n m: \"M月d日\",\n M: \"M月d日\",\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\n t: \"H:mm\",\n T: \"H:mm:ss\",\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\n y: \"yyyy'年'M'月'\",\n Y: \"yyyy'年'M'月'\"\n },\n \"/\": \"/\",\n \":\": \":\",\n firstDay: 1\n }\n }\n };\n }(this);\n});\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").config(ArrowMultiPolyLine);\n ArrowMultiPolyLine.$inject = [\"lodash\", \"leafletLib\"];\n\n function ArrowMultiPolyLine(_, L) {\n var defaultArrowHeadFactor = 0.2;\n var defaultArrowHeadAngle = 25;\n var defaultScale = 200;\n L.es = L.es || {};\n L.es.ArrowMultiPolyLine = L.Polyline.extend({\n initialize: function initialize(windArrows, options) {\n var _this = this;\n\n var arrowPointCollection = [];\n\n _.forEach(windArrows, function (windArrow) {\n var arrowPoints = _this._getArrowPoints(windArrow.point, windArrow.bearing, windArrow.magnitude, options || {});\n\n arrowPointCollection = arrowPointCollection.concat(arrowPoints);\n });\n\n L.Polyline.prototype.initialize.call(this, arrowPointCollection, options);\n },\n _getArrowPoints: function _getArrowPoints(point, bearing, magnitude, options) {\n var arrowHeadFactor = options.arrowHeadFactor || defaultArrowHeadFactor,\n arrowHeadAngle = options.arrowHeadAngle || defaultArrowHeadAngle,\n scale = options.scale || defaultScale;\n var tail = point.destinationPoint(bearing, magnitude * scale),\n arrowBackTick1 = point.destinationPoint(bearing + arrowHeadAngle, magnitude * scale * arrowHeadFactor),\n arrowBackTick2 = point.destinationPoint(bearing - arrowHeadAngle, magnitude * scale * arrowHeadFactor);\n var points = [[point, tail], [point, arrowBackTick1], [point, arrowBackTick2]];\n return points;\n }\n });\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").config(corridorPlugin);\n /*\r\n Borrowed from https://github.com/mikhailshilkov/leaflet-corridor\r\n */\n\n corridorPlugin.$inject = [\"leafletLib\"];\n\n function corridorPlugin(L) {\n L.Corridor = L.Polyline.extend({\n initialize: function initialize(latlngs, options) {\n var self = this;\n L.Polyline.prototype.initialize.call(this, latlngs, options);\n this.corridor = options.corridor;\n\n this.updateCallback = function () {\n self._updateWeight(this);\n };\n },\n onAdd: function onAdd(map) {\n L.Polyline.prototype.onAdd.call(this, map);\n map.on(\"zoomend\", this.updateCallback);\n\n this._updateWeight(map);\n },\n onRemove: function onRemove(map) {\n map.off(\"zoomend\", this.updateCallback);\n L.Polyline.prototype.onRemove.call(this, map);\n },\n _updateWeight: function _updateWeight(map) {\n this.setStyle({\n weight: this._getWeight(map, this.corridor)\n });\n },\n _getWeight: function _getWeight(map, corridor) {\n return corridor * 2 / this._getMetersPerPixel(map);\n },\n _getMetersPerPixel: function _getMetersPerPixel(map) {\n var centerLatLng = map.getCenter(); // get map center\n\n var pointC = map.latLngToContainerPoint(centerLatLng); // convert to containerpoint (pixels)\n\n var pointX = L.point(pointC.x + 10, pointC.y); // add 10 pixels to x\n // convert containerpoints to latlngs\n\n var latLngX = map.containerPointToLatLng(pointX);\n return centerLatLng.distanceTo(latLngX) / 10; // calculate distance between c and x (latitude)\n }\n });\n\n L.corridor = function (latlngs, options) {\n return new L.Corridor(latlngs, options || {\n corridor: 100\n });\n };\n }\n})();\n\n\n\"use strict\";\n\n(function (L) {\n \"use strict\";\n\n L.Control.EasyButtons = L.Control.extend({\n initialize: function initialize(options) {\n L.Control.prototype.initialize.call(this, options);\n },\n disable: function disable() {\n this.isEnabled = false;\n\n if (this.link) {\n L.DomUtil.addClass(this.link, \"leaflet-disabled\");\n }\n },\n enable: function enable() {\n this.isEnabled = true;\n\n if (this.link) {\n L.DomUtil.removeClass(this.link, \"leaflet-disabled\");\n }\n },\n onAdd: function onAdd() {\n var container = L.DomUtil.create(\"div\", \"leaflet-bar leaflet-control\");\n L.DomEvent.disableClickPropagation(container);\n this.link = L.DomUtil.create(\"a\", \"leaflet-bar-part\", container);\n this.link.href = \"#\";\n this.link.title = this.options.title;\n L.DomEvent.on(this.link, \"click\", this._click, this);\n\n if (!this.isEnabled) {\n L.DomUtil.addClass(this.link, \"leaflet-disabled\");\n }\n\n var icon = this.options.icon || \"fa-lemon-o\";\n var extraClasses = icon.lastIndexOf(\"fa\", 0) === 0 ? \" fa fa-lg\" : \" glyphicon\";\n L.DomUtil.create(\"i\", icon + extraClasses, this.link);\n return container;\n },\n onRemove: function onRemove() {\n L.DomEvent.off(this.link, \"click\", this._click);\n },\n setActive: function setActive() {\n if (this.link) {\n L.DomUtil.addClass(this.link, \"leaflet-active\");\n }\n },\n setInactive: function setInactive() {\n if (this.link) {\n L.DomUtil.removeClass(this.link, \"leaflet-active\");\n }\n },\n _click: function _click(e) {\n L.DomEvent.stop(e);\n\n if (this.options.click && this.isEnabled) {\n this.options.click(e);\n }\n }\n });\n})(L); // eslint-disable-line no-undef\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n /*\r\n Copied from https://github.com/shramov/leaflet-plugins/blob/1.9.3/layer/tile/Google.js - which doesn`t work with Leaflet 1.x.\r\n Looks like the Layer plugins now have to extend L.GridLayer/L.TileLayer where before they just extended L.Class\r\n */\n\n\n angular.module(\"app.core\").config(googlePlugin);\n googlePlugin.$inject = [\"leafletLib\", \"google\"];\n\n function googlePlugin(L, google) {\n L.GoogleLayer = L.TileLayer.extend({\n options: {\n minZoom: 0,\n maxZoom: 18,\n tileSize: 256,\n subdomains: \"abc\",\n errorTileUrl: \"\",\n attribution: \"\",\n opacity: 1,\n continuousWorld: false,\n noWrap: false,\n mapOptions: {\n backgroundColor: \"#dddddd\"\n }\n },\n initialize: function initialize(type, options) {\n L.Util.setOptions(this, options);\n this._ready = L.GoogleLayer.isGoogleMapsReady();\n\n if (!this._ready) {\n L.GoogleLayer.asyncWait.push(this);\n }\n\n this._type = type || \"SATELLITE\";\n },\n onAdd: function onAdd(map) {\n this._map = map; // create a container div for tiles\n\n this._initContainer();\n\n this._initMapObject(); // set up events\n\n\n map.on(\"viewreset\", this._reset, this);\n L.Util.throttle(this._update, 150, this);\n map.on(\"move\", this._update, this);\n map.on(\"zoomanim\", this._handleZoomAnim, this); //20px instead of 1em to avoid a slight overlap with google`s attribution\n\n map._controlCorners.bottomright.style.marginBottom = \"20px\";\n\n this._reset();\n\n this._update();\n\n L.TileLayer.prototype.onAdd.apply(this, [map]);\n },\n onRemove: function onRemove(map) {\n map._container.removeChild(this._container);\n\n map.off(\"viewreset\", this._reset, this);\n map.off(\"move\", this._update, this);\n map.off(\"zoomanim\", this._handleZoomAnim, this);\n\n if (map._controlCorners && map._controlCorners.bottomright) {\n map._controlCorners.bottomright.style.marginBottom = \"0em\";\n }\n\n L.TileLayer.prototype.onRemove.apply(this, [map]);\n },\n getAttribution: function getAttribution() {\n return this.options.attribution;\n },\n setOpacity: function setOpacity(opacity) {\n this.options.opacity = opacity;\n\n if (opacity < 1) {\n L.DomUtil.setOpacity(this._container, opacity);\n }\n },\n setElementSize: function setElementSize(e, size) {\n e.style.width = size.x + \"px\";\n e.style.height = size.y + \"px\";\n },\n _initContainer: function _initContainer() {\n var tilePane = this._map._container;\n var first = tilePane.firstChild;\n\n if (!this._container) {\n this._container = L.DomUtil.create(\"div\", \"leaflet-google-layer leaflet-top leaflet-left\");\n this._container.id = \"_GMapContainer_\" + L.Util.stamp(this);\n this._container.style.zIndex = \"auto\";\n }\n\n tilePane.insertBefore(this._container, first);\n this.setOpacity(this.options.opacity);\n this.setElementSize(this._container, this._map.getSize());\n },\n _initMapObject: function _initMapObject() {\n if (!this._ready) {\n return;\n }\n\n this._googleCenter = new google.maps.LatLng(0, 0);\n var map = new google.maps.Map(this._container, {\n center: this._googleCenter,\n zoom: 0,\n tilt: 0,\n mapTypeId: google.maps.MapTypeId[this._type],\n disableDefaultUI: true,\n keyboardShortcuts: false,\n draggable: false,\n disableDoubleClickZoom: true,\n scrollwheel: false,\n streetViewControl: false,\n styles: this.options.mapOptions.styles,\n backgroundColor: this.options.mapOptions.backgroundColor\n });\n var self = this;\n google.maps.event.addListenerOnce(map, \"center_changed\", function () {\n self.onReposition();\n });\n this._google = map;\n google.maps.event.addListenerOnce(map, \"idle\", function () {\n self._checkZoomLevels();\n });\n google.maps.event.addListenerOnce(map, \"tilesloaded\", function () {\n self.fire(\"load\");\n }); //Reporting that map-object was initialized.\n\n this.fire(\"MapObjectInitialized\", {\n mapObject: map\n });\n },\n _checkZoomLevels: function _checkZoomLevels() {\n //setting the zoom level on the Google map may result in a different zoom level than the one requested\n //(it won`t go beyond the level for which they have data).\n // verify and make sure the zoom levels on both Leaflet and Google maps are consistent\n if (this._map) {\n if (this._map.getZoom() !== undefined && this._google.getZoom() !== this._map.getZoom()) {\n //zoom levels are out of sync. Set the leaflet zoom level to match the google one\n this._map.setZoom(this._google.getZoom());\n }\n }\n },\n _reset: function _reset() {\n this._initContainer();\n },\n _update: function _update() {\n if (!this._google) {\n return;\n }\n\n this._resize();\n\n var center = this._map.getCenter();\n\n var centerLatLng = new google.maps.LatLng(center.lat, center.lng);\n\n this._google.setCenter(centerLatLng);\n\n if (this._map.getZoom() !== undefined) {\n this._google.setZoom(Math.round(this._map.getZoom()));\n }\n\n this._checkZoomLevels();\n },\n _resize: function _resize() {\n var size = this._map.getSize();\n\n if (this._container.style.width === size.x && this._container.style.height === size.y) {\n return;\n }\n\n this.setElementSize(this._container, size);\n this.onReposition();\n },\n _handleZoomAnim: function _handleZoomAnim(e) {\n var center = e.center;\n\n var _center = new google.maps.LatLng(center.lat, center.lng);\n\n this._google.setCenter(_center);\n\n this._google.setZoom(Math.round(e.zoom));\n },\n onReposition: function onReposition() {\n if (!this._google) {\n return;\n }\n\n google.maps.event.trigger(this._google, \"resize\");\n }\n });\n L.GoogleLayer.asyncWait = [];\n\n L.GoogleLayer.asyncInitialize = function () {\n for (var i = 0; i < L.GoogleLayer.asyncWait.length; i++) {\n var o = L.GoogleLayer.asyncWait[i];\n o._ready = true;\n\n if (o._container) {\n o._initMapObject();\n\n o._update();\n }\n }\n\n L.GoogleLayer.asyncWait = [];\n };\n\n L.GoogleLayer.isGoogleMapsReady = function () {\n return !!window.google && !!window.google.maps && !!window.google.maps.Map;\n };\n\n L.googleLayer = function (key, options) {\n return new L.GoogleLayer(key, options);\n };\n }\n})();\n\n\n\"use strict\";\n\n(function (L) {\n \"use strict\";\n\n L.HtmlIcon = L.Icon.extend({\n options: {\n iconUrl: null,\n shadowUrl: null,\n content: \"
    N/A
    \",\n className: \"leaflet-html-icon\" //iconSize: new L.Point(25, 41),\n //iconAnchor: new L.Point(13, 41),\n //popupAnchor: new L.Point(0, -33),\n\n },\n initialize: function initialize(options) {\n L.Util.setOptions(this, options);\n },\n createIcon: function createIcon() {\n if (!this.options.content) {\n return;\n }\n\n var content = document.createElement(\"div\");\n content.innerHTML = this.options.content;\n\n this._setIconStyles(content, \"icon\");\n\n return content;\n },\n //you could change this to add a shadow like in the normal marker if you really wanted\n createShadow: function createShadow() {\n return null;\n }\n });\n\n L.htmlIcon = function (options) {\n return new L.HtmlIcon(options);\n };\n})(L); // eslint-disable-line no-undef\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").config(ImageOverlay);\n ImageOverlay.$inject = [\"leafletLib\", \"app.core.appSettingsProvider\"];\n\n function ImageOverlay(L, appSettingsProvider) {\n var baseInitialize = L.ImageOverlay.prototype.initialize;\n\n L.ImageOverlay.prototype.initialize = function (url, bounds, options) {\n var isDataUrl = url.length > 4 && url.substr(0, 4).toLowerCase() === \"data\";\n\n if (isDataUrl) {\n baseInitialize.call(this, url, bounds, options);\n } else {\n var separator = url.indexOf(\"?\") === -1 ? \"?\" : \"&\";\n var settings = appSettingsProvider.settings;\n var urlWithAuth = \"\".concat(url).concat(separator, \"companyAlias=\").concat(settings.site.company.alias, \"&facilityAlias=\").concat(settings.site.facility.alias, \"&apiKey=\").concat(settings.apiKey);\n baseInitialize.call(this, urlWithAuth, bounds, options);\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.core\").config(addInfluenceArcPolygon);\n addInfluenceArcPolygon.$inject = [\"leafletLib\"];\n\n function addInfluenceArcPolygon(L) {\n L.es = L.es || {};\n L.es.InfluenceArcs = L.Polygon.extend({\n initialize: function initialize(map, arcsData, options) {\n this._buildArc(arcsData, options);\n },\n _buildArc: function _buildArc(influenceArc, options) {\n options = options || {}; // a windspeed of 1 (units?) will result in a 600m radius\n\n var _arcMultiplier = 600; //Set the center point for the arc\n\n var _centrePoint = new L.LatLng(influenceArc.latitude, influenceArc.longitude); //Determine the length of the arc\n\n\n var _arcLength = _arcMultiplier * influenceArc.windSpeed;\n\n var _arcColor = influenceArc ? influenceArc.thresholdColour : \"\"; //Draw the arc\n\n\n this._arcPts = this._drawArc(_centrePoint, influenceArc.windDirection - influenceArc.sigmaTheta, influenceArc.windDirection + influenceArc.sigmaTheta, _arcLength);\n\n this._arcPts.push(_centrePoint);\n\n this.setLatLngs(this._arcPts); //Apply the gradient to the arc\n\n options.fillColor = _arcColor;\n options.fillOpacity = 0.3; //border options\n\n options.color = _arcColor;\n options.weight = 2;\n options.opacity = 0.4; //Add the arc object as marker\n\n L.Polygon.prototype.initialize.call(this, [this._arcPts], options);\n this.setStyle(options);\n\n if (this._popup) {\n //set content while moving\n this._popup.setContent(this._getPopupContent(influenceArc.windDirection, influenceArc.windSpeed));\n } else {\n //Attach a popup\n this.bindPopup(this._getPopupContent(influenceArc.windDirection, influenceArc.windSpeed));\n } //Set the position of the popup to the center point in the event influence arcs rotates\n\n\n this._popup.setLatLng(_centrePoint);\n },\n _getPopupContent: function _getPopupContent(direction, windSpeed) {\n return \"Wind blowing from: \".concat(direction, \" deg
    Wind Speed(m/s): \").concat(windSpeed);\n },\n _drawInvArc: function _drawInvArc(center, initialBearing, finalBearing, radius) {\n var _newcenter = center.destinationPoint((initialBearing + finalBearing) / 2, radius * 2);\n\n var _initialPoint = center.destinationPoint(initialBearing, radius);\n\n var _finalPoint = center.destinationPoint(finalBearing, radius);\n\n var _newFinalBearing = _newcenter.bearing(_initialPoint); // Reverse initial and final to avoid a \"speech-bubble\"\n\n\n var _newInitialBearing = _newcenter.bearing(_finalPoint);\n\n return this._drawArc(_newcenter, _newInitialBearing, _newFinalBearing, radius);\n },\n _drawArc: function _drawArc(center, initialBearing, finalBearing, radius) {\n var _points = 32;\n var _extp = [];\n\n if (initialBearing > finalBearing) {\n finalBearing += 360;\n }\n\n var _deltaBearing = finalBearing - initialBearing;\n\n _deltaBearing = _deltaBearing / _points;\n\n for (var i = 0; i < _points + 1; i++) {\n _extp.push(center.destinationPoint(initialBearing + i * _deltaBearing, radius));\n }\n\n return _extp;\n },\n update: function update(arcsData, options) {\n this._buildArc(arcsData, options);\n }\n });\n\n L.es.influenceArcs = function (map, arcsData, options) {\n return new L.es.InfluenceArcs(map, arcsData, options);\n };\n }\n})();\n\n\n\"use strict\";\n\n(function (L) {\n \"use strict\";\n\n L.es = L.es || {};\n})(L); // eslint-disable-line no-undef\n\n\n\"use strict\";\n\n(function (L) {\n \"use strict\";\n\n L.LatLng.prototype.latRadians = function () {\n return Math.PI * this.lat() / 180;\n };\n\n L.LatLng.prototype.lngRadians = function () {\n return Math.PI * this.lng() / 180;\n };\n\n L.LatLng.prototype.bearing = function (latLng) {\n var _from = this;\n\n var _to = latLng;\n\n if (_from.equals(_to)) {\n return 0;\n }\n\n ;\n\n var _lat1 = _from.lat.toRad();\n\n var _lon1 = _from.lng.toRad();\n\n var _lat2 = _to.lat.toRad();\n\n var _lon2 = _to.lng.toRad();\n\n var _angle = -Math.atan2(Math.sin(_lon1 - _lon2) * Math.cos(_lat2), Math.cos(_lat1) * Math.sin(_lat2) - Math.sin(_lat1) * Math.cos(_lat2) * Math.cos(_lon1 - _lon2));\n\n if (_angle < 0.0) {\n _angle += Math.PI * 2.0;\n }\n\n if (_angle > Math.PI) {\n _angle -= Math.PI * 2.0;\n }\n\n return parseFloat(_angle.toDeg());\n };\n\n L.LatLng.prototype.destinationPoint = function (bearing, distance) {\n var _earthRadiusMeters = 6378137.0;\n\n var _brng = bearing.toRad();\n\n var _lat1 = this.lat.toRad();\n\n var _lon1 = this.lng.toRad();\n\n var _lat2 = Math.asin(Math.sin(_lat1) * Math.cos(distance / _earthRadiusMeters) + Math.cos(_lat1) * Math.sin(distance / _earthRadiusMeters) * Math.cos(_brng));\n\n var _lon2 = _lon1 + Math.atan2(Math.sin(_brng) * Math.sin(distance / _earthRadiusMeters) * Math.cos(_lat1), Math.cos(distance / _earthRadiusMeters) - Math.sin(_lat1) * Math.sin(_lat2));\n\n return new L.LatLng(_lat2.toDeg(), _lon2.toDeg());\n };\n})(L); // eslint-disable-line no-undef\n\n\n\"use strict\";\n\n(function (L) {\n \"use strict\";\n\n L.es.MapCredits = L.Control.extend({\n options: {\n position: \"bottomleft\"\n },\n onAdd: function onAdd() {\n var container = L.DomUtil.create(\"div\", \"leaflet-credits-control\"); // make contents stack vertically\n\n container.style.width = \"10px\";\n Object.defineProperty(this, \"container\", {\n value: container\n });\n return container;\n },\n addCredit: function addCredit(imageUrl, imageClick) {\n var image = L.DomUtil.create(\"img\", \"leaflet-credit\", this.container);\n image.src = imageUrl;\n\n if (imageClick) {\n L.DomEvent.addListener(image, \"mousedown\", L.DomEvent.stopPropagation).addListener(image, \"click\", L.DomEvent.stopPropagation).addListener(image, \"dblclick\", L.DomEvent.stopPropagation).addListener(image, \"click\", imageClick);\n }\n\n return image;\n }\n });\n})(L); // eslint-disable-line no-undef\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n /*\r\n Mostly picked from https://raw.githubusercontent.com/tombatossals/angular-leaflet-directive/master/dist/angular-leaflet-directive.js\r\n */\n angular.module(\"es-leaflet-directive\", []).directive(\"esLeaflet\", esLeaflet).controller(\"esLeafletController\", esLeafletController);\n esLeaflet.$inject = [\"esLeafletData\", \"esLeafletMapDefaults\", \"esLeafletHelpers\", \"esLeafletMapEvents\", \"leafletLib\"];\n\n function esLeaflet(esLeafletData, esLeafletMapDefaults, esLeafletHelpers, esLeafletMapEvents, L) {\n return {\n restrict: \"EA\",\n replace: true,\n scope: {\n center: \"=\",\n defaults: \"=\",\n markers: \"=\",\n layers: \"=\",\n paths: \"=\"\n },\n transclude: true,\n template: \"
    \",\n controller: esLeafletController,\n link: link\n };\n\n function link($scope, $element, attrs, controller) {\n var isDefined = esLeafletHelpers.isDefined;\n var defaults = esLeafletMapDefaults.setDefaults($scope.defaults, attrs.id);\n var mapEvents = esLeafletMapEvents.getAvailableMapEvents();\n var addEvents = esLeafletMapEvents.addEvents;\n $scope.mapId = attrs.id;\n esLeafletData.setDirectiveControls({}, attrs.id); // Create the Leaflet Map Object with the options\n\n var map = new L.Map($element[0], esLeafletMapDefaults.getMapCreationDefaults(attrs.id));\n\n controller._leafletMap.resolve(map);\n\n if (!isDefined(attrs.center)) {\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n }\n\n if (!isDefined(attrs.layers)) {\n var tileLayerObj = L.tileLayer(defaults.tileLayer, defaults.tileLayerOptions);\n tileLayerObj.addTo(map);\n esLeafletData.setTiles(tileLayerObj, attrs.id);\n } // Set zoom control configuration\n\n\n if (isDefined(map.zoomControl) && isDefined(defaults.zoomControlPosition)) {\n map.zoomControl.setPosition(defaults.zoomControlPosition);\n }\n\n if (isDefined(map.zoomControl) && defaults.zoomControl === false) {\n map.zoomControl.removeFrom(map);\n }\n\n if (isDefined(map.zoomsliderControl) && isDefined(defaults.zoomsliderControl) && defaults.zoomsliderControl === false) {\n map.zoomsliderControl.removeFrom(map);\n }\n\n addEvents(map, mapEvents, \"eventName\", $scope, \"broadcast\"); // Resolve the map object to the promises\n\n map.whenReady(function () {\n esLeafletData.setMap(map, attrs.id);\n });\n $scope.$on(\"$destroy\", function () {\n esLeafletMapDefaults.reset();\n map.remove();\n esLeafletData.unresolveMap(attrs.id);\n }); //Handle request to invalidate the map size\n //Up scope using $scope.$emit(`invalidateSize`)\n //Down scope using $scope.$broadcast(`invalidateSize`)\n\n $scope.$on(\"invalidateSize\", function () {\n map.invalidateSize();\n });\n }\n }\n\n esLeafletController.$inject = [\"$scope\", \"$q\"];\n\n function esLeafletController($scope, $q) {\n this._leafletMap = $q.defer();\n\n this.getMap = function () {\n return this._leafletMap.promise;\n };\n\n this.getLeafletScope = function () {\n return $scope;\n };\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletBoundsHelpers\", esLeafletBoundsHelpers);\n esLeafletBoundsHelpers.$inject = [\"leafletLib\"];\n\n function esLeafletBoundsHelpers(L) {\n return {\n createLeafletBounds: createLeafletBounds,\n isValidBounds: isValidBounds\n };\n\n function createLeafletBounds(bounds) {\n if (isValidBounds(bounds)) {\n return L.latLngBounds([bounds.southWest.lat, bounds.southWest.lng], [bounds.northEast.lat, bounds.northEast.lng]);\n }\n }\n\n function isValidBounds(bounds) {\n return angular.isDefined(bounds) && angular.isDefined(bounds.southWest) && angular.isDefined(bounds.northEast) && angular.isNumber(bounds.southWest.lat) && angular.isNumber(bounds.southWest.lng) && angular.isNumber(bounds.northEast.lat) && angular.isNumber(bounds.northEast.lng);\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").directive(\"center\", center).controller(\"centerController\", centerController);\n center.$inject = [\"$log\", \"$location\", \"$timeout\", \"esLeafletMapDefaults\", \"esLeafletHelpers\", \"esLeafletBoundsHelpers\", \"esLeafletMapEvents\"];\n\n function center($log, $location, $timeout, esLeafletMapDefaults, esLeafletHelpers, esLeafletBoundsHelpers, esLeafletMapEvents) {\n var isDefined = esLeafletHelpers.isDefined;\n var isSameCenterOnMap = esLeafletHelpers.isSameCenterOnMap;\n var safeApply = esLeafletHelpers.safeApply;\n var isValidCenter = esLeafletHelpers.isValidCenter;\n var isValidBounds = esLeafletBoundsHelpers.isValidBounds;\n var isUndefinedOrEmpty = esLeafletHelpers.isUndefinedOrEmpty;\n var errorHeader = esLeafletHelpers.errorHeader;\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: [\"esLeaflet\", \"center\"],\n controller: centerController,\n link: link\n };\n\n function link($scope, $element, attrs, controllers) {\n var controller = controllers[0];\n var centerController = controllers[1];\n var leafletScope = controller.getLeafletScope();\n var centerModel = leafletScope.center;\n controller.getMap().then(function (map) {\n var defaults = esLeafletMapDefaults.getDefaults(attrs.id);\n\n if (attrs.center.search(\"-\") !== -1) {\n $log.error(\"\".concat(errorHeader, \" The \\\"center\\\" variable can`t use a \\\"-\\\" on its key name: \\\"\").concat(attrs.center, \"\\\".\"));\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n return;\n } else if (shouldInitializeMapWithBounds(leafletScope.bounds, centerModel)) {\n map.fitBounds(esLeafletBoundsHelpers.createLeafletBounds(leafletScope.bounds), leafletScope.bounds.options);\n centerModel = map.getCenter();\n safeApply(leafletScope, function (scope) {\n angular.extend(scope.center, {\n lat: map.getCenter().lat,\n lng: map.getCenter().lng,\n zoom: map.getZoom(),\n autoDiscover: false\n });\n });\n safeApply(leafletScope, function (scope) {\n var mapBounds = map.getBounds();\n scope.bounds = {\n northEast: {\n lat: mapBounds._northEast.lat,\n lng: mapBounds._northEast.lng\n },\n southWest: {\n lat: mapBounds._southWest.lat,\n lng: mapBounds._southWest.lng\n }\n };\n });\n } else if (!isDefined(centerModel)) {\n $log.error(errorHeader + \" The \\\"center\\\" property is not defined in the main scope\");\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n return;\n } else if (!(isDefined(centerModel.lat) && isDefined(centerModel.lng)) && !isDefined(centerModel.autoDiscover)) {\n angular.copy(defaults.center, centerModel);\n }\n\n var urlCenterHash;\n var mapReady;\n\n if (attrs.urlHashCenter === \"yes\") {\n var extractCenterFromUrl = function extractCenterFromUrl() {\n var search = $location.search();\n var centerParam;\n\n if (isDefined(search.c)) {\n var cParam = search.c.split(\":\");\n\n if (cParam.length === 3) {\n centerParam = {\n lat: parseFloat(cParam[0]),\n lng: parseFloat(cParam[1]),\n zoom: parseInt(cParam[2], 10)\n };\n }\n }\n\n return centerParam;\n };\n\n urlCenterHash = extractCenterFromUrl();\n leafletScope.$on(\"$locationChangeSuccess\", function (event) {\n var scope = event.currentScope;\n var urlCenter = extractCenterFromUrl();\n\n if (isDefined(urlCenter) && !isSameCenterOnMap(urlCenter, map)) {\n angular.extend(scope.center, {\n lat: urlCenter.lat,\n lng: urlCenter.lng,\n zoom: urlCenter.zoom\n });\n }\n });\n }\n\n leafletScope.$watch(\"center\", function (center) {\n if (leafletScope.settingCenterFromLeaflet) {\n return;\n } // The center from the URL has priority\n\n\n if (isDefined(urlCenterHash)) {\n angular.copy(urlCenterHash, center);\n urlCenterHash = undefined;\n }\n\n if (!isValidCenter(center) && center.autoDiscover !== true) {\n $log.warn(errorHeader + \" invalid \\\"center\\\"\");\n return;\n }\n\n if (center.autoDiscover === true) {\n if (!angular.isNumber(center.zoom)) {\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n }\n\n if (angular.isNumber(center.zoom) && center.zoom > defaults.center.zoom) {\n map.locate({\n setView: true,\n maxZoom: center.zoom\n });\n } else if (isDefined(defaults.maxZoom)) {\n map.locate({\n setView: true,\n maxZoom: defaults.maxZoom\n });\n } else {\n map.locate({\n setView: true\n });\n }\n\n return;\n }\n\n if (mapReady && isSameCenterOnMap(center, map)) {\n return;\n }\n\n leafletScope.settingCenterFromScope = true;\n map.setView([center.lat, center.lng], center.zoom);\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\n $timeout(function () {\n leafletScope.settingCenterFromScope = false;\n });\n }, true);\n map.whenReady(function () {\n mapReady = true;\n });\n map.on(\"moveend\", function () {\n // Resolve the center after the first map position\n centerController._leafletCenter.resolve();\n\n esLeafletMapEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search());\n\n if (isSameCenterOnMap(centerModel, map) || leafletScope.settingCenterFromScope) {\n return;\n }\n\n leafletScope.settingCenterFromLeaflet = true;\n safeApply(leafletScope, function (scope) {\n if (!leafletScope.settingCenterFromScope) {\n angular.extend(scope.center, {\n lat: map.getCenter().lat,\n lng: map.getCenter().lng,\n zoom: map.getZoom(),\n autoDiscover: false\n });\n }\n\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\n $timeout(function () {\n leafletScope.settingCenterFromLeaflet = false;\n });\n });\n });\n\n if (centerModel.autoDiscover === true) {\n map.on(\"locationerror\", function () {\n $log.warn(errorHeader + \" The Geolocation API is unauthorized on this page.\");\n\n if (isValidCenter(centerModel)) {\n map.setView([centerModel.lat, centerModel.lng], centerModel.zoom);\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\n } else {\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\n }\n });\n }\n });\n\n function shouldInitializeMapWithBounds(bounds, center) {\n return isDefined(bounds) && isValidBounds(bounds) && isUndefinedOrEmpty(center);\n }\n }\n }\n\n centerController.$inject = [\"$q\"];\n\n function centerController($q) {\n this._leafletCenter = $q.defer();\n\n this.getCenter = function () {\n return this._leafletCenter.promise;\n };\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletControlHelpers\", esLeafletControlHelpers);\n esLeafletControlHelpers.$inject = [\"esLeafletHelpers\", \"esLeafletMapDefaults\", \"leafletLib\"];\n\n function esLeafletControlHelpers(esLeafletHelpers, esLeafletMapDefaults, L) {\n var isDefined = esLeafletHelpers.isDefined;\n var _controls = {};\n return {\n updateLayersControl: updateLayersControl\n };\n\n function updateLayersControl(map, mapId, loaded, baselayers, overlays, leafletLayers) {\n var layer;\n var _layersControl = _controls[mapId];\n var mustBeLoaded = layersControlMustBeVisible(baselayers, overlays, mapId);\n\n if (isDefined(_layersControl) && loaded) {\n for (layer in leafletLayers.baselayers) {\n if (layer) {\n _layersControl.removeLayer(leafletLayers.baselayers[layer]);\n }\n }\n\n for (layer in leafletLayers.overlays) {\n if (layer) {\n _layersControl.removeLayer(leafletLayers.overlays[layer]);\n }\n }\n\n map.removeControl(_layersControl);\n delete _controls[mapId];\n }\n\n if (mustBeLoaded) {\n _layersControl = createLayersControl(mapId);\n _controls[mapId] = _layersControl;\n\n for (layer in baselayers) {\n if (layer) {\n var hideOnSelector = isDefined(baselayers[layer].layerOptions) && baselayers[layer].layerOptions.showOnSelector === false;\n\n if (!hideOnSelector && isDefined(leafletLayers.baselayers[layer])) {\n _layersControl.addBaseLayer(leafletLayers.baselayers[layer], baselayers[layer].name);\n }\n }\n }\n\n for (layer in overlays) {\n if (overlays.hasOwnProperty(layer)) {\n var hideOverlayOnSelector = isDefined(overlays[layer].layerParams) && overlays[layer].layerParams.showOnSelector === false;\n\n if (!hideOverlayOnSelector && isDefined(leafletLayers.overlays[layer])) {\n _layersControl.addOverlay(leafletLayers.overlays[layer], overlays[layer].name);\n }\n }\n }\n\n map.addControl(_layersControl);\n }\n\n return mustBeLoaded;\n }\n\n function layersControlMustBeVisible(baselayers, overlays, mapId) {\n var defaults = esLeafletMapDefaults.getDefaults(mapId);\n\n if (!defaults.controls.layers.visible) {\n return false;\n }\n\n var atLeastOneControlItemMustBeShown = false;\n\n if (angular.isObject(baselayers)) {\n Object.keys(baselayers).forEach(function (key) {\n var layer = baselayers[key];\n\n if (!isDefined(layer.layerOptions) || layer.layerOptions.showOnSelector !== false) {\n atLeastOneControlItemMustBeShown = true;\n }\n });\n }\n\n if (angular.isObject(overlays)) {\n Object.keys(overlays).forEach(function (key) {\n var layer = overlays[key];\n\n if (!isDefined(layer.layerParams) || layer.layerParams.showOnSelector !== false) {\n atLeastOneControlItemMustBeShown = true;\n }\n });\n }\n\n return atLeastOneControlItemMustBeShown;\n }\n\n function createLayersControl(mapId) {\n var defaults = esLeafletMapDefaults.getDefaults(mapId);\n var controlOptions = {\n collapsed: defaults.controls.layers.collapsed,\n position: defaults.controls.layers.position,\n autoZIndex: false\n };\n angular.extend(controlOptions, defaults.controls.layers.options);\n var control;\n\n if (defaults.controls.layers && isDefined(defaults.controls.layers.control)) {\n control = defaults.controls.layers.control.apply(this, [[], [], controlOptions]);\n } else {\n control = new L.control.Layers([], [], controlOptions);\n }\n\n return control;\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").service(\"esLeafletData\", esLeafletData);\n esLeafletData.$inject = [\"esLeafletHelpers\"];\n\n function esLeafletData(esLeafletHelpers) {\n var getDefer = esLeafletHelpers.getDefer;\n var getUnresolvedDefer = esLeafletHelpers.getUnresolvedDefer;\n var setResolvedDefer = esLeafletHelpers.setResolvedDefer;\n var maps = {};\n var layers = {};\n var directiveControls = {};\n var tiles = {};\n var markers = {};\n var paths = {};\n return {\n setMap: setMap,\n getMap: getMap,\n getLayers: getLayers,\n setLayers: setLayers,\n setDirectiveControls: setDirectiveControls,\n getDirectiveControls: getDirectiveControls,\n getMarkers: getMarkers,\n setMarkers: setMarkers,\n getTiles: getTiles,\n setTiles: setTiles,\n unresolveMap: unresolveMap,\n setPaths: setPaths,\n getPaths: getPaths\n };\n\n function setMap(leafletMap, scopeId) {\n var defer = getUnresolvedDefer(maps, scopeId);\n defer.resolve(leafletMap);\n setResolvedDefer(maps, scopeId);\n }\n\n function getMap(scopeId) {\n var defer = getDefer(maps, scopeId);\n return defer.promise;\n }\n\n function setMarkers(leafletMarkers, scopeId) {\n var defer = getUnresolvedDefer(markers, scopeId);\n defer.resolve(leafletMarkers);\n setResolvedDefer(markers, scopeId);\n }\n\n function getMarkers(scopeId) {\n var defer = getDefer(markers, scopeId);\n return defer.promise;\n }\n\n function setPaths(leafletMarkers, scopeId) {\n var defer = getUnresolvedDefer(paths, scopeId);\n defer.resolve(leafletMarkers);\n setResolvedDefer(paths, scopeId);\n }\n\n function getPaths(scopeId) {\n var defer = getDefer(paths, scopeId);\n return defer.promise;\n }\n\n function getLayers(scopeId) {\n var defer = getDefer(layers, scopeId);\n return defer.promise;\n }\n\n function setLayers(leafletLayers, scopeId) {\n var defer = getUnresolvedDefer(layers, scopeId);\n defer.resolve(leafletLayers);\n setResolvedDefer(layers, scopeId);\n }\n\n function getTiles(scopeId) {\n var defer = getDefer(tiles, scopeId);\n return defer.promise;\n }\n\n function setTiles(leafletTiles, scopeId) {\n var defer = getUnresolvedDefer(tiles, scopeId);\n defer.resolve(leafletTiles);\n setResolvedDefer(tiles, scopeId);\n }\n\n function setDirectiveControls(leafletControl, scopeId) {\n var defer = getUnresolvedDefer(directiveControls, scopeId);\n defer.resolve(leafletControl);\n setResolvedDefer(directiveControls, scopeId);\n }\n\n function getDirectiveControls(scopeId) {\n var defer = getDefer(directiveControls, scopeId);\n return defer.promise;\n }\n\n function unresolveMap(scopeId) {\n var id = esLeafletHelpers.obtainEffectiveMapId(maps, scopeId);\n maps[id] = undefined;\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").service(\"esLeafletDirectiveControlsHelpers\", esLeafletDirectiveControlsHelpers);\n esLeafletDirectiveControlsHelpers.$inject = [\"$log\", \"esLeafletData\", \"esLeafletHelpers\"];\n\n function esLeafletDirectiveControlsHelpers($log, esLeafletData, esLeafletHelpers) {\n return {\n extend: extend\n };\n\n function extend(id, thingToAddName, createFn, cleanFn) {\n var _fnHeader = \"\".concat(esLeafletHelpers.errorHeader, \"[leafletDirectiveControlsHelpers.extend] \");\n\n var extender = {};\n\n if (!esLeafletHelpers.isDefined(thingToAddName)) {\n $log.error(\"\".concat(_fnHeader, \"thingToAddName cannot be undefined\"));\n return;\n }\n\n if (angular.isString(thingToAddName) && esLeafletHelpers.isDefined(createFn) && esLeafletHelpers.isDefined(cleanFn)) {\n extender[thingToAddName] = {\n create: createFn,\n clean: cleanFn\n };\n } else if (angular.isObject(thingToAddName) && !esLeafletHelpers.isDefined(createFn) && !esLeafletHelpers.isDefined(cleanFn)) {\n extender = thingToAddName;\n } else {\n $log.error(\"\".concat(_fnHeader, \"incorrect arguments\"));\n return;\n } //add external control to create / destroy markers without a watch\n\n\n esLeafletData.getDirectiveControls().then(function (controls) {\n angular.extend(controls, extender);\n esLeafletData.setDirectiveControls(controls, id);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletEventsHelpersFactory\", esLeafletEventsHelpersFactory).service(\"esLeafletEventsHelpers\", [\"esLeafletEventsHelpersFactory\", function (EsLeafletEventsHelpersFactory) {\n return new EsLeafletEventsHelpersFactory();\n }]);\n esLeafletEventsHelpersFactory.$inject = [\"$rootScope\", \"$log\", \"esLeafletHelpers\"];\n\n function esLeafletEventsHelpersFactory($rootScope, $log, esLeafletHelpers) {\n var safeApply = esLeafletHelpers.safeApply;\n var isDefined = esLeafletHelpers.isDefined;\n var errorHeader = esLeafletHelpers.errorHeader;\n\n var EventsHelper = function EventsHelper(rootBroadcastName, lObjectType) {\n this.rootBroadcastName = rootBroadcastName;\n $log.debug(\"LeafletEventsHelpersFactory: lObjectType: \" + lObjectType + \"rootBroadcastName: \" + rootBroadcastName); //used to path/key out certain properties based on the type , `markers`, `geojson`\n\n this.lObjectType = lObjectType;\n };\n\n EventsHelper.prototype.getAvailableEvents = function () {\n return [];\n };\n /*\r\n argument: name: Note this can be a single string or dot notation\r\n Example:\r\n markerModel : {\r\n m1: { lat:_, lon: _}\r\n }\r\n //would yield name of\r\n name = `m1`\r\n If nested:\r\n markerModel : {\r\n cars: {\r\n m1: { lat:_, lon: _}\r\n }\r\n }\r\n //would yield name of\r\n name = `cars.m1`\r\n */\n\n\n EventsHelper.prototype.genDispatchEvent = function (maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra) {\n var self = this;\n maybeMapId = maybeMapId || \"\";\n\n if (maybeMapId) {\n maybeMapId = \".\" + maybeMapId;\n }\n\n return function (e) {\n var broadcastName = self.rootBroadcastName + maybeMapId + \".\" + eventName;\n $log.debug(broadcastName);\n self.fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName, extra);\n };\n };\n\n EventsHelper.prototype.fire = function (scope, broadcastName, logic, event, lObject, model, modelName, layerName) {\n // Safely broadcast the event\n safeApply(scope, function () {\n var toSend = {\n leafletEvent: event,\n leafletObject: lObject,\n modelName: modelName,\n model: model\n };\n\n if (isDefined(layerName)) {\n angular.extend(toSend, {\n layerName: layerName\n });\n }\n\n if (logic === \"emit\") {\n scope.$emit(broadcastName, toSend);\n } else {\n $rootScope.$broadcast(broadcastName, toSend);\n }\n });\n };\n\n EventsHelper.prototype.bindEvents = function (maybeMapId, lObject, name, model, leafletScope, layerName, extra) {\n var events = [];\n var logic = \"emit\";\n var self = this;\n\n if (!isDefined(leafletScope.eventBroadcast)) {\n // Backward compatibility, if no event-broadcast attribute, all events are broadcasted\n events = this.getAvailableEvents();\n } else if (!angular.isObject(leafletScope.eventBroadcast)) {\n // Not a valid object\n $log.error(errorHeader + \"event-broadcast must be an object check your model.\");\n } else {\n // We have a possible valid object\n if (!isDefined(leafletScope.eventBroadcast[self.lObjectType])) {\n // We do not have events enable/disable do we do nothing (all enabled by default)\n events = this.getAvailableEvents();\n } else if (!angular.isObject(leafletScope.eventBroadcast[self.lObjectType])) {\n // Not a valid object\n $log.warn(errorHeader + \"event-broadcast.\" + [self.lObjectType] + \" must be an object check your model.\");\n } else {\n // We have a possible valid map object\n // Event propadation logic\n if (isDefined(leafletScope.eventBroadcast[this.lObjectType].logic)) {\n // We take care of possible propagation logic\n if (leafletScope.eventBroadcast[self.lObjectType].logic !== \"emit\" && leafletScope.eventBroadcast[self.lObjectType].logic !== \"broadcast\") {\n $log.warn(errorHeader + \"Available event propagation logic are: `emit` or `broadcast`.\");\n }\n } // Enable / Disable\n\n\n var eventsEnable = false;\n var eventsDisable = false;\n\n if (isDefined(leafletScope.eventBroadcast[self.lObjectType].enable) && angular.isArray(leafletScope.eventBroadcast[self.lObjectType].enable)) {\n eventsEnable = true;\n }\n\n if (isDefined(leafletScope.eventBroadcast[self.lObjectType].disable) && angular.isArray(leafletScope.eventBroadcast[self.lObjectType].disable)) {\n eventsDisable = true;\n }\n\n if (eventsEnable && eventsDisable) {\n // Both are active, this is an error\n $log.warn(errorHeader + \"can not enable and disable events at the same time\");\n } else if (!eventsEnable && !eventsDisable) {\n // Both are inactive, this is an error\n $log.warn(errorHeader + \"must enable or disable events\");\n } else {\n // At this point the object is OK, lets enable or disable events\n if (eventsEnable) {\n // Enable events\n leafletScope.eventBroadcast[this.lObjectType].enable.forEach(function (eventName) {\n // Do we have already the event enabled?\n if (events.indexOf(eventName) !== -1) {\n // Repeated event, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" is already enabled\");\n } else {\n // Does the event exists?\n if (self.getAvailableEvents().indexOf(eventName) === -1) {\n // The event does not exists, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist\");\n } else {\n // All ok enable the event\n events.push(eventName);\n }\n }\n });\n } else {\n // Disable events\n events = this.getAvailableEvents();\n leafletScope.eventBroadcast[self.lObjectType].disable.forEach(function (eventName) {\n var index = events.indexOf(eventName);\n\n if (index === -1) {\n // The event does not exist\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist or has been already disabled\");\n } else {\n events.splice(index, 1);\n }\n });\n }\n }\n }\n }\n\n events.forEach(function (eventName) {\n lObject.on(eventName, self.genDispatchEvent(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra));\n });\n return logic;\n };\n\n return EventsHelper;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").service(\"esLeafletGeoJsonHelpers\", esLeafletGeoJsonHelpers);\n esLeafletGeoJsonHelpers.$inject = [\"esLeafletHelpers\", \"esLeafletIterators\"];\n\n function esLeafletGeoJsonHelpers(esLeafletHelpers, esLeafletIterators) {\n return {\n validateCoords: validateCoords,\n getCoords: getCoords\n };\n\n function Point(lat, lng) {\n this.lat = lat;\n this.lng = lng;\n return this;\n }\n\n function validateCoords(coords) {\n if (esLeafletHelpers.isUndefined(coords)) {\n return false;\n }\n\n if (angular.isArray(coords)) {\n if (coords.length === 2 && angular.isNumber(coords[0]) && angular.isNumber(coords[1])) {\n return true;\n }\n } else if (esLeafletHelpers.isDefined(coords.type)) {\n if (coords.type === \"Point\" && angular.isArray(coords.coordinates) && coords.coordinates.length === 2 && angular.isNumber(coords.coordinates[0]) && angular.isNumber(coords.coordinates[1])) {\n return true;\n }\n }\n\n return esLeafletIterators.all([\"lat\", \"lng\"], function (pos) {\n return esLeafletHelpers.isDefined(coords[pos]) && angular.isNumber(coords[pos]);\n });\n }\n\n function getCoords(value) {\n if (!value || !validateCoords(value)) {\n return;\n }\n\n var p = null;\n\n if (Array.isArray(value) && value.length === 2) {\n p = new Point(value[1], value[0]);\n } else if (esLeafletHelpers.isDefined(value.type) && value.type === \"Point\") {\n p = new Point(value.coordinates[1], value.coordinates[0]);\n } else {\n return value;\n } //note angular.merge is avail in angular 1.4.X we might want to fill it here\n\n\n return angular.extend(value, p); //tap on lat, lng if it doesnt exist\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"es-leaflet-directive\").service(\"esLeafletHelpers\", esLeafletHelpers);\n esLeafletHelpers.$inject = [\"$q\", \"$log\", \"leafletLib\"];\n\n function esLeafletHelpers($q, $log, L) {\n var _errorHeader = \"[AngularJS - Leaflet] \";\n var SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\n var MOZ_HACK_REGEXP = /^moz([A-Z])/;\n return {\n errorHeader: _errorHeader,\n getObjectArrayPath: getObjectArrayPath,\n getObjectDotPath: getObjectDotPath,\n defaultTo: defaultTo,\n isTruthy: isTruthy,\n isEmpty: isEmpty,\n isDefined: isDefined,\n isUndefined: isUndefined,\n isFunction: angular.isFunction,\n isValidCenter: isValidCenter,\n isSameCenterOnMap: isSameCenterOnMap,\n safeApply: safeApply,\n obtainEffectiveMapId: obtainEffectiveMapId,\n getUnresolvedDefer: getUnresolvedDefer,\n getDefer: getDefer,\n setResolvedDefer: setResolvedDefer,\n isUndefinedOrEmpty: isUndefinedOrEmpty,\n isValidPoint: isValidPoint,\n FullScreenControlPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.Control.Fullscreen);\n }\n },\n MiniMapControlPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.Control.MiniMap);\n }\n },\n AwesomeMarkersPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.AwesomeMarkers) && angular.isDefined(L.AwesomeMarkers.Icon);\n },\n is: function is(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.AwesomeMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function equal(iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n VectorMarkersPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.VectorMarkers) && angular.isDefined(L.VectorMarkers.Icon);\n },\n is: function is(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.VectorMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function equal(iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n DomMarkersPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.DomMarkers) && angular.isDefined(L.DomMarkers.Icon);\n },\n is: function is(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.DomMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function equal(iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n PolylineDecoratorPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.PolylineDecorator);\n },\n is: function is(decoration) {\n if (this.isLoaded()) {\n return decoration instanceof L.PolylineDecorator;\n } else {\n return false;\n }\n },\n equal: function equal(decorationA, decorationB) {\n if (!this.isLoaded()) {\n return false;\n }\n\n if (this.is(decorationA)) {\n return angular.equals(decorationA, decorationB);\n } else {\n return false;\n }\n }\n },\n MakiMarkersPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.MakiMarkers) && angular.isDefined(L.MakiMarkers.Icon);\n },\n is: function is(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.MakiMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function equal(iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n ExtraMarkersPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.ExtraMarkers) && angular.isDefined(L.ExtraMarkers.Icon);\n },\n is: function is(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.ExtraMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function equal(iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n LabelPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.Label);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.MarkerClusterGroup;\n } else {\n return false;\n }\n }\n },\n MarkerClusterPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.MarkerClusterGroup);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.MarkerClusterGroup;\n } else {\n return false;\n }\n }\n },\n GoogleLayerPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.GoogleLayer);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.GoogleLayer;\n } else {\n return false;\n }\n }\n },\n LeafletProviderPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.TileLayer.Provider);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.TileLayer.Provider;\n } else {\n return false;\n }\n }\n },\n HeatLayerPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.heatLayer);\n }\n },\n WebGLHeatMapLayerPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.TileLayer.WebGLHeatMap);\n }\n },\n BingLayerPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.BingLayer);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.BingLayer;\n } else {\n return false;\n }\n }\n },\n AGSFeatureLayerPlugin: {\n isLoaded: function isLoaded() {\n return L.esri !== undefined && L.esri.featureLayer !== undefined;\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.featureLayer;\n } else {\n return false;\n }\n }\n },\n AGSTiledMapLayerPlugin: {\n isLoaded: function isLoaded() {\n return L.esri !== undefined && L.esri.tiledMapLayer !== undefined;\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.tiledMapLayer;\n } else {\n return false;\n }\n }\n },\n AGSDynamicMapLayerPlugin: {\n isLoaded: function isLoaded() {\n return L.esri !== undefined && L.esri.dynamicMapLayer !== undefined;\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.dynamicMapLayer;\n } else {\n return false;\n }\n }\n },\n AGSImageMapLayerPlugin: {\n isLoaded: function isLoaded() {\n return L.esri !== undefined && L.esri.imageMapLayer !== undefined;\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.imageMapLayer;\n } else {\n return false;\n }\n }\n },\n AGSClusteredLayerPlugin: {\n isLoaded: function isLoaded() {\n return L.esri !== undefined && L.esri.clusteredFeatureLayer !== undefined;\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.clusteredFeatureLayer;\n } else {\n return false;\n }\n }\n },\n YandexLayerPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.Yandex);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.Yandex;\n } else {\n return false;\n }\n }\n },\n GeoJSONPlugin: {\n isLoaded: function isLoaded() {\n return angular.isDefined(L.TileLayer.GeoJSON);\n },\n is: function is(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.TileLayer.GeoJSON;\n } else {\n return false;\n }\n }\n },\n Leaflet: {\n DivIcon: {\n is: function is(icon) {\n return icon instanceof L.DivIcon;\n },\n equal: function equal(iconA, iconB) {\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n Icon: {\n is: function is(icon) {\n return icon instanceof L.Icon;\n },\n equal: function equal(iconA, iconB) {\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n }\n },\n\n /*\r\n watchOptions - object to set deep nested watches and turn off watches all together\r\n (rely on control / functional updates)\r\n watchOptions - Object\r\n doWatch:boolean\r\n isDeep:boolean (sets $watch(function,isDeep))\r\n individual\r\n doWatch:boolean\r\n isDeep:boolean\r\n */\n //legacy defaults\n watchOptions: {\n doWatch: true,\n isDeep: true,\n individual: {\n doWatch: true,\n isDeep: true\n }\n }\n }; // BEGIN DIRECT PORT FROM AngularJS code base\n\n /**\r\n Converts snake_case to camelCase.\r\n Also there is special case for Moz prefix starting with upper case letter.\r\n @param name Name to normalize\r\n */\n\n function camelCase(name) {\n return name.replace(SPECIAL_CHARS_REGEXP, function (_, separator, letter, offset) {\n if (offset) {\n return letter.toUpperCase();\n } else {\n return letter;\n }\n }).replace(MOZ_HACK_REGEXP, \"Moz$1\");\n } //Determine if a reference is undefined or {}\n\n\n function isUndefinedOrEmpty(value) {\n return angular.isUndefined(value) || value === null || Object.keys(value).length === 0;\n }\n /*\r\n Object Array Notation\r\n _getObjectArrayPath(\"bike.one.two\")\r\n returns:\r\n 'bike[\"one\"][\"two\"]'\r\n */\n\n\n function getObjectArrayPath(pathStr) {\n return pathStr.split(\".\").reduce(function (previous, current) {\n return \"\".concat(previous, \"[\\\"\").concat(current, \"\\\"]\");\n });\n }\n /* Object Dot Notation\r\n _getObjectPath([\"bike\",\"one\",\"two\"])\r\n returns:\r\n \"bike.one.two\"\r\n */\n\n\n function getObjectDotPath(arrayOfStrings) {\n return arrayOfStrings.reduce(function (previous, current) {\n return \"\".concat(previous, \".\").concat(current);\n });\n }\n\n function defaultTo(val, _default) {\n return isDefined(val) ? val : _default;\n }\n\n function isDefined(value) {\n return angular.isDefined(value) && value !== null;\n }\n\n function isUndefined(value) {\n return !isDefined(value);\n } //mainly for checking attributes of directives lets keep this minimal (on what we accept)\n\n\n function isTruthy(val) {\n return val === \"true\" || val === true;\n } //Determine if a reference is {}\n\n\n function isEmpty(value) {\n return Object.keys(value).length === 0;\n }\n\n function isValidCenter(center) {\n return angular.isDefined(center) && angular.isNumber(center.lat) && angular.isNumber(center.lng) && angular.isNumber(center.zoom);\n }\n\n function isSameCenterOnMap(centerModel, map) {\n var mapCenter = map.getCenter();\n var zoom = map.getZoom();\n return centerModel.lat && centerModel.lng && mapCenter.lat.toFixed(4) === centerModel.lat.toFixed(4) && mapCenter.lng.toFixed(4) === centerModel.lng.toFixed(4) && zoom === centerModel.zoom;\n }\n\n function safeApply($scope, fn) {\n var phase = $scope.$root.$$phase;\n\n if (phase === \"$apply\" || phase === \"$digest\") {\n $scope.$eval(fn);\n } else {\n $scope.$evalAsync(fn);\n }\n }\n\n function obtainEffectiveMapId(d, mapId) {\n var id;\n var i;\n\n if (!angular.isDefined(mapId)) {\n if (Object.keys(d).length === 0) {\n id = \"main\";\n } else if (Object.keys(d).length >= 1) {\n for (i in d) {\n if (d.hasOwnProperty(i)) {\n id = i;\n }\n }\n } else {\n $log.error(\"\".concat(_errorHeader, \"- You have more than 1 map on the DOM, you must provide the map ID to the leafletData.getXXX call\"));\n }\n } else {\n id = mapId;\n }\n\n return id;\n }\n\n function getUnresolvedDefer(d, mapId) {\n var id = obtainEffectiveMapId(d, mapId);\n var defer;\n\n if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) {\n defer = $q.defer();\n d[id] = {\n defer: defer,\n resolvedDefer: false\n };\n } else {\n defer = d[id].defer;\n }\n\n return defer;\n }\n\n function getDefer(d, mapId) {\n var id = obtainEffectiveMapId(d, mapId);\n var defer;\n\n if (!angular.isDefined(d[id]) || d[id].resolvedDefer === false) {\n defer = getUnresolvedDefer(d, mapId);\n } else {\n defer = d[id].defer;\n }\n\n return defer;\n }\n\n function setResolvedDefer(d, mapId) {\n var id = obtainEffectiveMapId(d, mapId);\n d[id].resolvedDefer = true;\n }\n\n function isValidPoint(point) {\n if (!angular.isDefined(point)) {\n return false;\n }\n\n if (angular.isArray(point)) {\n return point.length === 2 && angular.isNumber(point[0]) && angular.isNumber(point[1]);\n }\n\n return angular.isNumber(point.lat) && angular.isNumber(point.lng);\n } // END AngularJS port\n\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").service(\"esLeafletIterators\", esLeafletIterators);\n esLeafletIterators.$inject = [\"$log\", \"esLeafletHelpers\"];\n\n function esLeafletIterators($log, esLeafletHelpers) {\n var errorHeader = esLeafletHelpers.errorHeader + \"leafletIterators: \"; //BEGIN COPY from underscore\n\n var _keys = Object.keys; // Helper for collection methods to determine whether a collection\n // should be iterated as an array or as an object\n // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength\n\n var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; // Assigns a given object with all the own properties in the passed-in object(s)\n // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\n\n var _extendOwn = createAssigner(_keys);\n\n return {\n each: each,\n all: all\n };\n\n function _isArrayLike(collection) {\n var length = collection !== null && collection.length;\n return angular.isNumber(length) && length >= 0 && length <= MAX_ARRAY_INDEX;\n } // Keep the identity function around for default iteratees.\n\n\n function _identity(value) {\n return value;\n }\n\n function _property(key) {\n return function (obj) {\n return obj === null ? void 0 : obj[key];\n };\n } // Internal function that returns an efficient (for current engines) version\n // of the passed-in callback, to be repeatedly applied in other Underscore\n // functions.\n\n\n function optimizeCb(func, context, argCount) {\n if (context === void 0) {\n return func;\n }\n\n switch (argCount === null ? 3 : argCount) {\n case 1:\n return function (value) {\n return func.call(context, value);\n };\n\n case 2:\n return function (value, other) {\n return func.call(context, value, other);\n };\n\n case 3:\n return function (value, index, collection) {\n return func.call(context, value, index, collection);\n };\n\n case 4:\n return function (accumulator, value, index, collection) {\n return func.call(context, accumulator, value, index, collection);\n };\n }\n\n return function () {\n return func.apply(context, arguments);\n };\n } // An internal function for creating assigner functions.\n\n\n function createAssigner(keysFunc, undefinedOnly) {\n return function (obj) {\n var length = arguments.length;\n\n if (length < 2 || obj === null) {\n return obj;\n }\n\n for (var index = 1; index < length; index++) {\n var source = arguments[index];\n var keys = keysFunc(source);\n var l = keys.length;\n\n for (var i = 0; i < l; i++) {\n var key = keys[i];\n\n if (!undefinedOnly || obj[key] === void 0) {\n obj[key] = source[key];\n }\n }\n }\n\n return obj;\n };\n } // Returns whether an object has a given set of `key:value` pairs.\n\n\n function _isMatch(object, attrs) {\n var keys = _keys(attrs);\n\n var length = keys.length;\n\n if (object === null) {\n return !length;\n }\n\n var obj = Object(object);\n\n for (var i = 0; i < length; i++) {\n var key = keys[i];\n\n if (attrs[key] !== obj[key] || !(key in obj)) {\n return false;\n }\n }\n\n return true;\n } // Returns a predicate for checking whether an object has a given set of\n // `key:value` pairs.\n\n\n function _matcher(attrs) {\n attrs = _extendOwn({}, attrs);\n return function (obj) {\n return _isMatch(obj, attrs);\n };\n } // A mostly-internal function to generate callbacks that can be applied\n // to each element in a collection, returning the desired result — either\n // identity, an arbitrary callback, a property matcher, or a property accessor.\n\n\n function cb(value, context, argCount) {\n if (value === null) {\n return _identity;\n }\n\n if (angular.isFunction(value)) {\n return optimizeCb(value, context, argCount);\n }\n\n if (angular.isObject(value)) {\n return _matcher(value);\n }\n\n return _property(value);\n }\n\n function all(obj, predicate, context) {\n predicate = cb(predicate, context);\n\n var keys = !_isArrayLike(obj) && _keys(obj);\n\n var length = (keys || obj).length;\n\n for (var index = 0; index < length; index++) {\n var currentKey = keys ? keys[index] : index;\n\n if (!predicate(obj[currentKey], currentKey, obj)) {\n return false;\n }\n }\n\n return true;\n } //END COPY fron underscore\n\n\n function _hasErrors(collection, cb, ignoreCollection, cbName) {\n if (!ignoreCollection) {\n if (!esLeafletHelpers.isDefined(collection) || !esLeafletHelpers.isDefined(cb)) {\n return true;\n }\n }\n\n if (!esLeafletHelpers.isFunction(cb)) {\n cbName = esLeafletHelpers.defaultTo(cb, \"cb\");\n $log.error(\"\".concat(errorHeader).concat(cbName, \" is not a function\"));\n return true;\n }\n\n return false;\n }\n\n function _iterate(collection, externalCb, internalCb) {\n if (_hasErrors(undefined, internalCb, true, \"internalCb\")) {\n return;\n }\n\n if (!_hasErrors(collection, externalCb)) {\n for (var key in collection) {\n if (collection.hasOwnProperty(key)) {\n internalCb(collection[key], key);\n }\n }\n }\n } //see http://jsperf.com/iterators/3\n //utilizing for in is way faster\n\n\n function each(collection, cb) {\n _iterate(collection, cb, function (val, key) {\n cb(val, key);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletLabelEvents\", esLeafletLabelEvents);\n esLeafletLabelEvents.$inject = [\"esLeafletHelpers\", \"esLeafletEventsHelpersFactory\"];\n\n function esLeafletLabelEvents(esLeafletHelpers, EsLeafletEventsHelpersFactory) {\n var LabelEvents = function LabelEvents() {\n EsLeafletEventsHelpersFactory.call(this, \"leafletDirectiveLabel\", \"markers\");\n };\n\n LabelEvents.prototype = new EsLeafletEventsHelpersFactory();\n\n LabelEvents.prototype.genDispatchEvent = function (maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\n var markerName = name.replace(\"markers.\", \"\");\n return EsLeafletEventsHelpersFactory.prototype.genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, markerName, model, layerName);\n };\n\n LabelEvents.prototype.getAvailableEvents = function () {\n return [\"click\", \"dblclick\", \"mousedown\", \"mouseover\", \"mouseout\", \"contextmenu\"];\n };\n\n LabelEvents.prototype.genEvents = function (maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\n var self = this;\n var labelEvents = this.getAvailableEvents();\n var scopeWatchName = esLeafletHelpers.getObjectArrayPath(\"markers.\" + name);\n labelEvents.forEach(function (eventName) {\n lObject.label.on(eventName, self.genDispatchEvent(maybeMapId, eventName, logic, leafletScope, lObject.label, scopeWatchName, model, layerName));\n });\n };\n\n LabelEvents.prototype.bindEvents = function () {};\n\n return new LabelEvents();\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletLayerHelpers\", esLeafletLayerHelpers);\n esLeafletLayerHelpers.$inject = [\"$q\", \"$log\", \"leafletLib\", \"esLeafletHelpers\", \"esLeafletIterators\"];\n\n function esLeafletLayerHelpers($q, $log, L, esLeafletHelpers, esLeafletIterators) {\n var isDefined = esLeafletHelpers.isDefined;\n var IteratorHelper = esLeafletIterators;\n var errorHeader = \"[esLeafletLayerHelpers\";\n var layerTypes = getLayerTypes();\n return {\n createLayer: _createLayer,\n safeAddLayer: safeAddLayer,\n safeRemoveLayer: safeRemoveLayer\n };\n\n function isValidLayerType(layerDefinition) {\n // Check if the baselayer has a valid type\n if (!angular.isString(layerDefinition.type)) {\n $log.error(\"[AngularJS - Leaflet] A layer must have a valid type defined.\");\n return false;\n }\n\n if (Object.keys(layerTypes).indexOf(layerDefinition.type) === -1) {\n $log.error(\"[AngularJS - Leaflet] A layer must have a valid type: \".concat(Object.keys(layerTypes)));\n return false;\n } // Check if the layer must have an URL\n\n\n if (layerTypes[layerDefinition.type].mustHaveUrl && !angular.isString(layerDefinition.url)) {\n $log.error(\"[AngularJS - Leaflet] A base layer must have an url\");\n return false;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveData && !isDefined(layerDefinition.data)) {\n $log.error(\"[AngularJS - Leaflet] The base layer must have a \\\"data\\\" array attribute\");\n return false;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveLayer && !isDefined(layerDefinition.layer)) {\n $log.error(\"[AngularJS - Leaflet] The type of layer \".concat(layerDefinition.type, \" must have an layer defined\"));\n return false;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveBounds && !isDefined(layerDefinition.bounds)) {\n $log.error(\"[AngularJS - Leaflet] The type of layer \".concat(layerDefinition.type, \" must have bounds defined\"));\n return false;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveKey && !isDefined(layerDefinition.key)) {\n $log.error(\"[AngularJS - Leaflet] The type of layer \".concat(layerDefinition.type, \" must have key defined\"));\n return false;\n }\n\n return true;\n }\n\n function _createLayer(layerDefinition) {\n if (!isValidLayerType(layerDefinition)) {\n return;\n }\n\n if (!angular.isString(layerDefinition.name)) {\n $log.error(\"[AngularJS - Leaflet] A base layer must have a name\");\n return;\n }\n\n if (!angular.isObject(layerDefinition.layerParams)) {\n layerDefinition.layerParams = {};\n }\n\n if (!angular.isObject(layerDefinition.layerOptions)) {\n layerDefinition.layerOptions = {};\n } // Mix the layer specific parameters with the general Leaflet options. Although this is an overhead\n // the definition of a base layers is more 'clean' if the two types of parameters are differentiated\n\n\n for (var attrname in layerDefinition.layerParams) {\n if (layerDefinition.layerParams.hasOwnProperty(attrname)) {\n layerDefinition.layerOptions[attrname] = layerDefinition.layerParams[attrname];\n }\n }\n\n var params = {\n url: layerDefinition.url,\n data: layerDefinition.data,\n options: layerDefinition.layerOptions,\n layer: layerDefinition.layer,\n icon: layerDefinition.icon,\n type: layerDefinition.layerType,\n bounds: layerDefinition.bounds,\n key: layerDefinition.key,\n apiKey: layerDefinition.apiKey,\n pluginOptions: layerDefinition.pluginOptions,\n user: layerDefinition.user\n }; //TODO Add $watch to the layer properties\n\n return layerTypes[layerDefinition.type].createLayer(params);\n }\n\n function safeAddLayer(map, layer) {\n if (layer && typeof layer.addTo === \"function\") {\n layer.addTo(map);\n } else {\n map.addLayer(layer);\n }\n }\n\n function safeRemoveLayer(map, layer, layerOptions) {\n if (isDefined(layerOptions) && isDefined(layerOptions.loadedDefer)) {\n if (angular.isFunction(layerOptions.loadedDefer)) {\n var defers = layerOptions.loadedDefer();\n $log.debug(\"Loaded Deferred\", defers);\n var count = defers.length;\n\n if (count > 0) {\n var resolve = function resolve() {\n count--;\n\n if (count === 0) {\n map.removeLayer(layer);\n }\n };\n\n for (var i = 0; i < defers.length; i++) {\n defers[i].promise.then(resolve);\n }\n } else {\n map.removeLayer(layer);\n }\n } else {\n layerOptions.loadedDefer.promise.then(function () {\n map.removeLayer(layer);\n });\n }\n } else {\n map.removeLayer(layer);\n }\n }\n\n function getLayerTypes() {\n return {\n xyz: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer(params.url, params.options);\n }\n },\n __mapbox: {\n // original mapbox entry\n mustHaveKey: true,\n createLayer: function createLayer(params) {\n var version = 3;\n\n if (isDefined(params.options.version) && params.options.version === 4) {\n version = params.options.version;\n }\n\n var url = version === 3 ? \"//{s}.tiles.mapbox.com/v3/\".concat(params.key, \"/{z}/{x}/{y}.png\") : \"//api.tiles.mapbox.com/v4/\".concat(params.key, \"/{z}/{x}/{y}.png?access_token=\").concat(params.apiKey);\n return L.tileLayer(url, params.options);\n }\n },\n mapbox: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n var url = \"\".concat(params.url, \"?access_token=\").concat(params.apiKey);\n return L.tileLayer(url, params.options);\n }\n },\n geoJSON: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.GeoJSONPlugin.isLoaded()) {\n return;\n }\n\n return new L.TileLayer.GeoJSON(params.url, params.pluginOptions, params.options);\n }\n },\n geoJSONShape: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n return new L.GeoJSON(params.data, params.options);\n }\n },\n geoJSONAwesomeMarker: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n return new L.GeoJSON(params.data, {\n pointToLayer: function pointToLayer(feature, latlng) {\n return L.marker(latlng, {\n icon: L.AwesomeMarkers.icon(params.icon)\n });\n }\n });\n }\n },\n geoJSONVectorMarker: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n return new L.GeoJSON(params.data, {\n pointToLayer: function pointToLayer(feature, latlng) {\n return L.marker(latlng, {\n icon: L.VectorMarkers.icon(params.icon)\n });\n }\n });\n }\n },\n wms: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer.wms(params.url, params.options);\n }\n },\n wmts: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer.wmts(params.url, params.options);\n }\n },\n group: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n var lyrs = [];\n IteratorHelper.each(params.options.layers, function (l) {\n lyrs.push(_createLayer(l));\n });\n\n params.options.loadedDefer = function () {\n var defers = [];\n\n if (isDefined(params.options.layers)) {\n for (var i = 0; i < params.options.layers.length; i++) {\n var d = params.options.layers[i].layerOptions.loadedDefer;\n\n if (isDefined(d)) {\n defers.push(d);\n }\n }\n }\n\n return defers;\n };\n\n return L.layerGroup(lyrs);\n }\n },\n featureGroup: {\n mustHaveUrl: false,\n createLayer: function createLayer() {\n return L.featureGroup();\n }\n },\n google: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n var type = params.type || \"SATELLITE\";\n\n if (!esLeafletHelpers.GoogleLayerPlugin.isLoaded()) {\n return;\n }\n\n return new L.GoogleLayer(type, params.options);\n }\n },\n here: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n var provider = params.provider || \"HERE.terrainDay\";\n\n if (!esLeafletHelpers.LeafletProviderPlugin.isLoaded()) {\n return;\n }\n\n return new L.TileLayer.Provider(provider, params.options);\n }\n },\n openstreetmap: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer(params.url, params.options);\n }\n },\n gaode: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer(params.url, params.options);\n }\n },\n baidu: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer(params.url, params.options);\n }\n },\n agsFeature: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.AGSFeatureLayerPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The esri plugin is not loaded.\"));\n return;\n }\n\n params.options.url = params.url;\n var layer = L.esri.featureLayer(params.options);\n\n var load = function load() {\n if (isDefined(params.options.loadedDefer)) {\n params.options.loadedDefer.resolve();\n }\n };\n\n layer.on(\"loading\", function () {\n params.options.loadedDefer = $q.defer();\n layer.off(\"load\", load);\n layer.on(\"load\", load);\n });\n return layer;\n }\n },\n agsTiled: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.AGSTiledMapLayerPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The esri plugin is not loaded.\"));\n return;\n }\n\n params.options.url = params.url;\n return L.esri.tiledMapLayer(params.options);\n }\n },\n agsDynamic: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.AGSDynamicMapLayerPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The esri plugin is not loaded.\"));\n return;\n }\n\n params.options.url = params.url;\n return L.esri.dynamicMapLayer(params.options);\n }\n },\n agsImage: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.AGSImageMapLayerPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The esri plugin is not loaded.\"));\n return;\n }\n\n params.options.url = params.url;\n return L.esri.imageMapLayer(params.options);\n }\n },\n agsClustered: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.AGSClusteredLayerPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The esri clustered layer plugin is not loaded.\"));\n return;\n }\n\n if (!esLeafletHelpers.MarkerClusterPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The markercluster plugin is not loaded.\"));\n return;\n }\n\n return L.esri.clusteredFeatureLayer(params.url, params.options);\n }\n },\n markercluster: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.MarkerClusterPlugin.isLoaded()) {\n $log.warn(\"\".concat(errorHeader, \" The markercluster plugin is not loaded.\"));\n return;\n }\n\n return new L.MarkerClusterGroup(params.options);\n }\n },\n bing: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.BingLayerPlugin.isLoaded()) {\n return;\n }\n\n return new L.BingLayer(params.key, params.options);\n }\n },\n webGLHeatmap: {\n mustHaveUrl: false,\n mustHaveData: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.WebGLHeatMapLayerPlugin.isLoaded()) {\n return;\n }\n\n var layer = new L.TileLayer.WebGLHeatMap(params.options);\n\n if (isDefined(params.data)) {\n layer.setData(params.data);\n }\n\n return layer;\n }\n },\n heat: {\n mustHaveUrl: false,\n mustHaveData: true,\n createLayer: function createLayer(params) {\n if (!esLeafletHelpers.HeatLayerPlugin.isLoaded()) {\n return;\n }\n\n var layer = new L.HeatLayer();\n\n if (angular.isArray(params.data)) {\n layer.setLatLngs(params.data);\n }\n\n if (angular.isObject(params.options)) {\n layer.setOptions(params.options);\n }\n\n return layer;\n }\n },\n yandex: {\n mustHaveUrl: false,\n createLayer: function createLayer(params) {\n var type = params.type || \"map\";\n\n if (!esLeafletHelpers.YandexLayerPlugin.isLoaded()) {\n return;\n }\n\n return new L.Yandex(type, params.options);\n }\n },\n imageOverlay: {\n mustHaveUrl: true,\n mustHaveBounds: true,\n createLayer: function createLayer(params) {\n return L.imageOverlay(params.url, params.bounds, params.options);\n }\n },\n iip: {\n mustHaveUrl: true,\n createLayer: function createLayer(params) {\n return L.tileLayer.iip(params.url, params.options);\n }\n },\n // This \"custom\" type is used to accept every layer that user want to define himself.\n // We can wrap these custom layers like heatmap or yandex, but it means a lot of work/code to wrap the world,\n // so we let user to define their own layer outside the directive,\n // and pass it on \"createLayer\" result for next processes\n custom: {\n createLayer: function createLayer(params) {\n if (params.layer instanceof L.Class) {\n return angular.copy(params.layer);\n } else {\n $log.error(\"[AngularJS - Leaflet] A custom layer must be a leaflet Class\");\n }\n }\n }\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").directive(\"layers\", layers).controller(\"layersController\", controller);\n layers.$inject = [\"esLeafletData\", \"esLeafletHelpers\", \"esLeafletLayerHelpers\", \"esLeafletControlHelpers\"];\n\n function layers(esLeafletData, esLeafletHelpers, esLeafletLayerHelpers, esLeafletControlHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: \"esLeaflet\",\n controller: controller,\n link: link\n };\n\n function link(scope, element, attrs, controller) {\n var isDefined = esLeafletHelpers.isDefined;\n var leafletLayers = {};\n var leafletScope = controller.getLeafletScope();\n var layers = leafletScope.layers;\n var createLayer = esLeafletLayerHelpers.createLayer;\n var safeAddLayer = esLeafletLayerHelpers.safeAddLayer;\n var safeRemoveLayer = esLeafletLayerHelpers.safeRemoveLayer;\n var updateLayersControl = esLeafletControlHelpers.updateLayersControl;\n var isLayersControlVisible = false;\n controller.getMap().then(function (map) {\n // We have baselayers to add to the map\n scope._leafletLayers.resolve(leafletLayers);\n\n esLeafletData.setLayers(leafletLayers, attrs.id);\n leafletLayers.baselayers = {};\n leafletLayers.overlays = {};\n var mapId = attrs.id; // Setup all baselayers definitions\n\n var oneVisibleLayer = false;\n\n for (var layerName in layers.baselayers) {\n if (layerName) {\n var newBaseLayer = createLayer(layers.baselayers[layerName]);\n\n if (!isDefined(newBaseLayer)) {\n delete layers.baselayers[layerName];\n continue;\n }\n\n leafletLayers.baselayers[layerName] = newBaseLayer; // Only add the visible layer to the map, layer control manages the addition to the map\n // of layers in its control\n\n if (layers.baselayers[layerName].top === true) {\n safeAddLayer(map, leafletLayers.baselayers[layerName]);\n oneVisibleLayer = true;\n }\n }\n } // If there is no visible layer add first to the map\n\n\n if (!oneVisibleLayer && Object.keys(leafletLayers.baselayers).length > 0) {\n safeAddLayer(map, leafletLayers.baselayers[Object.keys(layers.baselayers)[0]]);\n } // Setup the Overlays\n\n\n for (var _layerName in layers.overlays) {\n if (_layerName) {\n //if (layers.overlays[layerName].type === `cartodb`) {\n //\n //}\n var newOverlayLayer = createLayer(layers.overlays[_layerName]);\n\n if (!isDefined(newOverlayLayer)) {\n delete layers.overlays[_layerName];\n continue;\n }\n\n leafletLayers.overlays[_layerName] = newOverlayLayer; // Only add the visible overlays to the map\n\n if (layers.overlays[_layerName].visible === true) {\n safeAddLayer(map, leafletLayers.overlays[_layerName]);\n }\n }\n } // Watch for the base layers\n\n\n leafletScope.$watch(\"layers.baselayers\", function (newBaseLayers, oldBaseLayers) {\n if (angular.equals(newBaseLayers, oldBaseLayers)) {\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers);\n return true;\n } // Delete layers from the array\n\n\n for (var name in leafletLayers.baselayers) {\n if (!isDefined(newBaseLayers[name]) || newBaseLayers[name].doRefresh) {\n // Remove from the map if it`s on it\n if (map.hasLayer(leafletLayers.baselayers[name])) {\n map.removeLayer(leafletLayers.baselayers[name]);\n }\n\n delete leafletLayers.baselayers[name];\n\n if (newBaseLayers[name] && newBaseLayers[name].doRefresh) {\n newBaseLayers[name].doRefresh = false;\n }\n }\n } // add new layers\n\n\n for (var newName in newBaseLayers) {\n if (!isDefined(leafletLayers.baselayers[newName])) {\n var testBaseLayer = createLayer(newBaseLayers[newName]);\n\n if (isDefined(testBaseLayer)) {\n leafletLayers.baselayers[newName] = testBaseLayer; // Only add the visible layer to the map\n\n if (newBaseLayers[newName].top === true) {\n safeAddLayer(map, leafletLayers.baselayers[newName]);\n }\n }\n } else {\n if (newBaseLayers[newName].top === true && !map.hasLayer(leafletLayers.baselayers[newName])) {\n safeAddLayer(map, leafletLayers.baselayers[newName]);\n } else if (newBaseLayers[newName].top === false && map.hasLayer(leafletLayers.baselayers[newName])) {\n map.removeLayer(leafletLayers.baselayers[newName]);\n }\n }\n } //we have layers, so we need to make, at least, one active\n\n\n var found = false; // search for an active layer\n\n for (var key in leafletLayers.baselayers) {\n if (map.hasLayer(leafletLayers.baselayers[key])) {\n found = true;\n break;\n }\n } // If there is no active layer make one active\n\n\n if (!found && Object.keys(leafletLayers.baselayers).length > 0) {\n safeAddLayer(map, leafletLayers.baselayers[Object.keys(leafletLayers.baselayers)[0]]);\n } // Only show the layers switch selector control if we have more than one baselayer + overlay\n\n\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers);\n }, true); // Watch for the overlay layers\n\n leafletScope.$watch(\"layers.overlays\", function (newOverlayLayers, oldOverlayLayers) {\n if (angular.equals(newOverlayLayers, oldOverlayLayers)) {\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers);\n return true;\n } // Delete layers from the array\n\n\n for (var name in leafletLayers.overlays) {\n if (!isDefined(newOverlayLayers[name]) || newOverlayLayers[name].doRefresh) {\n // Remove from the map if it`s on it\n if (map.hasLayer(leafletLayers.overlays[name])) {\n // Safe remove when ArcGIS layers is loading.\n var options = isDefined(newOverlayLayers[name]) ? newOverlayLayers[name].layerOptions : null;\n safeRemoveLayer(map, leafletLayers.overlays[name], options);\n } // TODO: Depending on the layer type we will have to delete what`s included on it\n\n\n delete leafletLayers.overlays[name];\n\n if (newOverlayLayers[name] && newOverlayLayers[name].doRefresh) {\n newOverlayLayers[name].doRefresh = false;\n }\n }\n } // add new overlays\n\n\n for (var newName in newOverlayLayers) {\n if (!isDefined(leafletLayers.overlays[newName])) {\n var testOverlayLayer = createLayer(newOverlayLayers[newName]);\n\n if (!isDefined(testOverlayLayer)) {\n // If the layer creation fails, continue to the next overlay\n continue;\n }\n\n leafletLayers.overlays[newName] = testOverlayLayer;\n\n if (newOverlayLayers[newName].visible === true) {\n safeAddLayer(map, leafletLayers.overlays[newName]);\n }\n } else {\n // check for the .visible property to hide/show overLayers\n if (newOverlayLayers[newName].visible && !map.hasLayer(leafletLayers.overlays[newName])) {\n safeAddLayer(map, leafletLayers.overlays[newName]);\n } else if (newOverlayLayers[newName].visible === false && map.hasLayer(leafletLayers.overlays[newName])) {\n // Safe remove when ArcGIS layers is loading.\n safeRemoveLayer(map, leafletLayers.overlays[newName], newOverlayLayers[newName].layerOptions);\n }\n } //refresh heatmap data if present\n\n\n if (newOverlayLayers[newName].visible && map._loaded && newOverlayLayers[newName].data && newOverlayLayers[newName].type === \"heatmap\") {\n leafletLayers.overlays[newName].setData(newOverlayLayers[newName].data);\n leafletLayers.overlays[newName].update();\n }\n } // Only add the layers switch selector control if we have more than one baselayer + overlay\n\n\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers);\n }, true);\n });\n }\n }\n\n controller.$inject = [\"$scope\", \"$q\"];\n\n function controller($scope, $q) {\n var self = this;\n $scope._leafletLayers = $q.defer();\n\n self.getLayers = function () {\n return $scope._leafletLayers.promise;\n };\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletMapDefaults\", esLeafletMapDefaults);\n esLeafletMapDefaults.$inject = [\"esLeafletHelpers\", \"leafletLib\"];\n\n function esLeafletMapDefaults(esLeafletHelpers, L) {\n var isDefined = esLeafletHelpers.isDefined;\n var obtainEffectiveMapId = esLeafletHelpers.obtainEffectiveMapId;\n var defaults = {}; // Get the _defaults dictionary, and override the properties defined by the user\n\n return {\n reset: reset,\n getDefaults: getDefaults,\n getMapCreationDefaults: getMapCreationDefaults,\n setDefaults: setDefaults\n };\n\n function reset() {\n defaults = {};\n }\n\n function getDefaults(scopeId) {\n var mapId = obtainEffectiveMapId(defaults, scopeId);\n return defaults[mapId];\n }\n\n function getMapCreationDefaults(scopeId) {\n var mapId = obtainEffectiveMapId(defaults, scopeId);\n var scopeDefaults = defaults[mapId];\n var mapDefaults = {\n maxZoom: scopeDefaults.maxZoom,\n keyboard: scopeDefaults.keyboard,\n dragging: scopeDefaults.dragging,\n zoomControl: scopeDefaults.zoomControl,\n doubleClickZoom: scopeDefaults.doubleClickZoom,\n scrollWheelZoom: scopeDefaults.scrollWheelZoom,\n tap: scopeDefaults.tap,\n touchZoom: scopeDefaults.touchZoom,\n attributionControl: scopeDefaults.attributionControl,\n worldCopyJump: scopeDefaults.worldCopyJump,\n crs: scopeDefaults.crs\n };\n\n if (isDefined(scopeDefaults.minZoom)) {\n mapDefaults.minZoom = scopeDefaults.minZoom;\n }\n\n if (isDefined(scopeDefaults.zoomAnimation)) {\n mapDefaults.zoomAnimation = scopeDefaults.zoomAnimation;\n }\n\n if (isDefined(scopeDefaults.fadeAnimation)) {\n mapDefaults.fadeAnimation = scopeDefaults.fadeAnimation;\n }\n\n if (isDefined(scopeDefaults.markerZoomAnimation)) {\n mapDefaults.markerZoomAnimation = scopeDefaults.markerZoomAnimation;\n }\n\n if (scopeDefaults.map) {\n for (var option in scopeDefaults.map) {\n if (option) {\n mapDefaults[option] = scopeDefaults.map[option];\n }\n }\n }\n\n return mapDefaults;\n }\n\n function setDefaults(userDefaults, scopeId) {\n var newDefaults = _getDefaults();\n\n if (isDefined(userDefaults)) {\n newDefaults.doubleClickZoom = isDefined(userDefaults.doubleClickZoom) ? userDefaults.doubleClickZoom : newDefaults.doubleClickZoom;\n newDefaults.scrollWheelZoom = isDefined(userDefaults.scrollWheelZoom) ? userDefaults.scrollWheelZoom : newDefaults.doubleClickZoom;\n newDefaults.tap = isDefined(userDefaults.tap) ? userDefaults.tap : newDefaults.tap;\n newDefaults.touchZoom = isDefined(userDefaults.touchZoom) ? userDefaults.touchZoom : newDefaults.doubleClickZoom;\n newDefaults.zoomControl = isDefined(userDefaults.zoomControl) ? userDefaults.zoomControl : newDefaults.zoomControl;\n newDefaults.zoomsliderControl = isDefined(userDefaults.zoomsliderControl) ? userDefaults.zoomsliderControl : newDefaults.zoomsliderControl;\n newDefaults.attributionControl = isDefined(userDefaults.attributionControl) ? userDefaults.attributionControl : newDefaults.attributionControl;\n newDefaults.tileLayer = isDefined(userDefaults.tileLayer) ? userDefaults.tileLayer : newDefaults.tileLayer;\n newDefaults.zoomControlPosition = isDefined(userDefaults.zoomControlPosition) ? userDefaults.zoomControlPosition : newDefaults.zoomControlPosition;\n newDefaults.keyboard = isDefined(userDefaults.keyboard) ? userDefaults.keyboard : newDefaults.keyboard;\n newDefaults.dragging = isDefined(userDefaults.dragging) ? userDefaults.dragging : newDefaults.dragging;\n\n if (isDefined(userDefaults.controls)) {\n angular.extend(newDefaults.controls, userDefaults.controls);\n }\n\n if (angular.isObject(userDefaults.crs)) {\n newDefaults.crs = userDefaults.crs;\n } else if (isDefined(L.CRS[userDefaults.crs])) {\n newDefaults.crs = L.CRS[userDefaults.crs];\n }\n\n if (isDefined(userDefaults.center)) {\n angular.copy(userDefaults.center, newDefaults.center);\n }\n\n if (isDefined(userDefaults.tileLayerOptions)) {\n angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions);\n }\n\n if (isDefined(userDefaults.maxZoom)) {\n newDefaults.maxZoom = userDefaults.maxZoom;\n }\n\n if (isDefined(userDefaults.minZoom)) {\n newDefaults.minZoom = userDefaults.minZoom;\n }\n\n if (isDefined(userDefaults.zoomAnimation)) {\n newDefaults.zoomAnimation = userDefaults.zoomAnimation;\n }\n\n if (isDefined(userDefaults.fadeAnimation)) {\n newDefaults.fadeAnimation = userDefaults.fadeAnimation;\n }\n\n if (isDefined(userDefaults.markerZoomAnimation)) {\n newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation;\n }\n\n if (isDefined(userDefaults.worldCopyJump)) {\n newDefaults.worldCopyJump = userDefaults.worldCopyJump;\n }\n\n if (isDefined(userDefaults.map)) {\n newDefaults.map = userDefaults.map;\n }\n\n if (isDefined(userDefaults.path)) {\n newDefaults.path = userDefaults.path;\n }\n }\n\n var mapId = obtainEffectiveMapId(defaults, scopeId);\n defaults[mapId] = newDefaults;\n return newDefaults;\n }\n\n function _getDefaults() {\n return {\n keyboard: true,\n dragging: true,\n worldCopyJump: false,\n doubleClickZoom: true,\n scrollWheelZoom: true,\n tap: true,\n touchZoom: true,\n zoomControl: true,\n zoomSliderControl: false,\n //changed casing\n zoomControlPosition: \"topleft\",\n attributionControl: true,\n controls: {\n layers: {\n visible: true,\n position: \"topright\",\n collapsed: true\n }\n },\n nominatim: {\n server: \" http://nominatim.openstreetmap.org/search\"\n },\n crs: L.CRS.EPSG3857,\n tileLayer: \"//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\",\n tileLayerOptions: {\n attribution: \"© OpenStreetMap contributors\"\n },\n path: {\n weight: 10,\n opacity: 1,\n color: \"#0000ff\"\n },\n center: {\n lat: 0,\n lng: 0,\n zoom: 1\n }\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletMapEvents\", esLeafletMapEvents);\n esLeafletMapEvents.$inject = [\"$log\", \"esLeafletHelpers\", \"esLeafletEventsHelpers\", \"esLeafletIterators\"];\n\n function esLeafletMapEvents($log, esLeafletHelpers, esLeafletEventsHelpers, esLeafletIterators) {\n var isDefined = esLeafletHelpers.isDefined;\n var fire = esLeafletEventsHelpers.fire;\n return {\n getAvailableMapEvents: getAvailableMapEvents,\n genDispatchMapEvent: genDispatchMapEvent,\n notifyCenterChangedToBounds: notifyCenterChangedToBounds,\n notifyCenterUrlHashChanged: notifyCenterUrlHashChanged,\n addEvents: addEvents\n };\n\n function getAvailableMapEvents() {\n return [\"click\", \"dblclick\", \"mousedown\", \"mouseup\", \"mouseover\", \"mouseout\", \"mousemove\", \"contextmenu\", \"focus\", \"blur\", \"preclick\", \"load\", \"unload\", \"viewreset\", \"movestart\", \"move\", \"moveend\", \"dragstart\", \"drag\", \"dragend\", \"zoomstart\", \"zoomanim\", \"zoomend\", \"zoomlevelschange\", \"resize\", \"autopanstart\", \"layeradd\", \"layerremove\", \"baselayerchange\", \"overlayadd\", \"overlayremove\", \"locationfound\", \"locationerror\", \"popupopen\", \"popupclose\", \"draw:created\", \"draw:edited\", \"draw:deleted\", \"draw:drawstart\", \"draw:drawstop\", \"draw:editstart\", \"draw:editstop\", \"draw:deletestart\", \"draw:deletestop\"];\n }\n\n function genDispatchMapEvent(scope, eventName, logic, maybeMapId) {\n if (maybeMapId) {\n maybeMapId = maybeMapId + \".\";\n }\n\n return function (e) {\n // Put together broadcast name\n var broadcastName = \"leafletDirectiveMap.\".concat(maybeMapId).concat(eventName);\n $log.debug(broadcastName); // Safely broadcast the event\n\n fire(scope, broadcastName, logic, e, e.target, scope);\n };\n }\n\n function notifyCenterChangedToBounds(scope) {\n scope.$broadcast(\"boundsChanged\");\n }\n\n function notifyCenterUrlHashChanged(scope, map, attrs, search) {\n if (!isDefined(attrs.urlHashCenter)) {\n return;\n }\n\n var center = map.getCenter();\n var centerUrlHash = center.lat.toFixed(4) + \":\" + center.lng.toFixed(4) + \":\" + map.getZoom();\n\n if (!isDefined(search.c) || search.c !== centerUrlHash) {\n //$log.debug(`notified new center...`);\n scope.$emit(\"centerUrlHash\", centerUrlHash);\n }\n }\n\n function addEvents(map, mapEvents, contextName, scope, logic) {\n esLeafletIterators.each(mapEvents, function (eventName) {\n var context = {};\n context[contextName] = eventName;\n map.on(eventName, genDispatchMapEvent(scope, eventName, logic, map._container.id || \"\"), context);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletMarkerEvents\", esLeafletMarkerEvents);\n esLeafletMarkerEvents.$inject = [\"$rootScope\", \"esLeafletHelpers\", \"esLeafletEventsHelpersFactory\", \"esLeafletLabelEvents\"];\n\n function esLeafletMarkerEvents($rootScope, esLeafletHelpers, esLeafletEventsHelpersFactory, esLeafletLabelEvents) {\n var safeApply = esLeafletHelpers.safeApply;\n var isDefined = esLeafletHelpers.isDefined;\n var lblHelp = esLeafletLabelEvents;\n var EventsHelper = esLeafletEventsHelpersFactory;\n\n var MarkerEvents = function MarkerEvents() {\n EventsHelper.call(this, \"leafletDirectiveMarker\", \"markers\");\n };\n\n MarkerEvents.prototype = new EventsHelper();\n\n MarkerEvents.prototype.genDispatchEvent = function (maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\n var handle = EventsHelper.prototype.genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName);\n return function (e) {\n // Broadcast old marker click name for backwards compatibility\n if (eventName === \"click\") {\n safeApply(leafletScope, function () {\n $rootScope.$broadcast(\"leafletDirectiveMarkersClick\", name);\n });\n } else if (eventName === \"dragend\") {\n safeApply(leafletScope, function () {\n model.lat = lObject.getLatLng().lat;\n model.lng = lObject.getLatLng().lng;\n });\n\n if (model.message && model.focus === true) {\n lObject.openPopup();\n }\n }\n\n handle(e);\n };\n };\n\n MarkerEvents.prototype.getAvailableEvents = function () {\n return [\"click\", \"dblclick\", \"mousedown\", \"mouseover\", \"mouseout\", \"contextmenu\", \"dragstart\", \"drag\", \"dragend\", \"move\", \"remove\", \"popupopen\", \"popupclose\", \"touchend\", \"touchstart\", \"touchmove\", \"touchcancel\", \"touchleave\"];\n };\n\n MarkerEvents.prototype.bindEvents = function (maybeMapId, lObject, name, model, leafletScope, layerName) {\n var logic = EventsHelper.prototype.bindEvents.call(this, maybeMapId, lObject, name, model, leafletScope, layerName);\n\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) {\n lblHelp.genEvents(maybeMapId, name, logic, leafletScope, lObject, model, layerName);\n }\n };\n\n return new MarkerEvents();\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").directive(\"markers\", markers);\n markers.$inject = [\"$log\", \"$q\", \"esLeafletData\", \"esLeafletHelpers\", \"esLeafletMarkersHelpers\", \"esLeafletMarkerEvents\", \"esLeafletIterators\", \"esLeafletWatchHelpers\", \"esLeafletDirectiveControlsHelpers\", \"leafletLib\"];\n\n function markers($log, $q, esLeafletData, esLeafletHelpers, esLeafletMarkersHelpers, esLeafletMarkerEvents, esLeafletIterators, esLeafletWatchHelpers, esLeafletDirectiveControlsHelpers, L) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: [\"esLeaflet\", \"?layers\"],\n link: link\n };\n\n function link(scope, element, attrs, controllers) {\n //less terse vars to helpers\n var isDefined = esLeafletHelpers.isDefined;\n var errorHeader = esLeafletHelpers.errorHeader;\n var addMarkerWatcher = esLeafletMarkersHelpers.addMarkerWatcher;\n var updateMarker = esLeafletMarkersHelpers.updateMarker;\n var listenMarkerEvents = esLeafletMarkersHelpers.listenMarkerEvents;\n var addMarkerToGroup = esLeafletMarkersHelpers.addMarkerToGroup;\n var createMarker = esLeafletMarkersHelpers.createMarker;\n var deleteMarker = esLeafletMarkersHelpers.deleteMarker;\n var _markersWatchOptions = esLeafletHelpers.watchOptions;\n var maybeWatch = esLeafletWatchHelpers.maybeWatch;\n var extendDirectiveControls = esLeafletDirectiveControlsHelpers.extend;\n var mapController = controllers[0];\n var leafletScope = mapController.getLeafletScope();\n mapController.getMap().then(function (map) {\n var leafletMarkers = {};\n var getLayers; // If the layers attribute is used, we must wait until the layers are created\n\n if (isDefined(controllers[1])) {\n getLayers = controllers[1].getLayers;\n } else {\n getLayers = function getLayers() {\n var deferred = $q.defer();\n deferred.resolve();\n return deferred.promise;\n };\n }\n\n var watchOptions = leafletScope.markersWatchOptions || _markersWatchOptions; // backwards compat\n\n if (isDefined(attrs.watchMarkers)) {\n watchOptions.doWatch = watchOptions.individual.doWatch = !isDefined(attrs.watchMarkers) || esLeafletHelpers.isTruthy(attrs.watchMarkers);\n }\n\n var isNested = isDefined(attrs.markersNested) && esLeafletHelpers.isTruthy(attrs.markersNested);\n getLayers().then(function (layers) {\n var _clean = function _clean(models, oldModels) {\n if (isNested) {\n var oldModel;\n esLeafletIterators.each(models, function (markerToMaybeDel, layerName) {\n oldModel = isDefined(oldModel) ? oldModels[layerName] : undefined;\n destroy(markerToMaybeDel, oldModel, leafletMarkers[layerName], map, layers);\n });\n return;\n }\n\n destroy(models, oldModels, leafletMarkers, map, layers);\n };\n\n var _create = function _create(models, oldModels) {\n _clean(models, oldModels);\n\n var skips = null;\n\n if (isNested) {\n var oldModel;\n esLeafletIterators.each(models, function (markersToAdd, layerName) {\n oldModel = isDefined(oldModel) ? oldModels[layerName] : undefined;\n skips = getNewModelsToSkip(models[layerName], oldModel, leafletMarkers[layerName]);\n addMarkers(attrs.id, markersToAdd, oldModels, map, layers, leafletMarkers, leafletScope, watchOptions, layerName, skips);\n });\n return;\n }\n\n skips = getNewModelsToSkip(models, oldModels, leafletMarkers);\n addMarkers(attrs.id, models, oldModels, map, layers, leafletMarkers, leafletScope, watchOptions, undefined, skips);\n };\n\n extendDirectiveControls(attrs.id, \"markers\", _create, _clean);\n esLeafletData.setMarkers(leafletMarkers, attrs.id);\n maybeWatch(leafletScope, \"markers\", watchOptions, function (newMarkers, oldMarkers) {\n _create(newMarkers, oldMarkers);\n });\n });\n });\n\n function getLMarker(leafletMarkers, name, maybeLayerName) {\n if (!Object.keys(leafletMarkers).length) {\n return;\n }\n\n if (maybeLayerName && angular.isString(maybeLayerName)) {\n if (!leafletMarkers[maybeLayerName] || !Object.keys(leafletMarkers[maybeLayerName]).length) {\n return;\n }\n\n return leafletMarkers[maybeLayerName][name];\n }\n\n return leafletMarkers[name];\n }\n\n function setLMarker(lObject, leafletMarkers, name, maybeLayerName) {\n if (maybeLayerName && angular.isString(maybeLayerName)) {\n if (!isDefined(leafletMarkers[maybeLayerName])) {\n leafletMarkers[maybeLayerName] = {};\n }\n\n leafletMarkers[maybeLayerName][name] = lObject;\n } else {\n leafletMarkers[name] = lObject;\n }\n\n return lObject;\n }\n\n function maybeAddMarkerToLayer(layerName, layers, model, marker, doIndividualWatch, map) {\n if (!angular.isString(layerName)) {\n $log.error(errorHeader + \" A layername must be a string\");\n return false;\n }\n\n if (!isDefined(layers)) {\n $log.error(errorHeader + \" You must add layers to the directive if the markers are going to use this functionality.\");\n return false;\n }\n\n if (!isDefined(layers.overlays) || !isDefined(layers.overlays[layerName])) {\n $log.error(errorHeader + \" A marker can only be added to a layer of type 'group'\");\n return false;\n }\n\n var layerGroup = layers.overlays[layerName];\n\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\n $log.error(errorHeader + \" Adding a marker to an overlay needs a overlay of the type 'group' or 'featureGroup'\");\n return false;\n } // The marker goes to a correct layer group, so first of all we add it\n\n\n layerGroup.addLayer(marker); // The marker is automatically added to the map depending on the visibility\n // of the layer, so we only have to open the popup if the marker is in the map\n\n if (!doIndividualWatch && map.hasLayer(marker) && model.focus === true) {\n marker.openPopup();\n }\n\n return true;\n } //TODO: move to leafletMarkersHelpers??? or make a new class/function file (leafletMarkersHelpers is large already)\n\n\n function addMarkers(mapId, markersToRender, oldModels, map, layers, leafletMarkers, leafletScope, watchOptions, maybeLayerName, skips) {\n for (var newName in markersToRender) {\n if (skips[newName]) {\n continue;\n }\n\n if (newName.search(\"-\") !== -1) {\n $log.error(\"The marker can't use a '-' on his key name: \".concat(newName, \".\"));\n continue;\n }\n\n var model = angular.copy(markersToRender[newName]);\n var pathToMarker = esLeafletHelpers.getObjectDotPath(maybeLayerName ? [maybeLayerName, newName] : [newName]);\n var maybeLMarker = getLMarker(leafletMarkers, newName, maybeLayerName);\n var oldModel = void 0;\n\n if (!isDefined(maybeLMarker)) {\n //(nmccready) very important to not have model changes when lObject is changed\n //this might be desirable in some cases but it causes two-way binding to lObject which is not ideal\n //if it is left as the reference then all changes from oldModel vs newModel are ignored\n //see _destroy (where modelDiff becomes meaningless if we do not copy here)\n var marker = createMarker(model);\n var layerName = (model ? model.layer : undefined) || maybeLayerName; //original way takes pref\n\n if (!isDefined(marker)) {\n $log.error(errorHeader + \" Received invalid data on the marker \".concat(newName, \".\"));\n continue;\n }\n\n setLMarker(marker, leafletMarkers, newName, maybeLayerName); // Bind message\n\n if (isDefined(model.message)) {\n marker.bindPopup(model.message, model.popupOptions);\n } // Add the marker to a cluster group if needed\n\n\n if (isDefined(model.group)) {\n var groupOptions = isDefined(model.groupOption) ? model.groupOption : null;\n addMarkerToGroup(marker, model.group, groupOptions, map);\n } // Show label if defined\n\n\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(model.label) && isDefined(model.label.message)) {\n marker.bindTooltip(model.label.message, model.label.options);\n } // Check if the marker should be added to a layer\n\n\n if (isDefined(model) && (isDefined(model.layer) || isDefined(maybeLayerName))) {\n var pass = maybeAddMarkerToLayer(layerName, layers, model, marker, watchOptions.individual.doWatch, map);\n\n if (!pass) {\n continue; //something went wrong move on in the loop\n }\n } else if (!isDefined(model.group)) {\n // We do not have a layer attr, so the marker goes to the map layer\n map.addLayer(marker);\n\n if (!watchOptions.individual.doWatch && model.focus === true) {\n marker.openPopup();\n }\n }\n\n if (watchOptions.individual.doWatch) {\n addMarkerWatcher(marker, pathToMarker, leafletScope, layers, map, watchOptions.individual.isDeep);\n }\n\n listenMarkerEvents(marker, model, leafletScope, watchOptions.individual.doWatch, map);\n esLeafletMarkerEvents.bindEvents(mapId, marker, pathToMarker, model, leafletScope, layerName);\n } else {\n oldModel = isDefined(oldModel) ? oldModels[newName] : undefined;\n updateMarker(model, oldModel, maybeLMarker, pathToMarker, leafletScope, layers, map);\n }\n }\n }\n\n ;\n\n function seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, isEqual, cb) {\n var hasLogged = false;\n var equals = false;\n var oldMarker;\n var newMarker;\n var doCheckOldModel = isDefined(oldMarkerModels) && isDefined(markerModels);\n\n for (var name in lMarkers) {\n if (!hasLogged) {\n $log.debug(\"\".concat(errorHeader, \"[markers] destroy: \"));\n hasLogged = true;\n }\n\n if (doCheckOldModel) {\n //might want to make the option (in watch options) to disable deep checking\n //ie the options to only check !== (reference check) instead of angular.equals (slow)\n newMarker = markerModels[name];\n oldMarker = oldMarkerModels[name];\n equals = angular.equals(newMarker, oldMarker) && isEqual;\n }\n\n if (!isDefined(markerModels) || !Object.keys(markerModels).length || !isDefined(markerModels[name]) || !Object.keys(markerModels[name]).length || equals) {\n if (cb && esLeafletHelpers.isFunction(cb)) {\n cb(newMarker, oldMarker, name);\n }\n }\n }\n }\n\n ;\n\n function destroy(markerModels, oldMarkerModels, lMarkers, map, layers) {\n seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, false, function (newMarker, oldMarker, lMarkerName) {\n $log.debug(\"\".concat(errorHeader, \"[marker] is deleting marker: \") + lMarkerName);\n deleteMarker(lMarkers[lMarkerName], map, layers);\n delete lMarkers[lMarkerName];\n });\n }\n\n ;\n\n function getNewModelsToSkip(newModels, oldModels, lMarkers) {\n var skips = {};\n seeWhatWeAlreadyHave(newModels, oldModels, lMarkers, true, function (newMarker, oldMarker, lMarkerName) {\n $log.debug(\"\".concat(errorHeader, \"[marker] is already rendered, marker: \").concat(lMarkerName));\n skips[lMarkerName] = newMarker;\n });\n return skips;\n }\n\n ;\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").service(\"esLeafletMarkersHelpers\", esLeafletMarkersHelpers);\n esLeafletMarkersHelpers.$inject = [\"$rootScope\", \"$timeout\", \"esLeafletHelpers\", \"$log\", \"$compile\", \"esLeafletGeoJsonHelpers\", \"leafletLib\"];\n\n function esLeafletMarkersHelpers($rootScope, $timeout, esLeafletHelpers, $log, $compile, esLeafletGeoJsonHelpers, L) {\n var isDefined = esLeafletHelpers.isDefined;\n var defaultTo = esLeafletHelpers.defaultTo;\n var MarkerClusterPlugin = esLeafletHelpers.MarkerClusterPlugin;\n var AwesomeMarkersPlugin = esLeafletHelpers.AwesomeMarkersPlugin;\n var VectorMarkersPlugin = esLeafletHelpers.VectorMarkersPlugin;\n var MakiMarkersPlugin = esLeafletHelpers.MakiMarkersPlugin;\n var ExtraMarkersPlugin = esLeafletHelpers.ExtraMarkersPlugin;\n var DomMarkersPlugin = esLeafletHelpers.DomMarkersPlugin;\n var safeApply = esLeafletHelpers.safeApply;\n var groups = {};\n var errorHeader = esLeafletHelpers.errorHeader;\n return {\n deleteMarker: deleteMarker,\n createMarker: createMarker,\n addMarkerToGroup: addMarkerToGroup,\n listenMarkerEvents: listenMarkerEvents,\n updateMarker: updateMarker,\n addMarkerWatcher: addMarkerWatcher\n };\n\n function createLeafletIcon(iconData) {\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"awesomeMarker\") {\n if (!AwesomeMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + \" The AwesomeMarkers Plugin is not loaded.\");\n }\n\n return new L.AwesomeMarkers.Icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"vectorMarker\") {\n if (!VectorMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + \" The VectorMarkers Plugin is not loaded.\");\n }\n\n return new L.VectorMarkers.Icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"makiMarker\") {\n if (!MakiMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + \"The MakiMarkers Plugin is not loaded.\");\n }\n\n return new L.MakiMarkers.Icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"extraMarker\") {\n if (!ExtraMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + \"The ExtraMarkers Plugin is not loaded.\");\n }\n\n return new L.ExtraMarkers.Icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"div\") {\n return new L.DivIcon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"dom\") {\n if (!DomMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + \"The DomMarkers Plugin is not loaded.\");\n }\n\n var markerScope = angular.isFunction(iconData.getMarkerScope) ? iconData.getMarkerScope() : $rootScope;\n var template = $compile(iconData.template)(markerScope);\n var iconDataCopy = angular.copy(iconData);\n iconDataCopy.element = template[0];\n return new L.DomMarkers.Icon(iconDataCopy);\n } // allow for any custom icon to be used... assumes the icon has already been initialized\n\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === \"icon\") {\n return iconData.icon;\n }\n\n var base64icon = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAGmklEQVRYw7VXeUyTZxjvNnfELFuyIzOabermMZEeQC/OclkO49CpOHXOLJl/CAURuYbQi3KLgEhbrhZ1aDwmaoGqKII6odATmH/scDFbdC7LvFqOCc+e95s2VG50X/LLm/f4/Z7neY/ne18aANCmAr5E/xZf1uDOkTcGcWR6hl9247tT5U7Y6SNvWsKT63P58qbfeLJG8M5qcgTknrvvrdDbsT7Ml+tv82X6vVxJE33aRmgSyYtcWVMqX97Yv2JvW39UhRE2HuyBL+t+gK1116ly06EeWFNlAmHxlQE0OMiV6mQCScusKRlhS3QLeVJdl1+23h5dY4FNB3thrbYboqptEFlphTC1hSpJnbRvxP4NWgsE5Jyz86QNNi/5qSUTGuFk1gu54tN9wuK2wc3o+Wc13RCmsoBwEqzGcZsxsvCSy/9wJKf7UWf1mEY8JWfewc67UUoDbDjQC+FqK4QqLVMGGR9d2wurKzqBk3nqIT/9zLxRRjgZ9bqQgub+DdoeCC03Q8j+0QhFhBHR/eP3U/zCln7Uu+hihJ1+bBNffLIvmkyP0gpBZWYXhKussK6mBz5HT6M1Nqpcp+mBCPXosYQfrekGvrjewd59/GvKCE7TbK/04/ZV5QZYVWmDwH1mF3xa2Q3ra3DBC5vBT1oP7PTj4C0+CcL8c7C2CtejqhuCnuIQHaKHzvcRfZpnylFfXsYJx3pNLwhKzRAwAhEqG0SpusBHfAKkxw3w4627MPhoCH798z7s0ZnBJ/MEJbZSbXPhER2ih7p2ok/zSj2cEJDd4CAe+5WYnBCgR2uruyEw6zRoW6/DWJ/OeAP8pd/BGtzOZKpG8oke0SX6GMmRk6GFlyAc59K32OTEinILRJRchah8HQwND8N435Z9Z0FY1EqtxUg+0SO6RJ/mmXz4VuS+DpxXC3gXmZwIL7dBSH4zKE50wESf8qwVgrP1EIlTO5JP9Igu0aexdh28F1lmAEGJGfh7jE6ElyM5Rw/FDcYJjWhbeiBYoYNIpc2FT/SILivp0F1ipDWk4BIEo2VuodEJUifhbiltnNBIXPUFCMpthtAyqws/BPlEF/VbaIxErdxPphsU7rcCp8DohC+GvBIPJS/tW2jtvTmmAeuNO8BNOYQeG8G/2OzCJ3q+soYB5i6NhMaKr17FSal7GIHheuV3uSCY8qYVuEm1cOzqdWr7ku/R0BDoTT+DT+ohCM6/CCvKLKO4RI+dXPeAuaMqksaKrZ7L3FE5FIFbkIceeOZ2OcHO6wIhTkNo0ffgjRGxEqogXHYUPHfWAC/lADpwGcLRY3aeK4/oRGCKYcZXPVoeX/kelVYY8dUGf8V5EBRbgJXT5QIPhP9ePJi428JKOiEYhYXFBqou2Guh+p/mEB1/RfMw6rY7cxcjTrneI1FrDyuzUSRm9miwEJx8E/gUmqlyvHGkneiwErR21F3tNOK5Tf0yXaT+O7DgCvALTUBXdM4YhC/IawPU+2PduqMvuaR6eoxSwUk75ggqsYJ7VicsnwGIkZBSXKOUww73WGXyqP+J2/b9c+gi1YAg/xpwck3gJuucNrh5JvDPvQr0WFXf0piyt8f8/WI0hV4pRxxkQZdJDfDJNOAmM0Ag8jyT6hz0WGXWuP94Yh2jcfjmXAGvHCMslRimDHYuHuDsy2QtHuIavznhbYURq5R57KpzBBRZKPJi8eQg48h4j8SDdowifdIrEVdU+gbO6QNvRRt4ZBthUaZhUnjlYObNagV3keoeru3rU7rcuceqU1mJBxy+BWZYlNEBH+0eH4vRiB+OYybU2hnblYlTvkHinM4m54YnxSyaZYSF6R3jwgP7udKLGIX6r/lbNa9N6y5MFynjWDtrHd75ZvTYAPO/6RgF0k76mQla3FGq7dO+cH8sKn0Vo7nDllwAhqwLPkxrHwWmHJOo+AKJ4rab5OgrM7rVu8eWb2Pu0Dh4eDgXoOfvp7Y7QeqknRmvcTBEyq9m/HQQSCSz6LHq3z0yzsNySRfMS253wl2KyRDbcZPcfJKjZmSEOjcxyi+Y8dUOtsIEH6R2wNykdqrkYJ0RV92H0W58pkfQk7cKevsLK10Py8SdMGfXNXATY+pPbyJR/ET6n9nIfztNtZYRV9XniQu9IA2vOVgy4ir7GCLVmmd+zjkH0eAF9Po6K61pmCXHxU5rHMYd1ftc3owjwRSVRzLjKvqZEty6cRUD7jGqiOdu5HG6MdHjNcNYGqfDm5YRzLBBCCDl/2bk8a8gdbqcfwECu62Fg/HrggAAAABJRU5ErkJggg==\";\n var base64shadow = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAApCAYAAACoYAD2AAAC5ElEQVRYw+2YW4/TMBCF45S0S1luXZCABy5CgLQgwf//S4BYBLTdJLax0fFqmB07nnQfEGqkIydpVH85M+NLjPe++dcPc4Q8Qh4hj5D/AaQJx6H/4TMwB0PeBNwU7EGQAmAtsNfAzoZkgIa0ZgLMa4Aj6CxIAsjhjOCoL5z7Glg1JAOkaicgvQBXuncwJAWjksLtBTWZe04CnYRktUGdilALppZBOgHGZcBzL6OClABvMSVIzyBjazOgrvACf1ydC5mguqAVg6RhdkSWQFj2uxfaq/BrIZOLEWgZdALIDvcMcZLD8ZbLC9de4yR1sYMi4G20S4Q/PWeJYxTOZn5zJXANZHIxAd4JWhPIloTJZhzMQduM89WQ3MUVAE/RnhAXpTycqys3NZALOBbB7kFrgLesQl2h45Fcj8L1tTSohUwuxhy8H/Qg6K7gIs+3kkaigQCOcyEXCHN07wyQazhrmIulvKMQAwMcmLNqyCVyMAI+BuxSMeTk3OPikLY2J1uE+VHQk6ANrhds+tNARqBeaGc72cK550FP4WhXmFmcMGhTwAR1ifOe3EvPqIegFmF+C8gVy0OfAaWQPMR7gF1OQKqGoBjq90HPMP01BUjPOqGFksC4emE48tWQAH0YmvOgF3DST6xieJgHAWxPAHMuNhrImIdvoNOKNWIOcE+UXE0pYAnkX6uhWsgVXDxHdTfCmrEEmMB2zMFimLVOtiiajxiGWrbU52EeCdyOwPEQD8LqyPH9Ti2kgYMf4OhSKB7qYILbBv3CuVTJ11Y80oaseiMWOONc/Y7kJYe0xL2f0BaiFTxknHO5HaMGMublKwxFGzYdWsBF174H/QDknhTHmHHN39iWFnkZx8lPyM8WHfYELmlLKtgWNmFNzQcC1b47gJ4hL19i7o65dhH0Negbca8vONZoP7doIeOC9zXm8RjuL0Gf4d4OYaU5ljo3GYiqzrWQHfJxA6ALhDpVKv9qYeZA8eM3EhfPSCmpuD0AAAAASUVORK5CYII=\";\n\n if (!isDefined(iconData) || !isDefined(iconData.iconUrl)) {\n return new L.Icon.Default({\n iconUrl: base64icon,\n shadowUrl: base64shadow,\n iconSize: [25, 41],\n iconAnchor: [12, 41],\n popupAnchor: [1, -34],\n shadowSize: [41, 41]\n });\n }\n\n return new L.Icon(iconData);\n }\n\n function deleteMarker(marker, map, layers) {\n marker.closePopup(); // There is no easy way to know if a marker is added to a layer, so we search for it\n // if there are overlays\n\n if (isDefined(layers) && isDefined(layers.overlays)) {\n for (var key in layers.overlays) {\n if (layers.overlays[key] instanceof L.LayerGroup || layers.overlays[key] instanceof L.FeatureGroup) {\n if (layers.overlays[key].hasLayer(marker)) {\n layers.overlays[key].removeLayer(marker);\n return;\n }\n }\n }\n }\n\n if (isDefined(groups)) {\n for (var groupKey in groups) {\n if (groups[groupKey].hasLayer(marker)) {\n groups[groupKey].removeLayer(marker);\n }\n }\n }\n\n if (map.hasLayer(marker)) {\n map.removeLayer(marker);\n }\n }\n\n function adjustPopupPan(marker, map) {\n var containerHeight = marker._popup._container.offsetHeight;\n var layerPos = new L.Point(marker._popup._containerLeft, -containerHeight - marker._popup._containerBottom);\n var containerPos = map.layerPointToContainerPoint(layerPos);\n\n if (containerPos !== null) {\n marker._popup._adjustPan();\n }\n }\n\n function compilePopup(marker, markerScope) {\n $compile(marker._popup._contentNode)(markerScope);\n }\n\n function updatePopup(marker, markerScope, map) {\n //The innerText should be more than 1 once angular has compiled.\n //We need to keep trying until angular has compiled before we _updateLayout and _updatePosition\n //This should take care of any scenario , eg ngincludes, whatever.\n //Is there a better way to check for this?\n var innerText = marker._popup._contentNode.innerText || marker._popup._contentNode.textContent;\n\n if (innerText.length < 1) {\n $timeout(function () {\n updatePopup(marker, markerScope, map);\n });\n } //cause a reflow - this is also very important - if we don`t do this then the widths are from before $compile\n\n\n var reflow = marker._popup._contentNode.offsetWidth;\n\n marker._popup._updateLayout();\n\n marker._popup._updatePosition();\n\n if (marker._popup.options.autoPan) {\n adjustPopupPan(marker, map);\n } //using / returning reflow so jshint doesn`t moan\n\n\n return reflow;\n }\n\n function manageOpenPopup(marker, markerData, map) {\n // The marker may provide a scope returning function used to compile the message\n // default to $rootScope otherwise\n var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope;\n var compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true;\n\n if (compileMessage) {\n if (!isDefined(marker._popup) || !isDefined(marker._popup._contentNode)) {\n $log.error(errorHeader + \"Popup is invalid or does not have any content.\");\n return false;\n }\n\n compilePopup(marker, markerScope);\n updatePopup(marker, markerData, map);\n }\n }\n\n function manageOpenLabel(marker, markerData) {\n var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope;\n var labelScope = angular.isFunction(markerData.getLabelScope) ? markerData.getLabelScope() : markerScope;\n var compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true;\n\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(markerData.label)) {\n if (isDefined(markerData.label.options) && markerData.label.options.noHide === true) {\n marker.showLabel();\n }\n\n if (compileMessage && isDefined(marker.label)) {\n $compile(marker.label._container)(labelScope);\n }\n }\n }\n\n function updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map) {\n if (!isDefined(oldMarkerData)) {\n return;\n } // Update the lat-lng property (always present in marker properties)\n\n\n if (!esLeafletGeoJsonHelpers.validateCoords(markerData)) {\n $log.warn(\"There are problems with lat-lng data, please verify your marker model\");\n deleteMarker(marker, map, layers);\n return;\n } // watch is being initialized if old and new object is the same\n\n\n var isInitializing = markerData === oldMarkerData; // Update marker rotation\n\n if (isDefined(markerData.iconAngle) && oldMarkerData.iconAngle !== markerData.iconAngle) {\n marker.setIconAngle(markerData.iconAngle);\n } // It is possible that the layer has been removed or the layer marker does not exist\n // Update the layer group if present or move it to the map if not\n\n\n if (!angular.isString(markerData.layer)) {\n // There is no layer information, we move the marker to the map if it was in a layer group\n if (angular.isString(oldMarkerData.layer)) {\n // Remove from the layer group that is supposed to be\n if (isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) {\n layers.overlays[oldMarkerData.layer].removeLayer(marker);\n marker.closePopup();\n } // Test if it is not on the map and add it\n\n\n if (!map.hasLayer(marker)) {\n map.addLayer(marker);\n }\n }\n }\n\n if ((angular.isNumber(markerData.opacity) || angular.isNumber(parseFloat(markerData.opacity))) && markerData.opacity !== oldMarkerData.opacity) {\n // There was a different opacity so we update it\n marker.setOpacity(markerData.opacity);\n }\n\n if (angular.isString(markerData.layer) && oldMarkerData.layer !== markerData.layer) {\n // If it was on a layer group we have to remove it\n if (angular.isString(oldMarkerData.layer) && isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) {\n layers.overlays[oldMarkerData.layer].removeLayer(marker);\n }\n\n marker.closePopup(); // Remove it from the map in case the new layer is hidden or there is an error in the new layer\n\n if (map.hasLayer(marker)) {\n map.removeLayer(marker);\n } // The markerData.layer is defined so we add the marker to the layer if it is different from the old data\n\n\n if (!isDefined(layers.overlays[markerData.layer])) {\n $log.error(errorHeader + \"You must use a name of an existing layer\");\n return;\n } // Is a group layer?\n\n\n var layerGroup = layers.overlays[markerData.layer];\n\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\n $log.error(errorHeader + \"A marker can only be added to a layer of type 'group' or 'featureGroup'\");\n return;\n } // The marker goes to a correct layer group, so first of all we add it\n\n\n layerGroup.addLayer(marker); // The marker is automatically added to the map depending on the visibility\n // of the layer, so we only have to open the popup if the marker is in the map\n\n if (map.hasLayer(marker) && markerData.focus === true) {\n marker.openPopup();\n }\n } // Update the draggable property\n\n\n if (markerData.draggable !== true && oldMarkerData.draggable === true && isDefined(marker.dragging)) {\n marker.dragging.disable();\n }\n\n if (markerData.draggable === true && oldMarkerData.draggable !== true) {\n // The markerData.draggable property must be true so we update if there wasn't a previous value or it wasn't true\n if (marker.dragging) {\n marker.dragging.enable();\n } else {\n if (L.Handler.MarkerDrag) {\n marker.dragging = new L.Handler.MarkerDrag(marker);\n marker.options.draggable = true;\n marker.dragging.enable();\n }\n }\n } // Update the icon property\n\n\n if (!angular.isObject(markerData.icon)) {\n // If there is no icon property or it`s not an object\n if (angular.isObject(oldMarkerData.icon)) {\n // If there was an icon before restore to the default\n marker.setIcon(createLeafletIcon());\n marker.closePopup();\n marker.unbindPopup();\n\n if (angular.isString(markerData.message)) {\n marker.bindPopup(markerData.message, markerData.popupOptions);\n }\n }\n }\n\n if (angular.isObject(markerData.icon) && angular.isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) {\n var dragG = false;\n\n if (marker.dragging) {\n dragG = marker.dragging.enabled();\n }\n\n marker.setIcon(createLeafletIcon(markerData.icon));\n\n if (dragG) {\n marker.dragging.enable();\n }\n\n marker.closePopup();\n marker.unbindPopup();\n\n if (angular.isString(markerData.message)) {\n marker.bindPopup(markerData.message, markerData.popupOptions); // if marker has been already focused, reopen popup\n\n if (map.hasLayer(marker) && markerData.focus === true) {\n marker.openPopup();\n }\n }\n } // Update the Popup message property\n\n\n if (!angular.isString(markerData.message) && angular.isString(oldMarkerData.message)) {\n marker.closePopup();\n marker.unbindPopup();\n } // Update the label content or bind a new label if the old one has been removed.\n\n\n if (esLeafletHelpers.LabelPlugin.isLoaded()) {\n if (isDefined(markerData.label) && isDefined(markerData.label.message)) {\n if (\"label\" in oldMarkerData && \"message\" in oldMarkerData.label && !angular.equals(markerData.label.message, oldMarkerData.label.message)) {\n marker.updateLabelContent(markerData.label.message);\n } else if (!angular.isFunction(marker.getLabel) || angular.isFunction(marker.getLabel) && !isDefined(marker.getLabel())) {\n marker.bindTooltip(markerData.label.message, markerData.label.options);\n manageOpenLabel(marker, markerData);\n } else {\n manageOpenLabel(marker, markerData);\n }\n } else if (!(\"label\" in markerData && !(\"message\" in markerData.label))) {\n if (angular.isFunction(marker.unbindLabel)) {\n marker.unbindLabel();\n }\n }\n } // There is some text in the popup, so we must show the text or update existing\n\n\n if (angular.isString(markerData.message) && !angular.isString(oldMarkerData.message)) {\n // There was no message before so we create it\n marker.bindPopup(markerData.message, markerData.popupOptions);\n }\n\n if (angular.isString(markerData.message) && angular.isString(oldMarkerData.message) && markerData.message !== oldMarkerData.message) {\n // There was a different previous message so we update it\n marker.setPopupContent(markerData.message);\n } // Update the focus property\n\n\n var updatedFocus = false;\n\n if (markerData.focus !== true && oldMarkerData.focus === true) {\n // If there was a focus property and was true we turn it off\n marker.closePopup();\n updatedFocus = true;\n } // The markerData.focus property must be true so we update if there wasn`t a previous value or it wasn`t true\n\n\n if (markerData.focus === true && (!isDefined(oldMarkerData.focus) || oldMarkerData.focus === false) || isInitializing && markerData.focus === true) {\n // Reopen the popup when focus is still true\n marker.openPopup();\n updatedFocus = true;\n } // zIndexOffset adjustment\n\n\n if (oldMarkerData.zIndexOffset !== markerData.zIndexOffset) {\n marker.setZIndexOffset(markerData.zIndexOffset);\n }\n\n var markerLatLng = marker.getLatLng();\n var isCluster = angular.isString(markerData.layer) && esLeafletHelpers.MarkerClusterPlugin.is(layers.overlays[markerData.layer]); // If the marker is in a cluster it has to be removed and added to the layer when the location is changed\n\n if (isCluster) {\n // The focus has changed even by a user click or programatically\n if (updatedFocus) {\n // We only have to update the location if it was changed programatically, because it was\n // changed by a user drag the marker data has already been updated by the internal event\n // listened by the directive\n if (markerData.lat !== oldMarkerData.lat || markerData.lng !== oldMarkerData.lng) {\n layers.overlays[markerData.layer].removeLayer(marker);\n marker.setLatLng([markerData.lat, markerData.lng]);\n layers.overlays[markerData.layer].addLayer(marker);\n }\n } else {\n // The marker has possibly moved. It can be moved by a user drag (marker location and data are equal but old\n // data is diferent) or programatically (marker location and data are diferent)\n if (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) {\n // The marker was moved by a user drag\n layers.overlays[markerData.layer].removeLayer(marker);\n marker.setLatLng([markerData.lat, markerData.lng]);\n layers.overlays[markerData.layer].addLayer(marker);\n } else if (markerData.lat !== oldMarkerData.lat || markerData.lng !== oldMarkerData.lng) {\n // The marker was moved programatically\n layers.overlays[markerData.layer].removeLayer(marker);\n marker.setLatLng([markerData.lat, markerData.lng]);\n layers.overlays[markerData.layer].addLayer(marker);\n } else if (angular.isObject(markerData.icon) && angular.isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) {\n layers.overlays[markerData.layer].removeLayer(marker);\n layers.overlays[markerData.layer].addLayer(marker);\n }\n }\n } else if (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) {\n marker.setLatLng([markerData.lat, markerData.lng]);\n }\n }\n\n function createMarker(markerData) {\n if (!isDefined(markerData) || !esLeafletGeoJsonHelpers.validateCoords(markerData)) {\n $log.error(errorHeader + \"The marker definition is not valid.\");\n return;\n }\n\n var coords = esLeafletGeoJsonHelpers.getCoords(markerData);\n\n if (!isDefined(coords)) {\n $log.error(errorHeader + \"Unable to get coordinates from markerData.\");\n return;\n }\n\n var markerOptions = {\n icon: createLeafletIcon(markerData.icon),\n title: isDefined(markerData.title) ? markerData.title : \"\",\n draggable: isDefined(markerData.draggable) ? markerData.draggable : false,\n clickable: isDefined(markerData.clickable) ? markerData.clickable : true,\n riseOnHover: isDefined(markerData.riseOnHover) ? markerData.riseOnHover : false,\n zIndexOffset: isDefined(markerData.zIndexOffset) ? markerData.zIndexOffset : 0,\n iconAngle: isDefined(markerData.iconAngle) ? markerData.iconAngle : 0\n }; // Add any other options not added above to markerOptions\n\n for (var markerDatum in markerData) {\n if (markerData.hasOwnProperty(markerDatum) && !markerOptions.hasOwnProperty(markerDatum)) {\n markerOptions[markerDatum] = markerData[markerDatum];\n }\n }\n\n var marker = new L.Marker(coords, markerOptions);\n\n if (!angular.isString(markerData.message)) {\n marker.unbindPopup();\n }\n\n return marker;\n }\n\n function addMarkerToGroup(marker, groupName, groupOptions, map) {\n if (!angular.isString(groupName)) {\n $log.error(errorHeader + \"The marker group you have specified is invalid.\");\n return;\n }\n\n if (!MarkerClusterPlugin.isLoaded()) {\n $log.error(errorHeader + \"The MarkerCluster plugin is not loaded.\");\n return;\n }\n\n if (!isDefined(groups[groupName])) {\n groups[groupName] = new L.MarkerClusterGroup(groupOptions);\n map.addLayer(groups[groupName]);\n }\n\n groups[groupName].addLayer(marker);\n }\n\n function listenMarkerEvents(marker, markerData, leafletScope, doWatch, map) {\n marker.on(\"popupopen\", function ()\n /* event */\n {\n safeApply(leafletScope, function () {\n if (isDefined(marker._popup) || isDefined(marker._popup._contentNode)) {\n markerData.focus = true;\n manageOpenPopup(marker, markerData, map); //needed since markerData is now a copy\n }\n });\n });\n marker.on(\"popupclose\", function ()\n /* event */\n {\n safeApply(leafletScope, function () {\n markerData.focus = false;\n });\n });\n marker.on(\"add\", function ()\n /* event */\n {\n safeApply(leafletScope, function () {\n if (\"label\" in markerData) {\n manageOpenLabel(marker, markerData);\n }\n });\n });\n }\n\n function addMarkerWatcher(marker, name, leafletScope, layers, map, isDeepWatch) {\n var markerWatchPath = esLeafletHelpers.getObjectArrayPath(\"markers.\" + name);\n isDeepWatch = defaultTo(isDeepWatch, true);\n var clearWatch = leafletScope.$watch(markerWatchPath, function (markerData, oldMarkerData) {\n if (!isDefined(markerData)) {\n deleteMarker(marker, map, layers);\n clearWatch();\n return;\n }\n\n updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map);\n }, isDeepWatch);\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletPathEvents\", esLeafletPathEvents);\n esLeafletPathEvents.$inject = [\"$rootScope\", \"$q\", \"$log\", \"esLeafletHelpers\", \"esLeafletLabelEvents\", \"esLeafletEventsHelpers\"];\n\n function esLeafletPathEvents($rootScope, $q, $log, esLeafletHelpers, esLeafletLabelEvents, esLeafletEventsHelpers) {\n var isDefined = esLeafletHelpers.isDefined;\n var isObject = angular.isObject;\n var Helpers = esLeafletHelpers;\n var errorHeader = esLeafletHelpers.errorHeader;\n var lblHelp = esLeafletLabelEvents;\n var fire = esLeafletEventsHelpers.fire;\n\n var _genDispatchPathEvent = function _genDispatchPathEvent(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\n maybeMapId = maybeMapId || \"\";\n\n if (maybeMapId) {\n maybeMapId = \".\" + maybeMapId;\n }\n\n return function (e) {\n var broadcastName = \"leafletDirectivePath\" + maybeMapId + \".\" + eventName;\n $log.debug(broadcastName);\n fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName);\n };\n };\n\n var _bindPathEvents = function _bindPathEvents(maybeMapId, lObject, name, model, leafletScope) {\n var pathEvents = [];\n var i;\n var eventName;\n var logic = \"broadcast\";\n\n if (!isDefined(leafletScope.eventBroadcast)) {\n // Backward compatibility, if no event-broadcast attribute, all events are broadcasted\n pathEvents = _getAvailablePathEvents();\n } else if (!isObject(leafletScope.eventBroadcast)) {\n // Not a valid object\n $log.error(errorHeader + \"event-broadcast must be an object check your model.\");\n } else {\n // We have a possible valid object\n if (!isDefined(leafletScope.eventBroadcast.path)) {\n // We do not have events enable/disable do we do nothing (all enabled by default)\n pathEvents = _getAvailablePathEvents();\n } else if (isObject(leafletScope.eventBroadcast.paths)) {\n // Not a valid object\n $log.warn(errorHeader + \"event-broadcast.path must be an object check your model.\");\n } else {\n // We have a possible valid map object\n // Event propadation logic\n if (leafletScope.eventBroadcast.path.logic !== undefined && leafletScope.eventBroadcast.path.logic !== null) {\n // We take care of possible propagation logic\n if (leafletScope.eventBroadcast.path.logic !== \"emit\" && leafletScope.eventBroadcast.path.logic !== \"broadcast\") {\n // This is an error\n $log.warn(errorHeader + \"Available event propagation logic are: `emit` or `broadcast`.\");\n } else if (leafletScope.eventBroadcast.path.logic === \"emit\") {\n logic = \"emit\";\n }\n } // Enable / Disable\n\n\n var pathEventsEnable = false;\n var pathEventsDisable = false;\n\n if (leafletScope.eventBroadcast.path.enable !== undefined && leafletScope.eventBroadcast.path.enable !== null) {\n if (typeof leafletScope.eventBroadcast.path.enable === \"object\") {\n pathEventsEnable = true;\n }\n }\n\n if (leafletScope.eventBroadcast.path.disable !== undefined && leafletScope.eventBroadcast.path.disable !== null) {\n if (typeof leafletScope.eventBroadcast.path.disable === \"object\") {\n pathEventsDisable = true;\n }\n }\n\n if (pathEventsEnable && pathEventsDisable) {\n // Both are active, this is an error\n $log.warn(errorHeader + \"can not enable and disable events at the same time\");\n } else if (!pathEventsEnable && !pathEventsDisable) {\n // Both are inactive, this is an error\n $log.warn(errorHeader + \"must enable or disable events\");\n } else {\n // At this point the path object is OK, lets enable or disable events\n if (pathEventsEnable) {\n // Enable events\n for (i = 0; i < leafletScope.eventBroadcast.path.enable.length; i++) {\n eventName = leafletScope.eventBroadcast.path.enable[i]; // Do we have already the event enabled?\n\n if (pathEvents.indexOf(eventName) !== -1) {\n // Repeated event, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" is already enabled\");\n } else {\n // Does the event exists?\n if (_getAvailablePathEvents().indexOf(eventName) === -1) {\n // The event does not exists, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist\");\n } else {\n // All ok enable the event\n pathEvents.push(eventName);\n }\n }\n }\n } else {\n // Disable events\n pathEvents = _getAvailablePathEvents();\n\n for (i = 0; i < leafletScope.eventBroadcast.path.disable.length; i++) {\n eventName = leafletScope.eventBroadcast.path.disable[i];\n var index = pathEvents.indexOf(eventName);\n\n if (index === -1) {\n // The event does not exist\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist or has been already disabled\");\n } else {\n pathEvents.splice(index, 1);\n }\n }\n }\n }\n }\n }\n\n for (i = 0; i < pathEvents.length; i++) {\n eventName = pathEvents[i];\n lObject.on(eventName, _genDispatchPathEvent(maybeMapId, eventName, logic, leafletScope, pathEvents, name));\n }\n\n if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) {\n lblHelp.genEvents(maybeMapId, name, logic, leafletScope, lObject, model);\n }\n };\n\n var _getAvailablePathEvents = function _getAvailablePathEvents() {\n return [\"click\", \"dblclick\", \"mousedown\", \"mouseover\", \"mouseout\", \"contextmenu\", \"add\", \"remove\", \"popupopen\", \"popupclose\"];\n };\n\n return {\n getAvailablePathEvents: _getAvailablePathEvents,\n bindPathEvents: _bindPathEvents\n };\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").directive(\"paths\", paths);\n paths.$inject = [\"$log\", \"$q\", \"leafletLib\", \"esLeafletData\", \"esLeafletMapDefaults\", \"esLeafletHelpers\", \"esLeafletPathsHelpers\", \"esLeafletPathEvents\"];\n\n function paths($log, $q, L, esLeafletData, esLeafletMapDefaults, esLeafletHelpers, esLeafletPathsHelpers, esLeafletPathEvents) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: [\"esLeaflet\", \"?layers\"],\n link: link\n };\n\n function link(scope, element, attrs, controller) {\n var mapController = controller[0];\n var isDefined = esLeafletHelpers.isDefined;\n var isString = angular.isString;\n var leafletScope = mapController.getLeafletScope();\n var createPath = esLeafletPathsHelpers.createPath;\n var bindPathEvents = esLeafletPathEvents.bindPathEvents;\n var setPathOptions = esLeafletPathsHelpers.setPathOptions;\n mapController.getMap().then(function (map) {\n var defaults = esLeafletMapDefaults.getDefaults(attrs.id);\n var getLayers; // If the layers attribute is used, we must wait until the layers are created\n\n if (isDefined(controller[1])) {\n getLayers = controller[1].getLayers;\n } else {\n getLayers = function getLayers() {\n var deferred = $q.defer();\n deferred.resolve();\n return deferred.promise;\n };\n }\n\n getLayers().then(function (layers) {\n var leafletPaths = {};\n esLeafletData.setPaths(leafletPaths, attrs.id); // Should we watch for every specific marker on the map?\n\n var shouldWatch = !isDefined(attrs.watchPaths) || attrs.watchPaths === \"true\"; // Function for listening every single path once created\n\n var watchPathFn = function watchPathFn(leafletPath, name) {\n var clearWatch = leafletScope.$watch(\"paths[\\\"\" + name + \"\\\"]\", function (pathData, old) {\n if (!isDefined(pathData)) {\n if (isDefined(old.layer)) {\n for (var i in layers.overlays) {\n if (layers.overlays.hasOwnProperty(i)) {\n var overlay = layers.overlays[i];\n overlay.removeLayer(leafletPath);\n }\n }\n }\n\n map.removeLayer(leafletPath);\n clearWatch();\n return;\n }\n\n setPathOptions(leafletPath, pathData.type, pathData);\n }, true);\n };\n\n leafletScope.$watchCollection(\"paths\", function (newPaths) {\n // Delete paths (by name) from the array\n for (var name in leafletPaths) {\n if (!isDefined(newPaths[name])) {\n map.removeLayer(leafletPaths[name]);\n delete leafletPaths[name];\n }\n } // Create the new paths\n\n\n for (var newName in newPaths) {\n if (newName.search(\"\\\\$\") === 0) {\n continue;\n }\n\n if (newName.search(\"-\") !== -1) {\n $log.error(\"[AngularJS - Leaflet] The path name \\\"\" + newName + \"\\\" is not valid. It must not include \\\"-\\\" and a number.\");\n continue;\n }\n\n if (!isDefined(leafletPaths[newName])) {\n var pathData = newPaths[newName];\n var newPath = createPath(newName, newPaths[newName], defaults); // bind popup if defined\n\n if (isDefined(newPath) && isDefined(pathData.message)) {\n newPath.bindPopup(pathData.message, pathData.popupOptions);\n } // Show label if defined\n\n\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(pathData.label) && isDefined(pathData.label.message)) {\n newPath.bindLabel(pathData.label.message, pathData.label.options);\n } // Check if the marker should be added to a layer\n\n\n if (isDefined(pathData) && isDefined(pathData.layer)) {\n if (!isString(pathData.layer)) {\n $log.error(\"[AngularJS - Leaflet] A layername must be a string\");\n continue;\n }\n\n if (!isDefined(layers)) {\n $log.error(\"[AngularJS - Leaflet] You must add layers to the directive if the markers are going to use this functionality.\");\n continue;\n }\n\n if (!isDefined(layers.overlays) || !isDefined(layers.overlays[pathData.layer])) {\n $log.error(\"[AngularJS - Leaflet] A path can only be added to a layer of type \\\"group\\\"\");\n continue;\n }\n\n var layerGroup = layers.overlays[pathData.layer];\n\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\n $log.error(\"[AngularJS - Leaflet] Adding a path to an overlay needs a overlay of the type \\\"group\\\" or \\\"featureGroup\\\"\");\n continue;\n } // Listen for changes on the new path\n\n\n leafletPaths[newName] = newPath; // The path goes to a correct layer group, so first of all we add it\n\n layerGroup.addLayer(newPath);\n\n if (shouldWatch) {\n watchPathFn(newPath, newName);\n } else {\n setPathOptions(newPath, pathData.type, pathData);\n }\n } else if (isDefined(newPath)) {\n // Listen for changes on the new path\n leafletPaths[newName] = newPath;\n map.addLayer(newPath);\n\n if (shouldWatch) {\n watchPathFn(newPath, newName);\n } else {\n setPathOptions(newPath, pathData.type, pathData);\n }\n }\n\n bindPathEvents(attrs.id, newPath, newName, pathData, leafletScope);\n }\n }\n });\n });\n });\n }\n\n ;\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").factory(\"esLeafletPathsHelpers\", esLeafletPathsHelpers);\n esLeafletPathsHelpers.$inject = [\"$rootScope\", \"$log\", \"leafletLib\", \"esLeafletHelpers\"];\n\n function esLeafletPathsHelpers($rootScope, $log, L, esLeafletHelpers) {\n var isDefined = esLeafletHelpers.isDefined;\n var isArray = angular.isArray;\n var isNumber = angular.isNumber;\n var isValidPoint = esLeafletHelpers.isValidPoint;\n var availableOptions = [// Path options\n \"stroke\", \"weight\", \"color\", \"opacity\", \"fill\", \"fillColor\", \"fillOpacity\", \"dashArray\", \"lineCap\", \"lineJoin\", \"clickable\", \"pointerEvents\", \"className\", // Polyline options\n \"smoothFactor\", \"noClip\"];\n\n function _convertToLeafletLatLngs(latlngs) {\n return latlngs.filter(function (latlng) {\n return isValidPoint(latlng);\n }).map(function (latlng) {\n return _convertToLeafletLatLng(latlng);\n });\n }\n\n function _convertToLeafletLatLng(latlng) {\n if (isArray(latlng)) {\n return new L.LatLng(latlng[0], latlng[1]);\n } else {\n return new L.LatLng(latlng.lat, latlng.lng);\n }\n }\n\n function _convertToLeafletMultiLatLngs(paths) {\n return paths.map(function (latlngs) {\n return _convertToLeafletLatLngs(latlngs);\n });\n }\n\n function _getOptions(path, defaults) {\n var options = {};\n\n for (var i = 0; i < availableOptions.length; i++) {\n var optionName = availableOptions[i];\n\n if (isDefined(path[optionName])) {\n options[optionName] = path[optionName];\n } else if (isDefined(defaults.path[optionName])) {\n options[optionName] = defaults.path[optionName];\n }\n }\n\n return options;\n }\n\n var _updatePathOptions = function _updatePathOptions(path, data) {\n var updatedStyle = {};\n\n for (var i = 0; i < availableOptions.length; i++) {\n var optionName = availableOptions[i];\n\n if (isDefined(data[optionName])) {\n updatedStyle[optionName] = data[optionName];\n }\n }\n\n path.setStyle(data);\n };\n\n var _isValidPolyline = function _isValidPolyline(latlngs) {\n if (!isArray(latlngs)) {\n return false;\n }\n\n for (var i = 0; i < latlngs.length; i++) {\n var point = latlngs[i];\n\n if (!isValidPoint(point)) {\n return false;\n }\n }\n\n return true;\n };\n\n var pathTypes = {\n polyline: {\n isValid: function isValid(pathData) {\n var latlngs = pathData.latlngs;\n return _isValidPolyline(latlngs);\n },\n createPath: function createPath(options) {\n return new L.Polyline([], options);\n },\n setPath: function setPath(path, data) {\n path.setLatLngs(_convertToLeafletLatLngs(data.latlngs));\n\n _updatePathOptions(path, data);\n }\n },\n multiPolyline: {\n isValid: function isValid(pathData) {\n var latlngs = pathData.latlngs;\n\n if (!isArray(latlngs)) {\n return false;\n }\n\n for (var i in latlngs) {\n if (latlngs.hasOwnProperty(i)) {\n var polyline = latlngs[i];\n\n if (!_isValidPolyline(polyline)) {\n return false;\n }\n }\n }\n\n return true;\n },\n createPath: function createPath(options) {\n return new L.MultiPolyline([[[0, 0], [1, 1]]], options);\n },\n setPath: function setPath(path, data) {\n path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs));\n\n _updatePathOptions(path, data);\n }\n },\n polygon: {\n isValid: function isValid(pathData) {\n var latlngs = pathData.latlngs;\n return _isValidPolyline(latlngs);\n },\n createPath: function createPath(options) {\n return new L.Polygon([], options);\n },\n setPath: function setPath(path, data) {\n path.setLatLngs(_convertToLeafletLatLngs(data.latlngs));\n\n _updatePathOptions(path, data);\n }\n },\n multiPolygon: {\n isValid: function isValid(pathData) {\n var latlngs = pathData.latlngs;\n\n if (!isArray(latlngs)) {\n return false;\n }\n\n for (var i in latlngs) {\n if (latlngs.hasOwnProperty(i)) {\n var polyline = latlngs[i];\n\n if (!_isValidPolyline(polyline)) {\n return false;\n }\n }\n }\n\n return true;\n },\n createPath: function createPath(options) {\n return new L.MultiPolygon([[[0, 0], [1, 1], [0, 1]]], options);\n },\n setPath: function setPath(path, data) {\n path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs));\n\n _updatePathOptions(path, data);\n }\n },\n rectangle: {\n isValid: function isValid(pathData) {\n var latlngs = pathData.latlngs;\n\n if (!isArray(latlngs) || latlngs.length !== 2) {\n return false;\n }\n\n for (var i in latlngs) {\n if (latlngs.hasOwnProperty(i)) {\n var point = latlngs[i];\n\n if (!isValidPoint(point)) {\n return false;\n }\n }\n }\n\n return true;\n },\n createPath: function createPath(options) {\n return new L.Rectangle([[0, 0], [1, 1]], options);\n },\n setPath: function setPath(path, data) {\n path.setBounds(new L.LatLngBounds(_convertToLeafletLatLngs(data.latlngs)));\n\n _updatePathOptions(path, data);\n }\n },\n circle: {\n isValid: function isValid(pathData) {\n var point = pathData.latlngs;\n return isValidPoint(point) && isNumber(pathData.radius);\n },\n createPath: function createPath(options) {\n return new L.Circle([0, 0], 1, options);\n },\n setPath: function setPath(path, data) {\n path.setLatLng(_convertToLeafletLatLng(data.latlngs));\n\n if (isDefined(data.radius)) {\n path.setRadius(data.radius);\n }\n\n _updatePathOptions(path, data);\n }\n },\n circleMarker: {\n isValid: function isValid(pathData) {\n var point = pathData.latlngs;\n return isValidPoint(point) && isNumber(pathData.radius);\n },\n createPath: function createPath(options) {\n return new L.CircleMarker([0, 0], options);\n },\n setPath: function setPath(path, data) {\n path.setLatLng(_convertToLeafletLatLng(data.latlngs));\n\n if (isDefined(data.radius)) {\n path.setRadius(data.radius);\n }\n\n _updatePathOptions(path, data);\n }\n }\n };\n\n var _getPathData = function _getPathData(path) {\n var pathData = {};\n\n if (path.latlngs) {\n pathData.latlngs = path.latlngs;\n }\n\n if (path.radius) {\n pathData.radius = path.radius;\n }\n\n return pathData;\n };\n\n return {\n setPathOptions: function setPathOptions(leafletPath, pathType, data) {\n if (!isDefined(pathType)) {\n pathType = \"polyline\";\n }\n\n pathTypes[pathType].setPath(leafletPath, data);\n },\n createPath: function createPath(name, path, defaults) {\n if (!isDefined(path.type)) {\n path.type = \"polyline\";\n }\n\n var options = _getOptions(path, defaults);\n\n var pathData = _getPathData(path);\n\n if (!pathTypes[path.type].isValid(pathData)) {\n $log.error(\"[AngularJS - Leaflet] Invalid data passed to the \" + path.type + \" path\");\n return;\n }\n\n return pathTypes[path.type].createPath(options);\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n angular.module(\"es-leaflet-directive\").service(\"esLeafletWatchHelpers\", esLeafletWatchHelpers);\n\n function esLeafletWatchHelpers() {\n return {\n maybeWatch: maybeWatch\n };\n /*\r\n @name: maybeWatch\r\n @description: Utility to watch something once or forever.\r\n @returns unWatch function\r\n @param watchOptions - see markersWatchOptions and or derrivatives. This object is used\r\n to set watching to once and its watch depth.\r\n */\n\n function maybeWatch(scope, thingToWatchStr, watchOptions, initCb) {\n return maybe(scope, \"$watch\", thingToWatchStr, watchOptions, initCb);\n }\n\n function maybe(scope, watchFunctionName, thingToWatchStr, watchOptions, initCb) {\n //watchOptions.isDeep is/should be ignored in $watchCollection\n var unWatch = scope[watchFunctionName](thingToWatchStr, function (newValue, oldValue) {\n initCb(newValue, oldValue);\n\n if (!watchOptions.doWatch) {\n unWatch();\n }\n }, watchOptions.isDeep);\n return unWatch;\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n/* eslint-disable no-extend-native */\n\n\nNumber.prototype.toRad = function () {\n return this * Math.PI / 180;\n};\n\nNumber.prototype.toDeg = function () {\n return this * 180 / Math.PI;\n};\n\nNumber.prototype.toBrng = function () {\n return (this.toDeg() + 360) % 360;\n};\n/* eslint-enable no-extend-native */\n\n\n\"use strict\";\n\n(function () {\n 'use strict';\n\n angular.module(\"app\").config(configureRouteAliases).run(appRun);\n configureRouteAliases.$inject = [\"$urlRouterProvider\"];\n\n function configureRouteAliases($urlRouterProvider) {\n $urlRouterProvider.when(\"/\", redirectToDashboard);\n redirectToDashboard.$inject = [\"$state\", \"app.core.appSettings\"];\n\n function redirectToDashboard($state, appSettings) {\n if ($state.current.name === \"not-found\") {\n return;\n }\n\n $state.go(\"app.dashboard\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias\n });\n }\n }\n\n appRun.$inject = [\"routeHelper\"];\n\n function appRun(routeHelper) {\n routeHelper.configureRoutes(getRoutes());\n }\n\n function getRoutes() {\n return [{\n state: \"app\",\n abstract: true,\n templateUrl: \"/App/ui/core/layout/shell.html\",\n controller: \"app.ui.core.layout.Shell as vm\",\n resolve: {\n companyFacilities: companyFacilities\n },\n data: {\n layoutType: \"full\"\n },\n settings: {\n i18n: [\"/App/ui/core/layout/i18n/Shell\", \"/App/ui/core/alerts/controls/i18n/esAlerts\", \"/App/ui/core/messages/controls/i18n/esMessages\", \"/App/ui/core/jobs/controls/i18n/esJobs\", \"/App/core/models/jobs/i18n/Job\"]\n }\n }, {\n state: \"not-found\",\n url: \"*path\",\n templateUrl: \"/App/ui/core/NotFound.html\",\n controller: \"NotFound as vm\"\n }, {\n state: \"forbidden\",\n templateUrl: \"/App/ui/core/Forbidden.html\",\n controller: \"Forbidden as vm\"\n }];\n }\n\n companyFacilities.$inject = [\"app.core.services.companyService\"];\n\n function companyFacilities(companyService) {\n return companyService.getCompanies();\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esAlertDropdownOpener\", esAlertDropdownOpener);\n esAlertDropdownOpener.$inject = [];\n\n function esAlertDropdownOpener() {\n return {\n restrict: \"A\",\n link: link\n };\n\n function link($scope, $element) {\n var vm = $scope.vm;\n $scope.$watch(function () {\n return vm.openDropdown;\n }, function () {\n if (vm.openDropdown) {\n $element.addClass(\"open\");\n vm.openDropdown = false;\n }\n });\n $scope.$watch(function () {\n return vm.closeDropdown;\n }, function () {\n if (vm.closeDropdown) {\n $element.removeClass(\"open\");\n vm.closeDropdown = false;\n }\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esAlertLevelSpinner\", esAlertLevelSpinner);\n esAlertLevelSpinner.$inject = [\"$timeout\"];\n\n function esAlertLevelSpinner($timeout) {\n return {\n restrict: \"A\",\n link: link\n };\n\n function link($scope, $element) {\n var alert = $scope.alert;\n $scope.$watch(function () {\n return alert.level;\n }, function () {\n if ($scope.alert.hasLevelIncreased) {\n $element.removeClass(\"decreased\").addClass(\"increased bounce\");\n $timeout(function () {\n $element.removeClass(\"bounce\");\n }, 1000);\n } else {\n $element.removeClass(\"increased\").addClass(\"decreased bounce\");\n $timeout(function () {\n $element.removeClass(\"bounce\");\n }, 1000);\n }\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esAlerts\", esAlerts).controller(\"esAlertsController\", esAlertsController);\n esAlerts.$inject = [];\n\n function esAlerts() {\n return {\n scope: {},\n restrict: \"EA\",\n templateUrl: \"/App/ui/core/alerts/controls/esAlerts.html\",\n controller: esAlertsController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esAlertsController.$inject = [\"$scope\", \"$state\", \"$timeout\", \"lodash\", \"postal\", \"app.core.appSettings\", \"app.core.services.alertService\", \"app.core.signalR.alerts.state\", \"app.core.signalR.alerts.events\"];\n\n function esAlertsController($scope, $state, $timeout, _, postal, appSettings, alertService, state, alertEvents) {\n var subscriptions;\n var vm = this;\n var dismissedAlerts = {};\n vm.state = state;\n vm.alertCount = 0;\n vm.goToAlertHistory = goToAlertHistory;\n vm.dismissAlert = dismissAlert;\n vm.appSettings = appSettings;\n activate(); //////////////////////\n\n function activate() {\n $scope.$watch(function () {\n return appSettings.site.accessControls;\n }, refreshAlerts);\n $scope.$watch(function () {\n return vm.state.alerts.length;\n }, function () {\n $timeout(function () {\n vm.alertCount = vm.state.alerts.length;\n }, 600); // allow for the removal/addition animations to complete before updating the badge count\n });\n $scope.$on(\"$destroy\", unsubscribeFromNotifications);\n }\n\n function refreshAlerts() {\n unsubscribeFromNotifications();\n state.alerts.length = 0;\n alertService.getActiveWebAlerts().then(function (activeAlerts) {\n state.alerts.push.apply(state.alerts, activeAlerts);\n subscribeToNotifications();\n });\n }\n\n function dismissAlert(alert) {\n dismissedAlerts[alert.alertEventSourceId] = alert.level;\n removeAlertFromState(alert);\n alertService.dismissWebAlert(alert.id);\n }\n\n function goToAlertHistory() {\n vm.closeDropdown = true;\n $state.go(\"app.alerts\", {\n companyAlias: vm.appSettings.site.company.alias,\n facilityAlias: vm.appSettings.site.facility.alias\n });\n }\n\n function subscribeToNotifications() {\n var channel = postal.channel(alertEvents.channelName);\n subscriptions = [channel.subscribe(alertEvents.topics.notify, onAlertNotification), channel.subscribe(alertEvents.topics.dismiss, onAlertDismiss)];\n }\n\n function onAlertNotification(alert) {\n if (isAlertDismissed(alert)) {\n return;\n }\n\n var existingAlert = getAlertForSourceId(alert.alertEventSourceId);\n\n if (!existingAlert) {\n // cater for duplicate events where an alert has been downgraded to level 0.\n // the first event will remove it from the list. without this check the second event will add it back at the top.\n if (alert.level <= 0) {\n return;\n }\n\n moveAlertToFrontOfTheList(alert, true);\n } else {\n updateExistingAlert(existingAlert, alert);\n\n if (existingAlert.level <= 0) {\n removeAlertFromState(existingAlert);\n } else if (existingAlert.hasLevelIncreased) {\n moveAlertToFrontOfTheList(existingAlert);\n }\n }\n\n function isAlertDismissed(alert) {\n if (dismissedAlerts[alert.alertEventSourceId]) {\n if (alert.level <= dismissedAlerts[alert.alertEventSourceId]) {\n dismissedAlerts[alert.alertEventSourceId] = alert.level;\n return true;\n }\n\n delete dismissedAlerts[alert.alertEventSourceId];\n }\n\n return false;\n }\n }\n\n function getAlertForSourceId(alertEventSourceId) {\n return _.find(state.alerts, {\n alertEventSourceId: alertEventSourceId\n });\n }\n\n function updateExistingAlert(existingAlert, updateAlert) {\n existingAlert.id = updateAlert.id;\n existingAlert.level = updateAlert.level;\n existingAlert.name = updateAlert.name;\n existingAlert.message = updateAlert.message;\n existingAlert.triggerTime = updateAlert.triggerTime;\n existingAlert.sentTime = updateAlert.sentTime;\n }\n\n function removeAlertFromState(alert) {\n _.remove(state.alerts, {\n alertEventSourceId: alert.alertEventSourceId\n });\n }\n\n function moveAlertToFrontOfTheList(alert, isNewAlert) {\n vm.openDropdown = true;\n\n if (isNewAlert) {\n state.alerts.unshift(alert);\n return;\n }\n\n removeAlertFromState(alert);\n delete alert.$$hashKey; // NOTE: we delete the $$hashKey so that the ngRepeater treats this as a new object and applies the ng-leave and ng-enter animation events.\n\n state.alerts.unshift(alert);\n }\n\n function onAlertDismiss(alertId) {\n _.remove(state.alerts, {\n id: alertId\n });\n }\n\n function unsubscribeFromNotifications() {\n _.invokeMap(subscriptions, \"unsubscribe\");\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.core\").directive(\"esAccordionPreventCollapse\", esAccordionPreventCollapse);\n /* istanbul ignore next */\n\n esAccordionPreventCollapse.$inject = [\"$timeout\"];\n\n function esAccordionPreventCollapse($timeout) {\n return {\n restrict: \"A\",\n link: link\n };\n\n function link($scope, $element) {\n activate();\n\n function activate() {\n $timeout(preventCollapsingOpenPanelOnClick);\n } //////////////\n // we want to have one panel open at al times\n\n\n function preventCollapsingOpenPanelOnClick() {\n var accordionLinks = $element.find(\".panel-heading a a\");\n accordionLinks.on(\"click\", stopPropagation);\n $scope.$on(\"$destroy\", removeHandler);\n\n function removeHandler() {\n accordionLinks.off(\"click\", stopPropagation);\n }\n\n function stopPropagation(e) {\n if (angular.element(this).parents(\".panel\").children(\".panel-collapse\").hasClass(\"in\")) {\n e.stopPropagation();\n }\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esAddressLookup\", directive).controller(\"esAddressLookupController\", controller);\n directive.$inject = [];\n /* istanbul ignore next */\n\n function directive() {\n return {\n restrict: \"E\",\n templateUrl: \"/App/ui/core/controls/esAddressLookup.html\",\n require: [\"ngModel\"],\n scope: {\n model: \"=ngModel\",\n boundaries: \"=?\"\n },\n link: link,\n controller: \"esAddressLookupController\",\n controllerAs: \"vm\",\n bindToController: true\n };\n\n function link($scope, $element, attrs, controllers) {\n $scope.vm.configureAutoComplete($element.find(\"#address\")[0], controllers[0]);\n }\n }\n\n controller.$inject = [\"$scope\", \"$timeout\", \"google\", \"lodash\"];\n\n function controller($scope, $timeout, google, _) {\n var vm = this;\n vm.configureAutoComplete = configureAutoComplete;\n var locationChangedUnwatch;\n activate(); ////////////////\n\n function activate() {\n watchLocation();\n watchBoundaries();\n }\n\n function watchBoundaries() {\n $scope.$watchGroup([function () {\n return vm.boundaries;\n }, function () {\n return vm.autocomplete;\n }], updateBounds);\n\n function updateBounds() {\n if (vm.autocomplete) {\n if (vm.boundaries) {\n setAutocompleteBounds();\n } else {\n vm.autocomplete.setOptions({\n strictBounds: false\n });\n }\n }\n }\n\n function setAutocompleteBounds() {\n var bounds = new google.maps.LatLngBounds();\n vm.boundaries.forEach(function (boundary) {\n var _boundary = _slicedToArray(boundary, 2),\n lat = _boundary[0],\n lng = _boundary[1];\n\n bounds.extend({\n lat: lat,\n lng: lng\n });\n });\n vm.autocomplete.setOptions({\n bounds: bounds,\n strictBounds: true\n });\n }\n }\n\n function watchLocation() {\n locationChangedUnwatch = $scope.$watch(function () {\n return vm.model;\n }, locationChanged, true);\n\n function locationChanged(newValue, oldValue) {\n if (newValue && oldValue) {\n if (newValue.address === oldValue.address && (newValue.latitude !== oldValue.latitude || newValue.longitude !== oldValue.longitude)) {\n //lat & lng changed, but the address didn't. This was prob via the map pin or something.\n try {\n locationChangedUnwatch();\n vm.model.address = \"\".concat(newValue.latitude, \", \").concat(newValue.longitude);\n } finally {\n watchLocation();\n }\n } else if (newValue.address !== oldValue.address && newValue.latitude === oldValue.latitude && newValue.longitude === oldValue.longitude) {\n //address changed, but not lat & lng. This is prob due to user entering text into textbox.\n try {\n locationChangedUnwatch();\n var latLngMatch = newValue.address.match(/^(-?\\d+(?:\\.\\d+)?),\\s?(-?\\d+(?:\\.\\d+)?)$/);\n\n if (latLngMatch && latLngMatch.length === 3) {\n //[Entire Match, First Group, Second Group]\n var _latLngMatch = _slicedToArray(latLngMatch, 3),\n latitude = _latLngMatch[1],\n longitude = _latLngMatch[2];\n\n vm.model.latitude = latitude;\n vm.model.longitude = longitude;\n } else {\n vm.model.latitude = null;\n vm.model.longitude = null;\n }\n\n vm.controller.$setDirty();\n } finally {\n watchLocation();\n }\n }\n }\n }\n }\n\n function configureAutoComplete(element, controller) {\n vm.controller = controller;\n vm.autocomplete = new google.maps.places.Autocomplete(element); //todo : should we limit the types? { types: [`address_components`] }\n\n element.onfocus = function () {\n return vm.controller.$setTouched();\n };\n\n vm.autocomplete.addListener(\"place_changed\", function () {\n var place = vm.autocomplete.getPlace();\n\n if (place.geometry) {\n $timeout(function () {\n return addressPicked(place.geometry.location.lat(), place.geometry.location.lng(), place.formatted_address);\n });\n }\n });\n }\n\n function addressPicked(lat, lng, address) {\n try {\n locationChangedUnwatch();\n vm.model.latitude = lat;\n vm.model.longitude = lng;\n vm.model.address = address;\n vm.controller.$setDirty();\n } finally {\n watchLocation();\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esBusyLoading\", esBusyLoading);\n esBusyLoading.$inject = [\"$compile\", \"i18n\", \"esPageBlocker\"];\n\n function esBusyLoading($compile, i18n, esPageBlocker) {\n // Usage:\n //
    \n //\n // **** NOTE: ******\n //\n // Always stick this directive on an element with no other directives (including
    ) as it doesn't play nicely.\n //\n // *****************\n var blockerCount = 0; // used to generate unique named instances\n\n return {\n restrict: \"EA\",\n compile: compile,\n priority: 1000,\n terminal: true\n };\n\n function compile($target) {\n // We have to remove the db-busy attribute otherwise we end up in an infinite loop when we compile.\n var busy = $target.attr(\"es-busy-loading\") || $target.attr(\"data-es-busy-loading\");\n $target.removeAttr(\"es-busy-loading\").removeAttr(\"data-es-busy-loading\");\n return {\n post: function post($scope, $element) {\n var blockerName = $element.attr(\"data-es-busy-loading-id\");\n\n if (!blockerName) {\n // the directive wasn't given an existing block-ui identifier\n blockerName = \"block-ui-loading-\" + ++blockerCount; // eslint-disable-line no-extra-parens\n\n $element.attr(\"block-ui\", blockerName);\n }\n\n $compile($element)($scope);\n var busyTracker = $scope.$eval(busy); // note: this hack makes me cry; the esPageBlock watches the active function which is insane.\n\n if (typeof busyTracker.active !== \"function\") {\n busyTracker = {\n active: function active() {\n return !!$scope.$eval(busy);\n } // we are using !! to account for incrementing/decrementing loading counters rather than just true/false properties\n\n };\n }\n\n var messageKey = $element.attr(\"data-es-busy-loading-message-key\") || \"activityIndicator.loading.label\";\n var loadingMessage = i18n.i10n(messageKey);\n esPageBlocker.create($scope, blockerName, busyTracker, loadingMessage);\n }\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esBusySaving\", esBusySaving);\n esBusySaving.$inject = [\"i18n\", \"esPageBlocker\"];\n\n function esBusySaving(i18n, esPageBlocker) {\n // Usage:\n //
    \n //\n // **** NOTE: ******\n //\n // Always stick this directive on an element with no other directives (including ) as it doesn't play nicely.\n //\n // *****************\n return {\n restrict: \"EA\",\n link: link,\n priority: 1001\n };\n\n function link($scope, $element) {\n var blockerName = \"full-page\";\n var busy = $element.attr(\"es-busy-saving\") || $element.attr(\"data-es-busy-saving\");\n var busyTracker = $scope.$eval(busy); // note: this hack makes me cry; the esPageBlock watches the active function which is insane.\n\n if (typeof busyTracker.active !== \"function\") {\n busyTracker = {\n active: function active() {\n return !!$scope.$eval(busy);\n } // we are using !! to account for incrementing/decrementing loading counters rather than just true/false properties\n\n };\n }\n\n var messageKey = $element.attr(\"data-es-busy-saving-message-key\") || \"activityIndicator.saving.label\";\n var savingMessage = i18n.i10n(messageKey);\n esPageBlocker.create($scope, blockerName, busyTracker, savingMessage);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").component(\"esButtonCreate\", {\n bindings: {\n label: \"@?\",\n disabled: \"=ngDisabled\",\n type: \"@?\"\n },\n require: \"ng-click\",\n templateUrl: \"/App/ui/core/controls/esButtonCreate.html\",\n controllerAs: \"vm\",\n controller: controller\n }).controller(\"esButtonCreate\", controller);\n controller.$inject = [\"i18n\"];\n\n function controller(i18n) {\n var vm = this;\n\n if (!vm.label) {\n vm.label = i18n.i10n(\"buttons.create\");\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.core\").directive(\"esButtonGroup\", esButtonGroup).controller(\"esButtonGroupController\", esButtonGroupController);\n\n function esButtonGroup() {\n return {\n restrict: \"A\",\n replace: true,\n scope: {\n items: \"=esButtonGroup\",\n selected: \"=esSelected\",\n textField: \"=esTextField\",\n valueField: \"=esValueField\",\n translationKey: \"@esTranslationKey\"\n },\n templateUrl: \"/App/ui/core/controls/esButtonGroup.html\",\n controller: esButtonGroupController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esButtonGroupController.$inject = [];\n\n function esButtonGroupController() {\n var vm = this;\n vm.setSelected = setSelected; //////////////////\n\n function setSelected(item) {\n vm.selected = item;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").component(\"esButtonPrimary\", {\n bindings: {\n type: \"@?\",\n label: \"@\",\n disabled: \"=ngDisabled\"\n },\n require: \"ng-click\",\n templateUrl: \"/App/ui/core/controls/esButtonPrimary.html\",\n controllerAs: \"vm\"\n });\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esDateTimeSelector\", directive).controller(\"esDateTimeSelectorController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n require: [\"^form\", \"ngModel\"],\n scope: {\n containerName: \"@name\",\n dateTimeMillis: \"=ngModel\"\n },\n templateUrl: \"/App/ui/core/controls/esDateTimeSelector.html\",\n link: link,\n controller: \"esDateTimeSelectorController\",\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n function link($scope, $element, attrs, controllers) {\n var vm = $scope.vm;\n vm.$form = controllers[0];\n vm.ngModel = controllers[1];\n }\n\n controller.$inject = [\"$scope\", \"kendo\", \"lodash\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.dateTimeService\"];\n\n function controller($scope, kendo, _, timeZoneDateTime, dateTimeService) {\n var vm = this;\n vm.name = \"\".concat(vm.containerName, \"-dateTimeSelector\");\n vm.options = {\n format: dateTimeService.formats.kendo.dateTime\n };\n vm.onChange = onKendoDateChanged;\n activate(); ////////////////////\n\n function activate() {\n updateKendoDateWhenModelChanges();\n updateParentModelValidityWhenValidityChanges();\n }\n\n function updateKendoDateWhenModelChanges() {\n $scope.$watch(function () {\n return vm.dateTimeMillis;\n }, function (dateTimeMillis) {\n vm.date = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(dateTimeMillis));\n vm.dateString = kendo.toString(vm.date, vm.options.format);\n });\n }\n\n function onKendoDateChanged() {\n if (vm.$form[vm.name].$invalid) {\n return;\n }\n\n var localTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.date);\n vm.dateTimeMillis = localTime && localTime.getTime();\n }\n\n function updateParentModelValidityWhenValidityChanges() {\n $scope.$watch(function () {\n return vm.$form[vm.name].$error;\n }, onErrorsChanged, true);\n\n function onErrorsChanged(errors, previousErrors) {\n if (errors === previousErrors) {\n return;\n }\n\n var currentValidatorErrorKeys = Object.keys(errors);\n var previousValidatorErrorKeys = previousErrors ? Object.keys(previousErrors) : [];\n\n var keysRemoved = _.difference(previousValidatorErrorKeys, currentValidatorErrorKeys);\n\n keysRemoved.forEach(function (key) {\n return vm.ngModel.$setValidity(key, true);\n });\n currentValidatorErrorKeys.forEach(function (key) {\n return vm.ngModel.$setValidity(key, !errors[key]);\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n /* eslint-disable no-multi-spaces */\n\n\n angular.module(\"app.ui.core\").component(\"esFileUploader\", {\n controller: FileUploaderController,\n templateUrl: \"/App/ui/core/controls/esFileUploader.html\",\n controllerAs: \"vm\",\n bindings: {\n heading: \"@\",\n // Heading to be displayed\n uploadUrl: \"<\",\n // URL to use for the upload\n deleteFile: \"&\",\n // Function for deleting a file\n postData: \" -1) {\n matches.push(item);\n break;\n }\n }\n }\n\n vm.items = matches;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").factory(\"esPageBlocker\", esPageBlocker);\n esPageBlocker.$inject = [\"blockUI\"];\n\n function esPageBlocker(blockUI) {\n return {\n create: create\n }; ////////////////////\n\n function create($scope, blockerName, busyTracker, busyMessage) {\n $scope.blockers = $scope.blockers || {};\n $scope.blockers[blockerName] = blockUI.instances.get(blockerName);\n $scope.$watch(busyTracker.active, updatePageBlocker); // Make sure we turn off any blockers before going out of scope.\n\n $scope.$on(\"$destroy\", function () {\n var blockers = $scope.blockers;\n\n if (!blockers) {\n return;\n }\n\n Object.keys(blockers).forEach(function (blockerName) {\n blockers[blockerName].stop();\n });\n });\n\n function updatePageBlocker(isActive) {\n if (isActive) {\n $scope.blockers[blockerName].start(busyMessage);\n } else {\n $scope.blockers[blockerName].stop();\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esPersistenceStore\", esPersistenceStore).controller(\"esPersistenceStoreController\", esPersistenceStoreController);\n esPersistenceStore.$inject = [];\n /* istanbul ignore next */\n\n function esPersistenceStore() {\n return {\n restrict: \"E\",\n scope: {\n model: \"=ngModel\",\n item: \"@\",\n defaultModel: \"=\",\n storageKey: \"@\"\n },\n controller: \"esPersistenceStoreController\",\n controllerAs: \"vm\",\n bindToController: true,\n replace: false,\n link: link\n };\n\n function link($scope, $element, attrs, vm) {\n vm.deserializeItem();\n $scope.$watch(function () {\n return vm.model[vm.item];\n }, vm.serializeItem, true);\n }\n }\n\n esPersistenceStoreController.$inject = [\"browserStorage\", \"app.core.appSettings\"];\n\n function esPersistenceStoreController(browserStorage, appSettings) {\n var vm = this;\n\n vm.serializeItem = function () {\n var bucket = \"\".concat(appSettings.site.facility.alias, \"-\").concat(appSettings.userId);\n browserStorage.persistBucket(vm.storageKey, bucket, vm.model[vm.item]);\n };\n\n vm.deserializeItem = function () {\n var bucket = \"\".concat(appSettings.site.facility.alias, \"-\").concat(appSettings.userId);\n var storageItem = browserStorage.getBucket(vm.storageKey, bucket) || vm.defaultModel;\n\n if (storageItem) {\n vm.model[vm.item] = storageItem;\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\nangular.module(\"app.ui.core\").component(\"esRouteSwitch\", {\n controller: esRouteSwitch,\n bindings: {\n routes: \"<\",\n selectedRoute: \"<\",\n onChange: \"&\"\n },\n transclude: true,\n templateUrl: \"/App/ui/core/controls/esRouteSwitch.html\",\n controllerAs: \"vm\"\n});\nesRouteSwitch.$inject = [\"$state\"];\n\nfunction esRouteSwitch($state) {\n var vm = this;\n vm.changeRoute = changeRoute;\n\n vm.$onChanges = function (changes) {\n if (changes.selectedRoute) {\n vm.selectedRouteName = changes.selectedRoute.currentValue;\n }\n }; //////////////////\n\n\n function changeRoute(routeName) {\n var oldRoute = vm.selectedRouteName;\n $state.go(routeName);\n vm.onChange({\n newRoute: routeName,\n oldRoute: oldRoute\n });\n }\n}\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esSetSideBarDefaultWidth\", esSetSideBarDefaultWidth);\n /* istanbul ignore next */\n\n function esSetSideBarDefaultWidth() {\n return {\n scope: {\n width: \"=esSetSideBarDefaultWidth\"\n },\n restrict: \"A\",\n link: link\n };\n\n function link($scope, $elem) {\n var sidebarContainer = $elem.closest(\".sidebar-container\");\n sidebarContainer.css(\"width\", $scope.width);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esTabSet\", esTabSet).controller(\"esTabSetController\", esTabSetController);\n esTabSet.$inject = [];\n\n function esTabSet() {\n return {\n restrict: \"E\",\n transclude: true,\n templateUrl: \"/App/ui/core/controls/esTabSet.html\",\n scope: {\n tabs: \"=\"\n },\n bindToController: true,\n controller: esTabSetController,\n controllerAs: \"vm\"\n };\n }\n\n esTabSetController.$inject = [];\n\n function esTabSetController() {\n activate(); ////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").controller(\"esTimeSliderController\", esTimeSliderController).directive(\"esTimeSlider\", esTimeSlider);\n esTimeSlider.$inject = [\"jQuery\", \"lodash\"];\n /* istanbul ignore next */\n\n function esTimeSlider($, _) {\n return {\n restrict: \"E\",\n scope: {\n isEnabled: \"=\",\n min: \"=\",\n max: \"=\",\n stepSize: \"=\",\n stepTooltip: \"=\",\n onStepChanged: \"=\",\n modelDataAvailability: \"=\"\n },\n templateUrl: \"/App/ui/core/controls/esTimeSlider.html\",\n link: link,\n controller: esTimeSliderController,\n controllerAs: \"vm\",\n bindToController: true,\n transclude: true\n };\n\n function link($scope, $element) {\n var vm = $scope.vm;\n var availabilityClasses;\n activate(); ////////////////////\n\n function activate() {\n addTemporalDataClassToMapWhenEnabled();\n resizeSliderOnPageResize();\n redrawDataAvailabilityWhenUpdated();\n redrawDataAvailabilityWhenSliderCreated();\n }\n\n function addTemporalDataClassToMapWhenEnabled() {\n var cssClass = \"temporal-data-map-container\";\n $scope.$watch(function () {\n return vm.isEnabled;\n }, function (isEnabled) {\n var parent = $element.parent();\n\n if (isEnabled) {\n parent.addClass(cssClass);\n } else {\n parent.removeClass(cssClass);\n }\n });\n }\n\n function resizeSliderOnPageResize() {\n $scope.$on(\"resizePage\", resize);\n\n function resize(event, payload) {\n if (!vm.timeSlider.kendoSlider || payload && payload.sender === \"contentLoaded\") {\n return;\n }\n\n vm.timeSlider.kendoSlider.resize();\n redrawDataAvailabilityLayers();\n }\n }\n\n function redrawDataAvailabilityWhenUpdated() {\n $scope.$watch(function () {\n return vm.modelDataAvailability;\n }, function (modelDataAvailability) {\n redrawDataAvailabilityLayers(modelDataAvailability);\n }, true);\n }\n\n function redrawDataAvailabilityWhenSliderCreated() {\n $scope.$watch(function () {\n return vm.timeSlider.kendoSlider;\n }, function (kendoSlider) {\n if (!!kendoSlider) {\n redrawDataAvailabilityLayers();\n }\n });\n }\n\n function redrawDataAvailabilityLayers(modelDataAvailability) {\n if (modelDataAvailability) {\n buildAvailabilityClasses(modelDataAvailability);\n } // Each `slider-item` represents a single tick mark on the kendo slider. The first and last\n // ticks are half the width of the other ticks.\n\n\n var $sliderItemsContainer = $(\"ul.k-slider-items\", $element);\n\n if (!$sliderItemsContainer.length) {\n return;\n }\n\n var $esDataAvailability = resetDataAvailabilityContainer($sliderItemsContainer);\n\n if (!(availabilityClasses && availabilityClasses.length)) {\n return;\n }\n\n var $sliderItems = $(\"li\", $sliderItemsContainer);\n var itemCount = $sliderItems.length;\n var $items = [];\n\n for (var pointIndex = 0; pointIndex < itemCount; pointIndex++) {\n var item = $sliderItems[pointIndex];\n var $item = $(item);\n var availabilityClass = availabilityClasses[pointIndex];\n $items.push(buildDataAvailabilityIndicator($esDataAvailability, $item.width(), availabilityClass, pointIndex === 0, pointIndex === itemCount - 1));\n }\n\n $esDataAvailability.append($items);\n adjustDataAvailabilityContainerPosition($esDataAvailability);\n }\n\n function buildAvailabilityClasses(modelDataAvailability) {\n availabilityClasses = [];\n\n if (!(modelDataAvailability && vm.min && vm.max && vm.stepSize) || _.isEmpty(modelDataAvailability)) {\n return availabilityClasses;\n }\n\n var query = _.chain(modelDataAvailability);\n\n var modelCount = _.keys(modelDataAvailability).length;\n\n var _loop = function _loop(tick) {\n var modelsWithDataAtTick = query.filter(function (modelDataAvailability) {\n return modelDataAvailability[tick];\n }).value().length;\n var cssClass = modelsWithDataAtTick === modelCount ? \"all-data\" : modelsWithDataAtTick === 0 ? \"no-data\" : \"some-data\";\n availabilityClasses.push(cssClass);\n };\n\n for (var tick = vm.sliderMin; tick <= vm.max; tick += vm.stepSize) {\n _loop(tick);\n }\n\n return availabilityClasses;\n }\n\n function resetDataAvailabilityContainer($sliderItemsContainer) {\n var $parent = $sliderItemsContainer.parent();\n var $container = $(\".es-slider-data-availability\", $parent);\n return $container.length ? $container.empty() : $(\"
      \").appendTo($parent);\n }\n\n function buildDataAvailabilityIndicator($container, itemWidth, availabilityClass, isFirstChild, isLastChild) {\n var indicatorWidth, marginWidth; // Ideally, we want the indicator to be 20px wide. If the kendo item isn`t this wide, then we`ll make\n // our indicator take up the entire width of the kendo item.\n\n if (itemWidth < 20) {\n indicatorWidth = itemWidth;\n\n if (isFirstChild || isLastChild) {\n indicatorWidth = Math.min(20, indicatorWidth * 2);\n marginWidth = Math.max((itemWidth * 2 - indicatorWidth) / 2, 0);\n } else {\n marginWidth = 0;\n }\n } else {\n indicatorWidth = 20;\n marginWidth = itemWidth - indicatorWidth; // We add in additional margin to cater for the \"overhang\" - see the comment in\n // \"adjustDataAvailabilityContainerPosition\" below.\n\n if (isFirstChild || isLastChild) {\n marginWidth += indicatorWidth / 2;\n }\n }\n\n var $indicator = $(\"
    • \"));\n\n if (marginWidth > 0) {\n // The first and last indicator get all their margin applied to one side, where-as the other\n // items need the margin to be divided equally on both sides.\n if (isFirstChild || isLastChild) {\n var marginProperty = isFirstChild ? \"margin-right\" : \"margin-left\";\n $indicator.css(marginProperty, \"\".concat(marginWidth, \"px\"));\n } else {\n $indicator.css(\"margin\", \"0 \".concat(marginWidth / 2, \"px\"));\n }\n }\n\n return $indicator;\n }\n\n function adjustDataAvailabilityContainerPosition($container) {\n // At this point, the data availability container is the same length of the slider bar.\n // However, we want the first and the last indicators to overhang the edges of the slider bar.\n // In order to do that, we need to move our container to the left by half the width of the first\n // indicator (i.e. so that half of the first indicator overhangs the left hand side of the slider bar).\n // The right hand indicator will achieve the same effect simply by the extra margin that we added\n // when we rendered it.\n var originalMarginLeft = $container.data(\"original-margin-left\");\n\n if (!originalMarginLeft) {\n var marginLeftWithUnits = $container.css(\"margin-left\");\n originalMarginLeft = parseInt(/\\d+/.exec(marginLeftWithUnits)[0]); // Store the original measurement for margin-left so that when we redraw the container, it moves based\n // on the original margin, rather than the adjusted margin.\n\n $container.data(\"original-margin-left\", originalMarginLeft);\n }\n\n var firstIndicatorWidth = $(\"li:first-child\", $container).width();\n var marginLeft = originalMarginLeft - firstIndicatorWidth / 2;\n $container.css(\"margin-left\", \"\".concat(marginLeft, \"px\"));\n }\n }\n }\n\n esTimeSliderController.$inject = [\"$scope\", \"$timeout\", \"lodash\", \"app.ui.core.controls.StepTicker\"];\n /* istanbul ignore next */\n\n function esTimeSliderController($scope, $timeout, _, StepTicker) {\n var vm = this;\n vm.sliderMin = 0;\n vm.hasTimeSliderParameters = false;\n var tickerSpeeds, tickerSpeedIndex, tickerSpeedLabels;\n activate(); ///////////\n\n function activate() {\n vm.sliderMin = calculateSliderMin();\n vm.timeSlider = createTimeSlider();\n vm.ticker = createStepTicker();\n vm.changeTickerSpeed = changeTickerSpeed;\n vm.tickerSpeedLabel = \"\";\n updateTickerWhenBoundsChange();\n raiseStepChangedEvent();\n cleanupWhenScopeDestroyed();\n calculateTickerSpeeds();\n $scope.$watch(function () {\n return vm.min;\n }, function () {\n vm.sliderMin = calculateSliderMin();\n });\n var watches = [function () {\n return vm.stepSize;\n }, function () {\n return vm.min;\n }, function () {\n return vm.max;\n }];\n $scope.$watchGroup(watches, rebuildTimeSlider);\n $scope.$watch(function () {\n return vm.isEnabled;\n }, function (isEnabled) {\n vm.ticker.isRunning = vm.timeSlider.options.enabled = !!isEnabled;\n var slider = vm.timeSlider.kendoSlider;\n\n if (slider) {\n slider.enable(vm.ticker.isRunning);\n }\n });\n }\n\n function createTimeSlider() {\n var timeSlider = {\n options: {\n smallStep: vm.stepSize,\n // arrow keys\n largeStep: vm.stepSize,\n // page up/down\n tickPlacement: \"topLeft\",\n enabled: vm.isEnabled\n },\n step: vm.sliderMin,\n // the currently active step\n onChange: function onChange() {\n vm.ticker.isRunning = false;\n $timeout(function () {\n raiseStepChangedEvent(); // Reset the ticker to this date so when the user presses \"Play\" again, the ticker starts from here.\n\n vm.ticker.activeStep = calculateStepIndex(vm.timeSlider.step);\n });\n }\n };\n\n if (vm.stepTooltip) {\n timeSlider.options.tooltip = vm.stepTooltip;\n }\n\n return timeSlider;\n }\n\n function rebuildTimeSlider() {\n vm.timeSlider.options.min = vm.sliderMin || 0;\n vm.timeSlider.options.max = vm.max || 0;\n vm.timeSlider.options.smallStep = vm.stepSize || 0;\n vm.timeSlider.options.largeStep = vm.timeSlider.options.smallStep * 5; // We need to reset the `enabled` property because when the time slider's bounds change, it\n // re-reads the options object to recreate itself.\n\n vm.timeSlider.options.enabled = vm.isEnabled; // Don't bother showing the time slider unless it has enough parameters to display properly.\n // If you give the slider all \"0\" parameters it basically gets into an infinite loop and dies.\n\n vm.hasTimeSliderParameters = vm.sliderMin < vm.max && vm.stepSize;\n }\n\n function calculateSliderMin() {\n // The time slider's minimum value needs to be one interval bigger than the time range.\n // This is because each step on the slider effectively represents the end time of the \"interval\"\n // of data. e.g. a dataset from 8 AM - 10 AM will be represented by two steps on the slider:\n // - 9 AM (for the 8 AM - 9 AM step);\n // - 10 AM (for the 9 AM - 10 AM step).\n return vm.min && vm.stepSize ? vm.min + vm.stepSize : 0;\n }\n\n function updateTickerWhenBoundsChange() {\n $scope.$watch(function () {\n return vm.sliderMin + \"-\" + vm.max;\n }, function () {\n // Cater for the scenario where vm.min and vm.max have been updated in the same digest cycle,\n // but we`ve received this event (because vm.max has changed) before we`ve received the vm.min\n // changed event (which would consequently update vm.sliderMin).\n var sliderMin = calculateSliderMin();\n var stepCount = calculateStepIndex(vm.max);\n\n if (vm.sliderMin === sliderMin && vm.ticker.stepCount === stepCount) {\n return;\n }\n\n vm.sliderMin = sliderMin;\n vm.ticker.stepCount = stepCount;\n calculateTickerSpeeds();\n });\n }\n\n function raiseStepChangedEvent() {\n vm.onStepChanged(vm.timeSlider.step);\n }\n\n function cleanupWhenScopeDestroyed() {\n $scope.$on(\"$destroy\", function () {\n if (vm.timeSlider.kendoSlider) {\n vm.timeSlider.kendoSlider.destroy();\n }\n\n vm.ticker.destroy();\n });\n }\n\n function createStepTicker() {\n var ticker = new StepTicker();\n ticker.stepCount = calculateStepIndex(vm.max);\n ticker.loop = true;\n\n ticker.onTick = function (stepIndex) {\n vm.timeSlider.step = vm.sliderMin + stepIndex * vm.stepSize;\n raiseStepChangedEvent();\n };\n\n return ticker;\n }\n\n function calculateStepIndex(stepValue) {\n return (stepValue - vm.sliderMin) / vm.stepSize;\n }\n\n function calculateTickerSpeeds() {\n var stepCount = calculateStepIndex(vm.max);\n\n if (_.isNaN(stepCount)) {\n if (vm.ticker && vm.ticker.isRunning) {\n vm.ticker.isRunning = false;\n }\n\n return;\n }\n\n var defaultSpeed = getDefaultTickerSpeedForIntervalCount(stepCount);\n tickerSpeeds = [defaultSpeed * 2, defaultSpeed, defaultSpeed * 0.5];\n tickerSpeedLabels = [\"0.5\", \"1\", \"2\"];\n\n if (!tickerSpeedIndex) {\n tickerSpeedIndex = Math.floor(tickerSpeeds.length / 2);\n }\n\n changeTickerSpeed(0);\n }\n\n function getDefaultTickerSpeedForIntervalCount(intervalCount) {\n if (!intervalCount || intervalCount <= 15) {\n return 1000;\n }\n\n if (intervalCount <= 60) {\n return 500;\n }\n\n return 250;\n }\n\n function changeTickerSpeed(delta) {\n tickerSpeedIndex += delta;\n\n if (tickerSpeedIndex >= tickerSpeeds.length) {\n tickerSpeedIndex = 0;\n }\n\n vm.ticker.tickMillis = tickerSpeeds[tickerSpeedIndex];\n vm.tickerSpeedLabel = tickerSpeedLabels[tickerSpeedIndex];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").factory(\"app.ui.core.controls.StepTicker\", StepTickerFactory);\n StepTickerFactory.$inject = [\"lodash\", \"$timeout\"];\n\n function StepTickerFactory(_, $timeout) {\n function StepTicker() {\n var self = this;\n self.onTick = null;\n self.destroy = destroy;\n var stepCount = 0;\n var activeStep = 0;\n var tickMillis = 500;\n var loop = false;\n var timer = null;\n Object.defineProperty(self, \"stepCount\", {\n get: function get() {\n return stepCount;\n },\n set: function set(value) {\n return updatePropertyThenRestart(function () {\n stepCount = value;\n activeStep = Math.max(0, Math.min(activeStep, value));\n });\n }\n });\n Object.defineProperty(self, \"activeStep\", {\n get: function get() {\n return activeStep;\n },\n set: function set(value) {\n return updatePropertyThenRestart(function () {\n return activeStep = Math.max(0, value);\n });\n }\n });\n Object.defineProperty(self, \"tickMillis\", {\n get: function get() {\n return tickMillis;\n },\n set: function set(value) {\n return updatePropertyThenRestart(function () {\n return tickMillis = value;\n });\n }\n });\n Object.defineProperty(self, \"loop\", {\n get: function get() {\n return loop;\n },\n set: function set(value) {\n loop = value;\n\n if (value && !self.isRunning) {\n self.isRunning = true;\n }\n }\n });\n Object.defineProperty(self, \"isRunning\", {\n get: function get() {\n return !!timer;\n },\n set: function set(value) {\n if (value) {\n start();\n } else {\n pause();\n }\n }\n }); ////////////////////\n\n function updatePropertyThenRestart(update) {\n var shouldRestart = self.isRunning;\n pause();\n update();\n\n if (shouldRestart) {\n start();\n }\n }\n\n function start() {\n if (self.isRunning || !canStart()) {\n return;\n }\n\n ensureActiveStepIsValid();\n\n var tick = function tick() {\n var step = hasReachedFinalStep() ? 0 : activeStep + 1;\n updateActiveStep(step);\n timer = hasReachedFinalStep() && !loop ? null : $timeout(tick, tickMillis);\n };\n\n timer = $timeout(tick, tickMillis);\n }\n\n function canStart() {\n return stepCount > 0;\n }\n\n function ensureActiveStepIsValid() {\n if (!activeStep || hasReachedFinalStep()) {\n updateActiveStep(0);\n }\n }\n\n function hasReachedFinalStep() {\n return activeStep >= stepCount;\n }\n\n function updateActiveStep(step) {\n activeStep = step;\n\n if (_.isFunction(self.onTick)) {\n self.onTick.call(this, step);\n }\n }\n\n function pause() {\n $timeout.cancel(timer);\n timer = null;\n }\n\n function destroy() {\n pause();\n delete self.onTick;\n }\n }\n\n return StepTicker;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").value(\"app.ui.core.controls.Tab\", Tab);\n\n function Tab(name, getUrl) {\n var isActive = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {\n return false;\n };\n var isVisible = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {\n return true;\n };\n this.name = name;\n this.getUrl = getUrl;\n this.isActive = isActive;\n this.isVisible = isVisible;\n this.isDirty = false;\n this.isBusyLoading = false;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").factory(\"esComponentChangeHandlerFactory\", esComponentChangeHandlerFactory);\n esComponentChangeHandlerFactory.$inject = [];\n /*\r\n * Usage:\r\n *\r\n * function $onChanges(changes) {\r\n * const changeHandler = changeHandlerFactory(changes);\r\n *\r\n * // Check for initial change\r\n * changeHandler\r\n * .when(changes => changes.name)\r\n * .hasFirstChanged()\r\n * .then(name => vm.name = name);\r\n *\r\n * // Check if a primitive has changed\r\n * changeHandler\r\n * .when(changes => changes.name)\r\n * .hasChanged()\r\n * .then(name => vm.name = name);\r\n *\r\n * // Use a filter to check if a specific property has changed\r\n * changeHandler\r\n * .when(changes => changes.state)\r\n * .hasChanged(state => state.name)\r\n * .then(name => vm.name = name);\r\n *\r\n * // Use a custom comparer\r\n * changeHandler\r\n * .when(changes => changes.state)\r\n * .hasChanged(state => state.name)\r\n * .because((currentName, previousName) => currentName.toUpperCase() !== previousName.toUpperCase())\r\n * .then(name => vm.name = name);\r\n *\r\n * // Use a custom comparer to check for a single property change\r\n * changeHandler\r\n * .when(changes => changes.state)\r\n * .hasChanged()\r\n * .because((currentState, previousState) => currentState.id !== previousState.id)\r\n * .then(state => vm.name = state.name);\r\n *\r\n * // Check for multiple changes on the same property\r\n * const whenState = changeHandler.when(changes => changes.state);\r\n * whenState\r\n * .hasChanged(state => state.name)\r\n * .then(name => vm.name = name);\r\n * whenState\r\n * .hasChanged(state => state.age)\r\n * .then(age => vm.age = age);\r\n * }\r\n */\n\n function esComponentChangeHandlerFactory() {\n var defaultHasChangedEvaluator = function defaultHasChangedEvaluator(currentValue, previousValue) {\n return currentValue !== previousValue;\n };\n\n return function esComponentChangeHandlerFactory(changes) {\n return {\n when: when\n }; ////////////////////\n\n function when(propertySelector) {\n var propertyChanges = propertySelector(changes);\n var isPropertyInChangeMap = propertyChanges !== undefined;\n var isFirstChange = isPropertyInChangeMap && propertyChanges.isFirstChange();\n var currentBoundValue = isPropertyInChangeMap ? propertyChanges.currentValue : undefined;\n var previousBoundValue = isPropertyInChangeMap ? propertyChanges.previousValue : undefined;\n return {\n hasFirstChanged: hasFirstChanged,\n hasChanged: hasChanged\n };\n\n function hasFirstChanged(filter) {\n var fluentResult = {\n then: function then() {}\n };\n\n if (isFirstChange) {\n var currentValue = applyFilter(filter, currentBoundValue);\n fluentResult.then = createThenFunction(currentValue);\n }\n\n return fluentResult;\n }\n\n function hasChanged(filter) {\n return {\n because: function because(hasChangedEvaluator) {\n return hasPropertyChanged(filter, hasChangedEvaluator);\n },\n then: function then(processChange) {\n return hasPropertyChanged(filter, defaultHasChangedEvaluator).then(processChange);\n }\n };\n }\n\n function hasPropertyChanged(filter, hasChangedEvaluator) {\n var fluentResult = {\n then: function then() {}\n };\n\n if (isPropertyInChangeMap) {\n var _hasChanged = isFirstChange;\n var currentValue = applyFilter(filter, currentBoundValue);\n var previousValue = undefined;\n\n if (!isFirstChange) {\n previousValue = applyFilter(filter, previousBoundValue);\n _hasChanged = hasChangedEvaluator(currentValue, previousValue);\n }\n\n if (_hasChanged) {\n fluentResult.then = createThenFunction(currentValue, previousValue);\n }\n }\n\n return fluentResult;\n }\n }\n\n function applyFilter(filter, value) {\n return filter ? filter(value) : value;\n }\n\n function createThenFunction(currentValue, previousValue) {\n return function then(processChange) {\n processChange(currentValue, previousValue);\n };\n }\n };\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").factory(\"esStateStore\", esStateStore);\n esStateStore.$inject = [\"$rootScope\", \"lodash\", \"utils\"];\n /* istanbul ignore next */\n\n function esStateStore($rootScope, _, utils) {\n return function (initialStateResolver, dispatchers) {\n var _state = utils.freeze(getBaseState());\n\n var unsubscribeFromRouteChanges;\n var loading = 0;\n var saving = 0;\n var store = {\n get state() {\n return _state;\n },\n\n set state(newState) {\n _state = utils.freeze(newState);\n }\n\n };\n store.dispatch = _.mapValues(dispatchers, function (createDispatcher) {\n return createDispatcher(store);\n }); // this function is utilized by ui-router as a 'resolve' before transitioning to the route.\n // the store.state is then one-way bound down to the component.\n\n store.resolve = function () {\n var initialStateLoader = initialStateResolver().then(function (state) {\n return store.state = _extends({}, getBaseState(), state);\n });\n return store.load(initialStateLoader).then(function () {\n return store;\n });\n }; // Use the load function in a dispatcher when an asynchronous 'loading/fetching' operation is taking place.\n\n\n store.load = function (promise) {\n store.state = _extends({}, store.state, {\n loading: ++loading\n });\n return promise.then(function (delta) {\n store.state = _extends({}, store.state, {\n loading: --loading\n }, delta);\n });\n }; // Use the save function in a dispatcher when an asynchronous 'save' operation is taking place.\n\n\n store.save = function (promise) {\n store.state = _extends({}, store.state, {\n saving: ++saving\n });\n return promise.then(function (delta) {\n store.state = _extends({}, store.state, {\n saving: --saving\n }, delta);\n });\n };\n\n store.init = function () {\n unsubscribeFromRouteChanges = subscribeToRouteChanges(store);\n };\n\n store.destroy = function () {\n unsubscribeFromRouteChanges && unsubscribeFromRouteChanges();\n };\n\n return store;\n };\n\n function getBaseState() {\n return {\n loading: 0,\n saving: 0\n };\n }\n\n function subscribeToRouteChanges(store) {\n return $rootScope.$on(\"$stateChangeSuccess\", function ($scope, toRoute, toRouteParams) {\n store.state = _extends({}, store.state, {\n $routeParams: toRouteParams\n });\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").controller(\"Forbidden\", Forbidden);\n Forbidden.$inject = [\"app.core.services.locationService\"];\n\n function Forbidden(locationService) {\n var vm = this;\n vm.goHome = locationService.goHome;\n vm.logout = locationService.logout;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esJobs\", esJobs).controller(\"esJobsController\", esJobsController);\n esJobs.$inject = [];\n\n function esJobs() {\n return {\n scope: {},\n restrict: \"EA\",\n templateUrl: \"/App/ui/core/jobs/controls/esJobs.html\",\n controller: esJobsController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esJobsController.$inject = [\"$scope\", \"$timeout\", \"lodash\", \"postal\", \"app.core.appSettings\", \"app.core.services.gisModelService\", \"app.core.signalR.jobs.state\", \"app.core.signalR.jobs.events\"];\n\n function esJobsController($scope, $timeout, _, postal, appSettings, gisModelService, state, jobEvents) {\n var vm = this;\n var channel = postal.channel(jobEvents.channelName);\n var subscriptions = [];\n var subscribedFacility = null;\n vm.activeJobCount = 0;\n vm.jobs = [];\n vm.clearJob = clearJob;\n vm.clearCompleted = clearCompleted;\n activate(); //////////////////////\n\n function activate() {\n updateJobsWhenJobsChange();\n updateActiveJobCountOnJobCreated();\n updateActiveJobCountOnJobComplete();\n reloadJobsWhenFacilityChanges();\n }\n\n function updateJobsWhenJobsChange() {\n $scope.$watchCollection(function () {\n return state.jobs;\n }, function (newJobs, oldJobs) {\n var jobsAdded = _.difference(newJobs, oldJobs);\n\n var jobsRemoved = _.difference(oldJobs, newJobs);\n\n _.forEach(jobsAdded, function (job) {\n if (!job.hasCompleted) {\n vm.jobs.splice(0, 0, job);\n } else {\n vm.jobs.push(job);\n }\n });\n\n _.forEach(jobsRemoved, function (job) {\n return _.remove(vm.jobs, job);\n });\n });\n }\n\n function updateActiveJobCountOnJobCreated() {\n $scope.$watch(function () {\n return vm.jobs.length;\n }, recalculateActiveJobCount);\n }\n\n function updateActiveJobCountOnJobComplete() {\n subscriptions = [channel.subscribe(jobEvents.topics.jobCompleted, recalculateActiveJobCount)];\n $scope.$on(\"$destroy\", function () {\n _.invokeMap(subscriptions, \"unsubscribe\");\n });\n }\n\n function recalculateActiveJobCount() {\n var activeJobCount = 0;\n\n _.forEach(vm.jobs, function (job) {\n if (!job.hasCompleted) {\n activeJobCount++;\n }\n });\n\n vm.activeJobCount = activeJobCount;\n }\n\n function reloadJobsWhenFacilityChanges() {\n $scope.$watch(function () {\n return appSettings.site.accessControls;\n }, function () {\n if (!appSettings.site.accessControls || !appSettings.site.facility.alias || appSettings.site.facility.alias === subscribedFacility) {\n return;\n }\n\n state.jobs.length = 0;\n gisModelService.getModellingJobs().then(function (jobs) {\n _.forEach(jobs, function (job) {\n return state.jobs.push(job);\n });\n });\n });\n }\n\n function clearJob(job) {\n // Eagerly remove the job so the UI is more responsive.\n // If this fails, the job will come back after a refresh, but... meh.\n _.remove(state.jobs, job); // The jobStatusHub will only publish the jobDismissed event if it is responsible for removing the\n // job from the state; since we've already done that, we have to also publish the event.\n\n\n $timeout(function () {\n return channel.publish(jobEvents.topics.jobDismissed, job);\n });\n gisModelService.dismissJob(job.jobId);\n }\n\n function clearCompleted() {\n var jobsToDismiss = [];\n\n for (var i = state.jobs.length - 1; i >= 0; i--) {\n var job = state.jobs[i];\n\n if (!job.hasCompleted) {\n continue;\n }\n\n state.jobs.splice(i, 1);\n jobsToDismiss.push(job.jobId);\n }\n\n if (jobsToDismiss.length) {\n gisModelService.dismissJobs(jobsToDismiss);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").factory(\"app.ui.core.keyboardShortcuts\", keyboardShortcuts);\n keyboardShortcuts.$inject = [\"lodash\", \"Mousetrap\"];\n\n function keyboardShortcuts(_, Mousetrap) {\n var keyboardShortcutCollections = [];\n var originalCallback = Mousetrap.prototype.stopCallback;\n\n Mousetrap.prototype.stopCallback = function (event, element) {\n return element.className.indexOf(\"ignore-mousetrap\") > -1 || originalCallback(event, element);\n };\n\n return {\n add: add,\n remove: function remove() {\n return _.forEach(keyboardShortcutCollections, unbind);\n },\n list: function list() {\n return keyboardShortcutCollections;\n }\n };\n\n function add(description, shortcutCollection) {\n if (!shortcutCollection) {\n throw new Error(\"The shortcut collection must be defined.\");\n }\n\n _.forEach(_.values(shortcutCollection), function (shortcut) {\n if (!shortcut.hasOwnProperty(\"visible\")) {\n shortcut.visible = true;\n }\n });\n\n keyboardShortcutCollections.push({\n description: description,\n shortcuts: shortcutCollection\n });\n bind(shortcutCollection);\n return {\n remove: function remove() {\n return unbind(shortcutCollection);\n }\n };\n }\n\n function bind(shortcutCollection) {\n var shortcuts = Object.keys(shortcutCollection);\n\n _.forEach(shortcuts, function (shortcut) {\n Mousetrap.bind(shortcut, shortcutCollection[shortcut].action);\n });\n }\n\n function unbind(shortcutCollection) {\n var shortcuts = Object.keys(shortcutCollection);\n\n _.forEach(shortcuts, function (shortcut) {\n Mousetrap.unbind(shortcut);\n delete shortcuts[shortcut];\n });\n\n keyboardShortcutCollections = _.reject(keyboardShortcutCollections, {\n shortcuts: shortcutCollection\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esFullScreen\", esFullScreen);\n esFullScreen.$inject = [\"$rootScope\", \"$timeout\"];\n\n function esFullScreen($rootScope, $timeout) {\n var directive = {\n restrict: \"A\",\n scope: {\n isFullScreen: \"=esFullScreen\"\n },\n bindToController: true,\n controller: controller,\n controllerAs: \"vm\",\n link: link\n };\n\n function link($scope, $element) {\n $element.bind(\"click\", function () {\n $timeout(function () {\n $scope.vm.isFullScreen = !$scope.vm.isFullScreen;\n });\n });\n }\n\n controller.$inject = [\"$scope\", \"$state\", \"$timeout\"];\n\n function controller($scope, $state, $timeout) {\n var vm = this;\n var $shellView = angular.element(\"#shell-view\");\n activate(); //////////////\n\n function activate() {\n $scope.$watch(function () {\n return vm.isFullScreen;\n }, function () {\n if (vm.isFullScreen) {\n $shellView.addClass(\"full-screen\");\n } else {\n $shellView.removeClass(\"full-screen\");\n }\n\n $timeout(function () {\n return $rootScope.$broadcast(\"resizePage\");\n });\n }); // only overwrite $scope value if the query param is present\n\n if ($state.params.fullScreen) {\n vm.isFullScreen = true;\n }\n }\n }\n\n return directive;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esSideBar\", esSideBar);\n esSideBar.$inject = [\"$rootScope\", \"$window\", \"lodash\"];\n\n function esSideBar($rootScope, $window, _) {\n var directive = {\n link: link,\n scope: true,\n restrict: \"A\"\n };\n return directive;\n\n function link($scope, $element) {\n $element.find(\".sidebar-container\").resizable({\n handles: {\n e: \".ui-resizable-handle\"\n },\n maxWidth: $window.innerWidth / 3,\n minWidth: 300,\n resize: _.debounce(triggerResizePage, 50)\n });\n $element.find(\".sidebar-handle\").click(function () {\n $element.toggleClass(\"collapsed\");\n triggerResizePage();\n });\n\n function triggerResizePage() {\n $rootScope.$broadcast(\"resizePage\", {\n sender: \"esSideBar\"\n });\n }\n\n $element.find(\".sidebar-hide-overlay\").click(function () {\n $element.addClass(\"collapsed\");\n triggerResizePage();\n });\n $element.find(\".ui-resizable-handle\").click(function () {\n $element.toggleClass(\"collapsed\");\n triggerResizePage();\n });\n $scope.$on(\"resizePage\", function (evt, args) {\n if (args && args.sender === \"esSideBar\") {\n return;\n }\n\n window.innerWidth <= 996 ? $element.addClass(\"collapsed\") : $element.removeClass(\"collapsed\");\n });\n\n if (window.innerWidth <= 996) {\n $element.toggleClass(\"collapsed\");\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esWindowResize\", esWindowResize);\n esWindowResize.$inject = [\"$rootScope\", \"$window\", \"$timeout\", \"lodash\"];\n\n function esWindowResize($rootScope, $window, $timeout, _) {\n return {\n link: link,\n scope: true,\n restrict: \"A\"\n };\n\n function link($scope) {\n var unsubscribeMe;\n registerWindowResizeHandler();\n registerPageLoadedHandler();\n\n function triggerResizePage(sender) {\n $timeout($rootScope.$broadcast(\"resizePage\", {\n sender: sender\n }));\n }\n\n function registerWindowResizeHandler() {\n var debouncedResize = _.debounce(function () {\n triggerResizePage(\"windowResize\");\n }, 50);\n\n var window = angular.element($window);\n window.on(\"resize\", debouncedResize);\n }\n\n function registerPageLoadedHandler() {\n var debounceContentLoaded = _.debounce(function () {\n triggerResizePage(\"contentLoaded\");\n }, 50);\n\n unsubscribeMe = $rootScope.$on(\"$includeContentLoaded\", debounceContentLoaded);\n }\n\n $scope.$on(\"$destroy\", function () {\n unsubscribeMe();\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").controller(\"app.ui.core.layout.Shell\", Shell);\n Shell.$inject = [\"$scope\", \"jQuery\", \"$filter\", \"$timeout\", \"$state\", \"$window\", \"$modal\", \"i18n\", \"httpBatcher\", \"app.ui.core.keyboardShortcuts\", \"app.core.appSettings\", \"app.core.models.messages.messageList\", \"app.core.services.securityService\", \"app.core.services.companyService\", \"app.core.services.locationService\", \"app.core.providers.errorThrowingDataProvider\", \"app.core.signalR.jobs.state\", \"app.core.signalR.alerts.state\", \"companyFacilities\"];\n\n function Shell($scope, $, $filter, $timeout, $state, $window, $modal, i18n, httpBatcher, keyboardShortcuts, appSettings, messageList, securityService, companyService, locationService, errorThrower, jobState, alertState, companyFacilities) {\n var vm = this;\n vm.appSettings = appSettings;\n vm.messageList = messageList;\n vm.companies = companyFacilities;\n vm.changeRoute = changeRoute;\n vm.jobCount = 0;\n vm.alertCount = 0;\n vm.classes = [];\n vm.showLeftPanel = $state.$current.data.layoutType === \"split\";\n vm.filterText = \"\";\n vm.setFilterText = setFilterText;\n vm.resetFilterText = resetFilterText;\n vm.menu = null;\n vm.menuClick = calculateOperationsMenuHeight;\n vm.logout = logout;\n vm.filterCompanies = filterCompanies;\n var $dropdown;\n var menuShortcuts = {};\n var menuShortcutBindings;\n var globalShortcuts = {};\n activate(); ///////////\n\n function activate() {\n var showOperationsMenu = shouldShowOperationsMenu();\n $timeout(function () {\n return $dropdown = $(\".menu.dropdown-toggle\");\n });\n updateFacilityDetails(vm.appSettings.site.company.alias, vm.appSettings.site.facility.alias);\n vm.showFacilityMenu = !vm.appSettings.isGuestUser;\n setupGlobalShortcuts();\n $scope.$watch(function () {\n return jobState.jobs.length;\n }, function (jobCount) {\n vm.jobCount = jobCount;\n });\n $scope.$watch(function () {\n return alertState.alerts.length;\n }, function (alertCount) {\n vm.alertCount = alertCount;\n });\n $scope.$watch(function () {\n return locationService.pageHeading;\n }, function (pageHeading) {\n vm.pageHeading = pageHeading;\n });\n $scope.$watch(function () {\n return locationService.exitPoint;\n }, function (exitPoint) {\n vm.exitPoint = exitPoint;\n });\n $scope.$watch(function () {\n return $state.$current;\n }, function (route) {\n vm.showLeftPanel = route.data.layoutType === \"split\";\n vm.classes = getClasses();\n });\n $scope.$watch(function () {\n return vm.appSettings.site.accessControls;\n }, function (accessControls) {\n var companyAlias = vm.appSettings.site.company.alias;\n var facilityAlias = vm.appSettings.site.facility.alias;\n\n if (menuShortcutBindings) {\n menuShortcutBindings.remove();\n menuShortcuts = {};\n }\n\n if (showOperationsMenu) {\n vm.menu = {\n operations: getActionMenuItems(accessControls, companyAlias, facilityAlias),\n incidentIntelligence: getIncidentIntelligenceMenuItems(accessControls, companyAlias, facilityAlias),\n configuration: getConfigurationMenuItems(accessControls, companyAlias, facilityAlias)\n };\n }\n\n menuShortcutBindings = keyboardShortcuts.add(i18n.i10n(\"app.ui.core.layout.shell.navigation.menu.shortcut.description\"), menuShortcuts);\n\n if (showOperationsMenu) {\n vm.menu.columnClass = getColumnClass();\n }\n\n function getColumnClass() {\n var columnCount = 1; // profile\n\n if (showOperationsMenu) {\n if (vm.menu.operations.length) {\n columnCount++;\n }\n\n if (vm.menu.incidentIntelligence.length) {\n columnCount++;\n }\n }\n\n return \"col-sm-\".concat(12 / columnCount);\n }\n });\n $scope.$on(\"resizePage\", calculateOperationsMenuHeight);\n $scope.$on(\"$destroy\", function () {\n keyboardShortcuts.remove(); // remove all keyboard shortcut bindings\n });\n }\n\n function getClasses() {\n var classes = [];\n var routeState = $state.$current;\n\n if (vm.showLeftPanel) {\n classes.push(\"es-layout-split\");\n }\n\n if (vm.appSettings.icpCertificate && vm.appSettings.internetSecurityNumberText && vm.appSettings.internetSecurityRegistrationLink) {\n classes.push(\"display-icp-registrations-view\");\n }\n\n do {\n if (routeState.self.state) {\n classes.push(\"es-route-\" + routeState.self.state.replace(/\\./g, \"-\"));\n }\n } while (routeState = routeState.parent); // eslint-disable-line no-cond-assign\n\n\n return classes;\n }\n\n function changeRoute(selectedCompanyAlias, selectedFacilityAlias) {\n updateFacilityDetails(selectedCompanyAlias, selectedFacilityAlias);\n var currentState = $state.current.name;\n $state.go(currentState, {\n companyAlias: selectedCompanyAlias,\n facilityAlias: selectedFacilityAlias\n });\n }\n\n function updateFacilityDetails(companyAlias, facilityAlias) {\n // note: we flush the batch requests so that the web api doesn't get confused processing multiple company/facility database connections.\n httpBatcher.flush();\n companyService.getFacilityDetails(companyAlias, facilityAlias).then(function (facility) {\n vm.facilityName = facility.name;\n });\n }\n\n function setupGlobalShortcuts() {\n globalShortcuts[\"capslock capslock 5 0 0\"] = {\n visible: false,\n description: \"Receive a server-side error exception\",\n action: function action() {\n $timeout(errorThrower.getException());\n }\n };\n globalShortcuts[\"capslock capslock 4 0 0\"] = {\n visible: false,\n description: \"Receive a server-side failed result (non 200)\",\n action: function action() {\n $timeout(errorThrower.getFailedResult());\n }\n };\n globalShortcuts[\"capslock capslock f a t a l\"] = {\n visible: false,\n description: \"Throw an unrecoverable Javascript exception\",\n action: function action() {\n var monkey = {};\n console.log(monkey.balls.friday);\n $scope.$apply(function () {\n throw new Error(\"This is an unrecoverable JavaScript exception.\");\n });\n }\n };\n globalShortcuts[\"capslock capslock i n f o\"] = {\n visible: false,\n description: \"Test information messages\",\n action: function action() {\n $timeout(messageList.addInfo(\"Test Information Message\", \"This is an information message.\"));\n }\n };\n globalShortcuts[\"capslock capslock w a r n\"] = {\n visible: false,\n description: \"Test warning messages\",\n action: function action() {\n $timeout(messageList.addWarning(\"Test Warning Message\", \"This is a warning message.\"));\n }\n };\n globalShortcuts[\"g c\"] = {\n description: i18n.i10n(\"app.ui.core.layout.shell.globalShortcuts.company.openMenu\"),\n action: function action() {\n $dropdown.dropdown(\"toggle\");\n $dropdown.parent().focus();\n }\n };\n globalShortcuts[\"?\"] = {\n description: i18n.i10n(\"app.ui.core.layout.shell.globalShortcuts.help\"),\n action: function action() {\n var scope = $scope.$new();\n scope.keyboardShortcuts = keyboardShortcuts;\n $modal.open({\n templateUrl: \"/App/ui/core/keyboardShortcuts.html\",\n animation: false,\n // a bug means the backdrop stays when animations are on :(.\n size: \"modal-lg\",\n scope: scope\n });\n }\n };\n keyboardShortcuts.add(i18n.i10n(\"app.ui.core.layout.shell.globalShortcuts.description\"), globalShortcuts);\n }\n\n function setFilterText($event) {\n if ($event.keyCode === 27) {\n vm.filterText = \"\";\n } else if ($event.keyCode === 13) {\n vm.changeRoute(vm.filteredCompanies[0].alias, vm.filteredCompanies[0].filteredFacilities[0].alias);\n $dropdown.dropdown(\"toggle\");\n vm.filterText = \"\";\n $dropdown.parent().blur();\n } else if ($event.keyCode === 8) {\n vm.filterText = vm.filterText.length > 1 ? vm.filterText.substr(0, vm.filterText.length - 1) : \"\";\n } else {\n vm.filterText += String.fromCharCode($event.keyCode);\n }\n }\n\n function resetFilterText($event) {\n vm.filterText = \"\";\n $event.stopPropagation();\n }\n\n function filterCompanies() {\n return function (company) {\n var facilities = $filter(\"filter\")(company.facilities, {\n searchTerms: vm.filterText\n });\n return facilities.length;\n };\n }\n\n function getActionMenuItems(accessControls, companyAlias, facilityAlias) {\n var menuItems = [];\n\n if (!accessControls) {\n return menuItems;\n }\n\n if (!appSettings.isGuestUser) {\n menuItems.push({\n href: $state.href(\"app.dashboard\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"actions.dashboard\"),\n key: \"operations-menu-dashboard\"\n });\n menuShortcuts[\"/ d a s h\"] = {\n description: getMenuItemShortcutDescription(\"actions.dashboard\"),\n action: function action() {\n $state.go(\"app.dashboard\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n if (accessControls[\"app.monitoring\"] && !accessControls[\"zeus.monitoring\"]) {\n menuItems.push({\n href: $state.href(\"app.monitoring\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"actions.monitoring\"),\n key: \"operations-menu-monitoring\"\n });\n menuShortcuts[\"/ m o n\"] = {\n description: getMenuItemShortcutDescription(\"actions.monitoring\"),\n action: function action() {\n $state.go(\"app.monitoring\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n if (accessControls[\"zeus.monitoring\"]) {\n var url = \"\".concat(vm.appSettings.zeusHostUri, \"map/real-time?companyAlias=\").concat(companyAlias, \"&facilityAlias=\").concat(facilityAlias);\n menuItems.push({\n href: url,\n target: \"_blank\",\n label: getMenuItemLabel(\"actions.zeus.monitoring\"),\n key: \"operations-menu-monitoring\"\n });\n menuShortcuts[\"/ m o n\"] = {\n description: getMenuItemShortcutDescription(\"actions.zeus.monitoring\"),\n action: function action() {\n window.open(url, \"_blank\");\n }\n };\n }\n\n if (accessControls[\"app.modelling\"]) {\n menuItems.push({\n href: $state.href(\"app.modelling.gisModelling\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"actions.modelling\"),\n key: \"operations-menu-modelling\"\n });\n menuShortcuts[\"/ m o d\"] = {\n description: getMenuItemShortcutDescription(\"actions.modelling\"),\n action: function action() {\n $state.go(\"app.modelling.gisModelling\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n if (accessControls[\"app-legacy.modelling.first-response\"]) {\n menuItems.push({\n href: \"\".concat(vm.appSettings.mvcHostUri).concat(vm.appSettings.site.facility.es1RouteName, \"/FirstResponse/EventDetails\"),\n target: \"_blank\",\n label: getMenuItemLabel(\"actions.firstResponseModelling\"),\n key: \"operations-menu-first-response-modelling\"\n });\n }\n\n if (accessControls[\"app.blasting\"]) {\n menuItems.push({\n href: $state.href(\"app.blasting.scenarios\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"actions.blasting\"),\n key: \"operations-menu-blasting\"\n });\n menuShortcuts[\"/ b l a s t\"] = {\n description: getMenuItemShortcutDescription(\"actions.blasting\"),\n action: function action() {\n $state.go(\"app.blasting.scenarios\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n if (accessControls[\"app.modelling.trajectory\"]) {\n menuItems.push({\n href: $state.href(\"app.modelling.trajectory.runs\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"actions.trajectories\"),\n key: \"operations-menu-trajectories\"\n });\n }\n\n if (accessControls[\"app.reports\"]) {\n menuItems.push({\n href: $state.href(\"app.reporting\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"actions.reports\"),\n key: \"operations-menu-reports\"\n });\n }\n\n return menuItems;\n }\n\n function getIncidentIntelligenceMenuItems(accessControls, companyAlias, facilityAlias) {\n var menuItems = [];\n\n if (!accessControls || appSettings.isGuestUser) {\n return menuItems;\n }\n\n if (accessControls[\"app.incident-intelligence\"]) {\n if (appSettings.site.facility.ticketingSystem) {\n menuItems.push({\n href: appSettings.site.facility.ticketingSystem.ticketsUrl,\n target: \"_blank\",\n label: getMenuItemLabel(\"incidentIntelligence.ticketingSystem\"),\n key: \"operations-menu-ticketing-system\"\n });\n }\n\n menuItems = menuItems.concat([{\n href: $state.href(\"app.incidentIntelligence.tickets.summary.cluster\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"incidentIntelligence.summaryCluster\"),\n key: \"operations-menu-cluster-map\"\n }, {\n href: $state.href(\"app.incidentIntelligence.tickets.summary.heat\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"incidentIntelligence.summaryHeat\"),\n key: \"operations-menu-heat-map\"\n }]);\n menuShortcuts[\"/ i n c\"] = {\n description: getMenuItemShortcutDescription(\"incidentIntelligence\"),\n action: function action() {\n $state.go(\"app.incidentIntelligence.tickets.summary.cluster\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n return menuItems;\n }\n\n function getConfigurationMenuItems(accessControls, companyAlias, facilityAlias) {\n var menuItems = [];\n\n if (!accessControls || !accessControls[\"app.config\"]) {\n return menuItems;\n }\n\n if (accessControls[\"app.modelling.run-aermod-modelling\"]) {\n menuItems.push({\n href: $state.href(\"app.configuration.company.modelling.aermet\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"configuration.modelling.aermet\"),\n key: \"operations-menu-modelling-aermet\"\n });\n }\n\n if (accessControls[\"app.config.modelling\"]) {\n menuItems.push({\n href: $state.href(\"app.configuration.company.modelling.models\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"configuration.modelling.models\"),\n key: \"operations-menu-modelling-models\"\n });\n menuShortcuts[\"/ c m o d\"] = {\n description: getMenuItemShortcutDescription(\"configuration.modelling\"),\n action: function action() {\n $state.go(\"app.configuration.company.modelling.models\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n menuShortcuts[\"/ r m o d\"] = {\n visible: false,\n description: getMenuItemShortcutDescription(\"configuration.modelling.modelRuns\"),\n action: function action() {\n $state.go(\"app.configuration.system.modelling.modelRuns\");\n }\n };\n\n if (accessControls[\"app.config.modelling.run-models\"]) {\n menuItems.push({\n href: \"\".concat(vm.appSettings.mvcHostUri).concat(vm.appSettings.site.facility.es1RouteName, \"/plume/getmodelstatus\"),\n target: \"_blank\",\n label: getMenuItemLabel(\"configuration.modelling.model-status\"),\n key: \"operations-menu-modelling-model-status\"\n });\n menuShortcuts[\"/ x m a s\"] = {\n description: getMenuItemShortcutDescription(\"configuration.modelling.model-status\"),\n action: function action() {\n $window.location.href = \"\".concat(vm.appSettings.mvcHostUri).concat(vm.appSettings.site.facility.es1RouteName, \"/plume/getmodelstatus\");\n }\n };\n }\n }\n\n if (accessControls[\"app.config.modelling.emission-data\"]) {\n menuItems.push({\n href: $state.href(\"app.configuration.company.modelling.emissionsData\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"configuration.modelling.emissionsData\"),\n key: \"operations-menu-modelling-emissions-data\"\n });\n }\n\n if (accessControls[\"app.config.monitoring\"]) {\n menuItems.push({});\n menuItems.push({\n href: $state.href(\"app.configuration.company.monitoring.monitors\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"configuration.monitoring.monitors\"),\n key: \"operations-menu-monitoring-monitors\"\n });\n menuItems.push({\n href: $state.href(\"app.configuration.company.monitoring.measurementGroups\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"configuration.monitoring.measurementGroups\"),\n key: \"operations-menu-monitoring-measurement-groups\"\n });\n menuShortcuts[\"/ c m o n\"] = {\n description: getMenuItemShortcutDescription(\"configuration.monitoring\"),\n action: function action() {\n $state.go(\"app.configuration.company.monitoring.monitors\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n if (accessControls[\"app.config.annotations.monitor-pollutants\"]) {\n menuItems.push({});\n menuItems.push({\n href: $state.href(\"app.configuration.company.annotations.monitorPollutants\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n }),\n label: getMenuItemLabel(\"configuration.annotations.monitor-pollutants\"),\n key: \"operations-menu-annotations-monitor-pollutants\"\n });\n menuShortcuts[\"/ c a m p\"] = {\n description: getMenuItemShortcutDescription(\"configuration.annotations.monitor-pollutants\"),\n action: function action() {\n $state.go(\"app.configuration.company.annotations.monitorPollutants\", {\n companyAlias: companyAlias,\n facilityAlias: facilityAlias\n });\n }\n };\n }\n\n if (accessControls[\"app-legacy.mailer\"]) {\n menuItems.push({});\n menuItems.push({\n href: \"\".concat(vm.appSettings.mvcHostUri).concat(vm.appSettings.site.facility.es1RouteName, \"/Admin/Mailer\"),\n label: getMenuItemLabel(\"configuration.reporting.mailers\"),\n key: \"operations-menu-reporting-mailers\"\n });\n }\n\n return menuItems;\n }\n\n function getMenuItemLabel(menuItem) {\n return i18n.i10n(\"app.ui.core.layout.shell.navigation.menu.submenu.\".concat(menuItem, \".label\"));\n }\n\n function getMenuItemShortcutDescription(menuItem) {\n return i18n.i10n(\"app.ui.core.layout.shell.navigation.menu.submenu.\".concat(menuItem, \".shortcut\"));\n }\n\n function logout() {\n return securityService.logout();\n }\n\n var isAttached;\n /* istanbul ignore next */\n\n function calculateOperationsMenuHeight() {\n $timeout(function () {\n var dropdownMenu = $(\".open .dropdown-menu-large\");\n\n if (!dropdownMenu.length) {\n return;\n }\n\n if (!isAttached) {\n dropdownMenu.on(\"click\", function () {\n return $(\".navbar-toggle\").click();\n });\n isAttached = true;\n }\n\n var scrollHeight = window.innerWidth < 768 ? window.innerHeight - dropdownMenu.offset().top - $(\"#shell-view-header\").height() : \"inherit\";\n dropdownMenu.height(scrollHeight);\n });\n }\n\n function shouldShowOperationsMenu() {\n try {\n var params = new URLSearchParams(window.location.search);\n var from = params.get(\"from\");\n\n if (from !== \"omnis\") {\n return true;\n }\n\n return false;\n } catch (error) {\n console.error(error);\n return true;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapCenter\", esMapCentre).controller(\"esMapCentreController\", esMapCentreController);\n\n function esMapCentre() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n defaultCentre: \"=\",\n centre: \"=\",\n bounds: \"=?\"\n },\n replace: true,\n bindToController: true,\n controller: esMapCentreController,\n controllerAs: \"vm\"\n };\n }\n\n esMapCentreController.$inject = [\"$scope\", \"esLeafletData\", \"leafletLib\", \"i18n\", \"$timeout\", \"google\", \"lodash\"];\n\n function esMapCentreController($scope, esLeafletData, L, i18n, $timeout, google, _) {\n var vm = this;\n var originalCentre = angular.merge({}, vm.defaultCentre);\n activate(); ////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(addControl).then(fitMapToBounds);\n }\n\n function addControl(map) {\n var control = new L.Control.EasyButtons({\n icon: \"fa-crosshairs\",\n title: i18n.i10n(\"esMapCentre.button.tooltip\"),\n click: onClick\n });\n map.addControl(control);\n control.enable();\n map.on(\"dragend\", areCentresInSync);\n map.on(\"zoomend\", areCentresInSync);\n $scope.$watch(function () {\n return vm.centre;\n }, areCentresInSync);\n return map; //////////////\n\n function onClick() {\n control.setActive();\n fitBounds(map);\n }\n\n function areCentresInSync() {\n if (latLngMatch(vm.centre, originalCentre)) {\n control.setActive();\n } else {\n control.setInactive();\n }\n }\n }\n\n function fitMapToBounds(map) {\n var googleLayer = _.find(map._layers, function (layer) {\n return layer._google;\n });\n\n if (googleLayer) {\n google.maps.event.addListenerOnce(googleLayer._google, \"idle\", zoomToExtents);\n } else {\n // Get the first tile layer and setup trigger event on loaded.\n var firstTileLayer;\n map.eachLayer(function (layer) {\n if (!firstTileLayer && layer instanceof L.TileLayer) {\n firstTileLayer = layer;\n }\n });\n\n if (firstTileLayer) {\n firstTileLayer.on(\"load\", zoomToExtents);\n }\n } //////////////\n\n\n function zoomToExtents() {\n var unwatch = $scope.$watch(function () {\n return vm.bounds;\n }, function () {\n if (!vm.bounds || !vm.bounds.length) {\n return;\n }\n\n unwatch();\n\n if (!vm.centre || latLngMatch(vm.centre, vm.defaultCentre)) {\n fitBounds(map);\n }\n });\n }\n }\n\n ;\n\n function latLngMatch(current, original) {\n if (!(current && current.lat && current.lng && original && original.lat && original.lng)) {\n return false;\n }\n\n if (current.lat.toFixed(6) !== original.lat.toFixed(6)) {\n return false;\n }\n\n if (current.lng.toFixed(6) !== original.lng.toFixed(6)) {\n return false;\n }\n\n return current.zoom === original.zoom;\n }\n\n function fitBounds(map) {\n if (vm.bounds && vm.bounds.length) {\n map.fitBounds(vm.bounds);\n } else {\n map.setView(vm.defaultCentre, vm.defaultCentre.zoom);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").component(\"esMapCluster\", {\n controller: esMapCluster,\n bindings: {\n mapId: \"@\",\n models: \"<\",\n onclick: \"=\"\n }\n });\n esMapCluster.$inject = [\"lodash\", \"leafletLib\", \"esLeafletData\"];\n\n function esMapCluster(_, L, esLeafletData) {\n var vm = this;\n var clusterGroup;\n var mapReady;\n\n vm.$onInit = function () {\n mapReady = esLeafletData.getMap(vm.mapId);\n mapReady.then(renderClusters);\n };\n\n vm.$onChanges = function (changes) {\n if (changes.models && mapReady) {\n mapReady.then(function (map) {\n clearLayers();\n renderClusters(map);\n });\n }\n };\n\n vm.$onDestroy = function () {\n clearLayers();\n }; /////////////////////\n\n\n function renderClusters(map) {\n clusterGroup = L.markerClusterGroup({\n iconCreateFunction: function iconCreateFunction(cluster) {\n return getClusterIcon(cluster.getChildCount());\n },\n chunkedLoading: true,\n polygonOptions: {\n className: \"cluster-area\"\n }\n });\n\n var markers = _.map(vm.models, function (model) {\n var marker = L.marker(L.latLng(model.lat, model.long), {\n icon: getMarkerIcon(),\n riseOnHover: true\n });\n marker.bindTooltip(model.tooltip);\n\n if (vm.onclick) {\n marker.on(\"click\", function (e) {\n if (model.isToggleMarker) {\n var icon = {};\n\n if (model.isSelected) {\n icon = getMarkerIcon();\n } else {\n icon = getSelectedMarkerIcon();\n }\n\n model.isSelected = !model.isSelected;\n e.target.setIcon(icon);\n }\n\n vm.onclick && vm.onclick(model);\n });\n }\n\n return marker;\n });\n\n clusterGroup.addLayers(markers);\n map.addLayer(clusterGroup);\n }\n\n function clearLayers() {\n if (clusterGroup) {\n clusterGroup.clearLayers();\n }\n }\n\n function getMarkerIcon() {\n return L.AwesomeMarkers.icon({\n prefix: \"fa\",\n icon: \"bell-o\",\n markerColor: \"orange\"\n });\n }\n\n function getSelectedMarkerIcon() {\n return L.AwesomeMarkers.icon({\n prefix: \"fa\",\n icon: \"bell\",\n markerColor: \"orange\"\n });\n }\n\n function getClusterIcon(childCount) {\n var clusterSize = \"marker-cluster-\".concat(childCount < 10 ? \"small\" : childCount < 100 ? \"medium\" : \"large\");\n return new L.DivIcon({\n html: \"
      \".concat(childCount, \"
      \"),\n className: \"marker-cluster \".concat(clusterSize),\n iconSize: new L.Point(40, 40)\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapCredits\", esMapCredits).controller(\"esMapCreditsController\", esMapCreditsController);\n\n function esMapCredits() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\"\n },\n bindToController: true,\n controller: esMapCreditsController,\n controllerAs: \"vm\"\n };\n }\n\n esMapCreditsController.$inject = [\"$scope\", \"$modal\", \"leafletLib\", \"esLeafletData\", \"browserStorage\", \"lodash\", \"i18n\", \"app.core.services.mappingService\", \"app.core.appSettings\"];\n\n function esMapCreditsController($scope, $modal, L, esLeafletData, browserStorage, _, i18n, mappingService, appSettings) {\n var vm = this;\n var storageKey = \"map-credits\";\n var storageBucketKey = \"\".concat(appSettings.site.facility.alias, \"-\").concat(appSettings.userId);\n activate(); ///////\n\n function activate() {\n mappingService.getMapCredits().then(function (mapCredits) {\n if (!_.size(mapCredits)) {\n return;\n }\n\n var control = new L.es.MapCredits();\n esLeafletData.getMap(vm.mapId).then(function (map) {\n control.addTo(map);\n processCredits(control, mapCredits);\n });\n });\n }\n\n function processCredits(control, mapCredits) {\n mapCredits.forEach(function (mapCredit) {\n var text = mapCredit.text;\n var popupFunction = null;\n\n if (text) {\n var textVersion = mapCredit.textVersion;\n\n popupFunction = function popupFunction() {\n return showCreditText(text, textVersion);\n };\n\n if (!hasDismissedText(textVersion)) {\n showCreditText(text, textVersion);\n }\n }\n\n var imageUrl = \"data:\".concat(mapCredit.logoMimeType, \";base64,\").concat(mapCredit.logoData);\n control.addCredit(imageUrl, popupFunction);\n });\n }\n\n function hasDismissedText(textVersion) {\n var storedTextVersion = browserStorage.getBucket(storageKey, storageBucketKey);\n return storedTextVersion === textVersion;\n }\n\n function dismissVersion(textVersion) {\n browserStorage.persistBucket(storageKey, storageBucketKey, textVersion);\n }\n\n function showCreditText(text, textVersion) {\n var newScope = $scope.$new(true);\n newScope.text = text;\n newScope.title = i18n.i10n(\"esMapCredits.dialog.title\");\n var modalInstance = $modal.open({\n templateUrl: \"/App/ui/core/mapping/controls/esMapCreditsDialog.html\",\n animation: false,\n // a bug means the backdrop stays when animations are on :(.\n size: \"modal-lg\",\n scope: newScope\n });\n modalInstance.result.catch(function () {\n return dismissVersion(textVersion);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapDomainBoundaries\", directive).controller(\"esMapDomainBoundariesController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n boundaries: \"=?\",\n showModelling: \"=\",\n showBlasting: \"=\",\n showIncidentIntelligence: \"=\"\n },\n bindToController: true,\n controller: controller,\n controllerAs: \"vm\"\n };\n }\n\n controller.$inject = [\"$q\", \"esLeafletData\", \"leafletLib\", \"i18n\", \"app.core.services.companyService\"];\n\n function controller($q, esLeafletData, L, i18n, companyService) {\n var vm = this;\n var layerGroup = null;\n var isActive = false;\n activate(); ////////////////////\n\n function activate() {\n var mapPromise = esLeafletData.getMap(vm.mapId);\n var boundariesPromise = companyService.getDomainBoundaries(!!vm.showModelling, !!vm.showBlasting, !!vm.showIncidentIntelligence);\n $q.all([mapPromise, boundariesPromise]).then(function (results) {\n return addControl.apply(void 0, _toConsumableArray(results));\n });\n }\n\n function addControl(map, boundaries) {\n vm.boundaries = boundaries;\n var control = createToggleButtonAndAddToMap();\n buildLayerGroup();\n toggleDomainBoundaries(); ////////////////////\n\n function createToggleButtonAndAddToMap() {\n var easyButton = new L.Control.EasyButtons({\n icon: \"fa-clone\",\n title: i18n.i10n(\"esMapDomainBoundaries.button.tooltip\"),\n click: toggleDomainBoundaries\n });\n map.addControl(easyButton);\n easyButton.enable();\n return easyButton;\n }\n\n function buildLayerGroup() {\n layerGroup = new L.LayerGroup();\n\n if (!(vm.boundaries && vm.boundaries.length)) {\n return;\n }\n\n var lineOptions = {\n color: \"#1ba6d5\",\n // = @es-highlight\n opacity: 1,\n weight: 2,\n dashArray: \"2,3\"\n };\n vm.boundaries.forEach(function (boundary) {\n var bottomRight = new L.LatLng(boundary.bottomRight.latitude, boundary.bottomRight.longitude);\n var bottomLeft = new L.LatLng(boundary.bottomLeft.latitude, boundary.bottomLeft.longitude);\n var topRight = new L.LatLng(boundary.topRight.latitude, boundary.topRight.longitude);\n var topLeft = new L.LatLng(boundary.topLeft.latitude, boundary.topLeft.longitude);\n var firstPolyline = new L.Polyline([bottomLeft, bottomRight], lineOptions);\n var secondPolyline = new L.Polyline([bottomLeft, topLeft], lineOptions);\n var thirdPolyline = new L.Polyline([topLeft, topRight], lineOptions);\n var fourthPolyline = new L.Polyline([topRight, bottomRight], lineOptions);\n layerGroup.addLayer(firstPolyline);\n layerGroup.addLayer(secondPolyline);\n layerGroup.addLayer(thirdPolyline);\n layerGroup.addLayer(fourthPolyline);\n });\n }\n\n function toggleDomainBoundaries() {\n if (isActive) {\n control.setInactive();\n map.removeLayer(layerGroup);\n } else {\n control.setActive();\n layerGroup.addTo(map);\n }\n\n isActive = !isActive;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapEmissionSources\", esMapEmissionSources).controller(\"esMapEmissionSourcesController\", esMapEmissionSourcesController);\n\n function esMapEmissionSources() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\"\n },\n templateUrl: \"/App/ui/core/mapping/controls/esMapEmissionSources.html\",\n controller: esMapEmissionSourcesController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esMapEmissionSourcesController.$inject = [\"leafletLib\", \"esLeafletData\", \"app.core.services.mappingService\"];\n\n function esMapEmissionSourcesController(L, esLeafletData, mappingService) {\n var vm = this;\n var layerGroup = new L.LayerGroup();\n var map;\n vm.isVisible = true;\n vm.hasSources = true;\n vm.toggleSources = toggleSources;\n esLeafletData.getMap(vm.mapId).then(function (leafletMap) {\n map = leafletMap;\n activate();\n }); ////////////////////\n\n function activate() {\n loadSourcesOverlay();\n }\n\n function toggleSources() {\n if (vm.isVisible) {\n layerGroup.addTo(map);\n } else {\n map.removeLayer(layerGroup);\n }\n }\n\n function loadSourcesOverlay() {\n mappingService.getEmissionSourceKml().then(function (kml) {\n if (kml === null) {\n vm.hasSources = false;\n return;\n }\n\n var kmlLayer = new L.KML(null, {\n async: true,\n autoPan: false\n });\n var parser = new DOMParser();\n var xmlDoc = parser.parseFromString(kml.data, \"text/xml\");\n\n kmlLayer._addKML(xmlDoc);\n\n layerGroup.addLayer(kmlLayer);\n layerGroup.addTo(map);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.core\").component(\"esMapHeatMap\", {\n controller: esMapHeatMapController,\n bindings: {\n mapId: \"@\",\n models: \"<\"\n }\n });\n esMapHeatMapController.$inject = [\"$timeout\", \"lodash\", \"leafletLib\", \"esLeafletData\"];\n\n function esMapHeatMapController($timeout, _, L, esLeafletData) {\n var vm = this;\n vm.points = [];\n var heatLayer;\n var mapReady;\n var retryCount = 0;\n\n vm.$onInit = function () {\n mapReady = esLeafletData.getMap(vm.mapId);\n mapReady.then(renderClusters);\n };\n\n vm.$onChanges = function (changes) {\n if (changes.models && mapReady) {\n mapReady.then(function (map) {\n clearLayers(map);\n renderClusters(map);\n });\n }\n };\n\n vm.$onDestroy = function () {\n if (mapReady) {\n mapReady.then(clearLayers);\n }\n }; ////////////////\n\n\n function clearLayers() {\n if (heatLayer) {\n heatLayer.setLatLngs([]);\n }\n }\n\n function renderClusters(map) {\n if (map.getSize().y === 0 && retryCount < 10) {\n // workaround for a bug where the map is not yet ready.\n $timeout(function () {\n retryCount++;\n renderClusters(map);\n }, 100);\n } else {\n retryCount = 0;\n\n var points = _.map(vm.models, function (point) {\n return [point.lat, point.long, 1];\n });\n\n if (!heatLayer) {\n heatLayer = L.heatLayer(points);\n heatLayer.setOptions({\n radius: 25,\n max: 1,\n minOpacity: 0.1,\n maxZoom: 15\n });\n map.addLayer(heatLayer);\n } else {\n heatLayer.setLatLngs(points);\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapInfluenceArcs\", esMapInfluenceArcDirective).controller(\"esMapInfluenceArcsController\", esMapInfluenceArcsController);\n\n function esMapInfluenceArcDirective() {\n return {\n restrict: \"E\",\n require: \"esLeaflet\",\n scope: {\n mapId: \"@\",\n influenceArcs: \"=\"\n },\n controller: esMapInfluenceArcsController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esMapInfluenceArcsController.$inject = [\"$scope\", \"leafletLib\", \"esLeafletData\"];\n\n function esMapInfluenceArcsController($scope, L, esLeafletData) {\n var vm = this;\n var leafletArcs = {};\n esLeafletData.getMap(vm.mapId).then(function (map) {\n $scope.$watch(function () {\n return vm.influenceArcs;\n }, function (arcs) {\n if (!arcs) {\n return;\n }\n\n esLeafletData.getLayers().then(function (layers) {\n for (var i = 0; i < arcs.length; i++) {\n var influenceArc = arcs[i];\n\n if (!influenceArc) {\n continue;\n }\n\n var influenceArcPolygon = leafletArcs[influenceArc.monitorId];\n var layerGroup = layers.overlays[\"influenceArcs-\" + influenceArc.monitorType];\n\n if (influenceArc.unrender) {\n if (influenceArcPolygon) {\n layerGroup.removeLayer(influenceArcPolygon);\n delete leafletArcs[influenceArc.monitorId];\n }\n\n continue;\n }\n\n if (influenceArcPolygon) {\n influenceArcPolygon.update(influenceArc);\n } else {\n influenceArcPolygon = L.es.influenceArcs(map, influenceArc);\n leafletArcs[influenceArc.monitorId] = influenceArcPolygon;\n layerGroup.addLayer(influenceArcPolygon);\n }\n\n influenceArcPolygon.bringToBack();\n }\n });\n });\n });\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapKml\", directive).controller(\"esMapKmlController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n overlayProvider: \"=\",\n showControls: \"=\",\n interactive: \"=?\"\n },\n replace: true,\n bindToController: true,\n controller: controller,\n controllerAs: \"vm\"\n };\n }\n\n controller.$inject = [\"$scope\", \"leafletLib\", \"esLeafletData\", \"i18n\", \"lodash\"];\n\n function controller($scope, L, esLeafletData, i18n, _) {\n var vm = this;\n var layerGroup = new L.FeatureGroup();\n var map;\n var isShowing = false;\n var layerToggleControl = new L.Control.EasyButtons({\n icon: \"fa-pencil-square-o\",\n title: i18n.i10n(\"esMapKml.button.tooltip\"),\n click: toggleLayerGroup\n });\n esLeafletData.getMap(vm.mapId).then(function (leafletMap) {\n map = leafletMap;\n activate();\n }); ////////////////////\n\n function activate() {\n if (_.isUndefined(vm.interactive) || _.isNull(vm.interactive)) {\n vm.interactive = true;\n }\n\n showLayerToggleControlWhenShowControlsRequested();\n renderOverlaysWhenOverlaySourceChanges();\n }\n\n function showLayerToggleControlWhenShowControlsRequested() {\n $scope.$watch(function () {\n return vm.showControls;\n }, function (showControls) {\n var isAddedToMap = layerToggleControl._map;\n\n if (showControls && !isAddedToMap) {\n map.addControl(layerToggleControl);\n } else if (!showControls && isAddedToMap) {\n map.removeControl(layerToggleControl);\n }\n });\n }\n\n function renderOverlaysWhenOverlaySourceChanges() {\n $scope.$watchCollection(function () {\n return vm.overlayProvider;\n }, renderOverlays);\n\n function renderOverlays(overlayProvider) {\n layerGroup.clearLayers();\n layerToggleControl.setInactive();\n layerToggleControl.disable();\n\n if (!overlayProvider || _.isEmpty(overlayProvider)) {\n return;\n }\n\n layerToggleControl.enable();\n layerToggleControl.setActive();\n\n _.forEach(overlayProvider, function (kml) {\n var kmlLayer = new L.KML(null, {\n async: true,\n autoPan: false\n });\n var parser = new DOMParser();\n var xmlDoc = parser.parseFromString(kml.data, \"text/xml\");\n\n kmlLayer._addKML(xmlDoc);\n\n layerGroup.addLayer(kmlLayer);\n kmlLayer.on(\"click\", onKmlLayerClicked);\n });\n\n if (!isShowing) {\n toggleLayerGroup();\n }\n }\n }\n\n function onKmlLayerClicked(evnt) {\n if (vm.interactive) {\n return;\n }\n\n evnt.layer.closePopup(); // Since the user has clicked on a KML image (i.e. a marker), leaflet always sets the lat/lng of the event\n // to the lat/long of the marker. However, when we are in `non-interactive` mode, we want to pass-through\n // the event at the ACTUAL lat/lng of the mouse click. As such, we need to calculate where this is based\n // on the point that the user has clicked.\n //\n // To do this, we emulate (read: `copy`) the way that the leaflet Map fires mouse events (see\n // `_fireMouseEvent` in the L.map class for details).\n //\n // Note: Once we upgrade to Leaflet 1.0.0 (when it gets released), we should be able to achieve this\n // by simply making the marker non-interactive - see: http://mourner.github.io/Leaflet/reference.html#marker\n\n var originalEvent = evnt.originalEvent;\n var containerPoint = map.mouseEventToContainerPoint(originalEvent);\n var layerPoint = map.containerPointToLayerPoint(containerPoint);\n var latlng = map.layerPointToLatLng(layerPoint);\n map.fire(\"click\", {\n latlng: latlng,\n layerPoint: layerPoint,\n containerPoint: containerPoint,\n originalEvent: originalEvent\n });\n }\n\n function toggleLayerGroup() {\n if (isShowing) {\n map.removeLayer(layerGroup);\n layerToggleControl.setInactive();\n } else {\n layerGroup.addTo(map);\n layerToggleControl.setActive();\n }\n\n isShowing = !isShowing;\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapLocationSelector\", directive).controller(\"esMapLocationSelectorController\", controller);\n directive.$inject = [\"lodash\", \"esLeafletData\"];\n\n function directive(_, esLeafletData) {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n latitude: \"=\",\n longitude: \"=\",\n isActive: \"=\",\n boundaries: \"=?\",\n icon: \"@\",\n markerColor: \"@\"\n },\n link: link,\n bindToController: true,\n controller: controller,\n controllerAs: \"vm\"\n };\n\n function link($scope, $element) {\n var vm = $scope.vm;\n var targetingClassName = \"map-location-selector-active\";\n var outOfBoundsClassName = \"map-location-selector-out-of-bounds\";\n activate(); ////////////////////\n\n function activate() {\n var unregisterOutOfBoundsWatcher = null;\n var wasInBounds;\n $scope.$watch(function () {\n return vm.isActive;\n }, addTargetingCssClassWhenTargeting); ////////////////////\n\n function addTargetingCssClassWhenTargeting(isTargeting) {\n var $map = $element.closest(\".angular-leaflet-map\");\n\n if (isTargeting) {\n $map.addClass(targetingClassName);\n esLeafletData.getMap(vm.mapId).then(function (map) {\n unregisterOutOfBoundsWatcher = addOutOfBoundsCssClassWhenOutOfBounds($map, map);\n });\n } else {\n $map.removeClass(targetingClassName);\n $map.removeClass(outOfBoundsClassName);\n\n if (unregisterOutOfBoundsWatcher) {\n unregisterOutOfBoundsWatcher();\n unregisterOutOfBoundsWatcher = null;\n }\n }\n }\n\n function addOutOfBoundsCssClassWhenOutOfBounds($map, map) {\n var boundaries = vm.boundaries;\n\n if (!(boundaries && boundaries.length)) {\n return null;\n }\n\n map.on(\"mousemove\", onMouseMoved);\n return function () {\n wasInBounds = null;\n map.off(\"mousemove\", onMouseMoved);\n }; ////////////////////\n\n function onMouseMoved(evnt) {\n var location = evnt.latlng;\n var isInBounds = !!_.find(boundaries, function (boundary) {\n return boundary.contains(location.lat, location.lng);\n }); // coerce isInBounds to a boolean, otherwise we could be comparing two undefined values.\n\n if (wasInBounds === isInBounds) {\n return;\n }\n\n if (isInBounds) {\n $map.removeClass(outOfBoundsClassName);\n } else {\n $map.addClass(outOfBoundsClassName);\n }\n\n wasInBounds = isInBounds;\n }\n }\n }\n }\n }\n\n controller.$inject = [\"$scope\", \"esLeafletData\", \"leafletLib\", \"i18n\"];\n\n function controller($scope, esLeafletData, L, i18n) {\n var vm = this;\n var marker = null;\n activate(); ////////////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(function (map) {\n addControl(map);\n moveMarkerWhenLocationChanges(map);\n });\n }\n\n function addControl(map) {\n var control = new L.Control.EasyButtons({\n icon: \"fa-map-marker\",\n title: i18n.i10n(\"esMapLocationSelector.button.tooltip\"),\n click: toggleTargetting\n });\n map.addControl(control);\n control.enable(); //////////////\n\n function toggleTargetting() {\n var shouldEnableTargetting = !vm.isActive;\n\n if (shouldEnableTargetting) {\n enableTargetting();\n } else {\n disableTargetting();\n }\n }\n\n function enableTargetting() {\n control.setActive();\n map.on(\"click\", onLocationSelected);\n vm.isActive = true;\n }\n\n function disableTargetting() {\n control.setInactive();\n map.off(\"click\", onLocationSelected);\n vm.isActive = false;\n }\n\n function onLocationSelected(e) {\n var latLng = e.latlng;\n vm.latitude = latLng.lat;\n vm.longitude = latLng.lng;\n disableTargetting();\n }\n }\n\n function moveMarkerWhenLocationChanges(map) {\n var watches = [function () {\n return vm.latitude;\n }, function () {\n return vm.longitude;\n }];\n $scope.$watchGroup(watches, onLocationChanged); ////////////////////\n\n function onLocationChanged(location) {\n var _location = _slicedToArray(location, 2),\n latitude = _location[0],\n longitude = _location[1];\n\n if (!(latitude && longitude)) {\n if (marker !== null) {\n map.removeLayer(marker);\n marker = null;\n }\n\n return;\n }\n\n if (!marker) {\n var icon = new L.AwesomeMarkers.Icon({\n prefix: \"fa\",\n icon: vm.icon,\n markerColor: vm.markerColor\n });\n marker = new L.Marker([latitude, longitude], {\n icon: icon,\n clickable: false,\n keyboard: false\n });\n marker.addTo(map);\n } else {\n marker.setLatLng(new L.LatLng(latitude, longitude));\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapReady\", esMapReady).controller(\"esMapReadyController\", esMapReadyController);\n\n function esMapReady() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n isReady: \"=?\"\n },\n bindToController: true,\n controller: esMapReadyController,\n controllerAs: \"vm\",\n template: \"
      \"\n };\n }\n\n esMapReadyController.$inject = [\"$scope\", \"$timeout\", \"$log\", \"google\", \"lodash\", \"esLeafletData\", \"leafletLib\"];\n\n function esMapReadyController($scope, $timeout, $log, google, _, esLeafletData, L) {\n var vm = this;\n vm.isMapIdle = false;\n vm.isMapReady = false;\n vm.isReady = vm.isReady !== undefined ? vm.isReady : true;\n activate(); ////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(function (map) {\n var googleLayer = _.find(map._layers, function (layer) {\n return layer._google;\n }); // $timeouts() are to update the values within the angular digest cycle\n\n\n if (googleLayer) {\n google.maps.event.addListenerOnce(googleLayer._google, \"tilesloaded\", function () {\n $timeout(function () {\n return vm.mapTilesLoaded = true;\n });\n });\n google.maps.event.addListenerOnce(googleLayer._google, \"idle\", function () {\n $timeout(function () {\n return vm.isMapIdle = true;\n });\n });\n } else {\n // Using the load event would be nicer but the esLeafletData.getMap() promise resolves *after* the\n // map is loaded. Fortunately the moveend event seems to work as well.\n map.once(\"moveend\", function (e) {\n $timeout(function () {\n return vm.isMapIdle = true;\n });\n });\n var firstTileLayer;\n map.eachLayer(function (layer) {\n if (!firstTileLayer && layer instanceof L.TileLayer) {\n firstTileLayer = layer;\n }\n });\n\n if (firstTileLayer) {\n firstTileLayer.on(\"load\", function () {\n $timeout(function () {\n return vm.mapTilesLoaded = true;\n });\n });\n }\n }\n\n $scope.$watchGroup([\"vm.mapTilesLoaded\", \"vm.isReady\"], function () {\n vm.isMapReady = vm.mapTilesLoaded && vm.isReady && vm.isMapIdle;\n });\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapResizer\", esMapResizer).controller(\"esMapResizerController\", esMapResizerController);\n\n function esMapResizer() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\"\n },\n bindToController: true,\n controller: esMapResizerController,\n controllerAs: \"vm\"\n };\n }\n\n esMapResizerController.$inject = [\"$scope\", \"$log\", \"lodash\", \"esLeafletData\"];\n\n function esMapResizerController($scope, $log, _, esLeafletData) {\n var vm = this;\n activate(); ////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(function (map) {\n var debounceInvalidateMap = _.debounce(invalidateMap, 50);\n\n $scope.$on(\"resizePage\", debounceInvalidateMap);\n debounceInvalidateMap();\n\n function invalidateMap() {\n $log.debug(\"esMapResizer: invalidating map to force redraw\");\n\n try {\n map.invalidateSize();\n } catch (ex) {// swallow\n }\n }\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapScale\", directive).controller(\"esMapScaleController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\"\n },\n bindToController: true,\n controller: controller,\n controllerAs: \"vm\"\n };\n }\n\n controller.$inject = [\"leafletLib\", \"esLeafletData\"];\n\n function controller(L, esLeafletData) {\n var vm = this;\n activate(); ////////////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(addControl);\n }\n\n function addControl(map) {\n var control = new L.Control.Scale({\n imperial: false,\n position: \"bottomright\"\n });\n control.addTo(map);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapTemporalEvents\", directive);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n temporalEventGroups: \"=\",\n showControls: \"=\" // future enhancement to show a control that allows user to turn on/off geoJson at the map layer group level.\n\n },\n bindToController: true,\n controller: controller,\n controllerAs: \"vm\"\n };\n }\n\n controller.$inject = [\"$scope\", \"leafletLib\", \"esLeafletData\", \"lodash\"];\n\n function controller($scope, L, esLeafletData, _) {\n var vm = this;\n var geoJsonOptions = getGeoJsonOptions();\n var map;\n var leafletLayerGroups = [];\n esLeafletData.getMap(vm.mapId).then(function (leafletMap) {\n map = leafletMap;\n activate();\n }); ////////////////////\n\n function activate() {\n $scope.$watchCollection(function () {\n return vm.temporalEventGroups;\n }, function () {\n _.forEach(leafletLayerGroups, removeLeafletGeoJsonLayerGroup);\n\n _.forEach(vm.temporalEventGroups, createLeafletLayerGroups);\n });\n }\n\n function removeLeafletGeoJsonLayerGroup() {\n if (!(map && _.isArray(leafletLayerGroups))) {\n return;\n }\n\n _.forEach(leafletLayerGroups, function (llg) {\n map.removeLayer(llg);\n });\n\n leafletLayerGroups = [];\n }\n\n function createLeafletLayerGroups(eventGroup) {\n var geoJsonContentType = \"geojson\";\n var kmlContentType = \"kml\";\n var geoJsons = [];\n var kmls = [];\n var parser = new DOMParser();\n\n if (!(eventGroup.events && Object.keys(eventGroup.events).length) && eventGroup.fallbackContentType) {\n switch (eventGroup.fallbackContentType.toLowerCase()) {\n case kmlContentType:\n kmls.push(parser.parseFromString(eventGroup.fallbackContent, \"text/xml\"));\n break;\n\n case geoJsonContentType:\n geoJsons.push(JSON.parse(eventGroup.fallbackContent));\n break;\n }\n } else {\n _.forEach(eventGroup.events, function (temporalEvent) {\n switch (temporalEvent.contentType.toLowerCase()) {\n case kmlContentType:\n kmls.push(parser.parseFromString(temporalEvent.content, \"text/xml\"));\n break;\n\n case geoJsonContentType:\n geoJsons.push(JSON.parse(temporalEvent.content));\n break;\n }\n });\n }\n\n if (kmls.length > 0) {\n _.forEach(kmls, function (kml) {\n var kmlLayer = new L.KML(null, {\n async: true,\n autoPan: false\n });\n\n kmlLayer._addKML(kml);\n\n leafletLayerGroups.push(kmlLayer);\n kmlLayer.addTo(map);\n });\n }\n\n if (geoJsons.length > 0) {\n var leafletLayerGroup = L.geoJson(geoJsons, geoJsonOptions);\n leafletLayerGroups.push(leafletLayerGroup);\n leafletLayerGroup.addTo(map);\n }\n }\n\n function getGeoJsonOptions() {\n return {\n style: function style(feature) {\n return feature.properties && feature.properties.style;\n },\n onEachFeature: bindPopup,\n pointToLayer: createHtmlMarker\n };\n\n function bindPopup(feature, layer) {\n var popupContent = feature.properties && feature.properties.popupContent;\n\n if (popupContent) {\n layer.bindPopup(popupContent);\n }\n }\n\n function createHtmlMarker(feature, latlng) {\n var content = feature.properties && feature.properties.content;\n\n if (!content) {\n throw new Error(\"HTML content was not provided.\");\n }\n\n var options = {\n content: content\n };\n return L.marker(latlng, {\n icon: L.htmlIcon(options)\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapTiles\", esMapTiles).controller(\"esMapTilesController\", esMapTilesController);\n /*\r\n * This directive adds a layer to show custom tiles that a customer provides for the maps.\r\n */\n\n esMapTiles.$inject = [];\n\n function esMapTiles() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\"\n },\n replace: true,\n bindToController: true,\n controller: esMapTilesController,\n controllerAs: \"vm\"\n };\n }\n\n esMapTilesController.$inject = [\"$scope\", \"leafletLib\", \"lodash\", \"i18n\", \"app.core.services.mappingService\", \"app.core.appSettings\", \"esLeafletData\"];\n\n function esMapTilesController($scope, L, _, i18n, mappingService, appSettings, esLeafletData) {\n var vm = this;\n var tileServerUrl = \"\".concat(appSettings.webApiHostUri, \"map/tile/{facilityCode}/{name}/{z}/{x}/{y}\");\n var layerGroup = L.layerGroup();\n var layers = [];\n var layerToggleControl = new L.Control.EasyButtons({\n icon: \"fa-picture-o\",\n title: i18n.i10n(\"esMapTiles.button.tooltip\"),\n click: onClick\n });\n activate(); ///////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(function (map) {\n mappingService.getTileLayers().then(function (tileConfigs) {\n if (!_.size(tileConfigs)) {\n return;\n }\n\n layerGroup.addTo(map);\n map.addControl(layerToggleControl);\n layerToggleControl.enable();\n layerToggleControl.setActive();\n\n _.forEach(tileConfigs, function (config) {\n var layer = L.tileLayer(tileServerUrl, config);\n layers.push(layer);\n layerGroup.addLayer(layer);\n });\n });\n });\n }\n\n function onClick() {\n if (!!layerGroup.getLayers().length) {\n _.forEach(layerGroup.getLayers(), function (layer) {\n return layerGroup.removeLayer(layer);\n });\n\n layerToggleControl.setInactive();\n } else {\n _.forEach(layers, function (layer) {\n return layerGroup.addLayer(layer);\n });\n\n layerToggleControl.setActive();\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").directive(\"esMapType\", esMapType).controller(\"esMapTypeController\", esMapTypeController);\n /*\r\n * This directive enables the user to toggle between terrain and street view maps.\r\n */\n\n esMapType.$inject = [];\n\n function esMapType() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n isColor: \"=?\"\n },\n replace: true,\n bindToController: true,\n controller: esMapTypeController,\n controllerAs: \"vm\"\n };\n }\n\n esMapTypeController.$inject = [\"$scope\", \"$state\", \"leafletLib\", \"esLeafletData\", \"i18n\", \"lodash\", \"app.core.appSettings\"];\n\n function esMapTypeController($scope, $state, L, esLeafletData, i18n, _, appSettings) {\n var vm = this;\n var mapLayer;\n var control = new L.Control.EasyButtons({\n icon: \"fa-compass\",\n title: i18n.i10n(\"esMapType.button.tooltip\"),\n click: onClick\n });\n activate(); ///////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(function (map) {\n map.addControl(control);\n control.enable();\n control.setActive();\n esLeafletData.getLayers().then(function (layers) {\n mapLayer = layers.baselayers[appSettings.mapProvider] || layers.baselayers.google;\n toggleMapColours();\n });\n });\n }\n\n function onClick() {\n vm.isColor = !vm.isColor;\n toggleMapColours();\n }\n\n function toggleMapColours() {\n if (!vm.isColor) {\n angular.element(\"body\").addClass(\"grayscale-map\");\n } else {\n angular.element(\"body\").removeClass(\"grayscale-map\");\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").factory(\"app.ui.core.mapping.mapLayerRenderer\", mapLayerRenderer);\n mapLayerRenderer.$inject = [\"lodash\", \"i18n\", \"esLeafletHelpers\", \"leafletLib\", \"app.core.models.mapping.dataPointType\"];\n\n function mapLayerRenderer(_, i18n, esLeafletHelpers, L, dataPointType) {\n var millisPerMinute = 60 * 1000;\n return {\n renderLayer: renderLayer,\n removeLayer: removeLayer,\n renderPathLayer: buildPathLayer,\n getColour: getColour\n }; //////////////////\n\n function renderLayer(dataPoint) {\n if (dataPoint.layerGroup) {\n return;\n }\n\n dataPoint.layerGroup = new L.LayerGroup();\n\n switch (dataPoint.type) {\n case dataPointType.wind:\n buildArrowLayer(dataPoint);\n break;\n\n case dataPointType.plume:\n buildPolygonLayer(dataPoint);\n break;\n\n case dataPointType.path:\n buildPathLayer(dataPoint);\n break;\n\n default:\n throw new Error(\"Rendering of \".concat(dataPoint.type, \" layers has not been implemented.\"));\n }\n }\n\n function removeLayer(dataPoint) {\n delete dataPoint.layerGroup;\n }\n\n function buildPolygonLayer(dataPoint) {\n dataPoint.data.forEach(function (concentration) {\n var color = concentration.color;\n concentration.polygons.forEach(function (polygon) {\n var points = polygon.map(function (point) {\n return new L.LatLng(point.lat, point.lng);\n });\n dataPoint.layerGroup.addLayer(new L.Polygon(points, {\n color: color,\n weight: 3,\n opacity: 1,\n smoothFactor: 1\n }));\n });\n });\n }\n\n function buildArrowLayer(dataPoint) {\n dataPoint.data.forEach(function (speedRange) {\n var windVectors = speedRange.windVectors.filter(esLeafletHelpers.isValidPoint);\n var options = {\n color: speedRange.color,\n weight: 3,\n opacity: 0.75,\n smoothFactor: 1\n };\n var windArrows = windVectors.map(function (windVector) {\n return {\n point: new L.LatLng(windVector.lat, windVector.lng),\n bearing: windVector.bearing,\n magnitude: windVector.magnitude\n };\n });\n dataPoint.layerGroup.addLayer(new L.es.ArrowMultiPolyLine(windArrows, options));\n });\n }\n\n function buildPathLayer(dataPoint) {\n var isForward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var showLabels = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n dataPoint.layerGroup = dataPoint.layerGroup || new L.LayerGroup();\n dataPoint.labels = [];\n\n var sortedData = _.chain(dataPoint.data).sortBy(\"timeMillis\");\n\n var latLngs = sortedData.map(function (pathData) {\n var latLng = new L.LatLng(pathData.latitude, pathData.longitude);\n latLng.timeMillis = pathData.timeMillis;\n var testLatitude = pathData.latitude + (pathData.latitudeStdDev ? pathData.latitudeStdDev : 0);\n var testLongitude = pathData.longitude + (pathData.longitudeStdDev ? pathData.longitudeStdDev : 0); //make sure its a valid latitude.\n\n while (testLongitude > 180) {\n testLongitude = testLongitude - 360;\n }\n\n while (testLongitude < -180) {\n testLongitude = testLongitude + 360;\n }\n\n if (testLatitude > 90) {\n testLatitude = 180 - testLatitude;\n testLongitude = testLongitude * -1;\n } else if (testLatitude < -90) {\n testLatitude = (180 + testLatitude) * -1;\n testLongitude = testLongitude * -1;\n }\n\n var latitudeDistance = latLng.distanceTo(L.latLng(testLatitude, pathData.longitude));\n var longitudeDistance = latLng.distanceTo(L.latLng(pathData.latitude, testLongitude));\n latLng.stdDevRadius = (latitudeDistance + longitudeDistance) / 2;\n return latLng;\n }).value();\n var polylineOptions = createPolylineOptions(dataPoint);\n dataPoint.layerGroup.addLayer(new L.Polyline(latLngs, polylineOptions));\n var startTimeMillis = (isForward ? sortedData.first() : sortedData.last()).value().timeMillis;\n var green = \"#00ff00\";\n var red = \"#ff0000\";\n var stdDevPaneName = \"path-std-deviation\";\n var stdDevGroup = L.layerGroup([], {\n pane: stdDevPaneName\n });\n var stepIncrement = 100.0 / latLngs.length;\n latLngs.forEach(function (latLng, index) {\n var timeOffsetMinutes = Math.abs((latLng.timeMillis - startTimeMillis) / millisPerMinute);\n var markerOptions = {\n color: getColour(green, red, index * stepIncrement / 100.0),\n opacity: 0.8,\n fillOpacity: 0.8,\n radius: 5\n };\n var marker = new L.Circle(latLng, markerOptions);\n marker.bindTooltip(i18n.i10n(\"mapLayerRenderer.path.labels.timeOffset\", {\n sign: isForward ? \"+\" : \"-\",\n offsetMinutes: timeOffsetMinutes\n }));\n dataPoint.layerGroup.addLayer(marker);\n\n if (showLabels && (index === 0 || index === latLngs.length - 1)) {\n dataPoint.labels.push(marker);\n }\n\n var next = latLngs[index + 1];\n\n if (next) {\n var options = {\n corridor: Math.max(next.stdDevRadius, 50),\n // min 50 meters\n className: stdDevPaneName,\n pane: stdDevPaneName\n };\n stdDevGroup.addLayer(L.corridor([latLng, next], options));\n }\n });\n dataPoint.layerGroup.addLayer(stdDevGroup); ////////////////////\n\n function createPolylineOptions() {\n var options = {\n color: \"#111\",\n weight: 5,\n opacity: 0.7,\n smoothFactor: 0\n };\n return options;\n }\n }\n\n function getColour(startColour, endColour, ratio) {\n startColour = sanitizeColour(startColour);\n endColour = sanitizeColour(endColour);\n var r = Math.ceil(parseInt(startColour.substring(0, 2), 16) * ratio + parseInt(endColour.substring(0, 2), 16) * (1 - ratio));\n var g = Math.ceil(parseInt(startColour.substring(2, 4), 16) * ratio + parseInt(endColour.substring(2, 4), 16) * (1 - ratio));\n var b = Math.ceil(parseInt(startColour.substring(4, 6), 16) * ratio + parseInt(endColour.substring(4, 6), 16) * (1 - ratio));\n return \"#\".concat(toHex(r)).concat(toHex(g)).concat(toHex(b));\n\n function sanitizeColour(colour) {\n if (colour.indexOf(\"#\") === 0) {\n return colour.substring(1, 7);\n } else {\n return colour;\n }\n }\n\n function toHex(val) {\n val = val.toString(16);\n return val.length === 1 ? \"0\" + val : val;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").component(\"esMessages\", {\n templateUrl: \"/App/ui/core/messages/controls/esMessages.html\",\n controller: esMessagesController,\n controllerAs: \"vm\"\n });\n esMessagesController.$inject = [\"$scope\", \"lodash\", \"app.core.models.messages.messageList\"];\n\n function esMessagesController($scope, _, messageList) {\n var vm = this;\n vm.messageList = messageList;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.core\").controller(\"NotFound\", NotFound);\n NotFound.$inject = [\"app.core.services.locationService\"];\n\n function NotFound(locationService) {\n var vm = this;\n vm.goHome = locationService.goHome;\n vm.logout = locationService.logout;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.alerts\").controller(\"app.ui.features.alerts.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"i18n\", \"app.core.services.dateTimeService\", \"app.core.services.alertService\", \"$state\", \"app.core.appSettings\"];\n\n function ContentPanel(i18n, dateTimeService, alertService, $state, appSettings) {\n var formatMessage = function formatMessage(row) {\n var message = row.message || \"\";\n return message.replace(/\\<(?!p|br).*?\\>/g, \" \");\n };\n\n var defaultSentTime = new Date();\n defaultSentTime.setDate(defaultSentTime.getDate() - 30);\n defaultSentTime.setMinutes(Math.floor(defaultSentTime.getMinutes() / 30) * 30);\n var vm = this;\n vm.options = {\n dataProvider: alertService.getAlertsHistory,\n dataSource: {\n pageSize: 25,\n filter: {\n filters: [{\n field: \"sentTime\",\n operator: \"gte\",\n value: defaultSentTime\n }],\n logic: \"and\"\n }\n },\n columns: [{\n field: \"sentTime\",\n title: i18n.i10n(\"app.ui.features.alerts.contentPanel.dataGrid.headings.sentTime\"),\n width: 200,\n dataType: \"datetime\",\n sort: {\n order: 2,\n dir: \"desc\"\n },\n click: function click(dataItem) {\n var dateTime = dataItem && dataItem.sentTime && dateTimeService.formatAs.iso(dataItem.sentTime);\n $state.go(\"app.monitoring\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n dateTime: dateTime\n });\n }\n }, {\n field: \"type\",\n title: i18n.i10n(\"app.ui.features.alerts.contentPanel.dataGrid.headings.type\"),\n width: 120\n }, {\n field: \"description\",\n title: i18n.i10n(\"app.ui.features.alerts.contentPanel.dataGrid.headings.description\"),\n width: 200\n }, {\n field: \"message\",\n title: i18n.i10n(\"app.ui.features.alerts.contentPanel.dataGrid.headings.message\"),\n width: 800,\n sort: {\n order: 1,\n dir: \"asc\"\n },\n template: formatMessage,\n encoded: false\n }, {\n field: \"dismissed\",\n title: i18n.i10n(\"app.ui.features.alerts.contentPanel.dataGrid.headings.dismissed\"),\n dataType: \"datetime\",\n width: 200\n }]\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.alerts\").run(appRun);\n appRun.$inject = [\"routeHelper\"];\n\n function appRun(routeHelper) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.alerts\",\n url: \"/alerts/{companyAlias}/{facilityAlias}\",\n views: {\n contentPanel: {\n templateUrl: \"/App/ui/features/alerts/ContentPanel.html\",\n controller: \"app.ui.features.alerts.ContentPanel as vm\"\n }\n },\n settings: {\n requiredAccessControl: \"app.alerts\",\n i18n: [\"/App/ui/features/alerts/i18n/alerts\"]\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").controller(\"app.ui.features.blasting.AddScenarioContentPanel\", AddScenarioContentPanel);\n AddScenarioContentPanel.$inject = [\"app.core.appSettings\", \"app.core.services.locationService\", \"scenarioConfigurationState\"];\n\n function AddScenarioContentPanel(appSettings, locationService, scenarioConfigurationState) {\n var vm = this;\n vm.scenario = scenarioConfigurationState;\n activate(); //////////////////////\n\n function activate() {\n locationService.updatePageHeading({\n name: vm.scenarioAlias\n });\n locationService.updateExitPoint(\"app.blasting.scenarios\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").controller(\"app.ui.features.blasting.AddScenarioLeftPanel\", AddScenarioLeftPanel);\n AddScenarioLeftPanel.$inject = [\"$scope\", \"$state\", \"$window\", \"lodash\", \"promiseTracker\", \"app.core.appSettings\", \"app.core.services.dateTimeService\", \"app.core.services.configuration.blastingService\", \"app.core.services.blastingService\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastSetup\", \"scenarioConfigurationState\"];\n\n function AddScenarioLeftPanel($scope, $state, $window, _, promiseTracker, appSettings, dateTimeService, blastingConfigService, blastingService, blastModelType, blastSetup, scenarioConfigurationState) {\n var vm = this;\n vm.cancel = cancel;\n vm.save = save;\n vm.busy = promiseTracker();\n vm.allowedOverlayFileExtensions = [\".kml\", \".dxf\"];\n activate(); //////////////////////\n\n function activate() {\n var alias = $state.params.scenarioAlias;\n vm.scenario = scenarioConfigurationState;\n\n if (alias) {\n var scenarioPromise = blastingService.getScenario(alias);\n vm.busy.addPromise(scenarioPromise);\n scenarioPromise.then(function (existing) {\n _.merge(vm.scenario, existing.blastParameters, {\n blastTimesMillis: existing.blastTimesMillis\n });\n\n var hasModel = function hasModel(modelType) {\n return !!_.find(existing.models, {\n modelType: modelType\n });\n };\n\n Object.keys(vm.scenario.models).forEach(function (key) {\n return vm.scenario.models[key] = hasModel(blastModelType[key]);\n });\n });\n }\n }\n\n function save() {\n vm.scenario.isSubmitted = true;\n\n if (vm.$form.$invalid) {\n return;\n }\n\n var savingPromise = blastingConfigService.createScenario(scenarioConfigurationState);\n vm.busy.addPromise(savingPromise);\n savingPromise.then(function (result) {\n $state.go(\"app.blasting.scenarios.scenario\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n scenarioAlias: result.scenarioAlias\n });\n });\n }\n\n function cancel() {\n $window.history.back();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").factory(\"app.ui.features.blasting.BlastDataMediator\", blastDataMediatorFactory);\n blastDataMediatorFactory.$inject = [\"lodash\", \"postal\", \"app.core.models.modelLoadingStatus\", \"app.core.services.blastingService\", \"app.core.signalR.jobs.state\", \"app.core.signalR.jobs.events\", \"app.core.models.jobs.jobCompletionStatus\"];\n /* istanbul ignore next */\n\n function blastDataMediatorFactory(_, postal, modelLoadingStatus, blastingService, jobState, jobEvents, jobCompletionStatus) {\n return function BlastDataMediator(state, mapPromise, onRefreshed) {\n var self = this;\n var subscriptions;\n\n this.refresh = function () {\n mapPromise.then(function (map) {\n self.map = map;\n refresh();\n });\n };\n\n this.dispose = dispose;\n activate(); ////////////////////\n\n var dataStore = state.blastDataStore;\n\n function activate() {\n if (!state) {\n throw new Error(\"You must provide the state object\");\n }\n\n if (!_.isFunction(onRefreshed)) {\n throw new Error(\"You must provide a callback for 'onRefreshed'\");\n }\n\n var channel = postal.channel(jobEvents.channelName);\n subscriptions = [channel.subscribe(jobEvents.topics.jobStale, onJobStale), channel.subscribe(jobEvents.topics.jobCompleted, onJobCompleted), channel.subscribe(jobEvents.topics.jobDismissed, onJobDismissed)];\n }\n\n function refresh() {\n var wasModelDataImported = importDataForSelectedModels();\n var wasModelDataRemoved = removeUnselectedModelData();\n\n if (wasModelDataImported || wasModelDataRemoved) {\n onRefreshed();\n }\n }\n\n function importDataForSelectedModels() {\n var selectedModels = state.selectedModels;\n var wereModelsImported = false;\n\n _.forEach(selectedModels, function (blastTimesMillis, modelId) {\n var model = state.scenario.models[modelId];\n\n _.forEach(blastTimesMillis, function (blastTimeMillis) {\n // Don't do anything if the data is already imported\n if (dataStore.hasImportedData(modelId, blastTimeMillis)) {\n return;\n } // Check if we have any data for this model at the nominated blast time. Note that if the model\n // loaded with a failure, then blastData will be null. In this case, we'll try to load the\n // blast data again.\n\n\n var hasModelLoadedData = _.has(model.data, blastTimeMillis);\n\n var modelData = model.data[blastTimeMillis];\n\n if (hasModelLoadedData && modelData) {\n wereModelsImported |= importDataIntoDataStore(model, blastTimeMillis); // eslint-disable-line no-bitwise\n } else {\n // Request the data, even if the last time we tried it returned an error.\n loadData(model, blastTimeMillis);\n }\n });\n });\n\n return wereModelsImported;\n }\n\n function loadData(model, blastTimeMillis) {\n var currentStatus = state.getModelLoadingStatus(model.id, blastTimeMillis);\n\n if (currentStatus === modelLoadingStatus.loading) {\n return;\n } //TODO: 16/07/2015 - gthomas - Check if there is already a job running for this model / time range\n\n\n blastingService.getBlastData(state.scenario.alias, model.modelType, blastTimeMillis).then(loadBlastDataSuccess, loadBlastDataFailed);\n state.setModelLoadingStatus(model.id, blastTimeMillis, modelLoadingStatus.loading);\n\n function loadBlastDataSuccess(getBlastDataResult) {\n addBlastDataToModel(getBlastDataResult.availableBlastModelData);\n addActiveJobToJobState(getBlastDataResult.activeJobForBlastModel);\n\n function addBlastDataToModel(blastData) {\n model.data[blastTimeMillis] = blastData; // If this model/blast time has data, and it's still selected, then add the data to the map and refresh.\n\n if (!(blastData && state.isModelSelected(model.id, blastTimeMillis))) {\n return;\n }\n\n var wasDataImported = importDataIntoDataStore(model, blastTimeMillis);\n\n if (wasDataImported) {\n onRefreshed();\n }\n\n var status = blastData !== null ? modelLoadingStatus.loaded : modelLoadingStatus.failed;\n state.setModelLoadingStatus(model.id, blastTimeMillis, status);\n }\n\n function addActiveJobToJobState(job) {\n if (!job || job.requesterId !== model.id) {\n return;\n } // We also need to check if we are already tracking this job - depends on if the SignalR JobCreated\n // event was received before the call returned.\n\n\n var existingJob = _.find(jobState.jobs, {\n jobId: job.jobId\n });\n\n if (!existingJob) {\n jobState.jobs.push(job);\n }\n }\n }\n\n function loadBlastDataFailed() {\n model.data[blastTimeMillis] = null;\n state.setModelLoadingStatus(model.id, blastTimeMillis, modelLoadingStatus.failed);\n }\n }\n\n function importDataIntoDataStore(model, blastTimeMillis) {\n var dataPoints = model.getDataPoints(blastTimeMillis, self.map);\n return dataStore.importData(model.id, blastTimeMillis, dataPoints);\n }\n\n function removeUnselectedModelData() {\n var wereModelsRemoved = false;\n\n _.forEach(dataStore.importedModelsAndTimes, function (blastTimesMillis, modelId) {\n _.forEach(_.keys(blastTimesMillis), function (blastTimeMillis) {\n blastTimeMillis = parseInt(blastTimeMillis);\n\n if (state.isModelSelected(modelId, blastTimeMillis)) {\n return;\n }\n\n dataStore.removeData(modelId, blastTimeMillis);\n wereModelsRemoved = true;\n });\n });\n\n return wereModelsRemoved;\n }\n\n function onJobCompleted(job) {\n if (!(job && job.requesterId)) {\n return;\n }\n\n var modelId = job.requesterId;\n var model = state.scenario.models[modelId];\n\n if (!model) {\n return;\n }\n\n processJobCompleted(job, modelId, model);\n }\n\n function processJobCompleted(job, modelId, model) {\n if (job.hasFailed) {\n state.setModelLoadingStatus(modelId, job.fromMillis, modelLoadingStatus.failed);\n } else {\n // Note that we use `Pending` if the job didn't fail, to signal that the model should\n // now try to load its data if it is selected again.\n state.setModelLoadingStatus(modelId, job.fromMillis, modelLoadingStatus.pending); // If the job is currently selected, we force the update of the data\n\n if (state.selectedModels[modelId]) {\n loadData(model, job.fromMillis);\n }\n }\n } //todo refactor into jobservice\n\n\n function onJobDismissed(job) {\n if (!job.isStale) {\n return;\n }\n\n var modelId = job.requesterId;\n\n if (!modelId) {\n return;\n }\n\n var currentLoadingStatus = state.getModelLoadingStatus(modelId, job.fromMillis);\n\n if (currentLoadingStatus !== modelLoadingStatus.loading) {\n return;\n }\n\n var hasActiveJob = doesActiveJobExist(modelId, job.fromMillis);\n\n if (!hasActiveJob) {\n state.setModelLoadingStatus(modelId, job.fromMillis, modelLoadingStatus.failed);\n }\n } //todo refactor into jobservice\n\n\n function doesActiveJobExist(modelId, fromMillis) {\n var clearStaleJobs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var existingJobs = _.filter(jobState.jobs, function (job) {\n return job.requesterId === modelId && job.fromMillis === fromMillis && !job.hasCompleted;\n });\n\n if (!existingJobs.length) {\n return false;\n }\n\n var hasActiveJob = false;\n\n _.forEach(existingJobs, function (job) {\n if (!job.isStale) {\n hasActiveJob = true;\n } else if (clearStaleJobs) {\n blastingService.dismissJob(job.jobId);\n }\n });\n\n return hasActiveJob;\n }\n\n function onJobStale(job) {\n if (!(job && job.requesterId)) {\n return;\n }\n\n var modelId = job.requesterId;\n var model = state.scenario.models[modelId]; // get model data from the available models\n\n if (!model) {\n return;\n } // Cater for SignalR crapping itself by manually checking the job status\n\n\n blastingService.getStatus(job.jobId).then(function (status) {\n job.progress = status.progress;\n\n if (!status.hasCompleted) {\n job.completionStatus = jobCompletionStatus.incomplete;\n } else {\n job.completionStatus = jobCompletionStatus.calculate(status.jobSucceededCount, status.jobFailedCount);\n processJobCompleted(job, modelId, model);\n }\n });\n }\n\n function dispose() {\n _.invokeMap(subscriptions, \"unsubscribe\");\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").factory(\"app.ui.features.blasting.BlastDataStore\", blastDataStoreFactory);\n blastDataStoreFactory.$inject = [\"lodash\"];\n /* istanbul ignore next */\n\n function blastDataStoreFactory(_) {\n return function BlastDataStore() {\n this.hasImportedData = hasImportedData;\n this.importData = importData;\n this.removeData = removeData;\n this.getDataAtOffset = getDataAtOffset; ////////////////////\n\n /**\r\n * Quick lookup to find which models and times are currently imported. This is only used internally to\r\n * work out if blast data for a given model has already been imported into the data store. Stored as:\r\n *
      \r\n       *     ModelId => Blast Time => Visibility\r\n       * 
      \r\n * For example:\r\n *
      \r\n       *     {\r\n       *         \"model-1234\": {\r\n       *             \"1437010250000\": true,\r\n       *             \"1437010250000\": true,\r\n       *         },\r\n       *         \"model-5678\": {\r\n       *             \"1437010500000\": true,\r\n       *         }\r\n       *     }\r\n       * 
      \r\n *\r\n * @type {object}\r\n */\n\n var importedModelsAndTimes = {};\n /**\r\n * Time step data for all currently loaded models. This is used to quickly retrieve data for all models at\r\n * the given time offset. Since the user may look at multiple blast times at the same time, the thing in\r\n * common is the offset from the original blast time. Stored as:\r\n *
      \r\n       *     Offset from blast time => Model Id => Blast Time => Data\r\n       * 
      \r\n * For example, the data stored for each blast model at the actual time of the blast (T+0) may be:\r\n *
      \r\n       *     {\r\n       *         \"0\": {                       // offset from blast time\r\n       *             \"model-1234\": {              // model id (guid)\r\n       *                 \"1437010250000\": [],         // blast time => data points for this model / blast time / offset\r\n       *                 \"1437010500000\": [],         // blast time => data points for this model / blast time / offset\r\n       *             },\r\n       *             \"model-5678\": {              // model id (guid)\r\n       *                 \"1437010500000\": [],         // blast time => data points for this model / blast time / offset\r\n       *             },\r\n       *         }\r\n       *     }\r\n       * 
      \r\n *\r\n * @type {object}\r\n */\n\n var importedData = {}; ////////////////////\n\n Object.defineProperty(this, \"importedModelsAndTimes\", {\n get: function get() {\n return importedModelsAndTimes;\n }\n });\n /**\r\n * Determines if any data has been imported. If the modelId and blastTimeMillis\r\n * parameters are not passed, this method will report if data for any model/blast time\r\n * has been imported.\r\n *\r\n * @returns {bool}\r\n */\n\n function hasImportedData() {\n var modelId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var blastTimeMillis = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n if (modelId && blastTimeMillis) {\n return (importedModelsAndTimes[modelId] || {})[blastTimeMillis];\n }\n\n return !_.isEmpty(importedModelsAndTimes);\n }\n\n function setHasImportedData(modelId, blastTimeMillis, hasData) {\n if (hasData) {\n var importedTimesForModel = importedModelsAndTimes[modelId] || (importedModelsAndTimes[modelId] = {});\n importedTimesForModel[blastTimeMillis] = true;\n } else {\n var _importedTimesForModel = importedModelsAndTimes[modelId];\n\n if (!_importedTimesForModel) {\n return;\n }\n\n delete _importedTimesForModel[blastTimeMillis];\n\n if (_.isEmpty(_importedTimesForModel)) {\n delete importedModelsAndTimes[modelId];\n }\n }\n }\n\n function importData(modelId, blastTimeMillis, blastData) {\n var hasBlastData = blastData && blastData.length;\n setHasImportedData(modelId, blastTimeMillis, hasBlastData);\n\n if (!hasBlastData) {\n return false;\n }\n\n _.forEach(blastData, function (dataPoint) {\n var offset = dataPoint.offsetMinutes;\n var allDataForOffset = importedData[offset] || (importedData[offset] = {});\n var modelDataForOffset = allDataForOffset[modelId] || (allDataForOffset[modelId] = {});\n modelDataForOffset[blastTimeMillis] = dataPoint;\n });\n\n return true;\n }\n\n function removeData(modelId, blastTimeMillis) {\n blastTimeMillis = parseInt(blastTimeMillis);\n\n if (!hasImportedData(modelId, blastTimeMillis)) {\n return false;\n }\n\n _.forEach(importedData, function (allDataForTimeStep, offset) {\n var modelDataAtTimeStep = allDataForTimeStep[modelId];\n delete modelDataAtTimeStep[blastTimeMillis];\n\n if (_.isEmpty(modelDataAtTimeStep)) {\n delete allDataForTimeStep[modelId];\n\n if (_.isEmpty(allDataForTimeStep)) {\n delete importedData[offset];\n }\n }\n });\n\n setHasImportedData(modelId, blastTimeMillis, false);\n return true;\n }\n\n function getDataAtOffset(offsetMinutes) {\n if (!_.has(importedData, offsetMinutes)) {\n return null;\n }\n\n return _.chain(importedData[offsetMinutes]) // Key is modelId, value is a map of blast time => data point. All we want are the data points.\n .map(function (modelDataAtTimeStep) {\n return _.map(modelDataAtTimeStep, function (dataPoint) {\n return dataPoint;\n });\n }).flatten().value();\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscFileUploader\", directive).controller(\"esbscFileUploaderController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\",\n extensions: \"=\",\n maxSize: \"@\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscFileUploader.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"i18n\", \"lodash\", \"leafletLib\", \"FileUploader\", \"promiseTracker\", \"app.core.httpInterceptors\", \"app.core.services.configuration.blastingService\"];\n\n function controller(i18n, _, L, FileUploader, promiseTracker, httpInterceptors, blastingService) {\n var vm = this; // Used for validating uploaded overlays\n\n var xmlParser = new DOMParser();\n var kmlValidator = new L.KML(null);\n vm.uploader = null;\n vm.busyLoading = promiseTracker();\n vm.removeFile = removeFile;\n activate(); ////////////////////\n\n function activate() {\n vm.uploader = getUploader();\n restorePreviouslyUploadedFiles();\n }\n\n function getUploader() {\n var options = {\n autoUpload: false,\n alias: \"overlayFile\",\n // POST configuration\n headers: {},\n url: blastingService.getAddOverlayUrl(),\n // Events\n onAfterAddingFile: onFileAdded,\n onSuccessItem: validateUploadedFile,\n withCredentials: true\n };\n\n if (vm.scenario.id) {\n options.formData = [{\n scenarioId: vm.scenario.id\n }];\n } // The file upload component that we are using uses its own transport layer for uploading the files,\n // as opposed to using angular's $http service. Why? Goodness only knows; at a guess, its so it can\n // downgrade to using an iFrame + form post as the transport when the user is ignorantly using a\n // non HTML5 compatible browser.\n //\n // As such, we need to add in the request headers (e.g. for the current company/facility alias) that\n // would ordinarily be done for us by the $httpInterceptor. Thankfully, the `httpInterceptors.request`\n // method already expects to be passed an object with a `headers` property on it (yay for duck typing!),\n // and this is conveniently the same property which is expected by the file upload component. Win win!\n\n\n httpInterceptors.request(options);\n return new FileUploader(options);\n }\n\n function onFileAdded(fileItem) {\n var file = fileItem.file;\n var fileName = file.name.toLowerCase();\n\n if (validatePotentialUpload()) {\n fileItem.upload();\n } // Automatically overwrite any other files with the same name. We can skip the last item in\n // the queue as that's the item that has just been added.\n\n\n for (var i = 0; i < vm.uploader.queue.length - 1; i++) {\n var queuedItem = vm.uploader.queue[i];\n\n if (queuedItem.file.name.toLowerCase() === fileName) {\n vm.uploader.removeFromQueue(i);\n break;\n }\n }\n\n function validatePotentialUpload() {\n var isValidExtension = validateExtension();\n var isValidSize = validateSize();\n return isValidExtension && isValidSize;\n\n function validateExtension() {\n var fileNameLower = file.name.toLowerCase();\n\n var validExtension = _.find(vm.extensions, function (extension) {\n return _.endsWith(fileNameLower, extension);\n });\n\n if (!validExtension) {\n setValidationError(fileItem, \"extension\");\n fileItem.isError = true;\n }\n\n return validExtension;\n }\n\n function validateSize() {\n var canUpload = file.size <= vm.maxSize;\n\n if (!canUpload) {\n setValidationError(fileItem, \"size\");\n fileItem.isError = true;\n }\n\n return canUpload;\n }\n }\n }\n\n function restorePreviouslyUploadedFiles() {\n var loaderPromise = blastingService.getOverlayFiles(vm.scenario.id).then(function (files) {\n _.forEach(files, function (overlayFile) {\n var fileItem = new FileUploader.FileItem(vm.uploader, overlayFile);\n fileItem.progress = 100;\n fileItem.isUploaded = fileItem.isSuccess = true;\n vm.uploader.queue.push(fileItem);\n validateUploadedFile(fileItem);\n });\n });\n vm.busyLoading.addPromise(loaderPromise);\n }\n\n function validateUploadedFile(fileItem, overlayFile) {\n var file = fileItem.file;\n\n if (isResultFileDifferentToUploadedFile()) {\n file.name = overlayFile.name;\n file.size = overlayFile.length;\n dequeueDuplicates();\n }\n\n return blastingService.getOverlayFile(file.name).then(validateOverlay).then(function (overlay) {\n vm.scenario.overlayFiles[file.name] = overlay;\n return overlay;\n }).catch(angular.noop); //TODO: 28/02/2019 - ben.priebe - Test what happens in front-end\n ////////////////////\n\n function validateOverlay(overlay) {\n if (_.endsWith(overlay.name, \".kml\")) {\n return validateKmlOverlay(overlay);\n }\n\n return overlay;\n }\n\n function validateKmlOverlay(overlay) {\n var xmlDoc = xmlParser.parseFromString(overlay.data, \"text/xml\");\n\n kmlValidator._addKML(xmlDoc);\n\n var hasNoLayers = !_.size(kmlValidator._layers);\n kmlValidator.clearLayers();\n\n if (hasNoLayers) {\n setValidationError(fileItem, \"overlay\");\n throw {\n handled: true\n };\n }\n\n return overlay;\n }\n\n function isResultFileDifferentToUploadedFile() {\n return overlayFile && file.name !== overlayFile.name;\n }\n\n function dequeueDuplicates() {\n _.remove(vm.uploader.queue, function (queued) {\n return queued.file.name === file.name && queued.file !== file;\n });\n }\n }\n\n function setValidationError(fileItem, field) {\n fileItem.validationErrors = fileItem.validationErrors || {};\n fileItem.validationErrors[field] = i18n.i10n(\"esbscFileUploader.validationErrors.\" + field);\n }\n\n function removeFile(fileItem) {\n var file = fileItem.file;\n fileItem.remove();\n blastingService.deleteOverlayFile(vm.scenario.id, fileItem.file.name);\n delete vm.scenario.overlayFiles[file.name];\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\"use strict\";\n/* istanbul ignore next */\n\n\n(function () {\n angular.module(\"app.ui.features.blasting\").directive(\"esbscLocation\", directive).controller(\"esbscLocationController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscLocation.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"$scope\", \"lodash\"];\n\n function controller($scope, _) {\n var outOfBoundsValidationErrorKey = \"outOfBounds\";\n var vm = this;\n vm.isLocationOutOfBounds = false;\n activate(); ////////////////////\n\n function activate() {\n invalidateLocationWhenOutsideDomainBoundaries(); ////////////////////\n\n function invalidateLocationWhenOutsideDomainBoundaries() {\n var watches = [function () {\n return vm.scenario.latitude;\n }, function () {\n return vm.scenario.longitude;\n }];\n $scope.$watchGroup(watches, validateSelectedLocationIsWithinBounds);\n\n function validateSelectedLocationIsWithinBounds(location) {\n var isLocationOutOfBounds = isOutOfBounds(location);\n\n if (vm.isLocationOutOfBounds === isLocationOutOfBounds) {\n return;\n }\n\n angular.forEach(vm.$form, function (ctrl) {\n if (angular.isObject(ctrl) && angular.isDefined(ctrl.$setValidity)) {\n ctrl.$setValidity(outOfBoundsValidationErrorKey, !isLocationOutOfBounds);\n }\n });\n vm.isLocationOutOfBounds = isLocationOutOfBounds;\n }\n\n function isOutOfBounds(location) {\n var boundaries = vm.scenario.map && vm.scenario.map.boundaries;\n\n if (!(boundaries && boundaries.length)) {\n return false;\n }\n\n var _location = _slicedToArray(location, 2),\n latitude = _location[0],\n longitude = _location[1];\n\n if (!(latitude && longitude)) {\n return false;\n }\n\n return !_.find(boundaries, function (boundary) {\n return boundary.contains(latitude, longitude);\n });\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscMap\", directive).controller(\"esbscMapController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscMap.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"lodash\", \"app.core.mapDefaults\", \"app.core.services.mappingService\"];\n\n function controller(_, mapDefaults, mappingService) {\n var vm = this;\n vm.isSelectingBlastLocation = false;\n activate(); ///////////////////\n\n function activate() {\n initilizeMap();\n loadFacilityOverlays();\n }\n\n function initilizeMap() {\n vm.scenario.map = {\n defaultCentre: vm.scenario.lookups.facilityLocation,\n centre: vm.scenario.lookups.facilityLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n isColor: false,\n layers: {\n baselayers: mapDefaults.baselayers,\n overlays: buildLayers()\n }\n };\n }\n\n function buildLayers() {\n var layers = {};\n var vibrationLayer = createVibrationMarkerLayer();\n layers[vibrationLayer.name] = vibrationLayer;\n return layers;\n }\n\n function createVibrationMarkerLayer() {\n return {\n type: \"group\",\n visible: true,\n name: \"VibrationPOILayer\"\n };\n }\n\n function loadFacilityOverlays() {\n mappingService.getKmls().then(function (overlays) {\n _.forEach(overlays, function (overlay) {\n vm.scenario.overlayFiles[overlay.name] = overlay;\n });\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscModelParameters\", directive).controller(\"esbscModelParametersController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscModelParameters.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"$scope\", \"lodash\", \"app.core.services.mappingService\", \"app.core.models.blasting.blastSetup\"];\n\n function controller($scope, _, mappingService, blastSetup) {\n var vm = this;\n vm.isModelSelected = isModelSelected;\n\n vm.isStemming = function () {\n return vm.scenario.blastSetup === blastSetup.stemming;\n };\n\n vm.isBurden = function () {\n return vm.scenario.blastSetup === blastSetup.burden;\n };\n\n vm.selectedPollutant = vm.scenario.modelPollutantId && _.find(vm.scenario.lookups.pollutantOptions, {\n modelPollutantId: vm.scenario.modelPollutantId\n });\n activate(); ////////////////////\n\n function activate() {\n updatePollutantOptionsWhenPollutantChanges();\n updateAzimuthWhenValueFallsOutsideValidRange();\n updateElevationWhenBlastLocationChanges(); ////////////////////\n\n function updatePollutantOptionsWhenPollutantChanges() {\n $scope.$watch(function () {\n return vm.scenario.modelPollutantId;\n }, function (modelPollutantId) {\n vm.selectedPollutant = modelPollutantId && _.find(vm.scenario.lookups.pollutantOptions, {\n modelPollutantId: modelPollutantId\n });\n vm.scenario.displayUnitId = modelPollutantId && _.first(vm.selectedPollutant.displayUnitOptions).id;\n vm.scenario.pollutantScientificModelId = modelPollutantId && vm.selectedPollutant.associatedPlumeScientificModels.length ? _.first(vm.selectedPollutant.associatedPlumeScientificModels).id : null;\n });\n }\n\n function updateAzimuthWhenValueFallsOutsideValidRange() {\n $scope.$watch(function () {\n return vm.scenario.azimuth;\n }, function (azimuth) {\n if (!_.isNumber(azimuth) || azimuth >= 0 && azimuth < 360) {\n return;\n }\n\n if (azimuth < 0) {\n vm.scenario.azimuth = 360 - Math.abs(azimuth) % 360;\n } else {\n vm.scenario.azimuth = azimuth - (Math.abs(azimuth) % 360 + 360);\n }\n });\n }\n\n function updateElevationWhenBlastLocationChanges() {\n var watches = [function () {\n return vm.scenario.latitude;\n }, function () {\n return vm.scenario.longitude;\n }, function () {\n return vm.scenario.isPollutantModelSelected;\n }, function () {\n return vm.scenario.isOverpressureModelSelected;\n }];\n $scope.$watchGroup(watches, onLocationChanged);\n\n function onLocationChanged(locationData, oldLocationData) {\n if (locationData === oldLocationData) {\n return;\n }\n\n var _locationData = _slicedToArray(locationData, 2),\n latitude = _locationData[0],\n longitude = _locationData[1];\n\n if (isElevationRequired()) {\n getElevationForSelectedLocation();\n } ////////////////////\n\n\n function isElevationRequired() {\n var hasLocation = latitude && longitude;\n return hasLocation && isModelSelected();\n }\n\n function getElevationForSelectedLocation() {\n mappingService.getElevation(latitude, longitude).then(function (elevationData) {\n if (!elevationData) {\n return;\n }\n\n vm.scenario.elevation = parseFloat(elevationData.elevation.toFixed(2));\n });\n }\n }\n }\n }\n\n function isModelSelected() {\n return vm.scenario.isPollutantModelSelected || vm.scenario.isOverpressureModelSelected || vm.scenario.isPathModelSelected || vm.scenario.isFlyrockSelected || vm.scenario.isGroundVibrationSelected;\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscModelSelector\", directive).controller(\"esbscModelSelectorController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscModelSelector.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [];\n\n function controller() {\n activate(); ////////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n var directiveName = \"esbscModelTypeRequired\";\n angular.module(\"app.ui.features.blasting\").directive(directiveName, validator);\n validator.$inject = [\"lodash\"];\n /* istanbul ignore next */\n\n function validator(_) {\n return {\n restrict: \"A\",\n require: \"ngModel\",\n scope: {\n isValidationRequired: \"=\".concat(directiveName)\n },\n link: link\n };\n\n function link($scope, $element, $attrs, ngModel) {\n $scope.$watch(function () {\n return $scope.isValidationRequired;\n }, validateHasSelectedModel);\n $scope.$watch(function () {\n return ngModel.$modelValue;\n }, validateHasSelectedModel, true);\n\n function validateHasSelectedModel() {\n var isValid = !$scope.isValidationRequired;\n\n if ($scope.isValidationRequired) {\n isValid = _.some(ngModel.$modelValue, function (value) {\n return value;\n });\n }\n\n ngModel.$setValidity(\"modelTypeRequired\", isValid);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscName\", directive).controller(\"esbscName\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscName.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"$scope\", \"app.core.services.configuration.blastingService\"];\n\n function controller($scope, blastingService) {\n var vm = this;\n vm.isEditingAlias = false;\n vm.hasAlias = hasAlias;\n vm.setDefaultAlias = setDefaultAlias;\n vm.editAlias = editAlias;\n vm.refreshAlias = refreshAlias;\n activate(); ////////////////////\n\n function activate() {}\n\n function editAlias() {\n vm.isEditingAlias = true;\n }\n\n function setDefaultAlias() {\n if (hasAlias()) {\n return;\n }\n\n updateAlias(vm.scenario.name);\n }\n\n function hasAlias() {\n return vm.scenario.alias;\n }\n\n function refreshAlias() {\n updateAlias(vm.scenario.alias || vm.scenario.name);\n vm.isEditingAlias = false;\n } // calls the server to get a unique alias value\n\n\n function updateAlias(alias) {\n if (alias === null || alias === undefined) {\n return;\n }\n\n vm.isBusy = true;\n blastingService.getValidScenarioAlias(alias).then(function (validAlias) {\n vm.scenario.alias = validAlias;\n }).finally(function () {\n vm.isBusy = false;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscPollutantConcentrationSelector\", directive).controller(\"esbscPollutantConcentrationSelectorController\", controller);\n directive.$inject = [\"jQuery\"];\n\n function directive($) {\n return {\n restrict: \"E\",\n require: [\"^form\"],\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscPollutantConcentrationSelector.html\",\n link: link,\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n\n function link($scope, $element, attrs, controllers) {\n var vm = $scope.vm;\n vm.$form = controllers[0];\n vm.itemTemplate = $(\"#nox-item-template\").html();\n $scope.$watch(function () {\n return vm.noxComboBox;\n }, function () {\n if (vm.noxComboBox) {\n vm.noxComboBox.input.attr(\"type\", \"number\");\n vm.noxComboBox.input.attr(\"min\", \"0\");\n vm.noxComboBox.input.attr(\"step\", \"any\");\n }\n });\n }\n }\n\n controller.$inject = [\"$scope\", \"lodash\"];\n\n function controller($scope, _) {\n var vm = this;\n vm.isEditingInitialConcentration = false;\n vm.editInitialConcentration = editInitialConcentration;\n vm.hasInitialConcentration = hasInitialConcentration;\n vm.refreshInitialConcentration = refreshInitialConcentration;\n activate(); ////////////////////\n\n function editInitialConcentration() {\n vm.isEditingInitialConcentration = true;\n }\n\n function hasInitialConcentration() {\n return vm.scenario.initialConcentration !== undefined && vm.scenario.initialConcentration !== null;\n }\n\n function refreshInitialConcentration() {\n vm.isEditingInitialConcentration = false;\n }\n\n function updateInitialConcentration() {\n var modelPollutant = _.find(vm.scenario.lookups.pollutantOptions, {\n modelPollutantId: vm.scenario.modelPollutantId\n });\n\n vm.scenario.initialConcentration = modelPollutant ? vm.scenario.defaultConcentrations.get(modelPollutant.libraryPollutantId.toUpperCase()) : null;\n }\n\n function activate() {\n $scope.$watch(function () {\n return vm.scenario.modelPollutantId;\n }, updateInitialConcentration);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbscTimeSelector\", directive);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n scenario: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/configuration/esbscTimeSelector.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [];\n\n function controller() {\n var millisPerMinute = 60 * 1000;\n var millisPerHalfHour = 30 * millisPerMinute;\n var millisPerHour = 2 * millisPerHalfHour;\n var vm = this;\n vm.addAnotherBlastTimeSelector = addAnotherBlastTimeSelector;\n vm.removeBlastTimeSelector = removeBlastTimeSelector;\n activate(); ////////////////////\n\n function activate() {\n initialiseBlastTimeSelectors();\n }\n\n function initialiseBlastTimeSelectors() {\n if (vm.scenario.blastTimesMillis.length === 0) {\n var nextBlastTime = estimateNextBlastTime(new Date().getTime());\n vm.scenario.blastTimesMillis.push(nextBlastTime);\n }\n }\n\n function addAnotherBlastTimeSelector() {\n var latestBlastTime = Math.max.apply(Math, _toConsumableArray(vm.scenario.blastTimesMillis));\n var nextBlastTime = estimateNextBlastTime(latestBlastTime);\n vm.scenario.blastTimesMillis.push(nextBlastTime);\n }\n\n function removeBlastTimeSelector(index) {\n if (vm.scenario.blastTimesMillis.length <= 1) {\n return;\n }\n\n vm.scenario.blastTimesMillis.splice(index, 1);\n }\n\n function estimateNextBlastTime(lastBlastTime) {\n var nextBlastTime = roundUpToHalfHour(lastBlastTime + 2 * millisPerHour);\n return ensureBlastIsDuringDaylightHours(nextBlastTime); ////////////////////\n\n function roundUpToHalfHour(timeMillis) {\n var millisOverHalfHour = timeMillis % millisPerHalfHour;\n return millisOverHalfHour === 0 ? timeMillis : timeMillis + millisPerHalfHour - millisOverHalfHour;\n }\n\n function ensureBlastIsDuringDaylightHours(timeMillis) {\n var blastDate = new Date(timeMillis);\n var hours = blastDate.getHours();\n\n if (hours >= 7 && (hours < 19 || hours === 19 && blastDate.getMinutes() === 0)) {\n return timeMillis;\n }\n\n if (hours >= 19) {\n blastDate.setDate(blastDate.getDate() + 1);\n }\n\n blastDate.setHours(7);\n blastDate.setMinutes(0);\n return blastDate.getTime();\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsActualBlastTime\", esbsActualBlastTime).controller(\"esbsActualBlastTimeController\", esbsActualBlastTimeController);\n\n function esbsActualBlastTime() {\n return {\n restrict: \"E\",\n scope: {\n state: \"=state\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/esbsActualBlastTime.html\",\n controller: esbsActualBlastTimeController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esbsActualBlastTimeController.$inject = [\"$scope\", \"i18n\", \"lodash\", \"promiseTracker\", \"app.core.appSettings\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.dateTimeService\", \"app.core.services.configuration.blastingService\"];\n\n function esbsActualBlastTimeController($scope, i18n, _, promiseTracker, appSettings, timeZoneDateTime, dateTimeService, blastingService) {\n var vm = this;\n var canModifyBlasting = appSettings.site.accessControls[\"app.blasting.modify\"];\n vm.canUpdateBlastTime = true;\n vm.originalBlastTime = null;\n vm.actualBlastTimeModel = buildActualBlastTimeModel(null);\n vm.datePicker = getDatePicker();\n vm.isEditingBlastTime = false;\n vm.isSubmitted = false;\n vm.busySaving = promiseTracker();\n vm.changeBlastTime = changeBlastTime;\n vm.save = save;\n vm.cancel = cancel;\n activate(); ////////////////////\n\n function activate() {\n updateVisibilityWhenScenarioChanges();\n updateDisplayedBlastTimeWhenActualBlastTimeChanges();\n }\n\n function updateVisibilityWhenScenarioChanges() {\n $scope.$watch(function () {\n return vm.state.scenario;\n }, function (scenario) {\n if (!scenario) {\n return;\n }\n\n var actualBlastTime = scenario.actualBlastTime;\n vm.isEditingBlastTime = !actualBlastTime;\n vm.canUpdateBlastTime = vm.isEditingBlastTime || canModifyBlasting;\n\n if (vm.isEditingBlastTime) {\n changeBlastTime();\n }\n });\n }\n\n function updateDisplayedBlastTimeWhenActualBlastTimeChanges() {\n $scope.$watch(function () {\n return vm.state.scenario.actualBlastTime;\n }, function (actualBlastTime) {\n vm.actualBlastTimeModel = buildActualBlastTimeModel(actualBlastTime);\n });\n }\n\n function buildActualBlastTimeModel(actualBlastTime) {\n return {\n date: actualBlastTime,\n formattedString: actualBlastTime && dateTimeService.formatAs.dateTime(actualBlastTime) || \"-\"\n };\n }\n\n function getDatePicker() {\n return {\n hasFocus: false,\n options: {\n format: dateTimeService.formats.kendo.dateTime,\n timeFormat: dateTimeService.formats.kendo.time,\n interval: 1,\n max: new Date()\n }\n };\n }\n\n function changeBlastTime() {\n vm.isEditingBlastTime = true;\n vm.originalBlastTime = vm.state.scenario.actualBlastTime;\n vm.actualBlastTimeModel = buildActualBlastTimeModel(vm.state.scenario.actualBlastTime);\n }\n\n function save() {\n vm.isSubmitted = true;\n\n if (vm.$form.$invalid || !vm.$form.$dirty) {\n return;\n }\n\n var scenario = vm.state.scenario;\n var selectedBlastTime = vm.actualBlastTimeModel.date;\n var actualBlastTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(selectedBlastTime);\n var savingPromise = blastingService.updateActualBlastTime(scenario.alias, actualBlastTime);\n vm.busySaving.addPromise(savingPromise);\n savingPromise.then(function () {\n scenario.actualBlastTime = selectedBlastTime;\n vm.isEditingBlastTime = false;\n });\n }\n\n function cancel() {\n vm.isEditingBlastTime = false;\n vm.actualBlastTimeModel = buildActualBlastTimeModel(vm.originalBlastTime);\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.blasting\").directive(\"esbsFlyrockLegend\", esbsFlyrockLegend).controller(\"esbsFlyrockLegendController\", esbsFlyrockLegendController);\n\n function esbsFlyrockLegend() {\n return {\n restrict: \"E\",\n scope: {\n legend: \"=\",\n time: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/esbsFlyrockLegend.html\",\n controller: esbsFlyrockLegendController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n function esbsFlyrockLegendController() {}\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsModelCategorySelector\", esbsModelCategorySelector).controller(\"esbsModelCategorySelectorController\", esbsModelCategorySelectorController);\n\n function esbsModelCategorySelector() {\n return {\n restrict: \"E\",\n scope: {\n state: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/esbsModelCategorySelector.html\",\n controller: esbsModelCategorySelectorController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esbsModelCategorySelectorController.$inject = [\"$scope\", \"lodash\"];\n\n function esbsModelCategorySelectorController($scope, _) {\n var vm = this;\n vm.modelCategories = _.toArray(vm.state.modelCategories);\n vm.selectedModelCategory = null;\n activate(); ////////////////////\n\n function activate() {\n updateModelTypeWhenStateChanges();\n updateStateWhenModelTypeChanges();\n }\n\n function updateModelTypeWhenStateChanges() {\n $scope.$watch(function () {\n return vm.state.selectedModelCategory;\n }, function (type) {\n return vm.selectedModelCategory = _.find(vm.state.modelCategories, {\n type: type\n });\n });\n }\n\n function updateStateWhenModelTypeChanges() {\n $scope.$watch(function () {\n return vm.selectedModelCategory;\n }, function (category) {\n return vm.state.selectedModelCategory = category.type;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsModelGroupingSelector\", esbsModelGroupingSelector).controller(\"esbsModelGroupingSelectorController\", esbsModelGroupingSelectorController);\n\n function esbsModelGroupingSelector() {\n return {\n restrict: \"E\",\n scope: {\n state: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/esbsModelGroupingSelector.html\",\n controller: esbsModelGroupingSelectorController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esbsModelGroupingSelectorController.$inject = [\"$scope\", \"lodash\"];\n\n function esbsModelGroupingSelectorController($scope, _) {\n var vm = this;\n vm.groupingTypes = _.toArray(vm.state.modelGroupingTypes);\n vm.hasModelsForCategory = true;\n activate(); ////////////////////\n\n function activate() {\n updateHasModelsForCategoryWhenCategoryChanges();\n }\n\n function updateHasModelsForCategoryWhenCategoryChanges() {\n $scope.$watch(function () {\n return vm.state.selectedModelCategory;\n }, function (modelCategory) {\n if (!modelCategory) {\n return;\n }\n\n var scenario = vm.state.scenario;\n vm.hasModelsForCategory = scenario && scenario.models && _.find(scenario.models, {\n modelCategory: modelCategory\n });\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsModelLegendToggle\", esbsModelLegendToggle).controller(\"esbsModelLegendToggleController\", esbsModelLegendToggleController);\n\n function esbsModelLegendToggle() {\n return {\n restrict: \"E\",\n scope: {\n isShowing: \"=\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/esbsModelLegendToggle.html\",\n controller: esbsModelLegendToggleController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esbsModelLegendToggleController.$inject = [];\n\n function esbsModelLegendToggleController() {\n var vm = this;\n vm.toggleLegendVisible = toggleLegendVisible; ////////////////////\n\n function toggleLegendVisible() {\n vm.isShowing = !vm.isShowing;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsModelParameters\", esbsModelParameters).controller(\"esbsModelParametersController\", esbsModelParametersController);\n esbsModelParameters.$inject = [];\n\n function esbsModelParameters() {\n return {\n scope: {\n state: \"=\"\n },\n restrict: \"EA\",\n templateUrl: \"/App/ui/features/blasting/controls/esbsModelParameters.html\",\n controller: esbsModelParametersController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esbsModelParametersController.$inject = [\"$scope\", \"$state\", \"lodash\", \"app.core.models.blasting.blastSetup\"];\n\n function esbsModelParametersController($scope, $state, _, blastSetup) {\n var vm = this;\n vm.duplicate = duplicate;\n activate(); //////////////////////\n\n function activate() {\n $scope.$watch(function () {\n return vm.state.scenario;\n }, function () {\n vm.scenario = vm.state.scenario;\n\n if (!vm.scenario || !vm.scenario.blastParameters) {\n return;\n }\n\n vm.showPathParameters = hasBlastModelParameters(\"blastHeight\", \"windScientificModel\", \"forwardTrajectoryScientificModel\");\n vm.showPollutantParameters = hasBlastModelParameters(\"blastHeight\", \"blastLength\", \"blastWidth\", \"azimuth\", \"elevation\", \"windScientificModel\", \"pollutant\", \"pollutantScientificModel\", \"displayUnit\", \"initialConcentration\");\n vm.showOverpressureParameters = !!vm.scenario.blastParameters.blastSetup;\n vm.showOverpressureBurdenParameters = vm.scenario.blastParameters.blastSetup === blastSetup.burden;\n vm.showOverpressureStemmingParameters = vm.scenario.blastParameters.blastSetup === blastSetup.stemming;\n vm.showFlyrockParameters = hasBlastModelParameters(\"azimuth\", \"chargeMass\", \"burden\", \"stemmingHeight\", \"flyrockSiteConstantKv\", \"dispersalAngle\", \"holeAngle\");\n vm.showGroundVibrationParameters = hasBlastModelParameters(\"chargeMassPerHole\", \"groundVibrationSiteConstantKv\", \"groundVibrationSiteExponentKb\");\n });\n }\n\n function duplicate() {\n $state.go(\"app.blasting.scenarios.add\", {\n scenarioAlias: vm.scenario.alias\n });\n }\n\n function hasBlastModelParameters() {\n for (var _len = arguments.length, blastParameters = new Array(_len), _key = 0; _key < _len; _key++) {\n blastParameters[_key] = arguments[_key];\n }\n\n return !_.find(blastParameters, isNullOrUndefined);\n }\n\n function isNullOrUndefined(blastParameter) {\n var parameter = vm.scenario.blastParameters[blastParameter];\n return parameter === null || parameter === undefined;\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsPollutantOutline\", directive).controller(\"esbsPollutantOutlineController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n scenario: \"=\"\n },\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"$scope\", \"lodash\", \"esLeafletData\", \"leafletLib\"];\n\n function controller($scope, _, esLeafletData, L) {\n var vm = this;\n var outline = null;\n var arrows = null;\n activate(); ///////////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(function (map) {\n showPollutantBlastOutlineWhenBlastParametersAreValid(map);\n });\n }\n\n function getBlastParametersForDisplay() {\n if (!vm.scenario) {\n return null;\n }\n\n return {\n latitude: vm.scenario.latitude,\n longitude: vm.scenario.longitude,\n azimuth: vm.scenario.azimuth,\n blastLength: vm.scenario.blastLength,\n blastWidth: vm.scenario.blastWidth\n };\n }\n\n function showPollutantBlastOutlineWhenBlastParametersAreValid(map) {\n $scope.$watch(getBlastParametersForDisplay, updatePollutantBlastOutline, true); ///////////////////\n\n function updatePollutantBlastOutline(params) {\n var areParametersValid = params && _.every(params, function (value) {\n return _.isNumber(value);\n });\n\n if (!areParametersValid) {\n hidePollutantBlastOutline(map);\n } else {\n showPollutantBlastOutline(map, params);\n }\n }\n }\n\n function hidePollutantBlastOutline(map) {\n if (outline) {\n map.removeLayer(outline);\n outline = null;\n }\n\n if (arrows) {\n map.removeLayer(arrows);\n arrows = null;\n }\n }\n\n function showPollutantBlastOutline(map, params) {\n var polygonBounds = calculatePolygonBounds(map, params);\n\n if (polygonBounds.outline) {\n if (!outline) {\n outline = new L.Polygon(polygonBounds.outline, {\n color: \"#333\",\n weight: 3,\n opacity: 1\n });\n outline.addTo(map);\n } else {\n outline.setLatLngs(polygonBounds.outline);\n }\n }\n\n if (polygonBounds.arrows) {\n if (!arrows) {\n arrows = new L.Polyline(polygonBounds.arrows, {\n color: \"#ffd\",\n weight: 2,\n opacity: 1\n });\n arrows.addTo(map);\n } else {\n arrows.setLatLngs(polygonBounds.arrows);\n }\n }\n }\n\n function calculatePolygonBounds(map, params) {\n // Get a point (X,Y) for the centre of the blast\n var centreLatLng = L.latLng([params.latitude, params.longitude]);\n var centrePoint = convertToCartesian(centreLatLng);\n var scale = calculateScale(); // Map back to lat longs.\n\n return {\n outline: calculateOutlinePoints(),\n arrows: calculateArrowPoints()\n };\n\n function calculateScale() {\n var referencePoint = convertToLatLng([centrePoint.x + 1000, centrePoint.y]);\n var metresToReferencePoint = centreLatLng.distanceTo(referencePoint);\n return Math.abs(metresToReferencePoint) / 1000;\n }\n\n function calculateTranslationDelta(width, length, azimuth) {\n if (!(width && length)) {\n return null;\n }\n\n width /= scale;\n length /= scale; // Radius of the circle made up from this width/length\n\n var radius = Math.sqrt(Math.pow(width, 2) + Math.pow(length, 2)); // The angle between the diagonal (radius) and the long-edge of the bounding rectangle\n\n var theta = Math.atan(length / width); // Beta is the difference between the azimuth and +/- theta (depending on which point we are swinging to).\n\n var azimuthRad = azimuth.toRad();\n var beta = Math.PI / 2 - azimuthRad;\n return {\n x1: radius * Math.cos(beta + theta),\n y1: radius * Math.sin(beta + theta),\n x2: radius * Math.cos(beta - theta),\n y2: radius * Math.sin(beta - theta)\n };\n }\n\n function calculateOutlinePoints() {\n // Use half width/height since the centre point is half way along each edge\n var width = params.blastWidth / 2;\n var length = params.blastLength / 2;\n var delta = calculateTranslationDelta(width, length, params.azimuth);\n\n if (!delta) {\n return;\n }\n\n var points = [[centrePoint.x + delta.x1, centrePoint.y - delta.y1], [centrePoint.x + delta.x2, centrePoint.y - delta.y2], [centrePoint.x - delta.x1, centrePoint.y + delta.y1], [centrePoint.x - delta.x2, centrePoint.y + delta.y2]];\n return _.map(points, function (point) {\n return convertToLatLng(point);\n });\n }\n\n function calculateArrowPoints() {\n var arrowLength = params.blastWidth / 2 * 0.75;\n var offsetFromCentre = params.blastLength / 4;\n var arrowLineDelta = calculateTranslationDelta(arrowLength, offsetFromCentre, params.azimuth);\n\n if (!arrowLineDelta) {\n return;\n }\n\n var topArrow = createArrowPoints(L.point([centrePoint.x + arrowLineDelta.x1, centrePoint.y - arrowLineDelta.y1]), L.point([centrePoint.x - arrowLineDelta.x2, centrePoint.y + arrowLineDelta.y2]));\n var bottomArrow = createArrowPoints(L.point([centrePoint.x + arrowLineDelta.x2, centrePoint.y - arrowLineDelta.y2]), L.point([centrePoint.x - arrowLineDelta.x1, centrePoint.y + arrowLineDelta.y1]));\n return topArrow.concat(bottomArrow);\n\n function createArrowPoints(tip, tail) {\n var headLength = arrowLength * 0.4;\n var headSpread = arrowLength * 0.15;\n var arrowHeadDelta = calculateTranslationDelta(headLength, headSpread, params.azimuth);\n var tipPoint1 = [tip.x - arrowHeadDelta.x1, tip.y + arrowHeadDelta.y1];\n var tipPoint2 = [tip.x - arrowHeadDelta.x2, tip.y + arrowHeadDelta.y2];\n var arrowLines = [[tip, tail], [tip, tipPoint1], [tip, tipPoint2]];\n return _.map(arrowLines, function (linePoints) {\n return _.map(linePoints, function (point) {\n return convertToLatLng(point);\n });\n });\n }\n }\n\n function convertToCartesian(point) {\n return map.latLngToContainerPoint(point);\n }\n\n function convertToLatLng(point) {\n return map.containerPointToLatLng(point);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsTimeSelector\", esbsTimeSelector).controller(\"esbsTimeSelectorController\", esbsTimeSelectorController);\n\n function esbsTimeSelector() {\n return {\n restrict: \"E\",\n scope: {\n state: \"=state\"\n },\n templateUrl: \"/App/ui/features/blasting/controls/esbsTimeSelector.html\",\n controller: esbsTimeSelectorController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esbsTimeSelectorController.$inject = [\"$scope\", \"i18n\", \"lodash\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.dateTimeService\"];\n\n function esbsTimeSelectorController($scope, i18n, _, timeZoneDateTime, dateTimeService) {\n var vm = this;\n vm.modelGroups = null;\n vm.timeGroups = null;\n vm.toggleLegend = toggleLegend;\n vm.toggleTimeSelectedForModel = toggleTimeSelectedForModel;\n vm.toggleModelSelectedForTime = toggleModelSelectedForTime;\n activate(); ////////////////////\n\n function activate() {\n createGroupsWhenScenarioChanges();\n updateGroupsWhenGroupingChanges();\n }\n\n function createGroupsWhenScenarioChanges() {\n $scope.$watch(function () {\n return vm.state.scenario;\n }, createScenarioGroups);\n $scope.$watch(function () {\n return vm.state.selectedModelCategory;\n }, createScenarioGroups);\n\n function createScenarioGroups() {\n var scenario = vm.state.scenario;\n\n var models = _.chain(_.values(scenario.models)).filter(function (model) {\n return model.modelCategory === vm.state.selectedModelCategory;\n }).sortBy(function (model) {\n model.label = i18n.i10n(\"esbsTimeSelectorHeading.blastModelTypes.\".concat(model.modelType, \".label\"));\n return model.label;\n }).value();\n\n vm.modelGroups = createModelGroups(models, scenario.blastTimesMillis);\n vm.timeGroups = createTimeGroups(models, scenario.blastTimesMillis);\n updateGroupsFromState();\n }\n\n function createModelGroups(models, blastTimesMillis) {\n return _.map(models, function (model) {\n return {\n model: model,\n times: _.map(blastTimesMillis, function (timeMillis) {\n var facilityDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(timeMillis));\n return {\n timeMillis: timeMillis,\n label: dateTimeService.formatAs.dateTime(facilityDate),\n isSelected: false,\n isLegendVisible: false\n };\n })\n };\n });\n }\n\n function createTimeGroups(models, blastTimesMillis) {\n if (!(models && models.length)) {\n return;\n }\n\n return _.map(blastTimesMillis, function (timeMillis) {\n var facilityDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(timeMillis));\n return {\n timeMillis: timeMillis,\n label: dateTimeService.formatAs.dateTime(facilityDate),\n models: _.map(models, function (model) {\n return {\n model: model,\n isSelected: false,\n isLegendVisible: false\n };\n })\n };\n });\n }\n }\n\n function updateGroupsWhenGroupingChanges() {\n $scope.$watch(function () {\n return vm.state.selectedModelGroupingType;\n }, updateGroupsFromState);\n }\n\n function updateGroupsFromState() {\n if (!vm.state.selectedModelGroupingType) {\n return;\n }\n\n var selectedType = vm.state.selectedModelGroupingType;\n var selectedModels = vm.state.selectedModels;\n\n if (selectedType === vm.state.modelGroupingTypes.model.type) {\n updateModelGroupsFromState(selectedModels);\n } else if (selectedType === vm.state.modelGroupingTypes.time.type) {\n updateTimeGroupsFromState(selectedModels);\n } else {\n throw new Error(\"Unknown model grouping type: \".concat(selectedType));\n }\n }\n\n function updateModelGroupsFromState(selectedModels) {\n _.forEach(vm.modelGroups, function (grouping) {\n var selectedTimesForModel = selectedModels[grouping.model.id] || [];\n\n _.forEach(grouping.times, function (time) {\n time.isSelected = !!_.find(selectedTimesForModel, function (selectedTimeMillis) {\n return selectedTimeMillis === time.timeMillis;\n });\n });\n });\n }\n\n function updateTimeGroupsFromState(selectedModels) {\n // Remap the active models to be indexed by time\n var selectedTimes = {};\n\n _.forEach(selectedModels, function (timesMillis, modelId) {\n _.forEach(timesMillis, function (timeMillis) {\n var models = selectedTimes[timeMillis] || (selectedTimes[timeMillis] = []);\n models.push(modelId);\n });\n });\n\n _.forEach(vm.timeGroups, function (grouping) {\n var selectedModelsForTime = selectedTimes[grouping.timeMillis] || [];\n\n _.forEach(grouping.models, function (model) {\n model.isSelected = !!_.find(selectedModelsForTime, function (modelId) {\n return modelId === model.model.id;\n });\n });\n });\n }\n\n function toggleLegend(model) {\n model.isLegendVisible = !model.isLegendVisible;\n }\n\n function toggleTimeSelectedForModel(grouping, time) {\n vm.state.setModelSelected(grouping.model.id, time.timeMillis, time.isSelected);\n }\n\n function toggleModelSelectedForTime(grouping, model) {\n vm.state.setModelSelected(model.model.id, grouping.timeMillis, model.isSelected);\n }\n }\n})();\n\n\n\"use strict\";\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").directive(\"esbsVibrationPointsOfInterest\", directive).controller(\"esbsVibrationPointsOfInterestController\", controller);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n mapId: \"@\",\n scenario: \"=\"\n },\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"$scope\", \"$q\", \"lodash\", \"esLeafletData\", \"leafletLib\", \"app.core.services.monitoringService\", \"app.core.services.configuration.monitoringService\", \"app.core.models.blasting.VibrationPointOfInterestMapMarker\"];\n\n function controller($scope, $q, _, esLeafletData, L, monitoringService, configMonitoringService, VibrationPointOfInterestMapMarker) {\n var vm = this;\n activate(); ///////////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(getVibrationMonitors);\n }\n\n function getVibrationMonitors() {\n $scope.$watch(function () {\n return vm.scenario.isGroundVibrationSelected;\n }, loadAndDisplayVibrationMonitors);\n\n function loadAndDisplayVibrationMonitors(isSelected) {\n if (!vm.scenario.groundVibrationPois && isSelected) {\n loadVibrationMonitors().then(function (monitors) {\n vm.scenario.groundVibrationPois = monitors;\n vm.scenario.map.markers = bindMarkers();\n });\n } else {\n vm.scenario.map.markers = isSelected ? bindMarkers() : [];\n }\n }\n\n function bindMarkers() {\n return vm.scenario.groundVibrationPois && vm.scenario.groundVibrationPois.map(function (monitor) {\n return new VibrationPointOfInterestMapMarker(monitor);\n });\n }\n\n function loadVibrationMonitors() {\n return monitoringService.getMonitorsByType().then(function (monitorsByType) {\n if (monitorsByType.vibrationMonitor) {\n var monitorLoaders = _.map(monitorsByType.vibrationMonitor.monitorIds, function (id) {\n return configMonitoringService.getMonitor(monitorsByType.vibrationMonitor.monitorType, id);\n });\n\n return $q.all(monitorLoaders);\n }\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").factory(\"app.ui.features.blasting.hashParser\", hashParser);\n hashParser.$inject = [];\n /* istanbul ignore next */\n\n function hashParser() {\n return {\n buildScenarioOptionsHash: buildScenarioOptionsHash,\n configureScenarioOptionsFromHash: configureScenarioOptionsFromHash\n }; ////////////////////\n\n function buildScenarioOptionsHash(modelCategory) {\n return \"\".concat(modelCategory);\n }\n\n function configureScenarioOptionsFromHash(hash, scenarioModelsState) {\n var options = parseHashString(hash);\n scenarioModelsState.selectedModelCategory = options.modelCategory;\n }\n\n function parseHashString() {\n var hash = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n var parts = hash.split(\"|\");\n return {\n modelCategory: parts[0]\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").config(configureRouteAliases).run(appRun);\n configureRouteAliases.$inject = [\"$urlRouterProvider\"];\n\n function configureRouteAliases($urlRouterProvider) {\n $urlRouterProvider.when(\"/blasting/:companyAlias/:facilityAlias\", redirectTo);\n $urlRouterProvider.when(\"/blasting/:companyAlias/:facilityAlias/\", redirectTo);\n redirectTo.$inject = [\"$state\", \"$match\"];\n\n function redirectTo($state, $match) {\n $state.go(\"app.blasting.scenarios\", {\n companyAlias: $match.companyAlias,\n facilityAlias: $match.facilityAlias\n });\n }\n }\n\n appRun.$inject = [\"routeHelper\", \"app.ui.features.blasting.scenarioModelsState\", \"app.ui.features.blasting.scenarioConfigurationState\"];\n /* istanbul ignore next */\n\n function appRun(routeHelper, scenarioModelsState, scenarioConfigurationState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n abstract: true,\n state: \"app.blasting\",\n url: \"/blasting/:companyAlias/:facilityAlias\",\n data: {\n requiredAccessControl: \"app.blasting\"\n },\n settings: {\n i18n: [\"/App/ui/features/blasting/i18n/blasting\", \"/App/ui/features/blasting/controls/i18n/esBlastingScenario\"]\n }\n }, {\n state: \"app.blasting.scenarios\",\n url: \"/scenarios\",\n views: {\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/blasting/ScenarioSelectionContentPanel.html\",\n controller: \"app.ui.features.blasting.ScenarioSelectionContentPanel as vm\"\n }\n },\n data: {\n requiredAccessControl: \"app.blasting\"\n },\n settings: {\n i18n: [\"/App/ui/core/controls/i18n/esList\"]\n },\n resolve: {\n scenarioModelsState: scenarioModelsState\n }\n }, {\n state: \"app.blasting.scenarios.scenario\",\n url: \"/scenario/:scenarioAlias\",\n // view scenario models\n views: {\n 'actionsPanel@app': {\n templateUrl: \"/App/ui/features/blasting/ScenarioModelsActionsPanel.html\",\n controller: \"app.ui.features.blasting.ScenarioModelsActionsPanel as vm\"\n },\n 'leftPanel@app': {\n templateUrl: \"/App/ui/features/blasting/ScenarioModelsLeftPanel.html\",\n controller: \"app.ui.features.blasting.ScenarioModelsLeftPanel as vm\"\n },\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/blasting/ScenarioModelsContentPanel.html\",\n controller: \"app.ui.features.blasting.ScenarioModelsContentPanel as vm\"\n }\n },\n data: {\n // We need to explicitly set the layout type since this route's layout is different from the\n // layout of its parent route (app.blasting).\n layoutType: \"split\"\n },\n settings: {\n i18n: [\"/App/ui/core/mapping/i18n/mapLayerRenderer\", \"/App/ui/core/mapping/controls/i18n/esMapKml\", \"/App/ui/core/mapping/controls/i18n/esMapTiles\", \"/App/ui/core/mapping/controls/i18n/esMapType\", \"/App/ui/core/mapping/controls/i18n/esMapCredits\", \"/App/ui/core/mapping/controls/i18n/esMapCentre\", \"/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries\", \"/App/ui/core/controls/i18n/esTimeSlider\", \"/App/ui/features/blasting/controls/i18n/esbsFlyrockLegend\"]\n }\n }, {\n state: \"app.blasting.scenarios.add\",\n url: \"/scenario/add/:scenarioAlias\",\n // create a new scenario or duplicate an existing scenario\n views: {\n 'leftPanel@app': {\n templateUrl: \"/App/ui/features/blasting/AddScenarioLeftPanel.html\",\n controller: \"app.ui.features.blasting.AddScenarioLeftPanel as vm\"\n },\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/blasting/AddScenarioContentPanel.html\",\n controller: \"app.ui.features.blasting.AddScenarioContentPanel as vm\"\n }\n },\n data: {\n layoutType: \"split\"\n },\n settings: {\n i18n: [\"/App/ui/core/mapping/controls/i18n/esMapKml\", \"/App/ui/core/mapping/controls/i18n/esMapTiles\", \"/App/ui/core/mapping/controls/i18n/esMapType\", \"/App/ui/core/mapping/controls/i18n/esMapCredits\", \"/App/ui/core/mapping/controls/i18n/esMapCentre\", \"/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries\", \"/App/ui/core/mapping/controls/i18n/esMapLocationSelector\", \"/App/ui/features/blasting/controls/configuration/i18n/esBlastingScenarioConfig\"]\n },\n resolve: {\n scenarioConfigurationState: scenarioConfigurationState\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").factory(\"app.ui.features.blasting.scenarioConfigurationState\", stateFactory);\n stateFactory.$inject = [\"$q\", \"i18n\", \"lodash\", \"app.core.appSettings\", \"app.core.services.companyService\", \"app.core.services.configuration.blastingService\", \"app.core.models.blasting.blastModelType\", \"app.core.models.blasting.blastSetup\"];\n /* istanbul ignore next */\n\n function stateFactory($q, i18n, _, appSettings, companyService, blastingService, blastModelType, blastSetup) {\n return function stateFactoryResolver() {\n var loaders = [companyService.getFacilityLocation(), blastingService.getModelOptions(), blastingService.getModelTypes()];\n return $q.all(loaders).then(function (results) {\n var _results = _slicedToArray(results, 3),\n facilityLocation = _results[0],\n modelOptions = _results[1],\n modelTypes = _results[2];\n\n return new ScenarioConfigurationState(facilityLocation, modelOptions, modelTypes);\n });\n };\n\n function ScenarioConfigurationState(facilityLocation, modelOptions, modelTypes) {\n var self = this;\n self.lookups = {\n facilityLocation: facilityLocation,\n windScientificModelOptions: modelOptions.windGisModelOptions.windScientificModels,\n pollutantOptions: modelOptions.pollutantGisModelOptions.pollutantOptions,\n pollutantScientificModelOptions: modelOptions.pollutantGisModelOptions.pollutantScientificModelOptions,\n pollutantDisplayUnitOptions: modelOptions.pollutantGisModelOptions.pollutantDisplayUnitOptions,\n noxScale: modelOptions.pollutantGisModelOptions.noxScale,\n forwardTrajectoryScientificModelOptions: modelOptions.forwardTrajectoryModelOptions.forwardTrajectoryScientificModels\n }; // Default the wind to a two-minute interval if we have one\n\n var defaultWindScientificModel = _.find(self.lookups.windScientificModelOptions, {\n intervalDurationInMinutes: 2\n });\n\n var defaultWindScientificModelId = defaultWindScientificModel && defaultWindScientificModel.id || undefined; // Typically there should only be one forward track - \"Blast Traj\".\n\n var defaultForwardTrajectoryScientificModelId = self.lookups.forwardTrajectoryScientificModelOptions.length === 1 ? self.lookups.forwardTrajectoryScientificModelOptions[0].id : undefined; // Default the pollutant to oxide of nitrogen if present\n\n var nox = _.find(self.lookups.pollutantOptions, function (pollutant) {\n return pollutant.libraryPollutantId.toLowerCase() === \"b183985a-f356-4204-87e7-246a95ec3315\";\n });\n\n var defaultModelPollutantId = nox && nox.modelPollutantId || undefined;\n var defaultPollutantDisplayUnitId, defaultPollutantScientificModelId;\n\n if (nox) {\n // Default the display unit to micro-grams per cubic metre\n var defaultUnit = _.find(nox.displayUnitOptions, function (displayUnit) {\n return displayUnit.id.toLowerCase() === \"bd7b6b9c-d634-4a96-ba6b-35ef9dae82a3\";\n });\n\n defaultPollutantDisplayUnitId = defaultUnit && defaultUnit.id || undefined; // For scientific model, auto-select the first items in the cascaded drop-downs (like kendo does).\n\n defaultPollutantScientificModelId = nox.associatedPlumeScientificModels.length ? nox.associatedPlumeScientificModels[0].id : null;\n }\n\n self.canUpdateOverpressureModels = appSettings.site.accessControls[\"app.blasting.overpressure\"];\n self.canUpdateFlyrockModels = appSettings.site.accessControls[\"app.blasting.flyrock\"];\n self.canUpdateGroundvibrationModels = appSettings.site.accessControls[\"app.blasting.ground-vibration\"]; // the form data\n\n self.name = \"\";\n self.alias = \"\";\n self.blastTimesMillis = [];\n self.latitude = null;\n self.longitude = null;\n var overlayFiles = {};\n Object.defineProperty(self, \"overlayFiles\", {\n get: function get() {\n return overlayFiles;\n }\n });\n self.models = {\n path: false,\n dispersion: false,\n fmz: false,\n gain: false,\n contour: false,\n flyrock: false,\n groundVibration: false\n };\n self.windScientificModelId = defaultWindScientificModelId;\n self.forwardTrajectoryScientificModelId = defaultForwardTrajectoryScientificModelId;\n self.blastHeight = null;\n self.blastLength = null;\n self.blastWidth = null;\n self.azimuth = null;\n self.elevation = null;\n self.modelPollutantId = defaultModelPollutantId;\n self.pollutantScientificModelId = defaultPollutantScientificModelId;\n self.displayUnitId = defaultPollutantDisplayUnitId;\n self.defaultConcentrations = modelOptions.pollutantGisModelOptions.defaultConcentrations;\n self.initialConcentration = self.defaultConcentrations.get(defaultPollutantScientificModelId);\n self.chargeMass = null;\n self.chargeMassPerHole = null;\n self.holeDiameter = null;\n self.blastSetup = blastSetup.burden;\n self.burden = null;\n self.stemmingHeight = null;\n self.frontFaceKFactor = null;\n self.backFaceKFactor = null;\n self.flyrockSiteConstantKv = getDefaultConfigurationValue(blastModelType.flyrock, \"Kv\");\n self.dispersalAngle = getDefaultConfigurationValue(blastModelType.flyrock, \"DispersalAngle\");\n self.groundVibrationSiteExponentKb = getDefaultConfigurationValue(blastModelType.groundVibration, \"Kb\");\n self.groundVibrationSiteConstantKv = getDefaultConfigurationValue(blastModelType.groundVibration, \"Kv\");\n Object.defineProperty(self, \"isPathModelSelected\", {\n get: function get() {\n return self.models.path;\n }\n });\n Object.defineProperty(self, \"isPollutantModelSelected\", {\n get: function get() {\n return self.models.dispersion || self.models.fmz;\n }\n });\n Object.defineProperty(self, \"isOverpressureModelSelected\", {\n get: function get() {\n return self.models.contour || self.models.gain;\n }\n });\n Object.defineProperty(self, \"isFlyrockSelected\", {\n get: function get() {\n return self.models.flyrock;\n }\n });\n Object.defineProperty(self, \"isGroundVibrationSelected\", {\n get: function get() {\n return self.models.groundVibration;\n }\n });\n Object.defineProperty(self, \"isNOxPollutant\", {\n get: function get() {\n var modelPollutant = _.find(self.lookups.pollutantOptions, {\n modelPollutantId: self.modelPollutantId\n });\n\n return modelPollutant && blastingService.isNOxPollutant(modelPollutant.libraryPollutantId);\n }\n }); ////////////////////\n\n function getDefaultConfigurationValue(blastModelType, key) {\n var config = modelTypes[blastModelType];\n return config && config[key];\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").controller(\"app.ui.features.blasting.ScenarioModelsActionsPanel\", ActionsPanel);\n ActionsPanel.$inject = [\"scenarioModelsState\"];\n\n function ActionsPanel(state) {\n var vm = this;\n vm.state = state;\n activate(); /////////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").controller(\"app.ui.features.blasting.ScenarioModelsContentPanel\", ScenarioModelsContentPanel);\n ScenarioModelsContentPanel.$inject = [\"$scope\", \"$state\", \"esLeafletData\", \"leafletLib\", \"i18n\", \"lodash\", \"app.core.appSettings\", \"app.core.services.locationService\", \"app.ui.features.blasting.BlastDataMediator\", \"scenarioModelsState\", \"app.core.services.blastingService\", \"app.core.services.mappingService\"];\n /* istanbul ignore next */\n\n function ScenarioModelsContentPanel($scope, $state, esLeafletData, L, i18n, _, appSettings, locationService, BlastDataMediator, state, blastingService, mappingService) {\n var vm = this;\n var blastCentreMarker = null;\n var resolveMap = null;\n vm.state = state;\n vm.scenarioAlias = $state.params.scenarioAlias;\n vm.map = state.map;\n vm.map.id = \"map-canvas\";\n vm.map.overlayProvider = {};\n vm.mapLayerDatasets = [];\n vm.activeOffsetMinutes = 0;\n vm.onActiveOffsetChanged = onActiveOffsetChanged;\n vm.activeOffsetTooltip = {\n template: function template(stepValue) {\n return i18n.i10n(\"app.ui.features.blasting.scenarioModelsContentPanel.timeOffset\", {\n offsetMinutes: stepValue.value\n });\n }\n };\n vm.isAnimatedModel = false;\n vm.hasSelectedModels = false;\n vm.hasModelData = false;\n var mediator = new BlastDataMediator(state, esLeafletData.getMap(vm.map.id), onMediatorRefreshed);\n activate(); //////////////////////\n\n function activate() {\n locationService.updatePageHeading({\n name: vm.scenarioAlias\n });\n locationService.updateExitPoint(\"app.blasting.scenarios\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias\n });\n resolveMap = esLeafletData.getMap(vm.map.id);\n showBlastOriginWhenScenarioIsLoaded();\n updateIsAnimatedWhenModelCategoryChanges();\n updateVisibleModelsWhenSelectedModelsChange();\n destroyMediatorOnDeactivate();\n loadOverlays();\n }\n\n function loadOverlays() {\n $scope.$watch(function () {\n return vm.state.scenario;\n }, onScenarioUpdated);\n mappingService.getKmls().then(addOverlays);\n\n function onScenarioUpdated(scenario, existingScenario) {\n if (scenario === existingScenario) {\n return;\n }\n\n blastingService.getOverlays(scenario.id).then(addOverlays);\n }\n\n function addOverlays(overlays) {\n _.forEach(overlays, function (overlay) {\n vm.map.overlayProvider[overlay.name] = overlay;\n });\n }\n }\n\n function destroyMediatorOnDeactivate() {\n $scope.$on(\"$destroy\", mediator.dispose);\n }\n\n function showBlastOriginWhenScenarioIsLoaded() {\n $scope.$watch(function () {\n return vm.state.scenario.blastParameters;\n }, showBlastOrigin); ////////////////////\n\n function showBlastOrigin(blastParameters) {\n if (!blastParameters) {\n return;\n }\n\n if (blastCentreMarker) {\n blastCentreMarker.setLatLng(new L.LatLng(blastParameters.latitude, blastParameters.longitude));\n } else {\n var icon = new L.AwesomeMarkers.Icon({\n prefix: \"fa\",\n icon: \"bomb\",\n markerColor: \"orange\"\n });\n blastCentreMarker = new L.Marker([blastParameters.latitude, blastParameters.longitude], {\n icon: icon,\n clickable: false,\n keyboard: false\n });\n resolveMap.then(function (map) {\n return blastCentreMarker.addTo(map);\n });\n }\n }\n }\n\n function updateIsAnimatedWhenModelCategoryChanges() {\n $scope.$watch(function () {\n return vm.state.selectedModelCategory;\n }, function (category) {\n var isAnimatedModel = category === vm.state.modelCategories.animated.type;\n\n if (isAnimatedModel === vm.isAnimatedModel) {\n return;\n }\n\n vm.isAnimatedModel = isAnimatedModel;\n triggerMapResize();\n vm.activeOffsetMinutes = 0;\n mediator.refresh();\n });\n }\n\n function updateVisibleModelsWhenSelectedModelsChange() {\n var selectedModels = state.selectedModels;\n $scope.$watch(function () {\n return selectedModels;\n }, updateVisibleModels, true); ////////////////////\n\n function updateVisibleModels(selectedModels) {\n var hadSelectedModels = vm.hasSelectedModels;\n vm.hasSelectedModels = !_.isEmpty(selectedModels);\n\n if (vm.hasSelectedModels !== hadSelectedModels) {\n triggerMapResize();\n }\n\n mediator.refresh();\n }\n }\n\n function onActiveOffsetChanged(offsetMinutes) {\n vm.activeOffsetMinutes = offsetMinutes;\n bindVisibleTimeStepDataToMap(offsetMinutes);\n }\n\n function onMediatorRefreshed() {\n vm.hasModelData = state.blastDataStore.hasImportedData();\n bindVisibleTimeStepDataToMap();\n }\n\n function bindVisibleTimeStepDataToMap(offsetMinutes) {\n vm.mapLayerDatasets = state.blastDataStore.getDataAtOffset(offsetMinutes || vm.activeOffsetMinutes);\n }\n\n function triggerMapResize() {\n $scope.$broadcast(\"resizePage\");\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").controller(\"app.ui.features.blasting.ScenarioModelsLeftPanel\", ScenarioModelsLeftPanel);\n ScenarioModelsLeftPanel.$inject = [\"$state\", \"$location\", \"i18n\", \"promiseTracker\", \"lodash\", \"app.ui.features.blasting.hashParser\", \"app.core.models.blasting.blastModelCategory\", \"app.core.services.blastingService\", \"scenarioModelsState\", \"app.core.services.configuration.blastingService\", \"confirmationDialog\", \"app.core.appSettings\"];\n /* istanbul ignore next */\n\n function ScenarioModelsLeftPanel($state, $location, i18n, promiseTracker, _, hashParser, blastModelCategory, blastingService, scenarioModelsState, blastingConfigurationService, confirmationDialog, appSettings) {\n var vm = this;\n vm.scenarioAlias = $state.params.scenarioAlias;\n vm.state = scenarioModelsState;\n vm.deleteScenario = deleteScenario;\n vm.busyLoading = promiseTracker();\n vm.showBottomControls = appSettings.site.accessControls[\"app.blasting.modify\"];\n activate(); //////////////////////\n\n function activate() {\n configureScenarioOptions();\n loadScenarioModels();\n\n function configureScenarioOptions() {\n hashParser.configureScenarioOptionsFromHash($location.search().scenarioHash, scenarioModelsState);\n\n if (!scenarioModelsState.selectedModelCategory) {\n scenarioModelsState.selectedModelCategory = scenarioModelsState.getDefaultModelCategory().type;\n }\n\n if (!scenarioModelsState.selectedModelGroupingType) {\n scenarioModelsState.selectedModelGroupingType = scenarioModelsState.getDefaultModelGroupingType().type;\n }\n }\n }\n\n function deleteScenario() {\n var headingKey = \"app.ui.features.blasting.scenarioModelsLeftPanel.remove.heading\";\n var descKey = \"app.ui.features.blasting.scenarioModelsLeftPanel.remove.instructions\";\n var modalOptions = {\n css: \"modal-center\",\n buttons: {\n 'continue': {\n text: i18n.i10n(\"buttons.delete\")\n }\n }\n };\n confirmationDialog.ask(headingKey, descKey, modalOptions).then(onConfirm);\n\n function onConfirm() {\n var removalPromise = blastingConfigurationService.deleteScenario(vm.scenarioAlias);\n removalPromise.then(removeSuccess);\n }\n\n function removeSuccess() {\n $state.go(\"app.blasting.scenarios\");\n }\n }\n\n function loadScenarioModels() {\n var scenarioPromise = blastingService.getScenario(vm.scenarioAlias);\n vm.busyLoading.addPromise(scenarioPromise);\n scenarioPromise.then(function (scenario) {\n vm.state.scenario = scenario;\n\n var hasAnimatedModels = _.find(scenario.models, {\n modelCategory: blastModelCategory.animated\n });\n\n vm.state.selectedModelCategory = hasAnimatedModels ? blastModelCategory.animated : blastModelCategory.snapshot;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").factory(\"app.ui.features.blasting.scenarioModelsState\", stateFactory);\n stateFactory.$inject = [\"$q\", \"i18n\", \"lodash\", \"app.core.mapDefaults\", \"app.core.models.modelLoadingStatus\", \"app.core.models.blasting.blastModelCategory\", \"app.core.models.blasting.blastSetup\", \"app.core.services.companyService\", \"app.ui.features.blasting.BlastDataStore\"];\n\n function stateFactory($q, i18n, _, mapDefaults, modelLoadingStatus, blastModelCategory, blastSetup, companyService, BlastDataStore) {\n return function stateFactoryResolver() {\n var loaders = [companyService.getFacilityLocation(), companyService.getDomainBoundaries(false, true, false)];\n return $q.all(loaders).then(function (results) {\n var _results = _slicedToArray(results, 2),\n facilityLocation = _results[0],\n domainBoundaries = _results[1];\n\n return new ScenarioModelsState(facilityLocation, domainBoundaries);\n });\n };\n\n function ScenarioModelsState(facilityLocation, domainBoundaries) {\n var self = this;\n this.modelCategories = _.chain(blastModelCategory).map(buildModelCategory).keyBy(\"type\").value();\n this.modelGroupingTypes = {\n model: buildModelGroupingType(\"model\"),\n time: buildModelGroupingType(\"time\")\n };\n this.simulationParameters = {\n // How long each blast simulation runs for\n durationMinutes: 60,\n // Interval between each data point in the simulation data\n intervalMinutes: 2\n };\n this.scenario = {\n blastSetup: blastSetup.burden\n };\n this.selectedModelGroupingType = null;\n var selectedModels = {};\n var selectedModelCategory = null;\n Object.defineProperty(this, \"selectedModels\", {\n get: function get() {\n return selectedModels;\n }\n });\n Object.defineProperty(this, \"selectedModelCategory\", {\n get: function get() {\n return selectedModelCategory;\n },\n set: function set(value) {\n if (selectedModelCategory === value) {\n return;\n }\n\n selectedModelCategory = value;\n\n _.forEach(_.keys(selectedModels), function (key) {\n return delete selectedModels[key];\n });\n }\n });\n this.map = {\n defaultCentre: facilityLocation,\n centre: facilityLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n bounds: getMapBounds(),\n isColor: false,\n layers: {\n baselayers: mapDefaults.baselayers\n },\n overlayProvider: {}\n };\n this.getDefaultModelCategory = getDefaultModelCategory;\n this.getDefaultModelGroupingType = getDefaultModelGroupingType;\n this.setModelSelected = setModelSelected;\n this.isModelSelected = isModelSelected;\n this.getModelLoadingStatus = getModelLoadingStatus;\n this.setModelLoadingStatus = setModelLoadingStatus;\n var blastDataStore = new BlastDataStore();\n Object.defineProperty(this, \"blastDataStore\", {\n get: function get() {\n return blastDataStore;\n }\n });\n var modelLoadingStatuses = {};\n Object.defineProperty(this, \"modelLoadingStatuses\", {\n get: function get() {\n return modelLoadingStatuses;\n }\n }); ////////////////////\n\n function getDefaultModelCategory() {\n return self.modelCategories.animated;\n }\n\n function getDefaultModelGroupingType() {\n return self.modelGroupingTypes.model;\n }\n\n function setModelSelected(modelId, timeMillis, isSelected) {\n var isInSelectedModels = _.has(selectedModels, modelId);\n\n if (isSelected) {\n if (!isInSelectedModels) {\n selectedModels[modelId] = [];\n }\n\n selectedModels[modelId].push(timeMillis);\n } else {\n if (!isInSelectedModels) {\n return;\n }\n\n var selectedTimesForModel = selectedModels[modelId];\n\n _.remove(selectedTimesForModel, function (selectedTimeMillis) {\n return selectedTimeMillis === timeMillis;\n });\n\n if (!selectedTimesForModel.length) {\n delete selectedModels[modelId];\n }\n }\n }\n\n function isModelSelected(modelId, blastTimeMillis) {\n if (!_.has(selectedModels, modelId)) {\n return false;\n }\n\n var selectedBlastTimesForModel = selectedModels[modelId];\n return _.includes(selectedBlastTimesForModel, blastTimeMillis);\n }\n\n function getModelLoadingStatus(modelId, blastTimeMillis) {\n var key = buildModelLoadingStatusKey(modelId, blastTimeMillis);\n return modelLoadingStatuses[key] || modelLoadingStatus.pending;\n }\n\n function setModelLoadingStatus(modelId, blastTimeMillis, status) {\n var key = buildModelLoadingStatusKey(modelId, blastTimeMillis);\n modelLoadingStatuses[key] = status;\n }\n\n function buildModelLoadingStatusKey(modelId, blastTimeMillis) {\n if (!_.isString(modelId)) {\n throw new Error(\"The modelId must be passed as a string; modelId provided was \".concat(modelId));\n }\n\n if (!blastTimeMillis) {\n throw new Error(\"You must provide the blast time in order to retrieve the loading status.\");\n }\n\n return \"\".concat(modelId, \"-\").concat(blastTimeMillis);\n }\n\n function getMapBounds() {\n return domainBoundaries && _.reduce(domainBoundaries, function (memo, boundary) {\n var coordinates = [boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight];\n return memo.concat(_.map(coordinates, function (coordinate) {\n return [coordinate.latitude, coordinate.longitude];\n }));\n }, []);\n }\n }\n\n function buildModelCategory(type) {\n return {\n type: type,\n label: i18n.i10n(\"esbsModelCategorySelector.modelCategories.\".concat(type))\n };\n }\n\n function buildModelGroupingType(groupingType) {\n return {\n type: groupingType,\n label: i18n.i10n(\"esbsModelGroupingSelector.modelGroupingTypes.\".concat(groupingType))\n };\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.blasting\").controller(\"app.ui.features.blasting.ScenarioSelectionContentPanel\", ScenarioSelectionContentPanel);\n ScenarioSelectionContentPanel.$inject = [\"$state\", \"lodash\", \"promiseTracker\", \"app.core.services.locationService\", \"app.core.services.blastingService\", \"app.core.appSettings\", \"i18n\"];\n /* istanbul ignore next */\n\n function ScenarioSelectionContentPanel($state, _, promiseTracker, locationService, blastingService, appSettings, i18n) {\n var vm = this;\n vm.options = _defineProperty({\n dataProvider: blastingService.getScenarios,\n dataSource: {\n pageSize: 25\n },\n sortable: true,\n filterable: false,\n columns: [{\n title: i18n.i10n(\"app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.name.heading\"),\n field: \"name\",\n click: onScenarioSelected\n }, {\n title: i18n.i10n(\"app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.firstScenarioTime.heading\"),\n field: \"firstScenarioTime\",\n dataType: \"datetime\"\n }, {\n title: i18n.i10n(\"app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.actualBlastTime.heading\"),\n field: \"actualBlastTime\",\n dataType: \"datetime\"\n }, {\n title: i18n.i10n(\"app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.lastUpdated.heading\"),\n field: \"lastUpdated\",\n dataType: \"datetime\",\n sort: {\n order: 1,\n dir: \"desc\"\n }\n }],\n selectedItem: {\n field: \"alias\",\n value: null\n },\n busyLoading: promiseTracker(),\n onItemSelected: onScenarioSelected,\n addItem: appSettings.site.accessControls[\"app.blasting.modify\"] && addScenario\n }, \"dataSource\", {\n serverPaging: false,\n serverSorting: false,\n serverGrouping: false,\n serverFiltering: false,\n schema: {\n id: \"id\"\n }\n }); //////////////////////\n\n function onScenarioSelected(scenario) {\n locationService.updatePageHeading(scenario);\n $state.go(\"app.blasting.scenarios.scenario\", {\n scenarioAlias: scenario.alias\n });\n }\n\n function addScenario() {\n $state.go(\"app.blasting.scenarios.add\");\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.blasting\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.configuration.company.blasting.scenarios.state\"];\n\n function appRun(routeHelper, scenariosState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n abstract: true,\n state: \"app.configuration.company.blasting\",\n url: \"/blasting\",\n data: {\n requiredAccessControl: \"app.blasting.modify\"\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/blasting/i18n/blasting\"]\n }\n }, {\n state: \"app.configuration.company.blasting.scenarios\",\n url: \"/scenarios\",\n views: {\n 'contentPanel@app': {\n // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\n templateUrl: \"/App/ui/features/configuration/company/blasting/scenarios/ContentPanel.html\",\n controller: \"app.ui.features.configuration.company.blasting.scenarios.ContentPanel as vm\"\n }\n },\n resolve: {\n scenariosState: scenariosState\n }\n }, {\n state: \"app.configuration.company.blasting.scenarios.edit\",\n url: \"/edit/:scenarioId\",\n views: {\n detailPanel: {\n templateUrl: \"/App/ui/features/configuration/company/blasting/scenarios/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.blasting.scenarios.DetailPanel as vm\"\n }\n }\n }, {\n state: \"app.configuration.company.blasting.scenarios.add\",\n url: \"/add\",\n views: {\n detailPanel: {\n templateUrl: \"/App/ui/features/configuration/company/blasting/scenarios/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.blasting.scenarios.DetailPanel as vm\"\n }\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n//TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.blasting\").controller(\"app.ui.features.configuration.company.blasting.scenarios.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"$state\", \"lodash\", \"promiseTracker\", \"app.core.services.locationService\", \"app.core.services.configuration.blastingService\", \"scenariosState\"];\n\n function ContentPanel($scope, $state, _, promiseTracker, locationService, blastingService, scenariosState) {\n var vm = this;\n vm.listOptions = getListOptions();\n scenariosState.loadScenarios = loadScenarios;\n activate(); ///////////\n\n function activate() {\n loadScenarios().then(updateUIWithSelectedScenario); /////////////\n\n function updateUIWithSelectedScenario(scenarios) {\n $scope.$watch(function () {\n return $state.params.scenarioId;\n }, function (scenarioId) {\n vm.listOptions.selectedItem.value = scenarioId;\n locationService.updatePageHeading(_.find(scenarios, {\n scenarioId: scenarioId\n }));\n });\n }\n }\n\n function getListOptions() {\n return {\n columnDefs: [{\n heading: {\n i18n: {\n key: \"app.ui.features.configuration.company.blasting.scenarios.contentPanel.list.columns.name.heading\"\n }\n },\n field: \"name\"\n }],\n items: [],\n selectedItem: {\n field: \"scenarioId\",\n value: null\n },\n busyLoading: promiseTracker(),\n onItemSelected: onScenarioSelected,\n addItem: addScenario\n };\n }\n\n function addScenario() {\n $state.go(\"app.configuration.company.blasting.scenarios.add\");\n }\n\n function onScenarioSelected(scenario) {\n $state.go(\"app.configuration.company.blasting.scenarios.edit\", {\n scenarioId: scenario.scenarioId\n });\n }\n\n function loadScenarios() {\n var scenarios = blastingService.getAllScenarios().then(function (scenarios) {\n return vm.listOptions.items = scenarios;\n });\n vm.listOptions.busyLoading.addPromise(scenarios);\n return scenarios;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.blasting\").directive(\"esBlastScenarioForm\", esBlastScenarioForm).controller(\"esBlastScenarioFormController\", esBlastScenarioFormController);\n esBlastScenarioForm.$inject = [];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function esBlastScenarioForm() {\n var directive = {\n restrict: \"E\",\n scope: {\n state: \"=\"\n },\n controllerAs: \"vm\",\n bindToController: true,\n controller: esBlastScenarioFormController,\n templateUrl: \"/App/ui/features/configuration/company/blasting/scenarios/controls/esBlastScenarioForm.html\"\n };\n return directive;\n }\n\n esBlastScenarioFormController.$inject = [\"promiseTracker\"];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function esBlastScenarioFormController(promiseTracker) {\n var vm = this;\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n activate(); ///////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.blasting\").directive(\"esBlastScenarioFormMap\", esBlastScenarioFormMap).controller(\"esBlastScenarioFormMapController\", esBlastScenarioFormMapController);\n esBlastScenarioFormMap.$inject = [];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function esBlastScenarioFormMap() {\n var directive = {\n restrict: \"E\",\n scope: {\n state: \"=\"\n },\n controllerAs: \"vm\",\n bindToController: true,\n controller: esBlastScenarioFormMapController,\n templateUrl: \"/App/ui/features/configuration/company/blasting/scenarios/controls/esBlastScenarioFormMap.html\"\n };\n return directive;\n }\n\n esBlastScenarioFormMapController.$inject = [\"promiseTracker\", \"app.core.services.configuration.blastingService\"];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function esBlastScenarioFormMapController(promiseTracker) {\n var vm = this;\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n activate(); ///////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n//TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.blasting\").controller(\"app.ui.features.configuration.company.blasting.scenarios.DetailPanel\", DetailPanel);\n DetailPanel.$inject = [\"$q\", \"$state\", \"promiseTracker\", \"app.core.services.configuration.blastingService\", \"scenariosState\"];\n\n function DetailPanel($q, $state, promiseTracker, blastingService, scenariosState) {\n var vm = this;\n vm.state = scenariosState;\n var scenarioId = $state.params.scenarioId;\n vm.isNew = !scenarioId;\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n activate(); //////////////////\n\n function activate() {\n var loadingPromise = !vm.isNew ? loadScenario() : $q.when();\n vm.busyLoading.addPromise(loadingPromise);\n }\n\n function loadScenario() {\n return blastingService.getScenario(scenarioId).then(function (scenario) {\n return vm.state.selectedScenario = scenario;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.blasting\").factory(\"app.ui.features.configuration.company.blasting.scenarios.state\", stateFactory);\n stateFactory.$inject = [];\n\n function stateFactory() {\n function stateFactoryResolver() {\n return {\n loadScenarios: angular.noop\n };\n }\n\n return stateFactoryResolver;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").component(\"modelling.aermet.contentPanel\", {\n controller: ContentPanelController,\n templateUrl: \"/App/ui/features/configuration/company/modelling/aermet/ContentPanel.html\",\n controllerAs: \"vm\",\n bindings: {\n state: \"<\"\n }\n });\n ContentPanelController.$inject = [\"lodash\", \"i18n\", \"notifier\", \"app.core.services.dateTimeService\", \"esComponentChangeHandlerFactory\", \"app.ui.features.configuration.company.modelling.aermet.store\"];\n\n function ContentPanelController(_, i18n, notifier, dateTimeService, changeHandlerFactory, store) {\n var vm = this;\n vm.upperAirWeatherStationsDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.modelling.aermet.contentPanel.upperAirWeatherStations.defaultValue\");\n vm.surfaceWeatherStationsDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.modelling.aermet.contentPanel.surfaceWeatherStations.defaultValue\");\n vm.onUpperAirWeatherStationChanged = store.dispatch.selectedUpperAirWeatherStationChanged;\n vm.onSurfaceWeatherStationChanged = store.dispatch.selectedSurfaceWeatherStationChanged;\n vm.cancel = cancel;\n vm.runAermet = runAermet;\n\n vm.$onChanges = function (changes) {\n var changeHandler = changeHandlerFactory(changes);\n mapStateToVm(); ////////////////////\n\n function mapStateToVm() {\n var whenState = changeHandler.when(function (changes) {\n return changes.state;\n });\n whenState.hasChanged(function (state) {\n return state.selectedUpperAirWeatherStationId;\n }).then(function (value) {\n return vm.upperAirWeatherStationId = value;\n });\n whenState.hasChanged(function (state) {\n return state.selectedSurfaceWeatherStationId;\n }).then(function (value) {\n return vm.surfaceWeatherStationId = value;\n });\n whenState.hasFirstChanged().then(function (state) {\n vm.fromDate = buildDatePicker(state.fromDate, store.dispatch.fromDateChanged);\n vm.toDate = buildDatePicker(state.toDate, store.dispatch.toDateChanged);\n });\n whenState.hasChanged(function (state) {\n return state.fromDate;\n }).then(function (fromDate) {\n vm.fromDate.value = fromDate.value;\n vm.fromDate.formattedString = fromDate.value ? dateTimeService.formatAs.date(fromDate.value) : null;\n });\n whenState.hasChanged(function (state) {\n return state.toDate;\n }).then(function (toDate) {\n vm.toDate.value = toDate.value;\n vm.toDate.formattedString = toDate.value ? dateTimeService.formatAs.date(toDate.value) : null;\n });\n whenState.hasChanged(function (state) {\n return state.lastRunDetails;\n }).then(function (runDetails) {\n if (!runDetails) {\n return;\n }\n\n vm.$form.$setPristine();\n var runDates = {\n fromDate: dateTimeService.formatAs.date(runDetails.fromDate),\n toDate: dateTimeService.formatAs.date(runDetails.toDate)\n };\n notifier.success(i18n.i10n(\"app.ui.features.configuration.company.modelling.aermet.contentPanel.aermetRunScheduled.instructions\", runDates), i18n.i10n(\"app.ui.features.configuration.company.modelling.aermet.contentPanel.aermetRunScheduled.heading\"));\n });\n\n function buildDatePicker(dateObj, onChanged) {\n return {\n options: {\n format: dateTimeService.formats.kendo.date,\n min: dateObj.min,\n max: dateObj.max\n },\n onChanged: onChanged\n };\n }\n }\n };\n\n function runAermet() {\n if (vm.$form.$valid) {\n store.dispatch.runAermet();\n }\n }\n\n function cancel() {\n vm.$form.$setPristine();\n store.dispatch.resetState();\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").factory(\"app.ui.features.configuration.company.modelling.aermet.store\", aermetStore);\n aermetStore.$inject = [\"$q\", \"moment\", \"esStateStore\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.configuration.monitoringService\", \"app.core.services.configuration.modellingService\"];\n\n function aermetStore($q, moment, esStateStore, timeZoneDateTime, monitoringService, modellingService) {\n var initialStateResolver = function initialStateResolver() {\n var min = moment().add(-5, \"year\").startOf(\"year\").toDate();\n var state = {\n fromDate: {\n min: min,\n max: moment().startOf(\"day\").toDate()\n },\n toDate: {\n min: min,\n max: moment().startOf(\"day\").add(4, \"day\").toDate()\n },\n selectedUpperAirWeatherStationId: null,\n selectedSurfaceWeatherStationId: null\n };\n return $q.all([monitoringService.getSurfaceWeatherStations(), monitoringService.getUpperAirWeatherStations()]).then(function (monitors) {\n var _monitors = _slicedToArray(monitors, 2),\n surfaceWeatherStations = _monitors[0],\n upperAirWeatherStations = _monitors[1];\n\n return _extends({}, state, {\n surfaceWeatherStations: surfaceWeatherStations,\n upperAirWeatherStations: upperAirWeatherStations\n });\n });\n };\n\n var dispatchers = {\n fromDateChanged: fromDateChanged,\n toDateChanged: toDateChanged,\n selectedUpperAirWeatherStationChanged: selectedUpperAirWeatherStationChanged,\n selectedSurfaceWeatherStationChanged: selectedSurfaceWeatherStationChanged,\n runAermet: runAermet,\n resetState: resetState\n };\n return esStateStore(initialStateResolver, dispatchers); ////////////////////\n // DISPATCHERS\n\n function fromDateChanged(store) {\n return function (value) {\n store.state = _extends({}, store.state, {\n fromDate: _extends({}, store.state.fromDate, {\n value: value\n })\n });\n };\n }\n\n function toDateChanged(store) {\n return function (value) {\n store.state = _extends({}, store.state, {\n toDate: _extends({}, store.state.toDate, {\n value: value\n })\n });\n };\n }\n\n function selectedUpperAirWeatherStationChanged(store) {\n return function (selectedUpperAirWeatherStationId) {\n store.state = _extends({}, store.state, {\n selectedUpperAirWeatherStationId: selectedUpperAirWeatherStationId\n });\n };\n }\n\n function selectedSurfaceWeatherStationChanged(store) {\n return function (selectedSurfaceWeatherStationId) {\n store.state = _extends({}, store.state, {\n selectedSurfaceWeatherStationId: selectedSurfaceWeatherStationId\n });\n };\n }\n\n function resetState(store) {\n return function () {\n return store.resolve();\n };\n }\n\n function runAermet(store) {\n return function () {\n var fromDate = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(store.state.fromDate.value);\n var toDate = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(moment(store.state.toDate.value).endOf(\"day\").toDate());\n\n var runDetails = _extends({}, store.state, {\n fromDate: fromDate,\n toDate: toDate\n });\n\n modellingService.runAerModelling(store.state.selectedUpperAirWeatherStationId, store.state.selectedSurfaceWeatherStationId, fromDate, toDate).then(function () {\n store.dispatch.resetState().then(function () {\n store.state = _extends({}, store.state, {\n lastRunDetails: runDetails\n });\n });\n });\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").component(\"modelling.emissionsData.contentPanel\", {\n controller: ContentPanelController,\n templateUrl: \"/App/ui/features/configuration/company/modelling/emissionsData/ContentPanel.html\",\n controllerAs: \"vm\",\n bindings: {\n state: \"<\"\n }\n });\n ContentPanelController.$inject = [\"lodash\", \"i18n\", \"notifier\", \"confirmationDialog\", \"esComponentChangeHandlerFactory\", \"app.ui.features.configuration.company.modelling.emissionsData.store\"];\n\n function ContentPanelController(_, i18n, notifier, confirmationDialog, changeHandlerFactory, store) {\n var vm = this;\n vm.$onChanges = onChanges;\n vm.hasUploadedEmissionsData = false;\n vm.onSelectedCalpuffConfigChanged = store.dispatch.selectedCalpuffConfigChanged;\n vm.saving = 0;\n vm.save = store.dispatch.importEmissionsData;\n vm.cancel = cancel; ////////////////////\n\n function onChanges(changes) {\n var whenState = changeHandlerFactory(changes).when(function (changes) {\n return changes.state;\n });\n mapStateToVm(); ////////////////////\n\n function mapStateToVm() {\n whenState.hasFirstChanged().then(function (state) {\n vm.emissionsDataUpload = {\n maxSizeBytes: 5 * 1024 * 1024,\n allowedExtensions: [\"xlsx\"],\n url: state.emissionsDataFileUploadUrl,\n fileUploaded: store.dispatch.emissionsDataFileAdded,\n deleteFile: store.dispatch.emissionsDataFileDeleted,\n existingFiles: state.existingEmissionsDataFiles,\n postData: {\n calpuffConfigId: vm.selectedCalpuffConfigId\n }\n };\n });\n whenState.hasChanged(function (state) {\n return state.calpuffConfigs;\n }).then(function (calpuffConfigs) {\n vm.selectedCalpuffConfigId = null;\n vm.calpuffConfigs = _.sortBy(calpuffConfigs, \"name\");\n });\n whenState.hasChanged(function (state) {\n return state.selectedCalpuffConfigId;\n }).then(function (selectedCalpuffConfigId) {\n vm.selectedCalpuffConfigId = selectedCalpuffConfigId;\n vm.emissionsDataUpload.postData = {\n calpuffConfigId: selectedCalpuffConfigId\n };\n });\n whenState.hasChanged(function (state) {\n return state.existingEmissionsDataFiles;\n }).then(function (existingEmissionsDataFiles) {\n return vm.emissionsDataUpload.existingFiles = existingEmissionsDataFiles;\n });\n whenState.hasChanged(function (state) {\n return state.saving;\n }).then(function (saving) {\n return vm.saving = saving;\n });\n whenState.hasChanged(function (state) {\n return state.hasImportComplete;\n }).then(function (hasImportComplete) {\n if (!hasImportComplete) {\n return;\n }\n\n notifier.success(i18n.i10n(\"app.ui.features.configuration.company.modelling.emissionsData.contentPanel.importComplete.instructions\"), i18n.i10n(\"app.ui.features.configuration.company.modelling.emissionsData.contentPanel.importComplete.heading\"));\n });\n whenState.hasChanged(function (state) {\n return state.uploadedFiles;\n }).then(function (uploadedFiles) {\n vm.hasUploadedEmissionsData = uploadedFiles && uploadedFiles.length;\n });\n whenState.hasChanged(function (state) {\n return state.canRunImport;\n }).then(function (canRunImport) {\n return vm.canRunImport = canRunImport;\n });\n }\n }\n\n function cancel() {\n if (!vm.state.uploadedFiles.length) {\n return;\n }\n\n var headingKey = \"app.ui.features.configuration.company.modelling.emissionsData.contentPanel.cancel.heading\";\n var descKey = \"app.ui.features.configuration.company.modelling.emissionsData.contentPanel.cancel.instructions\";\n confirmationDialog.ask(headingKey, descKey).then(store.dispatch.emissionsDataImportCancelled);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").factory(\"app.ui.features.configuration.company.modelling.emissionsData.store\", store);\n store.$inject = [\"$q\", \"lodash\", \"esStateStore\", \"app.core.services.configuration.gisModelService\"];\n\n function store($q, _, esStateStore, gisModelService) {\n var initialStateResolver = function initialStateResolver() {\n var resolvers = [gisModelService.getCalpuffConfigs(), gisModelService.getEmissionsDataFileUploadUrl()];\n return $q.all(resolvers).then(function (results) {\n var _results = _slicedToArray(results, 2),\n calpuffConfigs = _results[0],\n emissionsDataFileUploadUrl = _results[1];\n\n return {\n calpuffConfigs: calpuffConfigs,\n emissionsDataFileUploadUrl: emissionsDataFileUploadUrl,\n selectedCalpuffConfigId: null,\n existingEmissionsDataFiles: [],\n uploadedFiles: [],\n hasImportComplete: false,\n canRunImport: false\n };\n });\n };\n\n var dispatchers = {\n selectedCalpuffConfigChanged: selectedCalpuffConfigChanged,\n emissionsDataFileAdded: emissionsDataFileAdded,\n emissionsDataFileDeleted: emissionsDataFileDeleted,\n emissionsDataImportCancelled: emissionsDataImportCancelled,\n importEmissionsData: importEmissionsData\n };\n return esStateStore(initialStateResolver, dispatchers); ////////////////////\n // DISPATCHERS\n\n function selectedCalpuffConfigChanged(store) {\n return function (calpuffConfigId) {\n store.state = _extends({}, store.state, {\n selectedCalpuffConfigId: calpuffConfigId,\n existingEmissionsDataFiles: [],\n uploadedFiles: [],\n hasImportComplete: false,\n canRunImport: false\n });\n\n if (calpuffConfigId) {\n gisModelService.getExistingEmissionsDataFiles(calpuffConfigId).then(function (existingFiles) {\n store.state = _extends({}, store.state, {\n existingEmissionsDataFiles: existingFiles,\n canRunImport: existingFiles.length > 0\n });\n });\n }\n };\n }\n\n function emissionsDataFileAdded(store) {\n return function (fileName) {\n var uploadedFiles = [].concat(_toConsumableArray(store.state.uploadedFiles), [fileName]);\n store.state = _extends({}, store.state, {\n uploadedFiles: uploadedFiles,\n hasImportComplete: false,\n canRunImport: true\n });\n };\n }\n\n function emissionsDataFileDeleted(store) {\n return function (fileName) {\n var calpuffConfigId = store.state.selectedCalpuffConfigId;\n var $delete$ = gisModelService.deleteEmissionsDataFiles(calpuffConfigId, [fileName]).then(function () {\n var uploadedFiles = _.filter(store.state.uploadedFiles, function (uploadedFileName) {\n return uploadedFileName !== fileName;\n });\n\n return {\n uploadedFiles: uploadedFiles,\n canRunImport: uploadedFiles.length > 0\n };\n });\n store.save($delete$);\n };\n }\n\n function importEmissionsData(store) {\n return function () {\n if (!store.state.canRunImport) {\n return;\n }\n\n var calpuffConfigId = store.state.selectedCalpuffConfigId;\n var $save$ = gisModelService.importEmissionsData(calpuffConfigId).then(function () {\n return {\n uploadedFiles: [],\n existingEmissionsDataFiles: [],\n hasImportComplete: true,\n canRunImport: false\n };\n });\n store.save($save$);\n };\n }\n\n function emissionsDataImportCancelled(store) {\n return function () {\n var calpuffConfigId = store.state.selectedCalpuffConfigId;\n var $delete$ = gisModelService.deleteEmissionsDataFiles(calpuffConfigId).then(function () {\n return {\n uploadedFiles: [],\n existingEmissionsDataFiles: [],\n hasImportComplete: false,\n canRunImport: false\n };\n });\n store.save($delete$);\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").controller(\"app.ui.features.configuration.company.modelling.models.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"$state\", \"lodash\", \"promiseTracker\", \"app.core.services.locationService\", \"app.core.services.configuration.gisModelService\", \"modelsState\"];\n\n function ContentPanel($scope, $state, _, promiseTracker, locationService, gisModelService, modelsState) {\n var vm = this;\n vm.listOptions = getListOptions();\n modelsState.loadModels = loadModels;\n activate(); ///////////\n\n function activate() {\n loadModels().then(updateUIWithSelectedModel); ///////////////\n\n function updateUIWithSelectedModel(models) {\n $scope.$watch(function () {\n return $state.params.modelId;\n }, function (modelId) {\n vm.listOptions.selectedItem.value = modelId;\n locationService.updatePageHeading(_.find(models, {\n modelId: modelId\n }));\n });\n }\n }\n\n function getListOptions() {\n return {\n columnDefs: [{\n heading: {\n i18n: {\n key: \"app.ui.features.configuration.company.modelling.models.contentPanel.list.columns.name.heading\"\n }\n },\n field: \"name\"\n }],\n items: [],\n selectedItem: {\n field: \"modelId\",\n value: null\n },\n busyLoading: promiseTracker(),\n onItemSelected: onModelSelected,\n addItem: onAddModel\n };\n }\n\n function onAddModel() {\n $state.go(\"app.configuration.company.modelling.models.add\");\n }\n\n function onModelSelected(model) {\n $state.go(\"app.configuration.company.modelling.models.model.edit\", {\n modelId: model.modelId\n });\n }\n\n function loadModels() {\n var models = gisModelService.getAll().then(function (models) {\n return vm.listOptions.items = models;\n });\n vm.listOptions.busyLoading.addPromise(models);\n return models;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").service(\"app.ui.features.configuration.company.modelling.models.DeleteModal\", DeleteModal);\n DeleteModal.$inject = [\"$state\", \"confirmationDialog\", \"app.core.services.configuration.gisModelService\"];\n\n function DeleteModal($state, confirmationDialog, gisModelService) {\n var headingKey = \"app.ui.features.configuration.company.modelling.models.detailPanel.remove.heading\";\n var descKey = \"app.ui.features.configuration.company.modelling.models.detailPanel.remove.instructions\";\n return {\n open: [\"$stateParams\", openModal]\n }; ////////////////\n\n function openModal($stateParams) {\n var modelId = $stateParams.modelId;\n\n if (!modelId) {\n navigateToModelsList();\n return;\n }\n\n confirmationDialog.ask(headingKey, descKey, {\n css: \"modal-center\"\n }).then(onConfirm).catch(returnToEdit);\n\n function onConfirm() {\n var removalPromise = gisModelService.remove(modelId);\n removalPromise.finally(navigateToModelsList);\n }\n\n function navigateToModelsList() {\n $state.go(\"app.configuration.company.modelling.models\", null, {\n reload: true\n });\n }\n\n function returnToEdit() {\n $state.go(\"app.configuration.company.modelling.models.model.edit\", {\n modelId: modelId\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration.company.modelling\").controller(\"app.ui.features.configuration.company.modelling.models.DetailPanel\", DetailPanel);\n DetailPanel.$inject = [\"$state\", \"lodash\", \"promiseTracker\", \"app.core.services.configuration.gisModelService\", \"modelsState\"];\n\n function DetailPanel($state, _, promiseTracker, gisModelService, modelsState) {\n var vm = this;\n var modelId = $state.params.modelId;\n vm.pollutants = [];\n vm.displayUnits = [];\n vm.isNew = !modelId;\n vm.updateDefaultName = updateDefaultName;\n vm.resetPollutantDependentFields = resetPollutantDependentFields;\n vm.resetField = resetField;\n vm.setModelType = setModelType;\n vm.cancel = cancel;\n vm.save = save;\n vm.remove = remove;\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n activate(); ///////////////////////////////\n\n function activate() {\n vm.model = {};\n var loadingPromise = loadDropDownData();\n\n if (!vm.isNew) {\n loadingPromise = loadingPromise.then(loadExistingModel);\n }\n\n vm.busyLoading.addPromise(loadingPromise);\n\n function loadDropDownData() {\n return gisModelService.getOptions().then(setDropDownDataToVm);\n }\n\n function loadExistingModel() {\n return gisModelService.get(modelId).then(setExistingModelToVm);\n }\n\n function setDropDownDataToVm(options) {\n vm.plumeOptions = {\n pollutants: options.plumeOptions.pollutants,\n windScientificModels: options.plumeOptions.windScientificModels\n };\n vm.windOptions = options.windOptions;\n }\n\n function setExistingModelToVm(model) {\n vm.model.type = model.type;\n vm.model.isPlume = model.type.toLowerCase() === \"plume\";\n vm.model.isWind = model.type.toLowerCase() === \"wind\";\n vm.model.name = model.name;\n vm.model.autoGenerate = model.autoGenerateGisModel;\n\n if (vm.model.isPlume) {\n vm.model.selectedPollutant = _.find(vm.plumeOptions.pollutants, {\n modelPollutantId: model.calpuffConfigPollutantId\n });\n vm.model.selectedDisplayUnit = _.find(vm.model.selectedPollutant.displayUnits, {\n id: model.displayUnitId\n });\n vm.model.selectedAssociatedWindScientificModel = _.find(vm.plumeOptions.windScientificModels, {\n id: model.associatedWindScientificModelId\n });\n vm.model.selectedPlumeScientificModel = _.find(vm.model.selectedPollutant.scientificModels, {\n id: model.scientificModelId\n });\n }\n\n if (vm.model.isWind) {\n vm.model.selectedDisplayUnit = _.find(vm.windOptions.displayUnits, {\n id: model.displayUnitId\n });\n vm.model.selectedWindScientificModel = _.find(vm.windOptions.scientificModels, {\n id: model.scientificModelId\n });\n }\n\n updateDefaultName();\n return model;\n }\n }\n\n function remove() {\n $state.go(\"app.configuration.company.modelling.models.model.delete\", {\n modelId: modelId\n });\n }\n\n function cancel() {\n vm.$form.$setPristine(true);\n activate();\n }\n\n function save() {\n var savingPromise = vm.model.isPlume ? getSavePlumePromise() : getSaveWindPromise();\n savingPromise.then(saveSuccess).then(modelsState.loadModels);\n vm.busySaving.addPromise(savingPromise);\n\n function saveSuccess(modelId) {\n vm.$form.$setPristine(true);\n $state.go(\"app.configuration.company.modelling.models.model.edit\", {\n modelId: modelId\n }, {\n reload: true\n });\n }\n\n function getSavePlumePromise() {\n var plumeModel = {\n id: modelId,\n name: vm.model.name || vm.model.defaultName,\n calpuffConfigPollutantId: vm.model.selectedPollutant.modelPollutantId,\n displayUnitId: vm.model.selectedDisplayUnit.id,\n associatedWindScientificModelId: vm.model.selectedAssociatedWindScientificModel.id,\n intervalDurationInMinutes: vm.model.selectedAssociatedWindScientificModel.intervalDurationInMinutes,\n scientificModelId: vm.model.selectedPlumeScientificModel.id,\n autoGenerateGisModel: vm.model.autoGenerate\n };\n return vm.isNew ? gisModelService.addPlume(plumeModel) : gisModelService.updatePlume(plumeModel);\n }\n\n function getSaveWindPromise() {\n var windModel = {\n id: modelId,\n name: vm.model.name || vm.model.defaultName,\n displayUnitId: vm.model.selectedDisplayUnit.id,\n type: vm.model.type,\n scientificModelId: vm.model.selectedWindScientificModel.id,\n intervalDurationInMinutes: vm.model.selectedWindScientificModel.intervalDurationInMinutes,\n autoGenerateGisModel: vm.model.autoGenerate\n };\n return vm.isNew ? gisModelService.addWind(windModel) : gisModelService.updateWind(windModel);\n }\n }\n\n function setModelType(modelType) {\n vm.model.type = modelType;\n vm.model.isPlume = modelType.toLowerCase() === \"plume\";\n vm.model.isWind = modelType.toLowerCase() === \"wind\";\n vm.$form.$setPristine(true);\n updateDefaultName();\n }\n\n function resetPollutantDependentFields(displayUnitField, plumeScientificModelField) {\n resetField(vm.model.selectedPollutant.displayUnits, function (newValue) {\n return vm.model.selectedDisplayUnit = newValue;\n }, displayUnitField);\n resetField(vm.model.selectedPollutant.scientificModels, function (newValue) {\n return vm.model.selectedPlumeScientificModel = newValue;\n }, plumeScientificModelField);\n updateDefaultName();\n }\n\n function resetField(allowedOptions, funcToSetNewValue, fieldToSetToPristine) {\n if (allowedOptions.length === 1) {\n funcToSetNewValue(allowedOptions[0]);\n } else {\n funcToSetNewValue(null);\n }\n\n fieldToSetToPristine.$setPristine(true);\n }\n\n function updateDefaultName() {\n if (vm.model.isPlume) {\n var pollutant = vm.model.selectedPollutant ? vm.model.selectedPollutant.modelPollutantShortName : \"plume\";\n var displayUnit = vm.model.selectedDisplayUnit ? \" (\".concat(vm.model.selectedDisplayUnit.name, \")\") : \"\";\n var associatedWindScientificModel = vm.model.selectedAssociatedWindScientificModel ? \", \".concat(vm.model.selectedAssociatedWindScientificModel.name) : \"\";\n vm.model.defaultName = pollutant + displayUnit + associatedWindScientificModel;\n } else {\n vm.model.defaultName = vm.model.type;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").factory(\"app.ui.features.configuration.company.modelling.models.state\", stateFactory);\n stateFactory.$inject = [];\n\n function stateFactory() {\n function stateFactoryResolver() {\n return {\n loadModels: angular.noop\n };\n }\n\n return stateFactoryResolver;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.modelling\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.configuration.company.modelling.models.state\", \"app.ui.features.configuration.company.modelling.models.DeleteModal\", \"app.ui.features.configuration.company.modelling.aermet.store\", \"app.ui.features.configuration.company.modelling.emissionsData.store\"];\n\n function appRun(routeHelper, modelsState, deleteModal, aermetStore, emissionsDataStore) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.configuration.company.modelling\",\n abstract: true,\n url: \"/modelling\",\n data: {\n requiredAccessControl: \"app.config.modelling\"\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/modelling/i18n/modelling\", \"/App/core/services/configuration/i18n/gisModelService\"]\n }\n }, {\n state: \"app.configuration.company.modelling.aermet\",\n url: \"/aermet\",\n data: {\n requiredAccessControl: \"app.modelling.run-aermod-modelling\"\n },\n views: {\n 'contentPanel@app': {\n // if we update to ui-router 1.x we can use route to component syntax.\n // https://ui-router.github.io/guide/ng1/route-to-component\n // e.g. component: `modelling.aermet.content-panel`\n template: \"\"\n }\n },\n resolve: {\n store: aermetStore.resolve\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/modelling/aermet/i18n/ContentPanel\"]\n }\n }, {\n state: \"app.configuration.company.modelling.emissionsData\",\n url: \"/emissions-data\",\n views: {\n 'contentPanel@app': {\n template: \"\"\n }\n },\n onEnter: function onEnter() {\n return emissionsDataStore.init();\n },\n onExit: function onExit() {\n return emissionsDataStore.destroy();\n },\n resolve: {\n store: emissionsDataStore.resolve\n },\n settings: {\n i18n: [\"/App/ui/core/controls/i18n/esFileUploader\", \"/App/ui/features/configuration/company/modelling/emissionsData/i18n/ContentPanel\"]\n }\n }, {\n state: \"app.configuration.company.modelling.models\",\n url: \"/models\",\n views: {\n 'contentPanel@app': {\n // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\n templateUrl: \"/App/ui/features/configuration/company/modelling/models/ContentPanel.html\",\n controller: \"app.ui.features.configuration.company.modelling.models.ContentPanel as vm\"\n }\n },\n resolve: {\n modelsState: modelsState\n }\n }, {\n state: \"app.configuration.company.modelling.models.add\",\n url: \"/add\",\n views: {\n 'detailPanel': {\n templateUrl: \"/App/ui/features/configuration/company/modelling/models/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.modelling.models.DetailPanel as vm\"\n }\n }\n }, {\n abstract: true,\n state: \"app.configuration.company.modelling.models.model\",\n url: \"/:modelId\",\n views: {\n 'detailPanel': {\n templateUrl: \"/App/ui/features/configuration/company/modelling/models/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.modelling.models.DetailPanel as vm\"\n }\n }\n }, {\n state: \"app.configuration.company.modelling.models.model.edit\",\n url: \"/edit\"\n }, {\n state: \"app.configuration.company.modelling.models.model.delete\",\n url: \"/delete\",\n onEnter: deleteModal.open\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.measurementGroups.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"$state\", \"lodash\", \"i18n\", \"app.core.services.locationService\", \"app.core.services.configuration.measurementGroupService\"];\n\n function ContentPanel($scope, $state, _, i18n, locationService, measurementGroupService) {\n var vm = this;\n vm.gridOptions = getGridOptions();\n activate(); ///////////\n\n function activate() {\n $scope.$watch(function () {\n return $state.params.measurementGroupId;\n }, function (measurementGroupId) {\n return vm.gridOptions.selectedId = measurementGroupId;\n });\n }\n\n function getGridOptions() {\n return {\n dataProvider: getMeasurementGroups,\n rowCallback: onSelectMeasurementGroup,\n addItem: addMeasurementGroup,\n sortable: false,\n columns: [{\n field: \"description\",\n title: i18n.i10n(\"app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.heading\"),\n dataType: \"string\"\n }, {\n field: \"defaultOrder\",\n title: \"Default Order\",\n hidden: true,\n sort: {\n order: 1,\n dir: \"asc\"\n }\n }, {\n format: i18n.i10n(\"app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.list.columns.command\"),\n click: function click(measurementGroup) {\n return $state.go(\"app.configuration.company.monitoring.measurementGroups.measurementGroup.delete\", {\n measurementGroupId: measurementGroup.id\n });\n },\n title: \" \",\n width: 100\n }],\n onDataBound: handleDataBound\n };\n }\n\n function getMeasurementGroups(searchCriteria) {\n return measurementGroupService.queryMeasurementGroups(searchCriteria).then(function (result) {\n if (vm.gridOptions.selectedId) {\n var selectedItem = _.find(result.data, function (measurementGroup) {\n return measurementGroup.id === vm.gridOptions.selectedId;\n });\n\n locationService.updatePageHeading(selectedItem);\n }\n\n var byId = _.reduce(result.data, function (map, mg) {\n return map.set(mg.id, mg);\n }, new Map());\n\n result.data = _.chain(result.data).map(function (mg) {\n // If this is a child measurement group, change the order so that it will appear underneath\n // its parent measurement group.\n var parent = byId.get(mg.parentId);\n\n if (parent) {\n mg.defaultOrder = parseFloat(\"\".concat(parent.defaultOrder, \".\").concat(byId.size - mg.defaultOrder));\n }\n\n return mg;\n }).sortBy(function (mg) {\n return mg.defaultOrder;\n }).value();\n return result;\n });\n }\n\n function onSelectMeasurementGroup(measurementGroup) {\n locationService.updatePageHeading(measurementGroup);\n $state.go(\"app.configuration.company.monitoring.measurementGroups.measurementGroup.edit\", {\n measurementGroupId: measurementGroup.id\n });\n }\n\n function addMeasurementGroup() {\n $state.go(\"app.configuration.company.monitoring.measurementGroups.add\");\n }\n\n function handleDataBound(event) {\n // This is pretty much the only way that we can style individual cells in a kendo grid.\n // See: https://docs.telerik.com/kendo-ui/knowledge-base/style-rows-cells-based-on-data-item-values\n var _event$sender = event.sender,\n dataSource = _event$sender.dataSource,\n tbody = _event$sender.tbody;\n var dataItems = dataSource.view();\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = dataItems[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var dataItem = _step.value;\n var isChild = !!dataItem.parentId;\n\n if (isChild) {\n var row = tbody.find(\"[data-uid='\".concat(dataItem.uid, \"']\"));\n row.addClass(\"child-measurement-group\");\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").service(\"app.ui.features.configuration.company.monitoring.measurementGroups.DeleteModal\", DeleteModal);\n DeleteModal.$inject = [\"$state\", \"$q\", \"confirmationDialog\", \"app.core.services.configuration.measurementGroupService\"];\n\n function DeleteModal($state, $q, confirmationDialog, measurementGroupService) {\n return {\n open: [\"$stateParams\", openModal]\n }; ////////////////\n\n function openModal($stateParams) {\n var measurementGroupId = $stateParams.measurementGroupId;\n\n if (!measurementGroupId) {\n navigateToMeasurementGroupsList();\n return;\n }\n\n $q.all([isInUse(), hasChildren()]).then(function () {\n var confirmRemove = \"app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.remove\";\n confirmationDialog.ask(\"\".concat(confirmRemove, \".heading\"), \"\".concat(confirmRemove, \".body\")).then(function () {\n return measurementGroupService.deleteMeasurementGroup(measurementGroupId);\n }).then(navigateToMeasurementGroupsList).catch(returnToEdit);\n }).catch(returnToEdit).finally(returnToEdit);\n\n function isInUse() {\n return measurementGroupService.isMeasurementGroupBeingUsed(measurementGroupId).then(function (response) {\n if (!response) {\n return;\n }\n\n var removeExisting = \"app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.remove.existing\";\n return confirmationDialog.notify(\"\".concat(removeExisting, \".heading\"), \"\".concat(removeExisting, \".body\")).finally(function () {\n return $q.reject(\"Measurement group in use\");\n });\n });\n }\n\n function hasChildren() {\n return measurementGroupService.getMeasurementGroupChildCount(measurementGroupId).then(function (response) {\n if (response === 0) {\n return;\n }\n\n var removeParent = \"app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.remove.parent\";\n return confirmationDialog.notify(\"\".concat(removeParent, \".heading\"), \"\".concat(removeParent, \".body\")).finally(function () {\n return $q.reject(\"Measurement group is a parent\");\n });\n });\n }\n\n function returnToEdit() {\n $state.go(\"app.configuration.company.monitoring.measurementGroups.measurementGroup.edit\", {\n measurementGroupId: measurementGroupId\n });\n }\n\n function navigateToMeasurementGroupsList() {\n $state.go(\"app.configuration.company.monitoring.measurementGroups\", null, {\n reload: true\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.measurementGroups.DetailPanel\", DetailPanel);\n DetailPanel.$inject = [\"$scope\", \"$state\", \"lodash\", \"promiseTracker\", \"app.core.services.configuration.measurementGroupService\"];\n\n function DetailPanel($scope, $state, _, promiseTracker, measurementGroupService) {\n var vm = this;\n var measurementGroupId = $state.params.measurementGroupId;\n vm.isNew = !measurementGroupId;\n vm.$form = undefined;\n vm.measurementGroupDescription = \"\";\n vm.measurementGroupDefaultOrder = 0;\n vm.measurementGroupParentId = null;\n vm.measurementGroupCanHaveParent = true;\n var measurementGroupsNested = [];\n vm.parents = [];\n vm.busySaving = promiseTracker();\n vm.busyLoading = promiseTracker();\n vm.save = save;\n vm.cancel = cancel;\n activate(); ///////////////////\n\n function activate() {\n loadMeasurementGroups();\n updateOrderWhenParentChanges();\n }\n\n function loadMeasurementGroups() {\n var loadingPromise = measurementGroupService.getMeasurementGroupsNested().then(function (measurementGroups) {\n measurementGroupsNested = measurementGroups;\n getPotentialParentMeasurementGroups();\n\n if (vm.isNew) {\n vm.measurementGroupDefaultOrder = getNextDefaultOrder(measurementGroups);\n } else {\n getMeasurementGroupToEdit();\n } ////////////////////\n\n\n function getPotentialParentMeasurementGroups() {\n vm.parents = _.chain(measurementGroups).filter(function (mg) {\n return !mg.parentId && mg.id !== $state.params.measurementGroupId;\n }).sortBy(function (mg) {\n return mg.description;\n }).value();\n }\n\n function getMeasurementGroupToEdit() {\n var editGroup = null; // Find the measurement group to edit - it may be a child of another measurement group.\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = measurementGroups[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var mg = _step.value;\n editGroup = mg.id === $state.params.measurementGroupId ? mg : _.find(mg.children, function (child) {\n return child.id === $state.params.measurementGroupId;\n });\n\n if (editGroup) {\n break;\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n if (editGroup) {\n vm.measurementGroupDescription = editGroup.description;\n vm.measurementGroupDefaultOrder = editGroup.defaultOrder;\n vm.measurementGroupParentId = editGroup.parentId;\n vm.measurementGroupCanHaveParent = !(editGroup.children && editGroup.children.length);\n }\n }\n });\n vm.busyLoading.addPromise(loadingPromise);\n }\n\n function updateOrderWhenParentChanges() {\n $scope.$watch(function () {\n return vm.measurementGroupParentId;\n }, function (parentId, oldParentId) {\n if (parentId === oldParentId) {\n return;\n }\n\n if (!parentId) {\n vm.measurementGroupDefaultOrder = getNextDefaultOrder(measurementGroupsNested);\n } else {\n var parent = _.find(measurementGroupsNested, function (measurementGroup) {\n return measurementGroup.id === parentId;\n });\n\n vm.measurementGroupDefaultOrder = getNextDefaultOrder(parent.children);\n }\n });\n }\n\n function getNextDefaultOrder(measurementGroups) {\n // The default order for a new measurement group has to be one higher than the previously\n // existing highest order.\n var measurementGroupWithHighestDefaultOrder = findHighestDefaultOrderRecursive(measurementGroups);\n\n if (measurementGroupWithHighestDefaultOrder === null) {\n return 1;\n }\n\n return measurementGroupWithHighestDefaultOrder.id !== measurementGroupId ? measurementGroupWithHighestDefaultOrder.defaultOrder + 1 : measurementGroupWithHighestDefaultOrder.defaultOrder; ////////////////////\n\n function findHighestDefaultOrderRecursive(measurementGroups) {\n if (!(measurementGroups && measurementGroups.length)) {\n return null;\n }\n\n return measurementGroups.reduce(function (max, measurementGroup) {\n return findHighestDefaultOrder(max, measurementGroup, findHighestDefaultOrderRecursive(measurementGroup.children));\n });\n }\n\n function findHighestDefaultOrder() {\n for (var _len = arguments.length, measurementGroups = new Array(_len), _key = 0; _key < _len; _key++) {\n measurementGroups[_key] = arguments[_key];\n }\n\n return measurementGroups.reduce(function (max, measurementGroup) {\n if (max && measurementGroup) {\n return max.defaultOrder > measurementGroup.defaultOrder ? max : measurementGroup;\n }\n\n return max ? max : measurementGroup;\n });\n }\n }\n\n function save() {\n var measurementGroup = {\n id: measurementGroupId,\n description: vm.measurementGroupDescription,\n defaultOrder: vm.measurementGroupDefaultOrder,\n parentId: vm.measurementGroupParentId || null\n };\n var savingPromise = vm.isNew ? measurementGroupService.createMeasurementGroup(measurementGroup) : measurementGroupService.updateMeasurementGroup(measurementGroup);\n savingPromise.then(function (measurementGroupId) {\n vm.$form.$setPristine(true);\n $state.go(\"app.configuration.company.monitoring.measurementGroups.measurementGroup.edit\", {\n measurementGroupId: measurementGroupId\n }, {\n reload: true\n });\n });\n vm.busySaving.addPromise(savingPromise);\n }\n\n function cancel() {\n activate();\n vm.$form.$setPristine(true);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").factory(\"app.ui.features.configuration.company.monitoring.measurementGroups.state\", stateFactory);\n stateFactory.$inject = [];\n\n function stateFactory() {\n return function () {\n return {};\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"$state\", \"lodash\", \"i18n\", \"app.core.services.locationService\", \"app.core.services.configuration.monitoringService\"];\n\n function ContentPanel($scope, $state, _, i18n, locationService, monitoringService) {\n var vm = this;\n vm.gridOptions = getGridOptions();\n activate(); ///////////\n\n function activate() {\n $scope.$watch(function () {\n return $state.params.monitorId;\n }, function (monitorId) {\n return vm.gridOptions.selectedId = monitorId;\n });\n }\n\n function getGridOptions() {\n return {\n dataProvider: getMonitors,\n rowCallback: onSelectMonitor,\n addItem: onAddMonitor,\n columns: [{\n field: \"name\",\n title: i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.contentPanel.list.columns.name.heading\"),\n dataType: \"string\",\n sort: {\n order: 1,\n dir: \"asc\"\n },\n template: \"
      #: name#
      \"\n }]\n };\n }\n\n function getMonitors(searchCriteria) {\n return monitoringService.queryMonitors(searchCriteria).then(function (result) {\n if (vm.gridOptions.selectedId) {\n var selectedItem = _.find(result.data, function (monitor) {\n return monitor.id === vm.gridOptions.selectedId;\n });\n\n locationService.updatePageHeading(selectedItem);\n }\n\n return result;\n });\n }\n\n function onSelectMonitor(monitor) {\n locationService.updatePageHeading(monitor);\n var aSelectedMonitorRoute = \"app.configuration.company.monitoring.monitors.tabs.monitor\";\n var aMeasurementTypeRoute = \"\".concat(aSelectedMonitorRoute, \".measurementTypes\");\n var aDataImportRoute = \"\".concat(aSelectedMonitorRoute, \".dataImport\");\n var detailsRoute = \"\".concat(aSelectedMonitorRoute, \".details\");\n var route = $state.$current.name; // we'll try and keep the user on the monitor route they are already on.\n\n if ($state.$current.name.indexOf(aMeasurementTypeRoute) >= 0) {\n // take off edit/delete route portion if it exists\n route = aMeasurementTypeRoute;\n } else if ($state.$current.name.indexOf(aDataImportRoute) >= 0) {\n route = aDataImportRoute;\n } else if ($state.$current.name.indexOf(aSelectedMonitorRoute) === -1) {\n // e.g. add monitor, list monitors routes\n route = detailsRoute;\n }\n\n $state.go(route, {\n monitorId: monitor.id\n });\n }\n\n function onAddMonitor() {\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.add\");\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").directive(\"esMeasurementTypeThresholds\", directive);\n\n function directive() {\n return {\n restrict: \"E\",\n scope: {\n measurementType: \"=\",\n unitTypes: \"=\",\n isSubmitted: \"=\"\n },\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/controls/esMeasurementTypeThresholds.html\",\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n controller.$inject = [\"$scope\", \"$timeout\", \"lodash\", \"promiseTracker\", \"app.core.services.mathService\"];\n\n function controller($scope, $timeout, _, promiseTracker, math) {\n var vm = this;\n var baseValue = math.floatMinValue;\n var thresholdColours = {\n green: \"#679B38\",\n yellow: \"#C58B32\",\n brown: \"#C05022\",\n red: \"#EF190F\",\n purple: \"#FF00F9\"\n };\n vm.colourPalette = _.values(thresholdColours);\n vm.addThreshold = addThreshold;\n vm.removeThreshold = removeThreshold;\n vm.validateThresholdColour = validateThresholdColour;\n vm.validateThresholdValue = validateThresholdValue;\n vm.influenceArcDisplayThresholdBaseValue = baseValue;\n vm.influenceArcDisplayThresholdMaxValue = -1 * baseValue;\n vm.setInfluenceArcThreshold = setInfluenceArcThreshold;\n vm.defaultDisplayUnitName = \"\";\n vm.busyLoading = promiseTracker();\n activate(); ////////////////////\n\n function activate() {\n $scope.$watch(function () {\n return vm.measurementType.defaultDisplayUnitId;\n }, function (displayUnitId) {\n if (!displayUnitId) {\n return;\n }\n\n updateBaseThreshold();\n setInfluenceArcThreshold();\n updateDisplayUnitText(displayUnitId);\n });\n\n function updateDisplayUnitText(displayUnitId) {\n var displayUnit = _.find(vm.unitTypes, {\n id: displayUnitId\n }); // Cater for PVs that have been set up incorrectly, where their display unit is not\n // available for the selected process variable type.\n\n\n vm.defaultDisplayUnitName = displayUnit && displayUnit.name || null;\n }\n\n function updateBaseThreshold() {\n var baseThreshold = _.find(vm.measurementType.exceedanceThresholds, {\n valueInBaseUnit: baseValue\n });\n\n if (!baseThreshold) {\n baseThreshold = {\n valueInBaseUnit: baseValue,\n valueInDisplayUnit: baseValue,\n hexColor: thresholdColours.green,\n description: \"Base Value\"\n };\n vm.measurementType.exceedanceThresholds.unshift(baseThreshold);\n }\n }\n }\n\n function validateThresholdValue(threshold) {\n var $index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var thirdPartyCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n var previousThresholdValue = $index === 0 ? undefined : vm.measurementType.exceedanceThresholds[$index - 1].valueInDisplayUnit;\n var isThresholdValid = _.isNumber(threshold.valueInDisplayUnit) && (previousThresholdValue === undefined || threshold.valueInDisplayUnit > previousThresholdValue);\n vm.$form[\"threshold-value-\".concat($index)].$setValidity(\"threshold-value-validator\", isThresholdValid);\n\n _.forEach(vm.measurementType.exceedanceThresholds, function (value, index) {\n if (index === $index || thirdPartyCheck) {\n return;\n }\n\n validateThresholdValue(vm.measurementType.exceedanceThresholds[index], index, true);\n });\n }\n\n function validateThresholdColour() {\n var uniqueColours = _.chain(vm.measurementType.exceedanceThresholds).map(\"hexColor\").map(function (hexColor) {\n return hexColor.toUpperCase();\n }).uniq().value();\n\n vm.hasDuplicateThresholdColour = uniqueColours.length !== vm.measurementType.exceedanceThresholds.length;\n }\n\n function setInfluenceArcThreshold() {\n var thresholdType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getThresholdType();\n vm.arcThresholdType = thresholdType;\n\n switch (thresholdType) {\n case \"always\":\n vm.measurementType.influenceArcDisplayThreshold = vm.influenceArcDisplayThresholdBaseValue;\n break;\n\n case \"never\":\n vm.measurementType.influenceArcDisplayThreshold = vm.influenceArcDisplayThresholdMaxValue;\n break;\n\n case \"custom\":\n if (hasExistingCustomThresholdValue()) {\n break;\n }\n\n vm.measurementType.influenceArcDisplayThreshold = vm.measurementType.exceedanceThresholds.length > 1 ? vm.measurementType.exceedanceThresholds[1].valueInDisplayUnit : null;\n }\n\n function hasExistingCustomThresholdValue() {\n return vm.measurementType.influenceArcDisplayThreshold !== vm.influenceArcDisplayThresholdBaseValue && vm.measurementType.influenceArcDisplayThreshold !== vm.influenceArcDisplayThresholdMaxValue && vm.measurementType.influenceArcDisplayThreshold !== undefined && vm.measurementType.influenceArcDisplayThreshold !== null;\n }\n }\n\n function getThresholdType() {\n if (vm.measurementType.influenceArcDisplayThreshold === null || vm.measurementType.influenceArcDisplayThreshold === undefined || vm.measurementType.influenceArcDisplayThreshold === vm.influenceArcDisplayThresholdBaseValue) {\n return \"always\";\n } else if (vm.measurementType.influenceArcDisplayThreshold === vm.influenceArcDisplayThresholdMaxValue) {\n return \"never\";\n } else {\n return \"custom\";\n }\n }\n\n function addThreshold() {\n if (vm.measurementType.exceedanceThresholds.length >= 5) {\n return;\n }\n\n var newThreshold = {\n valueInBaseUnit: undefined,\n valueInDisplayUnit: undefined,\n hexColor: vm.colourPalette[vm.measurementType.exceedanceThresholds.length]\n };\n vm.measurementType.exceedanceThresholds.push(newThreshold);\n $timeout(function () {\n return validateThresholdColour();\n });\n vm.$form.$setDirty();\n }\n\n function removeThreshold(index) {\n if (vm.measurementType.exceedanceThresholds.length <= 1) {\n return;\n }\n\n vm.measurementType.exceedanceThresholds.splice(index, 1);\n $timeout(function () {\n return validateThresholdColour();\n });\n vm.$form.$setDirty();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").directive(\"esMonitorVariableDisplay\", directive);\n directive.$inject = [];\n\n function directive() {\n return {\n restrict: \"A\",\n scope: {},\n bindToController: {\n processVariable: \"=esMonitorVariableDisplay\",\n sortable: \"=\",\n state: \"=\"\n },\n controllerAs: \"vm\",\n controller: controller,\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/controls/esMonitorVariableDisplay.html\"\n };\n }\n\n controller.$inject = [\"$scope\", \"lodash\"];\n\n function controller($scope, _) {\n var vm = this;\n activate();\n\n function activate() {\n vm.selectedMeasurementGroup = _.find(vm.state.measurementGroups, {\n id: vm.processVariable.measurementGroupId\n });\n $scope.$watch(function () {\n return vm.selectedMeasurementGroup;\n }, function () {\n vm.processVariable.measurementGroupId = vm.selectedMeasurementGroup && vm.selectedMeasurementGroup.id || null;\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").directive(\"esMonitorVariablePreferences\", directive);\n directive.$inject = [\"lodash\"];\n\n function directive(_) {\n return {\n restrict: \"A\",\n scope: {\n sortables: \"=esMonitorVariablePreferences\",\n state: \"=\"\n },\n link: link,\n controllerAs: \"vm\",\n bindToController: true,\n controller: controller,\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/controls/esMonitorVariablePreferences.html\"\n };\n\n function link($scope, $element, attrs, vm) {\n $scope.$watch(function () {\n return vm.sortables;\n }, function (sortables) {\n vm.sortableOptions = _.map(sortables, function (sortable, index) {\n switch (index) {\n case 0:\n sortable.listId = \"list-available\";\n break;\n\n case 1:\n sortable.listId = \"list-display\";\n break;\n\n case 2:\n sortable.listId = \"list-graph\";\n break;\n }\n\n return getSortableOptions(sortable);\n });\n });\n\n function getSortableOptions(sortable) {\n return {\n connectWith: \".connected-apps-container\",\n over: function over(event, ui) {\n var sourceList = ui.item.sortable.sourceModel;\n var item = ui.item.sortable.model;\n\n if (!draggingFromAvailableList() && !reorderingInSameList()) {\n addDangerZone();\n return;\n }\n\n if (!reorderingInSameList() && notInTheAvailableListEventHandler()) {\n var processVariableExistsInTargetList = _.find(sortable.items, {\n id: item.id\n });\n\n if (processVariableExistsInTargetList) {\n addDangerZone();\n return;\n }\n }\n\n addDropZone();\n\n function notInTheAvailableListEventHandler() {\n return sortable.listId !== \"list-available\";\n }\n\n function reorderingInSameList() {\n return sourceList === sortable.items;\n }\n\n function draggingFromAvailableList() {\n return sourceList === vm.sortables[0].items;\n }\n },\n out: function out() {\n removeDangerZone();\n removeDropZone();\n },\n update: function update(event, ui) {\n var sourceList = ui.item.sortable.sourceModel;\n var item = sourceList[ui.item.sortable.index];\n removeDangerZone();\n removeDropZone();\n\n if (!ui.item.sortable.received) {\n if (reorderingInTheSameList()) {\n return; // allow drag n drop\n }\n\n if (draggingFromAvailableList()) {\n var processVariableExistsInTargetList = _.find(ui.item.sortable.droptargetModel, {\n id: item.id\n });\n\n if (!processVariableExistsInTargetList) {\n return; // allow drag n drop.\n }\n }\n\n ui.item.sortable.cancel();\n }\n\n function reorderingInTheSameList() {\n return ui.item.sortable.sourceModel === ui.item.sortable.droptargetModel;\n }\n\n function draggingFromAvailableList() {\n return sourceList === vm.sortables[0].items;\n }\n },\n stop: function stop(event, ui) {\n if (droppingAvailableVariableIntoAnotherList()) {\n refreshAvailableListWithAllAvailableProcessVariables();\n }\n\n function droppingAvailableVariableIntoAnotherList() {\n return event.target.id === \"list-available\" && ui.item.sortable.droptarget && event.target !== ui.item.sortable.droptarget[0];\n }\n\n function refreshAvailableListWithAllAvailableProcessVariables() {\n vm.sortables[0].items = vm.refreshAvailableProcessVariables();\n }\n }\n };\n\n function removeDangerZone() {\n removeClass(\"danger-zone\");\n }\n\n function addDangerZone() {\n addClass(\"danger-zone\");\n }\n\n function removeDropZone() {\n removeClass(\"drop-zone\");\n }\n\n function addDropZone() {\n addClass(\"drop-zone\");\n }\n\n function addClass(className) {\n var $list = $element.find(\"#\".concat(sortable.listId));\n $list.addClass(className);\n }\n\n function removeClass(className) {\n var $list = $element.find(\"#\".concat(sortable.listId));\n $list.removeClass(className);\n }\n }\n }\n }\n\n controller.$inject = [\"$scope\", \"lodash\"];\n\n function controller($scope, _) {\n var vm = this;\n var availableProcessVariables;\n vm.refreshAvailableProcessVariables = refreshAvailableProcessVariables;\n vm.remove = remove;\n activate();\n\n function activate() {\n $scope.$watchCollection(function () {\n return vm.sortables;\n }, cloneTheAvailableProcessVariables);\n\n function cloneTheAvailableProcessVariables() {\n if (vm.sortables[0] && vm.sortables[0].items && !availableProcessVariables) {\n availableProcessVariables = _toConsumableArray(vm.sortables[0].items); // clone the array\n }\n }\n }\n\n function remove(index, itemIndex) {\n vm.sortables[index].items.splice(itemIndex, 1);\n }\n\n function refreshAvailableProcessVariables() {\n return availableProcessVariables.map(function (pv) {\n return _.assign({}, pv);\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n var directiveName = \"esRequireUniqueMeasurementGroupSelection\";\n angular.module(\"app.ui.features.configuration.company.monitoring\").directive(directiveName, validator);\n validator.$inject = [\"lodash\"];\n\n function validator(_) {\n return {\n restrict: \"A\",\n require: \"ngModel\",\n scope: {\n isValidationRequired: \"=\".concat(directiveName),\n sortable: \"=\"\n },\n link: link\n };\n\n function link($scope, $element, $attrs, ngModel) {\n $scope.$watch(function () {\n return $scope.isValidationRequired;\n }, validateUniqueMeasurementGroup);\n $scope.$watch(function () {\n return ngModel.$modelValue;\n }, validateUniqueMeasurementGroup, true);\n\n function validateUniqueMeasurementGroup() {\n var isValid = !$scope.isValidationRequired;\n\n if ($scope.isValidationRequired) {\n var selectedMeasurementGroup = ngModel.$modelValue;\n isValid = !selectedMeasurementGroup || _.filter($scope.sortable.items, {\n measurementGroupId: selectedMeasurementGroup.id\n }).length <= 1;\n }\n\n ngModel.$setValidity(\"uniqueMeasurementGroup\", isValid);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.DataImportTab\", DataImportTab);\n DataImportTab.$inject = [\"$scope\", \"$state\", \"promiseTracker\", \"i18n\", \"app.core.services.securityService\", \"dataImportState\"];\n\n function DataImportTab($scope, $state, promiseTracker, i18n, securityService, dataImportState) {\n var vm = this;\n var searchCriteria = {\n take: 0,\n pageSize: 0,\n sort: [{\n field: \"description\",\n dir: \"asc\",\n order: 1\n }]\n };\n vm.monitorId = $state.params.monitorId;\n vm.apiCredentialId = $state.params.apiCredentialId;\n vm.$form = null;\n vm.busySaving = promiseTracker();\n vm.busyLoading = promiseTracker();\n vm.apiCredentials = undefined;\n vm.apiCredentialsDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.monitor.dataImport.fields.credential.defaultValue\");\n vm.onSelectApiCredential = onSelectApiCredential;\n vm.onCreateApiCredential = onCreateApiCredential;\n activate(); /////////////////\n\n function activate() {\n registerForStateEvents();\n var loadingPromise = securityService.queryApiCredentials(vm.monitorId, searchCriteria).then(function (apiCredentials) {\n return vm.apiCredentials = apiCredentials;\n });\n vm.busyLoading.addPromise(loadingPromise); /////////////////////\n\n function registerForStateEvents() {\n $scope.$on(dataImportState.events.loading, function (event, loadingPromise) {\n return vm.busyLoading.addPromise(loadingPromise);\n });\n $scope.$on(dataImportState.events.saving, function (event, savingPromise) {\n return vm.busySaving.addPromise(savingPromise);\n });\n }\n }\n\n function onSelectApiCredential(apiCredentialId) {\n if (apiCredentialId) {\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential.edit\", {\n apiCredentialId: apiCredentialId\n });\n } else {\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport\");\n }\n }\n\n function onCreateApiCredential() {\n vm.apiCredentialId = null;\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.add\");\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.dataImport.DataImportTabEditPanel\", DataImportTabEditPanel);\n DataImportTabEditPanel.$inject = [\"$scope\", \"$state\", \"$q\", \"lodash\", \"app.core.errorService\", \"app.core.services.securityService\", \"monitorTabs\", \"dataImportState\", \"app.core.appSettings\"];\n\n function DataImportTabEditPanel($scope, $state, $q, _, errorService, securityService, monitorTabs, dataImportState, appSettings) {\n var _vm$accessControls;\n\n var vm = this;\n var emptyGuid = \"00000000-0000-0000-0000-000000000000\";\n vm.accessControls = (_vm$accessControls = {}, _defineProperty(_vm$accessControls, \"api.monitoring.data.read\", false), _defineProperty(_vm$accessControls, \"api.monitoring.data.write\", false), _vm$accessControls); // the access controls that a monitor can be assigned to\n\n vm.isNew = undefined;\n vm.isEdit = undefined;\n vm.apiCredential = undefined;\n vm.isActive = true;\n vm.cancel = cancel;\n vm.save = save;\n vm.toggleIsEnabled = toggleIsEnabled;\n activate(); /////////////////\n\n function activate() {\n vm.isNew = !$state.params.apiCredentialId;\n vm.isEdit = !vm.isNew;\n $scope.$watch(function () {\n return vm.$form.$dirty;\n }, function () {\n return monitorTabs.dataImport.isDirty = vm.$form.$dirty;\n });\n var loadingPromises = [];\n\n if (vm.isEdit) {\n var loadingCredentialPromise = securityService.getApiCredential($state.params.apiCredentialId).then(function (apiCredential) {\n vm.apiCredential = apiCredential;\n vm.isEnabled = apiCredential.deactivatedTime === null;\n\n _.forOwn(vm.accessControls, function (value, key) {\n vm.accessControls[key] = _.has(apiCredential.overrideAccessControls, key) ? apiCredential.overrideAccessControls[key] : vm.accessControls[key];\n });\n }).catch(function (response) {\n errorService.processError(response);\n $state.go(\"app.configuration.company.monitoring.monitors\");\n });\n loadingPromises.push(loadingCredentialPromise);\n } else {\n initialiseForm();\n }\n\n $scope.$emit(dataImportState.events.loading, $q.all(loadingPromises));\n }\n\n function initialiseForm() {\n vm.apiCredential = {\n id: $state.params.apiCredentialId,\n processId: $state.params.monitorId,\n apiKey: emptyGuid,\n requiresSecureConnection: true,\n deactivatedTime: null,\n overrideAccessControls: _extends({}, vm.accessControls)\n };\n vm.isEnabled = vm.apiCredential.deactivatedTime === null;\n }\n\n function cancel() {\n activate();\n vm.$form.$setPristine();\n }\n\n function save() {\n if (vm.$form.$invalid || !vm.$form.$dirty) {\n return;\n }\n\n vm.apiCredential.overrideAccessControls = _extends({}, vm.accessControls);\n var savingPromise = persistApiCredential();\n savingPromise.then(saveSuccess);\n $scope.$emit(dataImportState.events.saving, savingPromise);\n\n function persistApiCredential() {\n return vm.isNew ? securityService.createApiCredential(vm.apiCredential) : securityService.updateApiCredential(vm.apiCredential);\n }\n\n function saveSuccess(apiCredentialId) {\n vm.$form.$setPristine();\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential.edit\", {\n apiCredentialId: apiCredentialId\n }, {\n reload: true\n });\n }\n }\n\n function toggleIsEnabled() {\n vm.apiCredential.deactivatedTime = vm.isEnabled ? null : new Date();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.DetailPanel\", DetailPanel);\n DetailPanel.$inject = [\"monitorTabs\"];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function DetailPanel(monitorTabs) {\n var vm = this;\n vm.tabs = monitorTabs;\n activate(); ///////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.DetailsTab\", DetailsTab);\n DetailsTab.$inject = [\"$scope\", \"$state\", \"lodash\", \"i18n\", \"$q\", \"$timeout\", \"promiseTracker\", \"Utm\", \"LatLon\", \"app.core.mapDefaults\", \"app.core.appSettings\", \"app.core.errorService\", \"app.core.services.configuration.monitoringService\", \"app.core.services.mappingService\", \"monitorTabs\", \"detailsState\"];\n\n function DetailsTab($scope, $state, _, i18n, $q, $timeout, promiseTracker, Utm, LatLon, mapDefaults, appSettings, errorService, monitoringService, mappingService, monitorTabs, detailsState) {\n var vm = this;\n var formIsReady = false;\n vm.isNew = !$state.params.monitorId;\n vm.isEdit = !vm.isNew;\n vm.configurationOptions = detailsState.configurationOptions;\n vm.configurationOptions.typeDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.detailsTab.fields.type.defaultValue\");\n vm.configurationOptions.timeZoneDefaultValue = {\n id: null,\n description: i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.detailsTab.fields.timeZone.defaultValue\")\n };\n var monitorTemplate = \"
      {{ dataItem.name }}
      \";\n vm.configurationOptions.monitorTypeGridOptions = {\n valueTemplate: monitorTemplate,\n template: monitorTemplate,\n change: onMonitorTypeChanged\n };\n vm.configurationOptions.preferredWeatherMonitoringStationDefaultValue = {\n monitorId: null,\n name: i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.detailsTab.fields.preferredWeatherMonitoringStation.defaultValue\")\n };\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n vm.cancel = cancel;\n vm.save = save;\n var unwatchUtm = angular.noop;\n activate(); //////////////////\n\n function activate() {\n initialiseForm();\n $scope.$watch(function () {\n return vm.$form.$dirty;\n }, function () {\n return monitorTabs.details.isDirty = vm.$form.$dirty;\n });\n $scope.$watch(function () {\n return vm.busyLoading.active();\n }, function (isBusyLoading) {\n return monitorTabs.details.isBusyLoading = isBusyLoading;\n });\n var latlongWatches = [function () {\n return vm.monitor.latitude;\n }, function () {\n return vm.monitor.longitude;\n }];\n $scope.$watchGroup(latlongWatches, function () {\n if (!vm.monitor.latitude || !vm.monitor.longitude) {\n return;\n }\n\n updateMap();\n updateElevation();\n\n if (formIsReady) {\n vm.$form.latitude.$setDirty();\n vm.$form.longitude.$setDirty();\n }\n });\n $scope.$watch(function () {\n return vm.gcs;\n }, function () {\n if (vm.gcs === \"latlong\") {\n unwatchUtm();\n $scope.$watchGroup(latlongWatches, updateUtm);\n } else {\n unwatchUtm = $scope.$watch(function () {\n return vm.utm;\n }, updateLatLong, true);\n }\n });\n\n if (vm.isNew) {\n $timeout(function () {\n return formIsReady = true;\n });\n }\n\n if (vm.isEdit) {\n var getMonitorType = monitoringService.getMonitorType(vm.monitor.id).then(function (type) {\n vm.monitor.type = type;\n var getMonitor = monitoringService.getMonitor(type, vm.monitor.id);\n var getMonitorLocation = monitoringService.getMonitorLocation(vm.monitor.id);\n var loadingPromise = $q.all([getMonitor, getMonitorLocation]).then(function (results) {\n _.assign(vm.monitor, results[0], results[1]);\n\n $timeout(function () {\n return formIsReady = true;\n });\n }).catch(function (response) {\n errorService.processError(response);\n $state.go(\"app.configuration.company.monitoring.monitors\");\n });\n vm.busyLoading.addPromise(loadingPromise);\n });\n vm.busyLoading.addPromise(getMonitorType);\n }\n }\n\n function initialiseForm() {\n formIsReady = false;\n\n if (vm.timeZoneDDL) {\n vm.timeZoneDDL.value(\"\");\n vm.timeZoneDDL.trigger(\"change\");\n }\n\n if (vm.monitorTypeDDL) {\n vm.monitorTypeDDL.value(\"\");\n vm.monitorTypeDDL.trigger(\"change\");\n }\n\n vm.gcs = \"latlong\";\n vm.utm = {\n hemisphere: \"N\"\n };\n vm.map = {\n centre: detailsState.configurationOptions.facilityLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n layers: {\n baselayers: mapDefaults.baselayers\n }\n };\n vm.monitor = {\n id: $state.params.monitorId,\n type: undefined,\n isVisible: true,\n windowsTimeZoneId: appSettings.site.facility.windowsTimeZoneId\n };\n }\n\n function cancel() {\n activate();\n vm.$form.$setPristine();\n }\n\n function save() {\n var savingPromise = persistMonitor();\n savingPromise.then(saveSuccess);\n vm.busySaving.addPromise(savingPromise);\n\n function persistMonitor() {\n return vm.isNew ? monitoringService.createMonitor(vm.monitor.type, vm.monitor) : monitoringService.updateMonitor(vm.monitor.type, vm.monitor);\n }\n\n function saveSuccess(monitorId) {\n vm.$form.$setPristine();\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.details\", {\n monitorId: monitorId\n }, {\n reload: true\n });\n }\n }\n\n function updateLatLong() {\n if (!vm.utm.northing || !vm.utm.easting || !vm.utm.zone) {\n return;\n }\n\n var utm = new Utm(vm.utm.zone, vm.utm.hemisphere, vm.utm.easting, vm.utm.northing);\n var latlong = utm.toLatLonE();\n vm.monitor.latitude = latlong.lat;\n vm.monitor.longitude = latlong.lon;\n }\n\n function updateUtm() {\n if (!vm.monitor.latitude || !vm.monitor.longitude) {\n return;\n }\n\n var latlong = new LatLon(vm.monitor.latitude, vm.monitor.longitude);\n vm.utm = latlong.toUtm();\n }\n\n function updateElevation() {\n if (formIsReady) {\n mappingService.getElevation(vm.monitor.latitude, vm.monitor.longitude).then(function (result) {\n vm.monitor.elevation = parseFloat(result.elevation.toFixed(2));\n });\n }\n }\n\n function updateMap() {\n vm.map.centre = {\n lat: vm.monitor.latitude,\n lng: vm.monitor.longitude,\n zoom: vm.configurationOptions.facilityLocation.zoom\n };\n }\n\n function onMonitorTypeChanged() {\n // we need to jump back into a digest cycle from within the kendo event\n $timeout(function () {\n return vm.monitor.isVisible = vm.monitor.type !== \"upperAirWeatherStation\";\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.MapConfigurationTab\", MapConfigurationTab);\n MapConfigurationTab.$inject = [\"$scope\", \"$state\", \"lodash\", \"promiseTracker\", \"i18n\", \"app.core.errorService\", \"app.core.services.configuration.monitoringService\", \"monitorTabs\", \"mapConfigurationState\"];\n\n function MapConfigurationTab($scope, $state, _, promiseTracker, i18n, errorService, monitoringService, monitorTabs, mapConfigurationState) {\n var vm = this;\n var availableVariables, displayVariables, graphVariables;\n vm.monitorId = $state.params.monitorId;\n vm.$form = null;\n vm.sortables = [];\n vm.state = mapConfigurationState;\n vm.save = saveDisplay;\n vm.cancel = loadDisplay;\n vm.busySaving = promiseTracker();\n vm.busyLoading = promiseTracker();\n activate(); /////////////////\n\n function activate() {\n loadDisplay();\n syncDirtyStatus();\n $scope.$watch(function () {\n return vm.$form && vm.$form.$dirty;\n }, function (isFormDirty) {\n return monitorTabs.mapConfiguration.isDirty = isFormDirty;\n });\n $scope.$watch(function () {\n return vm.busyLoading.active();\n }, function (isBusyLoading) {\n return monitorTabs.mapConfiguration.isBusyLoading = isBusyLoading;\n });\n }\n\n function loadDisplay() {\n var loadingPromise = monitoringService.getMonitorDisplay(vm.monitorId).then(setSortables, processError);\n vm.busyLoading.addPromise(loadingPromise);\n\n function setSortables(display) {\n availableVariables = {\n name: i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.content.sortables.availableVariables\"),\n items: display.availableVariables\n };\n displayVariables = {\n name: i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.content.sortables.displayVariables\"),\n items: display.displayVariables,\n original: _.map(display.displayVariables, function (dv) {\n return _.assign({}, dv);\n })\n };\n graphVariables = {\n name: i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.content.sortables.graphVariables\"),\n items: display.graphVariables,\n original: _.map(display.graphVariables, function (dv) {\n return _.assign({}, dv);\n })\n };\n vm.sortables = [availableVariables, displayVariables, graphVariables];\n }\n\n function processError(response) {\n errorService.processError(response);\n $state.go(\"app.configuration.company.monitoring.monitors\");\n }\n }\n\n function syncDirtyStatus() {\n $scope.$watch(function () {\n return vm.sortables;\n }, function () {\n if (!vm.$form) {\n return;\n }\n\n if (!displayVariables || !graphVariables || !displayVariables.original || !graphVariables.original) {\n vm.$form.$setPristine(true);\n return;\n }\n\n if (haveVariablesChanged(graphVariables)) {\n vm.$form.$setDirty(true);\n return;\n }\n\n if (haveVariablesChanged(displayVariables)) {\n vm.$form.$setDirty(true);\n return;\n }\n\n vm.$form.$setPristine(true);\n }, true);\n\n function haveVariablesChanged(variableType) {\n if (!variableType.items) {\n return false;\n }\n\n return variableType.items.length !== variableType.original.length || _.zip(variableType.items, variableType.original).some(function (comparer) {\n var current = comparer[0];\n var original = comparer[1];\n return current.id !== original.id || current.measurementGroupId !== original.measurementGroupId;\n });\n }\n }\n\n function saveDisplay() {\n if (vm.$form.$invalid) {\n return;\n }\n\n var params = {\n displayVariables: _.map(displayVariables.items, getDisplayVariable),\n graphVariables: _.map(graphVariables.items, getId)\n };\n var savingPromise = monitoringService.updateMonitorDisplay(vm.monitorId, params).then(loadDisplay);\n vm.busySaving.addPromise(savingPromise);\n\n function getId(item) {\n return item.id;\n }\n\n function getDisplayVariable(item) {\n return {\n id: item.id,\n measurementGroupId: item.measurementGroupId\n };\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTab\", MeasurementTypesTab);\n MeasurementTypesTab.$inject = [\"$scope\", \"$state\", \"promiseTracker\", \"i18n\", \"app.core.services.configuration.monitoringService\", \"measurementTypesState\"];\n\n function MeasurementTypesTab($scope, $state, promiseTracker, i18n, monitoringService, measurementTypesState) {\n var vm = this;\n var searchCriteria = {\n take: 0,\n pageSize: 0,\n sort: [{\n field: \"name\",\n dir: \"asc\",\n order: 1\n }]\n };\n vm.monitorId = $state.params.monitorId;\n vm.measurementTypeId = $state.params.measurementTypeId;\n vm.$form = null;\n vm.busySaving = promiseTracker();\n vm.busyLoading = promiseTracker();\n vm.measurementTypesDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.measurementType.defaultValue\");\n vm.onSelectMeasurementType = onSelectMeasurementType;\n vm.onCreateMeasurementType = onCreateMeasurementType;\n activate(); /////////////////\n\n function activate() {\n registerForMeasurementTypeStateEvents();\n var loadingPromise = monitoringService.queryMonitorMeasurementTypes(vm.monitorId, searchCriteria).then(function (measurementTypes) {\n return vm.measurementTypes = measurementTypes;\n });\n vm.busyLoading.addPromise(loadingPromise); ////////////////////\n\n function registerForMeasurementTypeStateEvents() {\n $scope.$on(measurementTypesState.events.loading, function (event, loadingPromise) {\n return vm.busyLoading.addPromise(loadingPromise);\n });\n $scope.$on(measurementTypesState.events.saving, function (event, savingPromise) {\n return vm.busySaving.addPromise(savingPromise);\n });\n }\n }\n\n function onSelectMeasurementType(measurementTypeId) {\n if (measurementTypeId) {\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType.edit\", {\n measurementTypeId: measurementTypeId\n });\n } else {\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes\");\n }\n }\n\n function onCreateMeasurementType() {\n vm.measurementTypeId = null;\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.add\");\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTabEditPanel\", MeasurementTypesTabEditPanel);\n MeasurementTypesTabEditPanel.$inject = [\"$scope\", \"$state\", \"$timeout\", \"lodash\", \"i18n\", \"app.core.errorService\", \"app.core.services.configuration.monitoringService\", \"measurementTypesState\", \"monitorTabs\"];\n\n function MeasurementTypesTabEditPanel($scope, $state, $timeout, _, i18n, errorService, monitoringService, measurementTypesState, monitorTabs) {\n var vm = this;\n vm.maxStaleDataTimeoutSeconds = 60 * 60 * 24 * 7; // 7 days\n\n vm.isNew = !$state.params.measurementTypeId;\n vm.isEdit = !vm.isNew;\n vm.configurationOptions = measurementTypesState.configurationOptions;\n vm.configurationOptions.pollutantDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.pollutant.defaultValue\");\n vm.configurationOptions.categoryDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.category.defaultValue\");\n vm.configurationOptions.defaultDisplayUnitDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.defaultDisplayUnit.defaultValue\");\n vm.configurationOptions.defaultImportUnitDefaultValue = i18n.i10n(\"app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.defaultImportUnit.defaultValue\");\n\n vm.onCategoryChanged = function (categoryId) {\n onCategoryChanged(parseInt(categoryId));\n };\n\n vm.onDefaultImportUnitChanged = onDefaultImportUnitChanged;\n vm.onDefaultDisplayUnitChanged = onDefaultDisplayUnitChanged;\n vm.cancel = cancel;\n vm.save = save;\n activate(); /////////////////\n\n function activate() {\n initialiseForm();\n $scope.$watch(function () {\n return vm.$form.$dirty;\n }, function () {\n return monitorTabs.measurementTypes.isDirty = vm.$form.$dirty;\n });\n\n if (vm.isNew) {\n vm.measurementType.staleDataTimeoutSeconds = 3600;\n } else if (vm.isEdit) {\n var loadingPromise = monitoringService.getMeasurementType(vm.measurementType.id).then(importMeasurementType).catch(function (response) {\n errorService.processError(response);\n $state.go(\"app.configuration.company.monitoring.monitors\");\n });\n $scope.$emit(measurementTypesState.events.loading, loadingPromise);\n } /////////////////\n\n\n function importMeasurementType(measurementType) {\n onCategoryChanged(measurementType.categoryId); // make sure the units collection has been $digested.\n\n $timeout(function () {\n _.assign(vm.measurementType, measurementType);\n\n vm.showErrors = true;\n });\n }\n }\n\n function initialiseForm() {\n if (vm.$form) {\n vm.$form.$setPristine();\n }\n\n vm.unitCollection = [];\n vm.pollutantCollection = vm.configurationOptions.pollutants;\n vm.measurementType = {\n id: $state.params.measurementTypeId,\n monitorId: $state.params.monitorId,\n categoryId: null,\n defaultAggregateTypeId: vm.configurationOptions.aggregateTypes[0].type,\n exceedanceThresholds: [],\n dataAvailabilityThresholds: []\n };\n }\n\n function onCategoryChanged(categoryId) {\n vm.measurementType.defaultDisplayUnitId = null;\n vm.measurementType.defaultImportUnitId = null;\n\n if (!_.isNumber(categoryId)) {\n // i.e. chose `Select Category...` option.\n return;\n }\n\n var category = _.find(vm.configurationOptions.measurementTypeCategories, {\n id: categoryId\n });\n\n if (!category) {\n return;\n }\n\n if (category.id === monitoringService.genericMeasurementTypeCategoryId) {\n // user can choose any unit.\n vm.unitCollection = _.chain(vm.configurationOptions.units).map(function (unit) {\n return unit;\n }).flatten().value();\n } else {\n // user can only chose units for the selected category\n vm.unitCollection = vm.configurationOptions.units[category.unitTypeId];\n }\n }\n\n function onDefaultDisplayUnitChanged(unitId) {\n vm.measurementType.defaultImportUnitId = vm.measurementType.defaultImportUnitId || unitId;\n }\n\n function onDefaultImportUnitChanged(unitId) {\n vm.measurementType.defaultDisplayUnitId = vm.measurementType.defaultDisplayUnitId || unitId;\n }\n\n function cancel() {\n activate();\n vm.$form.$setPristine();\n }\n\n function save() {\n var savingPromise = persistMeasurementType();\n savingPromise.then(saveSuccess);\n $scope.$emit(measurementTypesState.events.saving, savingPromise);\n\n function persistMeasurementType() {\n return vm.isNew ? monitoringService.createMeasurementType(vm.measurementType) : monitoringService.updateMeasurementType(vm.measurementType);\n }\n\n function saveSuccess(measurementTypeId) {\n vm.$form.$setPristine();\n $state.go(\"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType.edit\", {\n measurementTypeId: measurementTypeId\n }, {\n reload: true\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").factory(\"app.ui.features.configuration.company.monitoring.monitors.state\", stateFactory);\n stateFactory.$inject = [\"$state\", \"$q\", \"app.core.services.companyService\", \"app.core.services.configuration.legacyLookupService\", \"app.core.services.configuration.measurementGroupService\", \"app.core.services.configuration.monitoringService\", \"app.core.appSettings\", \"app.ui.core.controls.Tab\"];\n /* istanbul ignore next */\n\n function stateFactory($state, $q, companyService, lookupService, measurementGroupService, monitoringService, appSettings, Tab) {\n return {\n monitorTabs: monitorTabs,\n detailsState: detailsState,\n measurementTypesState: measurementTypesState,\n mapConfigurationState: mapConfigurationState,\n dataImportState: dataImportState\n }; //////////////////\n\n function monitorTabs() {\n return {\n details: new Tab(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.details.heading\", function () {\n return getUrl(\"app.configuration.company.monitoring.monitors.tabs.monitor.details\");\n }, function () {\n return $state.$current.name === \"app.configuration.company.monitoring.monitors.tabs.add\" || $state.$current.name === \"app.configuration.company.monitoring.monitors.tabs.monitor.details\";\n }),\n measurementTypes: new Tab(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.measurementTypes.heading\", function () {\n return getUrl(\"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes\");\n }, function () {\n return $state.$current.name.indexOf(\"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes\") !== -1;\n }, hasMonitorId),\n mapConfiguration: new Tab(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.heading\", function () {\n return getUrl(\"app.configuration.company.monitoring.monitors.tabs.monitor.mapConfiguration\");\n }, function () {\n return $state.$current.name === \"app.configuration.company.monitoring.monitors.tabs.monitor.mapConfiguration\";\n }, hasMonitorId),\n dataImport: new Tab(\"app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.dataImport.heading\", function () {\n return getUrl(\"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport\");\n }, function () {\n return $state.$current.name.indexOf(\"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport\") !== -1;\n }, hasMonitorId)\n };\n\n function hasMonitorId() {\n return !!$state.params.monitorId;\n }\n\n function getUrl(stateName) {\n var stateParams = {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n monitorId: $state.params.monitorId\n };\n return $state.href(stateName, stateParams);\n }\n }\n\n function detailsState() {\n var monitorsPromise = monitoringService.getMonitors();\n var monitorTypesPromise = monitoringService.getMonitorTypes();\n var windowsTimeZonesPromise = lookupService.getWindowsTimeZones();\n var facilityLocationPromise = companyService.getFacilityLocation();\n return $q.all([monitorTypesPromise, windowsTimeZonesPromise, facilityLocationPromise, monitorsPromise]).then(function (results) {\n return {\n configurationOptions: {\n monitorTypes: results[0],\n timeZones: results[1],\n facilityLocation: results[2],\n monitors: results[3]\n }\n };\n });\n }\n\n function measurementTypesState() {\n var events = {\n loading: \"app.ui.features.configuration.company.monitoring.monitors.measurementTypes.loading\",\n saving: \"app.ui.features.configuration.company.monitoring.monitors.measurementTypes.saving\"\n };\n return monitoringService.getMeasurementTypeConfigurationOptions().then(function (configurationOptions) {\n return {\n events: events,\n configurationOptions: configurationOptions\n };\n });\n }\n\n function mapConfigurationState() {\n return measurementGroupService.getMeasurementGroupsFlattened(function (mg) {\n return mg.description;\n }).then(function (measurementGroups) {\n return {\n measurementGroups: measurementGroups\n };\n });\n }\n\n function dataImportState() {\n var events = {\n loading: \"app.ui.features.configuration.company.monitoring.monitors.dataImport.loading\",\n saving: \"app.ui.features.configuration.company.monitoring.monitors.dataImport.saving\"\n };\n return {\n events: events\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.core.controls.Tab\", \"app.ui.features.configuration.company.monitoring.monitors.state\", \"app.ui.features.configuration.company.monitoring.measurementGroups.state\", \"app.ui.features.configuration.company.monitoring.measurementGroups.DeleteModal\"];\n\n function appRun(routeHelper, Tab, monitorsState, measurementGroupsState, deleteModal) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n abstract: true,\n state: \"app.configuration.company.monitoring\",\n url: \"/monitoring\",\n data: {\n requiredAccessControl: \"app.config.monitoring\"\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/i18n/monitoring\"]\n }\n }, ///////////////////\n // Monitor Creation\n ///////////////////\n {\n // display monitors data grid and provides action to add a new monitor.\n state: \"app.configuration.company.monitoring.monitors\",\n url: \"/monitors\",\n views: {\n 'contentPanel@app': {\n // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/ContentPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.ContentPanel as vm\"\n }\n },\n resolve: {\n monitorTabs: monitorsState.monitorTabs\n }\n }, {\n // provides details panel responsible for managing the tabs.\n abstract: true,\n state: \"app.configuration.company.monitoring.monitors.tabs\",\n views: {\n detailPanel: {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.DetailPanel as vm\"\n }\n }\n }, {\n // create a new monitor\n state: \"app.configuration.company.monitoring.monitors.tabs.add\",\n url: \"/add\",\n views: {\n tab: {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/DetailsTab.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.DetailsTab as vm\"\n }\n },\n resolve: {\n detailsState: monitorsState.detailsState\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/monitors/i18n/DetailsTab\"]\n }\n }, {\n abstract: true,\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor\",\n url: \"/:monitorId\"\n }, {\n // edit the details of an existing monitor\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.details\",\n url: \"/details\",\n views: {\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/DetailsTab.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.DetailsTab as vm\"\n }\n },\n resolve: {\n detailsState: monitorsState.detailsState\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/monitors/i18n/DetailsTab\"]\n }\n }, ////////////////////\n // Measurement Types\n ////////////////////\n {\n // measurement types tab\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes\",\n url: \"/measurement-types\",\n views: {\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTab.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTab as vm\"\n }\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/monitors/i18n/MeasurementTypesTab\", \"/App/ui/features/configuration/company/monitoring/monitors/controls/i18n/esMeasurementTypeThresholds\"]\n },\n resolve: {\n measurementTypesState: monitorsState.measurementTypesState\n }\n }, {\n // add new measurement type\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.add\",\n url: \"/add\",\n views: {\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTabEditPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTabEditPanel as vm\"\n }\n },\n resolve: {\n measurementTypesState: monitorsState.measurementTypesState\n },\n onExit: [\"monitorTabs\", function (monitorTabs) {\n return monitorTabs.measurementTypes.isDirty = false;\n }]\n }, {\n abstract: true,\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType\",\n url: \"/:measurementTypeId\"\n }, {\n // edit a measurement type\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType.edit\",\n url: \"/edit\",\n views: {\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTabEditPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTabEditPanel as vm\"\n }\n },\n resolve: {\n measurementTypesState: monitorsState.measurementTypesState\n },\n onExit: [\"monitorTabs\", function (monitorTabs) {\n return monitorTabs.measurementTypes.isDirty = false;\n }]\n }, //////////////\n // Map Configuration\n //////////////\n {\n // edit the visibility and grouping of measurement types on the maps and graphs\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.mapConfiguration\",\n url: \"/map-configuration\",\n views: {\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/MapConfigurationTab.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.MapConfigurationTab as vm\"\n }\n },\n resolve: {\n mapConfigurationState: monitorsState.mapConfigurationState\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/monitors/controls/i18n/esMonitorVariableDisplay\"]\n }\n }, //////////////\n // Data Import\n //////////////\n {\n // index\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport\",\n url: \"/data-import\",\n views: {\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/DataImportTab.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.DataImportTab as vm\"\n }\n },\n resolve: {\n dataImportState: monitorsState.dataImportState\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/monitors/i18n/DataImportTab\"]\n }\n }, {\n // create\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.add\",\n url: \"/add\",\n views: {\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.dataImport': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/DataImportTabEditPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.dataImport.DataImportTabEditPanel as vm\"\n }\n },\n resolve: {\n dataImportState: monitorsState.dataImportState\n },\n onExit: [\"monitorTabs\", function (monitorTabs) {\n return monitorTabs.dataImport.isDirty = false;\n }]\n }, {\n abstract: true,\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential\",\n url: \"/:apiCredentialId\"\n }, {\n // update\n state: \"app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential.edit\",\n url: \"/edit\",\n views: {\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.dataImport': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/monitors/DataImportTabEditPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.monitors.dataImport.DataImportTabEditPanel as vm\"\n }\n },\n resolve: {\n dataImportState: monitorsState.dataImportState\n },\n onExit: [\"monitorTabs\", function (monitorTabs) {\n return monitorTabs.dataImport.isDirty = false;\n }]\n }, /////////////////////\n // Measurement Groups\n /////////////////////\n {\n state: \"app.configuration.company.monitoring.measurementGroups\",\n url: \"/measurement-groups\",\n views: {\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/measurementGroups/ContentPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.measurementGroups.ContentPanel as vm\"\n }\n },\n resolve: {\n measurementGroupsState: measurementGroupsState\n }\n }, {\n state: \"app.configuration.company.monitoring.measurementGroups.add\",\n url: \"/add\",\n views: {\n detailPanel: {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/measurementGroups/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.measurementGroups.DetailPanel as vm\"\n }\n }\n }, {\n abstract: true,\n state: \"app.configuration.company.monitoring.measurementGroups.measurementGroup\",\n url: \"/:measurementGroupId\",\n views: {\n detailPanel: {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/measurementGroups/DetailPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.measurementGroups.DetailPanel as vm\"\n }\n }\n }, {\n state: \"app.configuration.company.monitoring.measurementGroups.measurementGroup.edit\",\n url: \"/edit\"\n }, {\n state: \"app.configuration.company.monitoring.measurementGroups.measurementGroup.delete\",\n url: \"/delete\",\n onEnter: deleteModal.open\n }, ///////\n // Base\n ///////\n {\n state: \"app.configuration.company.monitoring.settings\",\n url: \"/settings\",\n views: {\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/configuration/company/monitoring/settings/ContentPanel.html\",\n controller: \"app.ui.features.configuration.company.monitoring.settings.ContentPanel as vm\"\n }\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/company/monitoring/settings/controls/i18n/esWeatherStationConfiguration\"]\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").controller(\"app.ui.features.configuration.company.monitoring.settings.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\"];\n\n function ContentPanel($scope) {\n var vm = this;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.company.monitoring\").directive(\"esWeatherStationConfiguration\", esWeatherStationConfiguration).controller(\"esWeatherStationConfigurationController\", esWeatherStationConfigurationController);\n esWeatherStationConfiguration.$inject = [];\n\n function esWeatherStationConfiguration() {\n return {\n scope: {},\n restrict: \"E\",\n controllerAs: \"vm\",\n bindToController: true,\n controller: esWeatherStationConfigurationController,\n templateUrl: \"/App/ui/features/configuration/company/monitoring/settings/controls/esWeatherStationConfiguration.html\"\n };\n }\n\n esWeatherStationConfigurationController.$inject = [\"$scope\", \"lodash\", \"app.core.services.configuration.monitoringService\", \"promiseTracker\"];\n\n function esWeatherStationConfigurationController($scope, _, configurationMonitoringService, promiseTracker) {\n var vm = this;\n vm.stations = [];\n vm.selectedStation = null;\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n vm.cancel = cancel;\n vm.save = save;\n activate(); ///////////\n\n function activate() {\n var promise = configurationMonitoringService.getAllMetStations().then(function (result) {\n vm.stations = result;\n vm.selectedStation = _.find(result, {\n isDefault: true\n });\n });\n vm.busyLoading.addPromise(promise);\n return promise;\n }\n\n function cancel() {\n vm.$form.$setPristine(true);\n return activate();\n }\n\n function save() {\n var promise = configurationMonitoringService.setDefaultMetStation(vm.selectedStation.id).then(function () {\n return vm.$form.$setPristine(true);\n });\n vm.busySaving.addPromise(promise);\n return promise;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration\").controller(\"app.ui.features.configuration.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function ContentPanel() {\n activate(); //////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration\").directive(\"esAccordionConfigurationSetContainerHeight\", esAccordionConfigurationSetContainerHeight);\n /* istanbul ignore next */\n\n esAccordionConfigurationSetContainerHeight.$inject = [\"lodash\"];\n\n function esAccordionConfigurationSetContainerHeight(_) {\n return {\n restrict: \"A\",\n link: link\n };\n\n function link($scope, $element) {\n activate();\n\n function activate() {\n $scope.$on(\"resizePage\", setAccordionBodyMaxSize);\n setAccordionBodyMaxSize();\n } //////////////\n\n\n function setAccordionBodyMaxSize() {\n var $container = angular.element(\"#module-view-sidebar .sidebar-container\");\n var $panels = $element.find(\".panel\");\n var $panelBody = $element.find(\".panel-body\");\n var $bottomToggle = $container.find(\".advanced-toggle\");\n\n if (!$panels.length) {\n return;\n }\n\n var availableHeight = $container.height();\n var bottomToggleHeight = $bottomToggle.height();\n\n var accordionScaffoldingHeight = _.reduce($panels, function (height, panel) {\n var $panel = angular.element(panel);\n return height + $panel.find(\".panel-heading\").innerHeight() + pxToInt($panel, \"border-top-width\") + pxToInt($panel, \"border-bottom-width\") + pxToInt($panel, \"margin-top\") + pxToInt($panel, \"margin-bottom\");\n }, 0);\n\n var maxPanelHeight = availableHeight - accordionScaffoldingHeight - bottomToggleHeight;\n $panelBody.css(\"max-height\", maxPanelHeight + \"px\");\n }\n\n function pxToInt(element, css) {\n return parseInt(element.css(css).replace(\"px\", \"\"));\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n\"use strict\";\n\n(function () {\n angular.module(\"app.ui.features.configuration\").directive(\"esFormStateTracker\", esFormStateTracker);\n esFormStateTracker.$inject = [];\n\n function esFormStateTracker() {\n return {\n restrict: \"E\",\n scope: {},\n bindToController: {\n isDirty: \"=\",\n discardChanges: \"&\",\n loading: \"=\"\n },\n controllerAs: \"vm\",\n controller: controller,\n templateUrl: \"/App/ui/features/configuration/controls/esFormStateTracker.html\"\n };\n }\n\n controller.$inject = [\"$scope\", \"$q\", \"$timeout\", \"$window\", \"i18n\", \"routeHelper\", \"confirmationDialog\"];\n\n function controller($scope, $q, $timeout, $window, i18n, routeHelper, confirmationDialog) {\n var vm = this;\n var unsavedChangesHeading = i18n.i10n(\"forms.unsaved.changes.heading\");\n var unsavedChangesText = i18n.i10n(\"forms.unsaved.changes.message.text\");\n var unsavedChangesHtml = i18n.i10n(\"forms.unsaved.changes.message.html\");\n var modalOptions = {\n css: \"modal-center\",\n buttons: {\n 'continue': {\n text: i18n.i10n(\"forms.unsaved.changes.buttons.continue\")\n },\n cancel: {\n text: i18n.i10n(\"forms.unsaved.changes.buttons.cancel\")\n }\n }\n };\n vm.discardChanges = vm.discardChanges || angular.noop;\n activate(); ////////////////////\n\n function activate() {\n var removeStateChangeStartEventHandler = routeHelper.addStateChangeStartEventHandler(routeChangingListener, -1); // run this before routeHandler pipeline.\n\n $window.addEventListener(\"beforeunload\", windowUnloadListener);\n $scope.$on(\"$destroy\", unbindListeners);\n\n function unbindListeners() {\n $window.removeEventListener(\"beforeunload\", windowUnloadListener);\n removeStateChangeStartEventHandler();\n }\n }\n\n function routeChangingListener() {\n return $q(function (resolve, reject) {\n // guard against the $state transition event occurring before the vm.dirty property is processed by a $digest cycle.\n $timeout(function () {\n if (!vm.isDirty) {\n resolve();\n return;\n }\n\n confirmationDialog.ask(unsavedChangesHeading, unsavedChangesHtml, modalOptions).then(function () {\n vm.discardChanges();\n resolve();\n }).catch(reject);\n });\n });\n }\n\n function windowUnloadListener(event) {\n if (vm.isDirty) {\n (event || $window.event).returnValue = unsavedChangesText; // GECKO and IE\n\n return unsavedChangesText; //Webkit, Safari, Chrome, etc.\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration\").controller(\"app.ui.features.configuration.LeftPanel\", LeftPanel);\n LeftPanel.$inject = [\"$state\", \"lodash\", \"app.core.appSettings\", \"configurationState\"];\n\n function LeftPanel($state, _, appSettings, configurationState) {\n var vm = this;\n vm.appSettings = appSettings;\n vm.companyNavigationGroups = [];\n vm.configurationState = configurationState;\n vm.isRouteSelected = isRouteSelected;\n vm.getCompanyRoute = getCompanyRoute;\n activate(); //////////////////\n\n function activate() {\n vm.companyNavigationGroups = getCompanyNavigationGroups();\n }\n\n function getCompanyNavigationGroups() {\n var accessControls = vm.appSettings.site.accessControls;\n var groups = [];\n\n if (accessControls[\"app.config.monitoring\"]) {\n var monitoringGroup = {\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.heading\",\n ref: \"monitoring\",\n items: [{\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.monitors.label\",\n ref: \"monitors\"\n }, {\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.measurementGroups.label\",\n ref: \"measurementGroups\"\n }, {\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.settings.label\",\n ref: \"settings\"\n }]\n };\n groups = [].concat(_toConsumableArray(groups), [monitoringGroup]);\n }\n\n if (accessControls[\"app.config.annotations.monitor-pollutants\"]) {\n var annotationsGroup = {\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.annotations.heading\",\n ref: \"annotations\",\n items: [{\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.annotations.pollutant.label\",\n ref: \"monitorPollutants\",\n isActive: isRouteSelected(\"annotations\", \"monitorPollutants\")\n }]\n };\n groups = [].concat(_toConsumableArray(groups), [annotationsGroup]);\n }\n\n var modellingGroup = {\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.heading\",\n ref: \"modelling\",\n items: []\n };\n\n if (accessControls[\"app.modelling.run-aermod-modelling\"]) {\n modellingGroup.items = [].concat(_toConsumableArray(modellingGroup.items), [{\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.aermet.label\",\n ref: \"aermet\"\n }]);\n }\n\n if (accessControls[\"app.config.modelling\"]) {\n modellingGroup.items = [].concat(_toConsumableArray(modellingGroup.items), [{\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.models.label\",\n ref: \"models\"\n }]);\n }\n\n if (accessControls[\"app.config.modelling.emission-data\"]) {\n modellingGroup.items = [].concat(_toConsumableArray(modellingGroup.items), [{\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.emissionsData.label\",\n ref: \"emissionsData\"\n }]);\n }\n\n if (accessControls[\"app.config.modelling.run-models\"]) {\n modellingGroup.items = [].concat(_toConsumableArray(modellingGroup.items), [{\n label: \"app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.modelStatus.label\",\n ref: \"\".concat(vm.appSettings.mvcHostUri).concat(vm.appSettings.site.facility.es1RouteName, \"/plume/getmodelstatus\"),\n target: \"_blank\",\n isActive: false\n }]);\n }\n\n groups = [].concat(_toConsumableArray(groups), [modellingGroup]);\n return groups;\n }\n\n function getCompanyRoute(groupRef, itemRef) {\n return $state.href(\"app.configuration.company.\".concat(groupRef, \".\").concat(itemRef), {\n companyAlias: vm.appSettings.site.company.alias,\n facilityAlias: vm.appSettings.site.facility.alias\n });\n }\n\n function isRouteSelected(groupRef, itemRef) {\n return $state.current.state.indexOf(\"app.configuration.company.\".concat(groupRef).concat(itemRef ? \".\".concat(itemRef) : \"\")) === 0;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.configuration.state\"];\n\n function appRun(routeHelper, configurationState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n abstract: true,\n state: \"app.configuration\",\n url: \"/configuration\",\n views: {\n leftPanel: {\n templateUrl: \"/App/ui/features/configuration/LeftPanel.html\",\n controller: \"app.ui.features.configuration.LeftPanel as vm\"\n },\n contentPanel: {\n templateUrl: \"/App/ui/features/configuration/ContentPanel.html\",\n controller: \"app.ui.features.configuration.ContentPanel as vm\"\n }\n },\n data: {\n requiredAccessControl: \"app.config\"\n },\n settings: {\n i18n: [\"/App/ui/features/configuration/i18n/configuration\", \"/App/ui/core/controls/i18n/esList\"]\n },\n resolve: {\n configurationState: configurationState\n }\n }, {\n state: \"app.configuration.system\",\n url: \"/system\",\n settings: {\n i18n: [\"/App/ui/features/configuration/system/i18n/system\"]\n }\n }, {\n state: \"app.configuration.company\",\n url: \"/{companyAlias}/{facilityAlias}\"\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration\").factory(\"app.ui.features.configuration.state\", configurationStateFactory);\n configurationStateFactory.$inject = [];\n /* istanbul ignore next */\n // Remove if\\when more logic is added\n\n function configurationStateFactory() {\n return function () {\n return {};\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.system\").controller(\"app.ui.features.configuration.system.modelling.modelRuns.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"promiseTracker\", \"app.core.services.configuration.modellingService\", \"app.core.services.dateTimeService\", \"notifier\", \"i18n\", \"moment\"];\n\n function ContentPanel(promiseTracker, modellingService, dateTimeService, notifier, i18n, moment) {\n var vm = this;\n vm.busyLoading = promiseTracker();\n vm.busySaving = promiseTracker();\n vm.wrfConfigurationNames = [];\n vm.selectedWrfConfigurationName = \"\";\n vm.forecastRunNames = [];\n vm.selectedForecastRunName = \"\";\n vm.datePicker = getDatePicker();\n vm.run = run;\n activate(); ///////////\n\n function activate() {\n var loadPromise = loadConfigurationNames();\n vm.busyLoading.addPromise(loadPromise);\n }\n\n function loadConfigurationNames() {\n var loadPromise = modellingService.getWrfConfiguration().then(function (configuration) {\n vm.wrfConfigurationNames = configuration.names;\n vm.forecastRunNames = configuration.forecastRuns;\n });\n return loadPromise;\n }\n\n function run() {\n var runDate = moment(vm.datePicker.date).startOf(\"day\").toDate();\n var runPromise = modellingService.runCalModelling(vm.selectedWrfConfigurationName, runDate, vm.selectedForecastRunName).then(function () {\n notifier.info(i18n.i10n(\"app.ui.features.configuration.system.modelling.modelRuns.contentPanel.notifications.running.message\"), i18n.i10n(\"app.ui.features.configuration.system.modelling.modelRuns.contentPanel.notifications.running.heading\"));\n });\n vm.busySaving.addPromise(runPromise);\n }\n\n function getDatePicker() {\n var today = moment(new Date()).endOf(\"day\").toDate();\n return {\n options: {\n max: today,\n format: dateTimeService.formats.kendo.date\n },\n date: today\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.configuration.system\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.configuration.state\"];\n\n function appRun(routeHelper, configurationState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n abstract: true,\n state: \"app.configuration.system.modelling\",\n url: \"/modelling\",\n data: {\n requiredAccessControl: \"app.config.modelling\"\n }\n }, {\n state: \"app.configuration.system.modelling.modelRuns\",\n url: \"/modelruns\",\n views: {\n 'contentPanel@app': {\n // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\n templateUrl: \"/App/ui/features/configuration/system/modelling/modelRuns/ContentPanel.html\",\n controller: \"app.ui.features.configuration.system.modelling.modelRuns.ContentPanel as vm\"\n }\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.dashboard\").controller(\"app.ui.features.dashboard.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"$timeout\", \"$log\", \"lodash\", \"jQuery\", \"app.core.services.dashboardService\", \"dashboardState\", \"Mousetrap\", \"notifier\", \"i18n\"];\n\n function ContentPanel($scope, $timeout, $log, _, $, dashboardService, dashboardState, Mousetrap, notifier, i18n) {\n var vm = this;\n var dashboardCopy = dashboardState.dashboard;\n vm.dashboard = dashboardState.dashboard;\n vm.widgetFilter = dashboardService.canAccessWidget;\n activate(); //////////////////////////\n\n function activate() {\n moveDashboardTitleInclude();\n registerForEvents();\n setupKeyboardShortcuts();\n $scope.$on(\"$destroy\", removeDashboardTitleInclude);\n }\n\n function moveDashboardTitleInclude() {\n $(\"#module-view-body\").hide();\n $timeout(function () {\n var dashboardTitle = $(\"[src=\\\"model.titleTemplateUrl\\\"]\");\n var actionsPanel = $(\"[ui-view=\\\"actionsPanel\\\"]\");\n actionsPanel.append(dashboardTitle.contents());\n $(\"#module-view-body\").show();\n });\n }\n\n function removeDashboardTitleInclude() {\n var actionsPanel = $(\"[ui-view=\\\"actionsPanel\\\"]\");\n actionsPanel.empty();\n }\n\n function setupKeyboardShortcuts() {\n var dashboardResetKeyboardSequence = \"capslock capslock d r\";\n Mousetrap.bind(dashboardResetKeyboardSequence, resetDashboard);\n $scope.$on(\"$destroy\", function () {\n Mousetrap.unbind(dashboardResetKeyboardSequence);\n });\n\n function resetDashboard() {\n dashboardService.deleteDashboard();\n $timeout(function () {\n // the timeout is needed to ensure the local storage has been written to.\n dashboardCopy = vm.dashboard = dashboardState.dashboard = dashboardService.getDashboard();\n notifier.info(i18n.i10n(\"app.ui.features.dashboard.contentPanel.notifications.dashboardReset.message\"), i18n.i10n(\"app.ui.features.dashboard.contentPanel.notifications.dashboardReset.title\"));\n });\n }\n }\n\n function registerForEvents() {\n var unwatchDashboard = angular.noop;\n /*\n * We have modified the DashboardActions.html to provide the dashboard.editMode property.\n * When the dashboard model is modified we want to persist the changes to local storage.\n * Ideally we could $watch the dashboard model BUT the act of setting the dashboard.editMode\n * property triggers the watch and causes the model to be persisted even thought the user has\n * not actually modified the model yet. So this code here watches for editMode changes, only adding\n * a $watch on the dashboard model when in editMode.\n */\n\n $scope.$watch(function () {\n return vm.dashboard.editMode;\n }, function (editMode) {\n var log = _.debounce(function (dashboard) {\n $log.info(\"The dashboard was changed.
      Details:
      \".concat(JSON.stringify(dashboard)));\n }, 30000); // bundle up changes to the dashboard before logging.\n\n\n if (!editMode) {\n unwatchDashboard();\n return;\n }\n\n unwatchDashboard = $scope.$watch(function () {\n return vm.dashboard;\n }, function (oldValue, newValue) {\n if (angular.equals(oldValue, newValue)) {\n // make sure we don't persist the default dashboard.\n return;\n }\n\n decorateColumnsWithCssSizingClasses();\n dashboardService.persistDashboard(vm.dashboard);\n log(vm.dashboard);\n }, true);\n }); // the `adfDAshboardChanged` event is fired when the user exits `edit` mode.\n\n $scope.$on(\"adfDashboardChanged\", function () {\n dashboardCopy = vm.dashboard;\n });\n $scope.$on(\"adfDashboardEditsCancelled\", function () {\n vm.dashboard = dashboardCopy;\n\n if (vm.dashboard.isDefault) {\n dashboardService.deleteDashboard();\n }\n });\n $scope.$on(\"adfWidgetAdded\", function (event, name, model, widget) {\n widget.titleTemplateUrl = \"/App/ui/features/dashboard/WidgetHeader.html\";\n });\n $scope.$on(\"resizePage\", decorateColumnsWithCssSizingClasses);\n\n function decorateColumnsWithCssSizingClasses() {\n $scope.$broadcast(\"dashboard-layout-changed\");\n\n _.forEach($(\"[column=\\\"column\\\"]\"), function (column) {\n var $column = $(column);\n var width = $column.width();\n $column.removeClass(function (index, cssClass) {\n return /^widget-column-.+/.test(cssClass);\n });\n\n if (width >= 1200) {\n $column.addClass(\"widget-column-lg\");\n return;\n }\n\n if (width >= 992) {\n $column.addClass(\"widget-column-md\");\n return;\n }\n\n if (width >= 768) {\n $column.addClass(\"widget-column-sm\");\n return;\n }\n\n if (width >= 480) {\n $column.addClass(\"widget-column-xs\");\n return;\n }\n\n $column.addClass(\"widget-column-xxs\");\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n var widgetName = \"esBlastScenariosDashboardWidget\";\n angular.module(\"app.ui.features.dashboard\").config([\"dashboardProvider\", function (dashboardProvider) {\n dashboardProvider.widget(widgetName, {\n name: \"\".concat(widgetName, \".heading\"),\n description: \"\".concat(widgetName, \".description\"),\n templateUrl: \"/App/ui/features/dashboard/controls/blasting/\".concat(widgetName, \"View.html\"),\n controller: widgetName,\n controllerAs: \"vm\",\n version: \"1.0\",\n accessControls: [\"app.blasting\"],\n route: \"app.blasting.scenarios\"\n });\n }]).controller(widgetName, controller);\n controller.$inject = [\"$scope\", \"$state\", \"promiseTracker\", \"app.core.appSettings\", \"app.core.services.blastingService\", \"app.core.services.dateTimeService\"];\n\n function controller($scope, $state, promiseTracker, appSettings, blastingService, dateTimeService) {\n var vm = this;\n vm.appSettings = appSettings;\n vm.busyLoading = promiseTracker();\n vm.navigateToScenario = navigateToScenario;\n vm.dateTimeService = dateTimeService;\n activate(); //////////////////\n\n function activate() {\n var getScenarios = blastingService.getScenarios();\n vm.busyLoading.addPromise(getScenarios);\n getScenarios.then(function (scenarios) {\n return vm.scenarios = scenarios.data.slice(0, 5);\n });\n }\n\n function navigateToScenario(scenarioAlias) {\n $state.go(\"app.blasting.scenarios.scenario\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n scenarioAlias: scenarioAlias\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n var widgetName = \"esDailyModelsDashboardWidget\";\n angular.module(\"app.ui.features.dashboard\").config([\"dashboardProvider\", function (dashboardProvider) {\n dashboardProvider.widget(widgetName, {\n name: \"\".concat(widgetName, \".heading\"),\n description: \"\".concat(widgetName, \".heading\"),\n templateUrl: \"/App/ui/features/dashboard/controls/modelling/\".concat(widgetName, \"View.html\"),\n controller: widgetName,\n controllerAs: \"vm\",\n version: \"1.0\",\n accessControls: [\"app.modelling\"],\n route: \"app.modelling.gisModelling\"\n });\n }]).controller(widgetName, controller);\n controller.$inject = [\"$scope\", \"$q\", \"$state\", \"promiseTracker\", \"app.core.appSettings\", \"app.ui.features.modelling.hashParser\", \"app.core.services.gisModelService\"];\n\n function controller($scope, $q, $state, promiseTracker, appSettings, hashParser, gisModelService) {\n var vm = this;\n var oneDayInMinutes = 24 * 60;\n vm.appSettings = appSettings;\n vm.linkHandlers = {\n last24hrs: function last24hrs(modelId) {\n return navigateToModel(modelId, \"last24hrs\");\n },\n midnight: function midnight(modelId) {\n return navigateToModel(modelId, \"today\");\n }\n };\n vm.busyLoading = promiseTracker();\n activate(); //////////////////\n\n function activate() {\n var getModels = appSettings.site.accessControls[\"app.modelling\"] ? gisModelService.getAllModels() : $q.when([]);\n vm.busyLoading.addPromise(getModels);\n getModels.then(function (models) {\n vm.models = models;\n });\n }\n\n function navigateToModel(modelId, from) {\n $state.go(\"app.modelling.gisModelling\", {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n modelhash: hashParser.buildModelRunOptionsHash(modelId, from, 0, oneDayInMinutes)\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n var widgetName = \"esMonitorGraphsDashboardWidget\";\n var controllerName = \"\".concat(widgetName, \"Controller\");\n var editControllerName = \"\".concat(widgetName, \"EditController\");\n angular.module(\"app.ui.features.dashboard\").config(widget).controller(controllerName, controller).controller(editControllerName, editController);\n widget.$inject = [\"dashboardProvider\"];\n\n function widget(dashboardProvider) {\n var widgetDefinition = {\n name: \"\".concat(widgetName, \".heading\"),\n description: \"\".concat(widgetName, \".description\"),\n templateUrl: \"/App/ui/features/dashboard/controls/monitoring/\".concat(widgetName, \"View.html\"),\n controller: controller,\n controllerAs: \"vm\",\n majorVersion: 1,\n accessControls: [\"app.monitoring\"],\n route: \"app.monitoring\",\n edit: {\n controller: editController,\n controllerAs: \"vm\",\n templateUrl: \"/App/ui/features/dashboard/controls/monitoring/\".concat(widgetName, \"Edit.html\")\n }\n };\n dashboardProvider.widget(widgetName, widgetDefinition);\n }\n\n controller.$inject = [\"$scope\", \"$timeout\", \"jQuery\", \"app.core.services.settingsService\", \"app.core.services.monitoringService\"];\n\n function controller($scope, $timeout, $, settingsService, monitoringService) {\n var vm = this;\n var refreshMonitorDataTimeout;\n vm.config = $scope.config;\n vm.contentBounds = {\n height: 400,\n width: 320\n };\n vm.setContentBounds = setContentBoundsWidth;\n activate(); //////////////////\n\n function activate() {\n $scope.$on(\"dashboard-layout-changed\", setContentBoundsWidth);\n $timeout(setContentBoundsWidth);\n\n if (vm.config.selectedMonitorId) {\n loadGraphs();\n monitoringService.getGraphVariables(vm.config.selectedMonitorId).then(function (processVariableIds) {\n vm.processVariableIds = processVariableIds; //re-calculate widget size in next digest cycle.\n\n $timeout(setContentBoundsWidth);\n });\n }\n }\n\n function setContentBoundsWidth() {\n var $widgetContent = $(\"#monitoring-popup-monitor-\".concat(vm.config.selectedMonitorId));\n\n if (!$widgetContent.length) {\n return;\n }\n\n vm.contentBounds.width = $widgetContent.width() - 20;\n }\n\n function loadGraphs() {\n vm.sampleDateTime = settingsService.getSampleDateTime();\n refreshMonitorDataTimeout = $timeout(loadGraphs, getTimeoutMillis());\n }\n\n function getTimeoutMillis() {\n var refreshTimeoutSeconds = 60 - new Date().getSeconds();\n\n if (refreshTimeoutSeconds < 10) {\n refreshTimeoutSeconds += 60;\n }\n\n return refreshTimeoutSeconds * 1000;\n }\n\n $scope.$on(\"$destroy\", function () {\n $timeout.cancel(refreshMonitorDataTimeout);\n });\n }\n\n editController.$inject = [\"$scope\", \"lodash\", \"i18n\", \"app.core.services.configuration.monitoringService\", \"promiseTracker\"];\n\n function editController($scope, _, i18n, monitoringService, promiseTracker) {\n var vm = this;\n vm.busyLoading = promiseTracker();\n vm.config = $scope.config;\n vm.availableMonitors = undefined;\n vm.optionLabel = {\n monitorId: null,\n name: i18n.i10n(\"esMonitorGraphsDashboardWidget.selectMonitor.label\")\n };\n activate(); //////////////////\n\n function activate() {\n loadAvailableMonitors();\n $scope.$watch(function () {\n return vm.config.selectedMonitorId;\n }, function () {\n if (!vm.config.selectedMonitorId || !vm.availableMonitors) {\n $scope.model.title = null;\n return;\n }\n\n var selectedMonitor = _.find(vm.availableMonitors, {\n monitorId: vm.config.selectedMonitorId\n });\n\n $scope.model.title = selectedMonitor ? selectedMonitor.name : null;\n });\n }\n\n function loadAvailableMonitors() {\n var promise = monitoringService.getMonitors(true).then(function (monitors) {\n vm.availableMonitors = monitors;\n });\n vm.busyLoading.addPromise(promise);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n var widgetName = \"esMonitorHealthDashboardWidget\";\n var controllerName = \"\".concat(widgetName, \"Controller\");\n var editControllerName = \"\".concat(widgetName, \"EditController\");\n angular.module(\"app.ui.features.dashboard\").config(widget).controller(controllerName, controller).controller(editControllerName, editController);\n widget.$inject = [\"dashboardProvider\"];\n\n function widget(dashboardProvider) {\n var widgetDefinition = {\n name: \"\".concat(widgetName, \".heading\"),\n description: \"\".concat(widgetName, \".description\"),\n templateUrl: \"/App/ui/features/dashboard/controls/monitoring/\".concat(widgetName, \"View.html\"),\n controller: controller,\n controllerAs: \"vm\",\n majorVersion: 1,\n accessControls: [\"app.monitoring\"],\n route: \"app.monitoring\",\n edit: {\n controller: editController,\n controllerAs: \"vm\",\n templateUrl: \"/App/ui/features/dashboard/controls/monitoring/\".concat(widgetName, \"Edit.html\"),\n reload: false\n }\n };\n dashboardProvider.widget(widgetName, widgetDefinition);\n }\n\n controller.$inject = [\"$scope\", \"$timeout\", \"promiseTracker\", \"app.core.services.settingsService\", \"app.core.services.monitoringService\"];\n\n function controller($scope, $timeout, promiseTracker, settingsService, monitoringService) {\n var vm = this;\n vm.busyLoading = promiseTracker();\n vm.config = $scope.config;\n vm.monitorDataAlarms = [];\n vm.hasSelectedMonitorTypes = false;\n var refreshMonitorDataAlarmsTimeout;\n activate(); //////////////////\n\n function activate() {\n $scope.$watch(function () {\n return vm.config.selectedMonitorTypes;\n }, onSelectedMonitorTypesChanged);\n\n function onSelectedMonitorTypesChanged(selectedMonitorTypes) {\n cancelMonitorDataAlarmsTimeout();\n vm.hasSelectedMonitorTypes = selectedMonitorTypes && selectedMonitorTypes.length;\n getMonitorDataAlarms();\n }\n }\n\n function getMonitorDataAlarms() {\n if (!vm.hasSelectedMonitorTypes) {\n return;\n }\n\n var loadMonitorDataAlarmsPromise = monitoringService.getMonitorDataAlarms(vm.config.selectedMonitorTypes, settingsService.getSampleDateTime());\n vm.busyLoading.addPromise(loadMonitorDataAlarmsPromise);\n loadMonitorDataAlarmsPromise.then(function (monitorDataAlarms) {\n vm.monitorDataAlarms = monitorDataAlarms;\n scheduleMonitorDataAlarmsTimeout();\n });\n }\n\n function scheduleMonitorDataAlarmsTimeout() {\n var refreshTimeoutSeconds = 60 - new Date().getSeconds();\n\n if (refreshTimeoutSeconds < 10) {\n refreshTimeoutSeconds += 60;\n }\n\n var refreshTimeoutMillis = refreshTimeoutSeconds * 1000;\n refreshMonitorDataAlarmsTimeout = $timeout(getMonitorDataAlarms, refreshTimeoutMillis);\n }\n\n function cancelMonitorDataAlarmsTimeout() {\n if (!refreshMonitorDataAlarmsTimeout) {\n return;\n }\n\n $timeout.cancel(refreshMonitorDataAlarmsTimeout);\n refreshMonitorDataAlarmsTimeout = null;\n }\n\n $scope.$on(\"$destroy\", function () {\n $timeout.cancel(refreshMonitorDataAlarmsTimeout);\n });\n }\n\n editController.$inject = [\"$scope\", \"lodash\", \"promiseTracker\", \"app.core.services.monitoringService\"];\n\n function editController($scope, _, promiseTracker, monitoringService) {\n var vm = this;\n vm.config = $scope.config;\n vm.availableMonitorTypes = [];\n vm.isMonitorTypeSelected = isMonitorTypeSelected;\n vm.toggleMonitorType = toggleMonitorType;\n vm.busyLoading = promiseTracker();\n activate(); ////////////////////\n\n function activate() {\n if (!vm.config.selectedMonitorTypes) {\n vm.config.selectedMonitorTypes = [];\n }\n\n loadMonitorTypes(); ////////////////////\n\n function loadMonitorTypes() {\n var getMonitorTypesPromise = monitoringService.getMonitorTypes();\n vm.busyLoading.addPromise(getMonitorTypesPromise);\n getMonitorTypesPromise.then(function (availableMonitorTypes) {\n vm.availableMonitorTypes = availableMonitorTypes;\n });\n }\n }\n\n function isMonitorTypeSelected(monitorType) {\n return vm.config.selectedMonitorTypes.indexOf(monitorType) >= 0;\n }\n\n function toggleMonitorType(monitorType) {\n var index = _.indexOf(vm.config.selectedMonitorTypes, monitorType);\n\n if (index >= 0) {\n vm.config.selectedMonitorTypes.splice(index, 1);\n vm.config.selectedMonitorTypes = _toConsumableArray(vm.config.selectedMonitorTypes);\n } else {\n vm.config.selectedMonitorTypes = vm.config.selectedMonitorTypes.concat(monitorType);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.dashboard\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.dashboard.state\"];\n\n function appRun(routeHelper, dashboardState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.dashboard\",\n url: \"/dashboard/{companyAlias}/{facilityAlias}?dateTime\",\n views: {\n contentPanel: {\n templateUrl: \"/App/ui/features/dashboard/ContentPanel.html\",\n controller: \"app.ui.features.dashboard.ContentPanel as vm\"\n }\n },\n data: {\n requiredAccessControl: \"app.dashboard\"\n },\n settings: {\n i18n: [\"/App/ui/features/dashboard/i18n/dashboard\", \"/App/ui/features/dashboard/controls/blasting/i18n/esBlastScenariosDashboardWidget\", \"/App/ui/features/dashboard/controls/modelling/i18n/esDailyModelsDashboardWidget\", \"/App/ui/features/dashboard/controls/monitoring/i18n/esMonitorGraphsDashboardWidget\", \"/App/ui/features/dashboard/controls/monitoring/i18n/esMonitorHealthDashboardWidget\", \"/App/ui/features/monitoring/controls/i18n/esMonitoringWidget\", \"/App/i18n/Shared\"]\n },\n resolve: {\n dashboardState: dashboardState\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.dashboard\").factory(\"app.ui.features.dashboard.state\", dashboardStateFactory);\n dashboardStateFactory.$inject = [\"app.core.services.dashboardService\"];\n\n function dashboardStateFactory(dashboardService) {\n return function () {\n return {\n dashboard: dashboardService.getDashboard()\n };\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.extras\").controller(\"app.ui.features.extras.about.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"i18n\", \"app.core.appSettings\", \"app.core.services.diagnosticsService\", \"app.core.services.dateTimeService\"];\n\n function ContentPanel(i18n, appSettings, diagnosticsService, dateTimeService) {\n var vm = this;\n vm.appSettings = appSettings;\n vm.processDataLastReceived;\n activate(); //////////////////\n\n function activate() {\n updateProcessDataLastReceived(\"loading\");\n diagnosticsService.getLatestProcessDataEndTime().then(function (endTime) {\n if (endTime) {\n var localEndTime = dateTimeService.formatAs.dateTime(endTime);\n updateProcessDataLastReceived(\"lastReceived\", {\n endTime: localEndTime\n });\n } else {\n updateProcessDataLastReceived(\"neverReceived\");\n }\n });\n }\n\n function updateProcessDataLastReceived(labelKeySuffix, formattingArgs) {\n var labelKey = \"app.ui.features.extras.about.contentPanel.diagnostics.processData.\".concat(labelKeySuffix);\n vm.processDataLastReceived = i18n.i10n(labelKey, formattingArgs || {});\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.extras\").controller(\"app.ui.features.extras.help.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"app.core.appSettings\"];\n\n function ContentPanel(appSettings) {\n var vm = this;\n vm.appSettings = appSettings;\n activate(); //////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.extras\").run(appRun);\n appRun.$inject = [\"routeHelper\"];\n\n function appRun(routeHelper) {\n routeHelper.configureRoutes(getRoutes());\n }\n\n function getRoutes() {\n return [{\n state: \"app.about\",\n url: \"/about\",\n views: {\n contentPanel: {\n templateUrl: \"/App/ui/features/extras/about/ContentPanel.html\",\n controller: \"app.ui.features.extras.about.ContentPanel as vm\"\n }\n },\n settings: {\n i18n: [\"/App/ui/features/extras/about/i18n/about\"]\n }\n }, {\n state: \"app.help\",\n url: \"/help\",\n views: {\n contentPanel: {\n templateUrl: \"/App/ui/features/extras/help/ContentPanel.html\",\n controller: \"app.ui.features.extras.help.ContentPanel as vm\"\n }\n },\n settings: {\n i18n: [\"/App/ui/features/extras/help/i18n/help\"]\n }\n }];\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").controller(\"app.ui.features.incidentIntelligence.artifacts.ActionsPanel\", ActionsPanel);\n ActionsPanel.$inject = [];\n\n function ActionsPanel() {\n var vm = this;\n vm.actions = {\n fullScreen: {\n isEnabled: false\n }\n };\n activate(); /////////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").controller(\"app.ui.features.incidentIntelligence.artifacts.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$q\", \"lodash\", \"notifier\", \"i18n\", \"$state\", \"app.core.services.dateTimeService\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.locationService\", \"state\", \"app.core.mapDefaults\", \"app.ui.core.mapping.mapLayerRenderer\", \"app.core.services.incidentIntelligenceService\", \"app.core.services.mappingService\", \"esLeafletData\"];\n /* istanbul ignore next */\n\n function ContentPanel($q, _, notifier, i18n, $state, dateTimeService, timeZoneService, locationService, state, mapDefaults, mapLayerRenderer, incidentIntelligenceService, mappingService, esLeafletData) {\n var vm = this;\n vm.state = state;\n vm.map = getMap();\n vm.mapLayerDatasets = [];\n vm.isReady = false;\n vm.showOverControls = false;\n activate(); //////////////////////\n\n function activate() {\n locationService.updatePageHeading({\n ticketId: $state.params.ticketId\n });\n incidentIntelligenceService.getPathModel($state.params.ticketId, $state.params.ticketActivityId).then(updateViewModel).then(loadOverlays).catch(processError).finally(function () {\n return vm.isReady = true;\n });\n }\n\n function loadOverlays() {\n return mappingService.getKmls().then(function (overlays) {\n vm.map.overlayProvider = overlays;\n vm.showOverlayControls = overlays && overlays.length;\n });\n }\n\n function updateViewModel(result) {\n var facilityTimeZoneStartTime = timeZoneService.convertDateTimeToFacilityTimeZone(result.startTime);\n locationService.updatePageHeading({\n ticketId: $state.params.ticketId,\n startTime: dateTimeService.formatAs.dateTime(facilityTimeZoneStartTime)\n });\n optimiseMapBounds(result.primaryTrack.data);\n var primaryTrackDataPoints = renderDataPoints(result.primaryTrack, result.isForwardTrajectory);\n vm.mapLayerDatasets.push(primaryTrackDataPoints); //////////////////\n\n function renderDataPoints(dataPoint, isForwardTrajectory) {\n mapLayerRenderer.renderPathLayer(dataPoint, isForwardTrajectory);\n delete dataPoint.data;\n return dataPoint;\n }\n\n function optimiseMapBounds(dataPoints) {\n return esLeafletData.getMap(vm.map.id).then(function (map) {\n map.fitBounds(getBounds(dataPoints));\n });\n\n function getBounds(dataPoints) {\n return _.map(dataPoints, function (dataPoint) {\n return [dataPoint.latitude, dataPoint.longitude];\n });\n }\n }\n }\n\n function processError(error) {\n if (error.status === 404) {\n notifier.error(i18n.i10n(\"app.ui.features.incidentIntelligence.artifacts.contentPanel.errors.notFound.message\", {\n ticketActivityId: $state.params.ticketActivityId\n }), i18n.i10n(\"app.ui.features.incidentIntelligence.artifacts.contentPanel.errors.notFound.title\"));\n error.handled = true;\n }\n }\n\n function getMap() {\n return {\n id: \"map-canvas\",\n defaultCentre: state.facilityLocation,\n centre: state.facilityLocation,\n isColor: false,\n defaults: {\n settings: mapDefaults.settings\n },\n layers: {\n baselayers: mapDefaults.baselayers\n },\n overlayProvider: {}\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").factory(\"app.ui.features.incidentIntelligence.hashParser\", hashParser);\n hashParser.$inject = [];\n /* istanbul ignore next */\n\n function hashParser() {\n return {\n buildOptionsHash: buildOptionsHash,\n configureOptionsFromHash: configureOptionsFromHash\n }; ////////////////////\n\n function buildOptionsHash(modelCategory) {\n return \"\".concat(modelCategory);\n }\n\n function configureOptionsFromHash(hash, modelsState) {\n var options = parseHashString(hash);\n modelsState.selectedModel = options.model;\n }\n\n function parseHashString() {\n var hash = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n var parts = hash.split(\"|\");\n return {\n model: parts[0]\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.incidentIntelligence.state\", \"app.ui.features.incidentIntelligence.summary.state\"];\n /* istanbul ignore next */\n\n function appRun(routeHelper, state, summaryState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.incidentIntelligence\",\n abstract: true,\n url: \"/incident-intelligence/:companyAlias/:facilityAlias\",\n data: {\n requiredAccessControl: \"app.incident-intelligence\"\n },\n settings: {\n i18n: [\"/App/ui/features/incidentIntelligence/i18n/incidentIntelligence\"]\n }\n }, {\n state: \"app.incidentIntelligence.tickets\",\n abstract: true,\n url: \"/tickets\"\n }, {\n state: \"app.incidentIntelligence.tickets.summary\",\n abstract: true,\n url: \"/summary\",\n views: {\n 'actionsPanel@app': {\n template: \"\"\n },\n 'leftPanel@app': {\n template: \"\"\n },\n 'contentPanel@app': {\n template: \"\"\n }\n },\n data: {\n layoutType: \"split\"\n },\n settings: {\n i18n: [\"/App/ui/core/mapping/i18n/mapLayerRenderer\", \"/App/ui/core/mapping/controls/i18n/esMapKml\", \"/App/ui/core/mapping/controls/i18n/esMapTiles\", \"/App/ui/core/mapping/controls/i18n/esMapCredits\", \"/App/ui/core/mapping/controls/i18n/esMapCentre\", \"/App/ui/core/mapping/controls/i18n/esMapType\", \"/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries\", \"/App/ui/features/incidentIntelligence/summary/i18n/LeftPanel\", \"/App/ui/features/incidentIntelligence/summary/i18n/ContentPanel\", \"/App/ui/features/incidentIntelligence/summary/i18n/ActionsPanel\"]\n },\n resolve: {\n summaryState: summaryState\n }\n }, ////////////////////////\n {\n state: \"app.incidentIntelligence.tickets.summary.heat\",\n url: \"/heat?fullScreen&mapType\",\n onEnter: onSummaryRouteEnter\n }, {\n state: \"app.incidentIntelligence.tickets.summary.cluster\",\n url: \"/cluster?fullScreen&mapType\",\n onEnter: onSummaryRouteEnter\n }, ////////////////////////\n {\n state: \"app.incidentIntelligence.tickets.ticket\",\n abstract: true,\n url: \"/:ticketId\"\n }, {\n state: \"app.incidentIntelligence.tickets.ticket.artifacts\",\n url: \"/artifacts/:ticketActivityId?fullScreen&mapType\",\n views: {\n 'actionsPanel@app': {\n templateUrl: \"/App/ui/features/incidentIntelligence/artifacts/ActionsPanel.html\",\n controller: \"app.ui.features.incidentIntelligence.artifacts.ActionsPanel as vm\"\n },\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/incidentIntelligence/artifacts/ContentPanel.html\",\n controller: \"app.ui.features.incidentIntelligence.artifacts.ContentPanel as vm\"\n }\n },\n resolve: {\n state: state\n },\n settings: {\n i18n: [\"/App/ui/core/mapping/i18n/mapLayerRenderer\", \"/App/ui/core/mapping/controls/i18n/esMapKml\", \"/App/ui/core/mapping/controls/i18n/esMapTiles\", \"/App/ui/core/mapping/controls/i18n/esMapCredits\", \"/App/ui/core/mapping/controls/i18n/esMapCentre\", \"/App/ui/core/mapping/controls/i18n/esMapType\", \"/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries\"]\n }\n }];\n } ////////////////////////\n\n\n onSummaryRouteEnter.$inject = [\"summaryState\"];\n\n function onSummaryRouteEnter(summaryState) {\n summaryState.map.isCluster = this.name === \"app.incidentIntelligence.tickets.summary.cluster\";\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n/* istanbul ignore next */\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").factory(\"app.ui.features.incidentIntelligence.state\", stateFactory);\n stateFactory.$inject = [\"$q\", \"app.core.services.companyService\"];\n\n function stateFactory($q, companyService) {\n return function stateFactoryResolver() {\n var loaders = [companyService.getFacilityLocation()];\n return $q.all(loaders).then(function (results) {\n var _results = _slicedToArray(results, 1),\n facilityLocation = _results[0];\n\n return new State(facilityLocation);\n });\n };\n\n function State(facilityLocation) {\n var self = this;\n self.facilityLocation = facilityLocation;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").component(\"incidentIntelligence.summary.actionsPanel\", {\n controller: ActionsPanelController,\n templateUrl: \"App/ui/features/incidentIntelligence/summary/ActionsPanel.html\",\n controllerAs: \"vm\",\n bindings: {}\n });\n ActionsPanelController.$inject = [];\n\n function ActionsPanelController() {\n var vm = this;\n\n vm.$onInit = function () {\n vm.actions = {\n fullScreen: {\n isEnabled: false\n }\n };\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").component(\"incidentIntelligence.summary.contentPanel\", {\n controller: ContentPanelController,\n templateUrl: \"/App/ui/features/incidentIntelligence/summary/ContentPanel.html\",\n controllerAs: \"vm\",\n bindings: {\n state: \"=\"\n }\n });\n ContentPanelController.$inject = [\"$window\", \"$state\", \"app.core.appSettings\", \"app.core.mapDefaults\", \"i18n\", \"app.core.services.mappingService\"];\n\n function ContentPanelController($window, $state, appSettings, mapDefaults, i18n, mappingService) {\n var vm = this;\n vm.$window = $window;\n vm.$state = $state;\n vm.map = getMap();\n vm.routes = getRoutes();\n vm.showOverlayControls = false;\n vm.onclick = onclick;\n activate(); ////////////////////\n\n function activate() {\n loadOverlays();\n }\n\n function getMap() {\n return {\n defaultCentre: vm.state.facilityLocation,\n centre: vm.state.facilityLocation,\n isColor: false,\n defaults: {\n settings: mapDefaults.settings\n },\n layers: {\n baselayers: mapDefaults.baselayers\n },\n overlayProvider: {},\n bounds: vm.state.map.bounds\n };\n }\n\n function loadOverlays() {\n return mappingService.getKmls().then(function (overlays) {\n vm.map.overlayProvider = overlays;\n vm.showOverlayControls = overlays && overlays.length;\n });\n }\n\n function onclick(marker) {\n if (appSettings.site.facility.ticketingSystem) {\n vm.$window.open(appSettings.site.facility.ticketingSystem.ticketUrl(marker.ticketId), \"_blank\");\n }\n }\n\n function getRoutes() {\n return [{\n name: i18n.i10n(\"app.ui.features.incidentIntelligence.summary.contentPanel.routes.heatmap.label\"),\n routeName: \"app.incidentIntelligence.tickets.summary.heat\"\n }, {\n name: i18n.i10n(\"app.ui.features.incidentIntelligence.summary.contentPanel.routes.cluster.label\"),\n routeName: \"app.incidentIntelligence.tickets.summary.cluster\"\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").component(\"incidentIntelligence.summary.leftPanel\", {\n controller: LeftPanelController,\n templateUrl: \"/App/ui/features/incidentIntelligence/summary/LeftPanel.html\",\n controllerAs: \"vm\",\n bindings: {\n state: \"=\"\n }\n });\n LeftPanelController.$inject = [\"$window\", \"$timeout\", \"lodash\", \"moment\", \"app.core.services.dateTimeService\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.incidentIntelligenceService\"];\n\n function LeftPanelController($window, $timeout, _, moment, dateTimeService, timeZoneDateTime, incidentIntelligenceService) {\n var vm = this;\n\n var search = _.debounce(function () {\n $timeout(searchSummaryValues);\n }, 1000);\n\n vm.toggleStatus = toggleStatus;\n vm.toggleType = toggleType;\n vm.criteriaChanged = search;\n\n vm.$onInit = function () {\n buildControls();\n searchSummaryValues(); /////////////////////\n\n function buildControls() {\n var maxDate = vm.state.ticket.facilityTimeZoneToDate;\n vm.controls = {\n fromDate: buildDatePicker(vm.state.ticket.facilityTimeZoneFromDate, maxDate),\n toDate: buildDatePicker(vm.state.ticket.facilityTimeZoneToDate, maxDate)\n };\n\n function buildDatePicker(dateTime) {\n return {\n formattedString: dateTimeService.formatAs.date(dateTime),\n options: {\n format: dateTimeService.formats.kendo.date,\n max: maxDate\n }\n };\n }\n }\n }; /////////////////////\n\n\n function toggleStatus(item) {\n toggleItem(vm.state.ticket.selectedStatuses, item);\n search();\n }\n\n function toggleType(item) {\n toggleItem(vm.state.ticket.selectedTypes, item);\n search();\n }\n\n function toggleItem(selectedItems, item) {\n if (item.isSelected) {\n selectedItems.push(item);\n } else {\n _.remove(selectedItems, {\n id: item.id\n });\n }\n }\n\n function searchSummaryValues() {\n if (vm.form && vm.form.$invalid) {\n return;\n }\n\n if (vm.state.ticket.selectedTypes.length && vm.state.ticket.selectedStatuses.length) {\n var fromDate = getDateInLocalTimeZone(moment(vm.state.ticket.facilityTimeZoneFromDate).startOf(\"day\").toDate());\n var toDate = getDateInLocalTimeZone(moment(vm.state.ticket.facilityTimeZoneToDate).endOf(\"day\").toDate());\n return incidentIntelligenceService.getTicketSummaryLocations({\n fromDate: fromDate,\n toDate: toDate,\n selectedCategoryId: vm.state.ticket.selectedCategoryId,\n selectedTypes: _.map(vm.state.ticket.selectedTypes, \"id\"),\n selectedStatuses: _.map(vm.state.ticket.selectedStatuses, \"id\")\n }).then(mapResults);\n } else {\n vm.state.ticketLocations = [];\n }\n } ////////////////////\n\n\n function getDateInLocalTimeZone(date) {\n return timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(date);\n }\n\n function mapResults(data) {\n vm.state.ticketLocations = _.map(data, function (result) {\n return {\n ticketId: result.ticketId,\n lat: result.latitude,\n long: result.longitude,\n tooltip: result.ticketId\n };\n });\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.incidentIntelligence\").factory(\"app.ui.features.incidentIntelligence.summary.state\", summaryStateFactory);\n summaryStateFactory.$inject = [\"$q\", \"lodash\", \"app.core.services.companyService\", \"app.core.services.incidentIntelligenceService\", \"app.core.datetime.timeZoneDateTime\"];\n\n function summaryStateFactory($q, _, companyService, incidentIntelligenceService, timeZoneDateTime) {\n return function () {\n var loaders = [companyService.getFacilityLocation(), incidentIntelligenceService.getSummaryLookupValues(), companyService.getDomainBoundaries(false, false, true)];\n return $q.all(loaders).then(function (results) {\n var _results = _slicedToArray(results, 3),\n facilityLocation = _results[0],\n lookupValues = _results[1],\n domainBoundaries = _results[2];\n\n return createState(facilityLocation, lookupValues, domainBoundaries);\n });\n };\n\n function createState(facilityLocation, lookupValues, domainBoundaries) {\n var nowTime = new Date();\n return {\n facilityLocation: facilityLocation,\n map: {\n isCluster: undefined,\n // this value is set in the route.onEnter event function\n bounds: getMapBounds()\n },\n ticketLocations: [],\n ticket: {\n categories: lookupValues.categories,\n selectedCategoryId: lookupValues.categories[0].id,\n types: _.map(lookupValues.types, function (type) {\n type.isSelected = true;\n return type;\n }),\n selectedTypes: _toConsumableArray(lookupValues.types),\n statuses: _.map(lookupValues.statuses, function (status) {\n status.isSelected = true;\n return status;\n }),\n selectedStatuses: _toConsumableArray(lookupValues.statuses),\n facilityTimeZoneFromDate: timeZoneDateTime.getFacilityStartOfDay(nowTime),\n facilityTimeZoneToDate: timeZoneDateTime.getFacilityEndOfDay(nowTime)\n }\n };\n\n function getMapBounds() {\n return domainBoundaries && _.reduce(domainBoundaries, function (memo, boundary) {\n var coordinates = [boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight];\n return memo.concat(_.map(coordinates, function (coordinate) {\n return [coordinate.latitude, coordinate.longitude];\n }));\n }, []);\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").controller(\"app.ui.features.modelling.ActionsPanel\", ActionsPanel);\n ActionsPanel.$inject = [\"$scope\", \"modellingState\"];\n\n function ActionsPanel($scope, modellingState) {\n var vm = this;\n vm.map = modellingState.map;\n vm.actions = {\n fullScreen: {\n isEnabled: false\n }\n };\n activate(); /////////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").controller(\"app.ui.features.modelling.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"lodash\", \"moment\", \"app.ui.features.modelling.mediator\", \"app.ui.features.modelling.timeStepCalculator\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.dateTimeService\", \"modellingState\", \"app.core.services.mappingService\", \"app.core.services.gisModelService\", \"app.core.models.monitoring.createMonitorMapMarker\"];\n /* istanbul ignore next */\n\n function ContentPanel($scope, _, moment, ModellingMediator, timeStepCalculator, timeZoneDateTime, dateTimeService, modellingState, mappingService, gisModelService, createMonitorMapMarker) {\n var millisPerMinute = 60 * 1000;\n var vm = this;\n var mediator = new ModellingMediator(modellingState, onModelDataRefreshed);\n vm.map = modellingState.map;\n vm.mapLayerDatasets = [];\n vm.overlayProvider = {};\n vm.showControls = false;\n vm.modellingState = modellingState;\n vm.timeSliderStart = null;\n vm.timeSliderEnd = null;\n vm.timeSliderStepSize = 0;\n vm.onActiveTimeStepChanged = onActiveTimeStepChanged;\n vm.hasTimeSteps = false;\n vm.hasSelectedModels = false;\n vm.hasModellingParameters = false;\n vm.hasDataForAnySelectedModel = false;\n vm.modelDataAvailability = modellingState.modelDataAvailability;\n vm.activeTimeStepStart = null;\n vm.activeTimeStepEnd = null;\n var discreteReceptorDisplayOptions = {\n monitorNames: false,\n units: false,\n heroMode: false,\n thresholdExceeded: false,\n dataValue: false,\n icons: true\n };\n activate(); //////////////////////\n\n function activate() {\n refreshWhenDateRangeChanges();\n refreshWhenChangingRealTimeModellingMode();\n refreshWhenSelectedModelsChange();\n watchTimeSlider();\n enableTimeSliderWhenSelectedModelsHaveData();\n destroyMediatorOnDeactivate();\n loadOverlays();\n }\n\n function watchTimeSlider() {\n $scope.$watchGroup([function () {\n return vm.hasSelectedModels;\n }, function () {\n return vm.isSingleTimeStep;\n }], function () {\n vm.showTimeSlider = vm.hasSelectedModels && !vm.isSingleTimeStep;\n triggerMapResize();\n });\n }\n\n function loadOverlays() {\n mappingService.getKmls().then(function (overlays) {\n vm.overlayProvider = overlays;\n vm.showControls = overlays && overlays.length > 0;\n });\n }\n\n function onModelDataRefreshed() {\n evaluateIfSelectedModelsHaveData();\n bindEnabledTimeStepDataToMap();\n }\n\n function onActiveTimeStepChanged(endTime) {\n var intervalMinutes = vm.modellingState.selectedInterval.minutes;\n var activeTimeRange = timeStepCalculator.calculateTimeStepRange(endTime, intervalMinutes, 0, intervalMinutes);\n\n if (Date.equals(vm.activeTimeStepStart, activeTimeRange.fromDate) && Date.equals(vm.activeTimeStepEnd, activeTimeRange.toDate)) {\n return;\n }\n\n vm.activeTimeStepStart = activeTimeRange.fromDate;\n vm.activeTimeStepEnd = activeTimeRange.toDate;\n bindEnabledTimeStepDataToMap();\n }\n\n function bindEnabledTimeStepDataToMap() {\n if (vm.activeTimeStepEnd) {\n vm.mapLayerDatasets = modellingState.modellingDataStore.getTimeStepDataForEnabledModels(vm.activeTimeStepEnd);\n renderDiscreteReceptors(modellingState.modellingDataStore.getTimeStepDiscreteReceptorDataForEnabledModels(vm.activeTimeStepEnd));\n }\n }\n\n function renderDiscreteReceptors(discreteReceptors) {\n vm.map.markers = discreteReceptors && discreteReceptors.map(function (discreteReceptor) {\n return createMonitorMapMarker(discreteReceptor, discreteReceptorDisplayOptions, getReportUri(vm.modellingState.alertPointReports, discreteReceptor));\n });\n\n function getReportUri(reports, discreteReceptor) {\n if (!reports) {\n return null;\n }\n\n var report = reports.find(function (report) {\n return report.processVariableIds.find(function (pv) {\n return pv === discreteReceptor.processVariable.id;\n });\n });\n\n if (!(report && report.uri)) {\n return null;\n }\n\n var monitorId = discreteReceptor.id;\n\n if (report && report.uri) {\n var startDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.modellingState.dataSetStartDate);\n var endDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.modellingState.dataSetEndDate);\n return \"\".concat(report.uri, \"?s=\").concat(dateTimeService.formatAs.iso(startDate), \"&e=\").concat(dateTimeService.formatAs.iso(endDate), \"&m=\").concat(monitorId);\n }\n }\n }\n\n function refreshWhenDateRangeChanges() {\n $scope.$watch(function () {\n return modellingState.dataSetStartDate + \"-\" + modellingState.dataSetEndDate;\n }, function () {\n if (!(modellingState.dataSetStartDate && modellingState.dataSetEndDate)) {\n return;\n }\n\n adjustActiveTimeStepToDataSetDateRange();\n updateTimeSliderParameters();\n mediator.refresh();\n });\n }\n\n function refreshWhenChangingRealTimeModellingMode() {\n $scope.$watch(function () {\n return \"\".concat(modellingState.dataSetStartDate, \"-\").concat(modellingState.dataSetEndDate, \"-\").concat(modellingState.autoUpdateEnabled);\n }, function () {\n var currentRealTimeMode = modellingState.realTimeMode;\n modellingState.realTimeMode = isRealTimeMode();\n\n if (currentRealTimeMode !== modellingState.realTimeMode) {\n vm.modellingState.clear();\n mediator.refresh();\n }\n });\n\n function isRealTimeMode() {\n return modellingState.dataSetStartDate && modellingState.dataSetEndDate && modellingState.dataSetStartDate.getTime() === modellingState.dataSetEndDate.getTime() && modellingState.autoUpdateEnabled;\n }\n }\n\n function adjustActiveTimeStepToDataSetDateRange() {\n if (!(modellingState.dataSetStartDate && modellingState.dataSetEndDate)) {\n return;\n }\n\n var intervalMillis = vm.modellingState.selectedInterval.minutes * millisPerMinute;\n var startMillis = modellingState.dataSetStartDate.getTime();\n var endMillis = modellingState.dataSetEndDate.getTime();\n var activeEndMillis = vm.activeTimeStepEnd ? vm.activeTimeStepEnd.getTime() : 0;\n var isUpdateRequired = false;\n\n if (activeEndMillis <= startMillis) {\n activeEndMillis = startMillis + intervalMillis;\n isUpdateRequired = true;\n } // We need to also check against the end time in case the user is looking at a \"0 => 0\" interval -\n // in this case, adjusting to startMillis + intervalMillis will have put us over the endMillis.\n\n\n if (activeEndMillis >= endMillis) {\n activeEndMillis = endMillis;\n isUpdateRequired = true;\n }\n\n if (isUpdateRequired) {\n onActiveTimeStepChanged(activeEndMillis);\n }\n }\n\n function refreshWhenSelectedModelsChange() {\n $scope.$watchCollection(function () {\n return modellingState.selectedModels;\n }, function (selectedModels, oldSelectedModels) {\n if (selectedModels === oldSelectedModels) {\n return;\n }\n\n var newModelIds = _.map(selectedModels, \"modelId\");\n\n var oldModelIds = _.map(oldSelectedModels, \"modelId\");\n\n _.difference(oldModelIds, newModelIds).forEach(function (modelId) {\n return modellingState.modellingDataStore.disableModel(modelId);\n });\n\n _.difference(newModelIds, oldModelIds).forEach(function (modelId) {\n return modellingState.modellingDataStore.enableModel(modelId);\n });\n\n vm.hasSelectedModels = !!newModelIds.length;\n mediator.refresh();\n bindEnabledTimeStepDataToMap();\n evaluateIfSelectedModelsHaveData();\n });\n }\n\n function triggerMapResize() {\n $scope.$broadcast(\"resizePage\");\n }\n\n function enableTimeSliderWhenSelectedModelsHaveData() {\n $scope.$watch(function () {\n return modellingState.modelLoadingStatuses;\n }, evaluateIfSelectedModelsHaveData, true);\n }\n\n function evaluateIfSelectedModelsHaveData() {\n var dateRange = modellingState.getDataSetDateRange();\n var intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\n vm.hasDataForAnySelectedModel = _.some(modellingState.selectedModels, function (model) {\n var modelDataAvailability = modellingState.modelDataAvailability[model.modelId];\n\n if (!modelDataAvailability) {\n return false;\n }\n\n for (var timeStepMillis = dateRange.toMillis; timeStepMillis > dateRange.fromMillis; timeStepMillis -= intervalMillis) {\n var hasData = modelDataAvailability[timeStepMillis];\n\n if (hasData) {\n return true;\n }\n }\n\n return false;\n });\n }\n\n function updateTimeSliderParameters() {\n vm.isSingleTimeStep = modellingState.dataSetStartDate.getTime() === modellingState.dataSetEndDate.getTime();\n\n var getTimeMillis = function getTimeMillis(date) {\n return date ? date.getTime() : 0;\n };\n\n vm.timeSliderStart = getTimeMillis(vm.modellingState.dataSetStartDate);\n vm.timeSliderEnd = getTimeMillis(vm.modellingState.dataSetEndDate);\n vm.timeSliderStepSize = vm.modellingState.selectedInterval.minutes * millisPerMinute;\n vm.timeSliderTooltip = {\n template: function template(data) {\n return moment(data.value).add(timeZoneDateTime.getFacilityTimeZoneOffsetDifferenceFromLocal(new Date(data.value)), \"minutes\").format(dateTimeService.formats.moment.dateTime);\n }\n };\n }\n\n function destroyMediatorOnDeactivate() {\n $scope.$on(\"$destroy\", mediator.dispose);\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").directive(\"esMapModels\", esMapModels);\n esMapModels.$inject = [\"leafletLib\", \"lodash\"];\n\n function esMapModels(L, _) {\n return {\n restrict: \"E\",\n require: \"^esLeaflet\",\n scope: {\n mapId: \"@\",\n models: \"=\"\n },\n link: link\n };\n\n function link($scope, $element, attrs, esLeafletData) {\n esLeafletData.getMap($scope.mapId).then(function (map) {\n var modelLayerIndex = {}; // eslint-disable-line no-unused-vars\n\n var baseLayer = new L.LayerGroup();\n baseLayer.addTo(map);\n map.createPane(\"path-std-deviation\");\n $scope.$watchCollection(function () {\n return $scope.models;\n }, toggleActiveLayers);\n $scope.$on(\"$destroy\", function () {\n return modelLayerIndex = {};\n });\n\n function toggleActiveLayers(currentDataPoints, previousDataPoints) {\n if (previousDataPoints) {\n previousDataPoints.forEach(function (dataPoint) {\n _.forEach(dataPoint.labels, function (label) {\n return label.closeTooltip();\n });\n\n baseLayer.removeLayer(dataPoint.layerGroup);\n });\n }\n\n if (currentDataPoints) {\n currentDataPoints.forEach(function (dataPoint) {\n baseLayer.addLayer(dataPoint.layerGroup);\n\n _.forEach(dataPoint.labels, function (label) {\n label.openTooltip();\n });\n });\n }\n }\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").directive(\"esModellingDurationSelect\", esModellingDurationSelect).controller(\"esModellingDurationSelectController\", esModellingDurationSelectController);\n\n function esModellingDurationSelect() {\n return {\n restrict: \"E\",\n scope: {\n selectedDuration: \"=\",\n availableDurations: \"=\",\n textPrefix: \"=\"\n },\n templateUrl: \"/App/ui/features/modelling/controls/esModellingDurationSelect.html\",\n controller: esModellingDurationSelectController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esModellingDurationSelectController.$inject = [\"$scope\", \"i18n\", \"lodash\"];\n\n function esModellingDurationSelectController($scope, i18n, _) {\n var vm = this;\n vm.select = null;\n activate(); ////////////////////\n\n function activate() {\n updateSelectableDurationsWhenAvailableDurationsChange();\n }\n\n function updateSelectableDurationsWhenAvailableDurationsChange() {\n $scope.$watch(function () {\n return vm.availableDurations;\n }, function () {\n vm.formattedDurations = _.map(vm.availableDurations, function (val) {\n return {\n text: vm.textPrefix + minutesToText(val),\n value: val\n };\n });\n });\n }\n\n function minutesToText(minutes) {\n if (minutes <= 90) {\n return \"\".concat(minutes, \" \").concat(i18n.i10n(\"esModellingDurationSelect.labels.minutes\"));\n }\n\n var hours = minutes / 60;\n\n if (hours !== Math.floor(hours)) {\n hours = hours.toFixed(2);\n }\n\n return \"\".concat(hours, \" \").concat(i18n.i10n(\"esModellingDurationSelect.labels.hours\"));\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").directive(\"esModellingModelSelect\", esModellingModelSelect).controller(\"esModellingModelSelectController\", esModellingModelSelectController);\n\n function esModellingModelSelect() {\n return {\n restrict: \"E\",\n scope: {\n state: \"=\",\n textPrefix: \"=\"\n },\n templateUrl: \"/App/ui/features/modelling/controls/esModellingModelSelect.html\",\n controller: esModellingModelSelectController,\n controllerAs: \"vm\",\n bindToController: true\n };\n }\n\n esModellingModelSelectController.$inject = [\"$scope\", \"$timeout\", \"lodash\", \"app.core.models.modelLoadingStatus\"];\n\n function esModellingModelSelectController($scope, $timeout, _, modelLoadingStatus) {\n var vm = this;\n var unwatchLegends = [];\n vm.toggleModel = _.debounce(function (args) {\n return $timeout(toggleModel(args));\n }, 500);\n vm.toggleLegend = toggleLegend;\n vm.modelLegendClasses = {};\n vm.modelLegendTooltips = {};\n activate(); ////////////////////\n\n function activate() {\n updateModelLegendClassesAndTooltipsWhenDataSetChanges();\n updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges();\n }\n\n function updateModelLegendClassesAndTooltipsWhenDataSetChanges() {\n var dataSetDateWatchers = [function () {\n return vm.state.dataSetStartDate;\n }, function () {\n return vm.state.dataSetEndDate;\n }];\n $scope.$watchGroup(dataSetDateWatchers, rebuildAllLegendClassesAndTooltips);\n $scope.$watch(function () {\n return vm.state.modelLoadingStatuses;\n }, rebuildAllLegendClassesAndTooltips, true);\n $scope.$watch(function () {\n return vm.state.selectedInterval;\n }, updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges);\n }\n\n function updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges() {\n unwatchLegends.forEach(function (unwatch) {\n return unwatch();\n });\n unwatchLegends = vm.state.selectedInterval.models.map(function (model) {\n return $scope.$watch(function () {\n return model.legend.visible;\n }, function () {\n return rebuildLegendClassesAndTooltipForModel(model);\n });\n });\n }\n\n function rebuildAllLegendClassesAndTooltips() {\n vm.state.selectedInterval.models.forEach(rebuildLegendClassesAndTooltipForModel);\n }\n\n function rebuildLegendClassesAndTooltipForModel(model) {\n var modelId = model.modelId;\n var status = vm.state.getModelLoadingStatus(modelId);\n var isLoading = status === modelLoadingStatus.loading;\n var hasFailed = status === modelLoadingStatus.failed;\n var classes = [\"fa\"];\n var tooltip;\n\n if (!(isLoading || hasFailed)) {\n classes.push(model.legend.visible ? \"fa-caret-down\" : \"fa-caret-right\");\n tooltip = \"legend\";\n } else if (!isLoading) {\n classes.push(\"fa-exclamation-circle\");\n tooltip = \"loadingFailed\";\n } else {\n classes.push(\"fa-circle-o-notch fa-spin\");\n tooltip = \"loadingModel\";\n }\n\n vm.modelLegendClasses[modelId] = classes.join(\" \");\n vm.modelLegendTooltips[modelId] = \"esModellingModelSelect.\".concat(tooltip, \".tooltip\");\n }\n\n function toggleModel(model) {\n vm.state.setModelSelected(model, model.isSelected);\n }\n\n function toggleLegend(legend) {\n legend.visible = !legend.visible;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").factory(\"app.ui.features.modelling.hashParser\", hashParser);\n hashParser.$inject = [\"lodash\", \"moment\", \"app.core.services.dateTimeService\"];\n\n function hashParser(_, moment, dateTimeService) {\n var AUTO_UPDATE = \"auto\";\n var KNOWN_DATES = [\"yesterday\", \"last24hrs\", \"today\", \"now\", \"tomorrow\"];\n return {\n buildModelRunOptionsHash: buildModelRunOptionsHash,\n configureModelRunOptionsFromHash: configureModelRunOptionsFromHash\n }; ////////////////////\n\n function buildModelRunOptionsHash(modelIds) {\n var date = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"now\";\n var durationFrom = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var durationTo = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;\n var autoUpdate = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;\n\n if (modelIds === undefined || modelIds === null) {\n throw new Error(\"A model id must be provided.\");\n }\n\n var hashDate = buildHashDate(date, autoUpdate);\n var modelIdList = modelIds instanceof Array ? modelIds.join(\",\") : modelIds;\n return autoUpdate ? \"\".concat(modelIdList, \"|\").concat(hashDate, \"|0|0\") : \"\".concat(modelIdList, \"|\").concat(hashDate, \"|\").concat(durationFrom, \"|\").concat(durationTo);\n }\n\n function buildHashDate(date, autoUpdate) {\n if (autoUpdate) {\n return AUTO_UPDATE;\n }\n\n if (date instanceof Date) {\n return dateTimeService.formatAs.iso(date);\n }\n\n if (moment.isMoment(date)) {\n return dateTimeService.formatAs.iso(date.toDate());\n }\n\n return KNOWN_DATES.find(function (knownDate) {\n return knownDate === date;\n }) && date || \"now\";\n }\n\n function configureModelRunOptionsFromHash(hash, leftPanelController) {\n var parsedHash = parseHashString(hash);\n setSelectedModelDetails(parsedHash, leftPanelController);\n setSelectedDateDetails(parsedHash, leftPanelController);\n }\n\n function setSelectedDateDetails(parsedHash, leftPanelController) {\n if (parsedHash.autoUpdate) {\n leftPanelController.modellingState.autoUpdateEnabled = true;\n return;\n }\n\n var availableIntervals = leftPanelController.modellingState.selectedInterval.durationRanges;\n leftPanelController.durationTo = getClosestMatchingInterval(parsedHash.durationTo);\n leftPanelController.durationFrom = getClosestMatchingInterval(parsedHash.durationFrom);\n\n if (!isNaN(+parsedHash.date)) {\n leftPanelController.datePicker.date = parsedHash.date;\n leftPanelController.datePicker.dateString = dateTimeService.formatAs.dateTime(parsedHash.date);\n }\n\n function getClosestMatchingInterval(requestedInterval) {\n requestedInterval = Math.abs(requestedInterval || 0);\n\n for (var i = 0; i < availableIntervals.length; i++) {\n var interval = availableIntervals[i];\n\n if (interval >= requestedInterval) {\n return interval;\n }\n }\n\n return _.last(availableIntervals);\n }\n }\n\n function setSelectedModelDetails(parsedHash, leftPanelController) {\n var modellingState = leftPanelController.modellingState;\n\n for (var i = 0; i < modellingState.intervals.length; i++) {\n var interval = modellingState.intervals[i];\n var validModels = getIntervalModelsFoundInHash(parsedHash.modelIds, interval);\n\n if (!(validModels && validModels.length)) {\n continue;\n }\n\n Array.prototype.push.apply(modellingState.selectedModels, validModels);\n modellingState.selectedInterval = interval;\n\n _.forEach(validModels, function (model) {\n return model.isSelected = true;\n });\n\n break;\n }\n }\n\n function getIntervalModelsFoundInHash(modelIds, interval) {\n return _.filter(interval.models, function (model) {\n return _.includes(modelIds, model.modelId);\n });\n }\n\n function parseHashString() {\n var hash = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n\n if (!hash) {\n return {};\n }\n\n var parts = hash.split(\"|\");\n var modelIds = (parts[0] || \"\").split(\",\").map(function (modelId) {\n return modelId.toLowerCase();\n });\n var date = parts.length > 1 && parts[1];\n return {\n modelIds: modelIds,\n autoUpdate: date && date.toLocaleLowerCase() === AUTO_UPDATE,\n date: getDate(date),\n durationFrom: parts.length > 2 && parseInt(parts[2]),\n durationTo: parts.length > 3 && parseInt(parts[3])\n };\n\n function getDate() {\n var dateString = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n\n switch (dateString.toLowerCase()) {\n case \"yesterday\":\n return moment().add(-1, \"day\").startOf(\"day\").toDate();\n\n case \"last24hrs\":\n return moment().add(-1, \"day\").startOf(\"hour\").toDate();\n\n case \"now\":\n case AUTO_UPDATE:\n return new Date();\n\n case \"today\":\n return moment().startOf(\"day\").toDate();\n\n case \"tomorrow\":\n return moment().add(1, \"day\").startOf(\"day\").toDate();\n\n default:\n return new Date(dateString);\n }\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").controller(\"app.ui.features.modelling.LeftPanel\", LeftPanel);\n LeftPanel.$inject = [\"$scope\", \"$timeout\", \"$state\", \"$location\", \"$log\", \"i18n\", \"lodash\", \"Mousetrap\", \"notifier\", \"app.core.appSettings\", \"app.core.models.jobs.Job\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.gisModelService\", \"app.core.services.dateTimeService\", \"app.core.signalR.jobs.state\", \"app.ui.features.modelling.timeStepCalculator\", \"app.ui.features.modelling.hashParser\", \"modellingState\", \"kendo\"];\n\n function LeftPanel($scope, $timeout, $state, $location, $log, i18n, _, Mousetrap, notifier, appSettings, Job, timeZoneDateTime, gisModelService, dateTimeService, jobState, timeStepCalculator, hashParser, modellingState, kendo) {\n var vm = this;\n var trackModelDurationWarnings = false;\n var modelDurationTimeStepWarningCount = 240;\n var millisPerMinute = 60 * 1000;\n var autoUpdateTimeout = null;\n vm.modellingState = modellingState;\n vm.datePicker = getDatePicker();\n vm.durationFrom = 0;\n vm.durationTo = 0;\n vm.onAutoUpdateChanged = onAutoUpdateChanged;\n vm.appSettings = appSettings;\n vm.warningClassName = null;\n\n var updateModelHashUrlParameter = _.debounce(function (modelHash) {\n var toParams = {\n modelhash: modelHash\n };\n $timeout(function () {\n return $state.go(\"app.modelling.gisModelling\", toParams, {\n notify: false\n });\n });\n }, 50);\n\n activate();\n\n function activate() {\n hashParser.configureModelRunOptionsFromHash($location.search().modelhash, vm);\n subscribeToDateChanges();\n subscribeToIntervalChanges();\n updateModelHashIfAutoUpdateChanges();\n updateModelHashIfSelectedModelsChange();\n }\n\n function onAutoUpdateChanged() {\n $timeout.cancel(autoUpdateTimeout);\n\n if (modellingState.autoUpdateEnabled) {\n scheduleNextAutoUpdateOfSelectedDate();\n }\n\n function scheduleNextAutoUpdateOfSelectedDate() {\n var lastInterval = rebaseSelectedTimeToLastInterval();\n var intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\n var nextIntervalAt = new Date(lastInterval.getTime() + intervalMillis);\n var now = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date());\n var timeUntilNextIntervalMillis = nextIntervalAt.getTime() - now.getTime();\n var seconds = parseInt(timeUntilNextIntervalMillis / 1000);\n $log.debug(\"Next tick scheduled in: \".concat(parseInt(seconds / 60), \"m \").concat(parseInt(seconds % 60), \"s.\"));\n autoUpdateTimeout = $timeout(function () {\n if (modellingState.autoUpdateEnabled) {\n scheduleNextAutoUpdateOfSelectedDate();\n }\n }, timeUntilNextIntervalMillis);\n }\n\n function rebaseSelectedTimeToLastInterval() {\n var now = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date());\n var lastIntervalMillis = timeStepCalculator.getLastIntervalMillis(now, modellingState.selectedInterval.minutes);\n var lastInterval = new Date(lastIntervalMillis);\n $log.debug(\"Current date time set to last interval: \".concat(lastInterval, \".\"));\n return vm.datePicker.date = lastInterval;\n }\n }\n\n function subscribeToDateChanges() {\n var i10nWarningPrefix = \"app.ui.features.modelling.leftPanel.model.duration.warning\";\n $scope.$watch(function () {\n return vm.durationFrom + \"-\" + vm.durationTo + \"-\" + vm.datePicker.date;\n }, function () {\n if (vm.form && vm.form.date && vm.form.date.$invalid) {\n return;\n }\n\n var intervalMinutes = modellingState.selectedInterval.minutes;\n var selectedDate = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.datePicker.date);\n var timeRange = timeStepCalculator.calculateTimeStepRange(selectedDate, vm.durationFrom, vm.durationTo, intervalMinutes);\n\n if (trackModelDurationWarnings) {\n if (timeRange.timeStepCount > modelDurationTimeStepWarningCount) {\n var suffix = modellingState.selectedModels.length ? i18n.i10n(\"\".concat(i10nWarningPrefix, \".existing-models.label\")) : \"\";\n var prefix = i18n.i10n(\"\".concat(i10nWarningPrefix, \".label\"));\n modellingState.modelDurationWarning = \"\".concat(prefix, \" \").concat(suffix);\n vm.warningClassName = modellingState.selectedModels.length ? \"duration-warning-models\" : \"duration-warning\";\n modellingState.selectedModels.length = 0;\n modellingState.selectedInterval.models.forEach(function (model) {\n return model.isSelected = false;\n });\n } else {\n modellingState.modelDurationWarning = null;\n }\n }\n\n trackModelDurationWarnings = true;\n vm.modellingState.dataSetStartDate = timeRange.fromDate;\n vm.modellingState.dataSetEndDate = timeRange.toDate;\n recalculateModelHash();\n });\n }\n\n function subscribeToIntervalChanges() {\n $scope.$watch(function () {\n return modellingState.selectedInterval;\n }, function (interval, oldInterval) {\n modellingState.modelDurationWarning = interval.minutes === oldInterval.minutes ? modellingState.modelDurationWarning : null;\n resetSelectedModels(interval, oldInterval);\n updateTimePickerDropdownTimeIntervals(interval);\n\n if (!modellingState.autoUpdateEnabled) {\n rebaseSelectedTimeToIntervalBoundary();\n } else {\n onAutoUpdateChanged();\n }\n\n recalculateModelHash();\n });\n\n function resetSelectedModels(interval, oldInterval) {\n if (interval === oldInterval) {\n return;\n }\n\n modellingState.selectedModels.length = 0;\n modellingState.selectedInterval.models.forEach(function (model) {\n return model.isSelected = false;\n });\n vm.durationFrom = 0;\n vm.durationTo = 0;\n }\n\n function updateTimePickerDropdownTimeIntervals(interval) {\n // ensure the date - picker has been rendered before doing this.\n if (!vm.datePicker.kendoDatePicker) {\n return;\n }\n\n angular.extend(vm.datePicker.options, {\n interval: interval.minutes\n });\n vm.datePicker.kendoDatePicker.setOptions(vm.datePicker.options);\n }\n }\n\n function updateModelHashIfAutoUpdateChanges() {\n $scope.$watch(function () {\n return modellingState.autoUpdateEnabled;\n }, function (current, previous) {\n if (current !== previous) {\n recalculateModelHash();\n }\n });\n }\n\n function updateModelHashIfSelectedModelsChange() {\n $scope.$watch(function () {\n return modellingState.selectedModels.length;\n }, function (current, previous) {\n if (current !== previous) {\n recalculateModelHash();\n }\n });\n }\n\n function recalculateModelHash() {\n var selectedModels = modellingState.selectedModels,\n autoUpdateEnabled = modellingState.autoUpdateEnabled;\n var selectedDate = vm.datePicker.date,\n durationFrom = vm.durationFrom,\n durationTo = vm.durationTo;\n var modelIds = selectedModels.map(function (model) {\n return model.modelId;\n });\n var modelHash = hashParser.buildModelRunOptionsHash(modelIds, selectedDate, durationFrom, durationTo, autoUpdateEnabled);\n updateModelHashUrlParameter(modelHash);\n }\n\n function getDatePicker() {\n var initialDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date());\n return {\n hasFocus: false,\n date: initialDate,\n dateString: dateTimeService.formatAs.dateTime(initialDate),\n options: {\n // note: anything provided in here is angular bound. don't put an event handler in here otherwise you have to run $scope.$apply()\n format: dateTimeService.formats.kendo.dateTime,\n timeFormat: dateTimeService.formats.kendo.time,\n interval: modellingState.selectedInterval.minutes\n },\n onChange: function onChange() {\n if (!vm.form || !vm.form.date || vm.form.date.$invalid) {\n return;\n }\n\n vm.datePicker.dateString = kendo.toString(vm.datePicker.date, dateTimeService.formats.kendo.dateTime);\n rebaseSelectedTimeToIntervalBoundary();\n vm.datePicker.onBlur();\n },\n onFocus: function onFocus() {\n vm.datePicker.hasFocus = true;\n },\n onBlur: function onBlur() {\n vm.datePicker.hasFocus = false;\n }\n };\n }\n\n function rebaseSelectedTimeToIntervalBoundary() {\n var intervalMillis = timeStepCalculator.getLastIntervalMillis(vm.datePicker.date, modellingState.selectedInterval.minutes);\n vm.datePicker.date = new Date(intervalMillis);\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").factory(\"app.ui.features.modelling.ModellingDataStore\", modellingDataStore);\n modellingDataStore.$inject = [\"lodash\", \"app.core.models.mapping.dataPointFactory\", \"app.ui.core.mapping.mapLayerRenderer\"];\n\n function modellingDataStore(_, dataPointFactory, mapLayerRenderer) {\n function ModellingDataStore() {\n // Used by consumer to get the current modelDataPoints for specific `active` date\n this._dateIndex = {}; // Used by consumer to get all the imported time steps for a specific model\n // so missing periods can be retrieved from server\n\n this._importedTimeSteps = {}; // Used internally so that if the same dataPoints happen to be\n // provided twice, it is only processed once\n\n this._availableTimeStepDataIds = {}; // Used internally to ascertain which models have been flagged as disabled\n // so that when #getTimeStepDataForEnabledModels() is invoked, only those that are active are retrieved.\n // This is to allow us to retain dataPoints even if toggled off in case it is toggled straight back on\n\n this._disabledModels = {}; // Used by consumer to get all discrete receptor values at a specific `active` date\n\n this._discreteReceptorValues = {};\n }\n\n ModellingDataStore.prototype.importDiscreteReceptorData = function (modelId, discreteReceptorData) {\n var self = this;\n\n if (_.isEmpty(discreteReceptorData)) {\n return;\n }\n\n Object.entries(discreteReceptorData).forEach(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n key = _ref2[0],\n value = _ref2[1];\n\n var dateKey = new Date(key).getTime();\n var bucket = self._discreteReceptorValues[dateKey] || (self._discreteReceptorValues[dateKey] = {});\n bucket[modelId] = value;\n });\n };\n\n ModellingDataStore.prototype.getTimeStepDiscreteReceptorDataForEnabledModels = function (date) {\n var self = this;\n var dateKey = date.getTime();\n var bucket = self._discreteReceptorValues[dateKey];\n\n if (!bucket) {\n return;\n }\n\n return Object.keys(bucket).reduce(function (data, key) {\n if (!self._disabledModels[key]) {\n data.push.apply(data, _toConsumableArray(bucket[key]));\n }\n\n return data;\n }, []);\n };\n\n ModellingDataStore.prototype.importModelDataSets = function (modelDataSets) {\n var self = this;\n return _.chain(modelDataSets).map(importTimeStepData).flatten().value(); ////////////////////\n\n function importTimeStepData(dataSet) {\n var timeStepDataSet = dataSet.temporalData;\n\n if (!(timeStepDataSet && timeStepDataSet.data.length)) {\n // we may not have time step data for this model.\n return [];\n }\n\n var modelId = dataSet.modelId;\n var modelType = timeStepDataSet.type;\n return timeStepDataSet.data.map(function (timeStepData) {\n var timeStepEndDate = new Date(timeStepData.utcEndTime);\n var timeStepMillis = timeStepEndDate.getTime();\n var dataPointId = \"\".concat(modelId, \"-\").concat(timeStepMillis);\n var dataPoint = dataPointFactory.create(modelType, timeStepData);\n dataPoint.id = dataPointId;\n dataPoint.modelId = modelId;\n mapLayerRenderer.renderLayer(dataPoint);\n delete dataPoint.data;\n addToDateIndex(timeStepEndDate, dataPoint);\n addToImportedTimeSteps(modelId, timeStepMillis);\n addToModelDataPointIndex(dataPointId);\n return timeStepMillis;\n });\n }\n\n function addToDateIndex(date, dataPoint) {\n var key = date.getTime();\n var bucket = self._dateIndex[key] || (self._dateIndex[key] = []); // overwrite old data\n\n var itemAdded = false;\n\n for (var i = 0; !itemAdded && i < bucket.length; i++) {\n var existingDataPoint = bucket[i];\n\n if (existingDataPoint.modelId === dataPoint.modelId && existingDataPoint.id === dataPoint.id && existingDataPoint.type === dataPoint.type) {\n bucket[i] = dataPoint;\n itemAdded = true;\n }\n }\n\n if (!itemAdded) {\n bucket.push(dataPoint);\n }\n }\n\n function addToImportedTimeSteps(modelId, timeStepMillis) {\n var bucket = self._importedTimeSteps[modelId] || (self._importedTimeSteps[modelId] = {});\n bucket[timeStepMillis] = true;\n }\n\n function addToModelDataPointIndex(timeStepDataId) {\n self._availableTimeStepDataIds[timeStepDataId] = true;\n }\n };\n\n ModellingDataStore.prototype.enableModel = function (modelId) {\n delete this._disabledModels[modelId];\n rebuildRenderingLayers(modelId);\n\n function rebuildRenderingLayers(modelId) {\n _.forEach(self._dateIndex, function (dataPoint) {\n //TODO: 28/04/2016 - bpriebe - investigate how this got in\n if (item.modelId !== modelId) {\n // eslint-disable-line no-undef\n return;\n }\n\n mapLayerRenderer.addLayer(dataPoint);\n });\n }\n };\n\n ModellingDataStore.prototype.disableModel = function (modelId) {\n this._disabledModels[modelId] = modelId;\n releaseRenderingLayers(modelId);\n\n function releaseRenderingLayers(modelId) {\n _.forEach(self._dateIndex, function (dataPoint) {\n //TODO: 28/04/2016 - bpriebe - investigate how this got in\n if (item.modelId !== modelId) {\n // eslint-disable-line no-undef\n return;\n }\n\n mapLayerRenderer.removeLayer(dataPoint);\n });\n }\n };\n\n ModellingDataStore.prototype.getTimeStepDataForEnabledModels = function (date) {\n var self = this;\n var key = date.getTime();\n\n if (!self._dateIndex[key]) {\n return null;\n }\n\n return self._dateIndex[key].filter(function (item) {\n return !self._disabledModels[item.modelId];\n });\n };\n\n ModellingDataStore.prototype.getImportedTimeStepsForModel = function (modelId) {\n var self = this;\n\n if (!self._importedTimeSteps[modelId]) {\n return [];\n }\n\n var timeSteps = Object.keys(self._importedTimeSteps[modelId]).map(function (key) {\n return parseInt(key);\n });\n timeSteps.sort(function (left, right) {\n return left - right;\n });\n return timeSteps;\n };\n\n ModellingDataStore.prototype.modelHasDataAt = function (modelId, timeMillis) {\n var self = this;\n return _.has(self._dateIndex, timeMillis);\n };\n\n return ModellingDataStore;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").factory(\"app.ui.features.modelling.mediator\", modellingMediatorFactory);\n modellingMediatorFactory.$inject = [\"$q\", \"lodash\", \"postal\", \"moment\", \"app.core.services.gisModelService\", \"app.core.signalR.jobs.state\", \"app.core.signalR.jobs.events\", \"app.core.models.jobs.jobCompletionStatus\", \"app.core.models.modelLoadingStatus\"];\n\n function modellingMediatorFactory($q, _, postal, moment, gisModelService, jobState, jobEvents, jobCompletionStatus, modelLoadingStatus) {\n var millisPerMinute = 60 * 1000;\n return function ModellingMediator(modellingState, onMediatorRefreshed) {\n var subscriptions;\n var currentState = {\n selectedModelIds: [],\n fromMillis: 0,\n toMillis: 0\n };\n this.refresh = _.debounce(refresh, 0);\n this.dispose = dispose;\n activate(); ////////////////////\n\n function activate() {\n if (!modellingState) {\n throw new Error(\"You must provide the modelling state.\");\n }\n\n var channel = postal.channel(jobEvents.channelName);\n subscriptions = [channel.subscribe(jobEvents.topics.jobStale, onJobStale), channel.subscribe(jobEvents.topics.jobCompleted, onJobCompleted), channel.subscribe(jobEvents.topics.jobDismissed, onJobDismissed)];\n }\n\n function refresh() {\n var modelIdsToLoad;\n\n var selectedModelIds = _.map(modellingState.selectedModels, \"modelId\");\n\n var fromMillis = modellingState.dataSetStartDate && modellingState.dataSetStartDate.getTime();\n var toMillis = modellingState.dataSetEndDate && modellingState.dataSetEndDate.getTime();\n var autoUpdateEnabled = modellingState.autoUpdateEnabled; // No point trying to refresh until we have at least one model selected and a valid date/time range.\n\n var canRefresh = selectedModelIds.length && fromMillis && toMillis;\n var isRefreshRequired = false;\n\n if (canRefresh) {\n isRefreshRequired = currentState.fromMillis !== fromMillis || currentState.toMillis !== toMillis || currentState.autoUpdateEnabled !== autoUpdateEnabled;\n\n if (isRefreshRequired) {\n modelIdsToLoad = selectedModelIds;\n } else {\n modelIdsToLoad = _.difference(selectedModelIds, currentState.selectedModelIds);\n isRefreshRequired = !!modelIdsToLoad.length;\n }\n } // Store the current state at the point the mediator is refreshing so we can determine if anything\n // has changed the next time something calls `refresh`.\n\n\n currentState = {\n selectedModelIds: selectedModelIds,\n fromMillis: fromMillis,\n toMillis: toMillis,\n autoUpdateEnabled: autoUpdateEnabled\n };\n\n if (isRefreshRequired) {\n loadDataForModels(modelIdsToLoad);\n } else {\n resyncModelDataAvailability();\n }\n }\n\n function loadDataForModels(modelIds) {\n var loaders = [];\n var dateRange = modellingState.getDataSetDateRange();\n var intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\n\n _.forEach(modelIds, function (modelId) {\n var indexedTimeSteps = modellingState.modellingDataStore.getImportedTimeStepsForModel(modelId);\n var latestUnindexedTimeStepMillis = null; // Work through the entire data set time range to work out the parts that need to be loaded. For example, if the time range\n // is from 12 PM - 9 PM, and we already have data from 3 PM - 6 PM, this will end up asking for two sets of data to be loaded\n // (from 6 PM - 9 PM, and 12 PM - 3 PM).\n\n for (var timeStepMillis = dateRange.toMillis; timeStepMillis > dateRange.fromMillis; timeStepMillis -= intervalMillis) {\n if (isTimeStepIndexed(timeStepMillis) && latestUnindexedTimeStepMillis) {\n loadTimeRangeIfRequired(timeStepMillis, latestUnindexedTimeStepMillis);\n latestUnindexedTimeStepMillis = null;\n } else if (!latestUnindexedTimeStepMillis) {\n latestUnindexedTimeStepMillis = timeStepMillis;\n }\n }\n\n if (latestUnindexedTimeStepMillis) {\n loadTimeRangeIfRequired(dateRange.fromMillis, latestUnindexedTimeStepMillis);\n }\n\n function isTimeStepIndexed(timeStepMillis) {\n return indexedTimeSteps.indexOf(timeStepMillis) >= 0;\n }\n\n function loadTimeRangeIfRequired(fromMillis, toMillis) {\n if (!doesActiveJobExist(modelId, fromMillis, toMillis, true)) {\n // We need to ask for the data again UNLESS we already have a job running for this exact time range\n if (modellingState.realTimeMode) {\n // In this scenario we want to show the plume/wind model for the latest data we have, not the exact time.\n loaders.push(loadTimeAdjustedDataForModel(modelId, fromMillis, toMillis));\n } else {\n loaders.push(loadDataForModel(modelId, fromMillis, toMillis));\n } // Update data availability for this model to reflect the fact there are unloaded data segments\n\n\n updateModelDataAvailability(modelId);\n } else {\n // We are already loading data, so make sure the loading state reflects this (caters for the\n // user asking for the same set of data after refreshing the screen and there is an active\n // job already running).\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.loading, fromMillis, toMillis);\n }\n }\n });\n\n if (!loaders.length) {\n return;\n }\n\n $q.all(loaders).then(function () {\n return onMediatorRefreshed();\n });\n }\n\n function loadTimeAdjustedDataForModel(modelId, fromMillis, toMillis) {\n var intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\n var oneHourBeforeToTimeMillis = toMillis - millisPerMinute * 60;\n return gisModelService.getModelDataAvailability(modelId).then(function (availability) {\n var latestModelAvailabilityMillis = availability.latestTime.getTime();\n var adjustedToMillis = latestModelAvailabilityMillis < oneHourBeforeToTimeMillis ? toMillis : Math.min(toMillis, availability.latestTime.getTime());\n var adjustedFromMillis = adjustedToMillis - intervalMillis;\n var adjustedOffsetMilliseconds = Math.abs(toMillis - adjustedToMillis);\n console.log(\"modelId\", modelId, \"latest available data\", moment(latestModelAvailabilityMillis).format(\"YYYY-MM-DDTHH:mm:ssZ\"), \"-- requested ---->\", \"from\", moment(fromMillis).format(\"YYYY-MM-DDTHH:mm:ssZ\"), \"to\", moment(toMillis).format(\"YYYY-MM-DDTHH:mm:ssZ\"), \"-- offsetting \".concat(adjustedOffsetMilliseconds / millisPerMinute / 60, \" hours ---->\"), \"from\", moment(adjustedFromMillis).format(\"YYYY-MM-DDTHH:mm:ssZ\"), \"to\", moment(adjustedToMillis).format(\"YYYY-MM-DDTHH:mm:ssZ\"));\n return loadDataForModel(modelId, adjustedFromMillis, adjustedToMillis, adjustedOffsetMilliseconds);\n });\n }\n\n function doesActiveJobExist(modelId, fromMillis, toMillis) {\n var clearStaleJobs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n\n var existingJobs = _.filter(jobState.jobs, function (job) {\n return job.requesterId === modelId && job.fromMillis === fromMillis && job.toMillis === toMillis && !job.hasCompleted;\n });\n\n if (!existingJobs.length) {\n return false;\n }\n\n var hasActiveJob = false;\n\n _.forEach(existingJobs, function (job) {\n if (!job.isStale) {\n hasActiveJob = true;\n } else if (clearStaleJobs) {\n gisModelService.dismissJob(job.jobId);\n }\n });\n\n return hasActiveJob;\n }\n\n function loadDataForModel(modelId, fromMillis, toMillis) {\n var offsetMillis = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.loading, fromMillis, toMillis);\n var fromDate = new Date(fromMillis);\n var toDate = new Date(toMillis);\n var promises$ = [];\n var discreteReceptor$ = gisModelService.getDiscreteReceptorData(modelId, fromDate, toDate).then(processDiscreteReceptorData).catch(angular.noop);\n promises$.push(discreteReceptor$);\n var model$ = gisModelService.getModelDataSet([modelId], fromDate, toDate).then(processModelDataSet).catch(processModelDataSetErrors);\n promises$.push(model$);\n return $q.all(promises$); ////////////////////\n\n function processDiscreteReceptorData(response) {\n modellingState.modellingDataStore.importDiscreteReceptorData(modelId, offsetResponseData(response)); /////\n\n function offsetResponseData(response) {\n var adjustedResponse = {};\n\n var _arr = Object.keys(response);\n\n for (var _i = 0; _i < _arr.length; _i++) {\n var key = _arr[_i];\n var value = response[key];\n var offsetAdjustedKey = new Date(new Date(key).getTime() + offsetMillis).toISOString();\n adjustedResponse[offsetAdjustedKey] = value;\n }\n\n return adjustedResponse;\n }\n }\n\n function processModelDataSet(response) {\n var adjustedGisModels = offsetResponseData(response.availableGisModels);\n var importedTimeSteps = modellingState.modellingDataStore.importModelDataSets(adjustedGisModels);\n setStatusForImportedTimeStepsToLoaded(importedTimeSteps);\n updateModelDataAvailability(modelId);\n var activeJobs = response.activeJobsForGisModels;\n\n if (activeJobs && _.has(activeJobs, modelId)) {\n addActiveJobsToJobState(activeJobs, modelId);\n } ////\n\n\n function offsetResponseData() {\n var gisModels = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n\n _.forEach(gisModels, function (gisModel) {\n _.forEach(gisModel.temporalData.data, function (dataPoint) {\n dataPoint.utcEndTime = new Date(new Date(dataPoint.utcEndTime).getTime() + offsetMillis).toISOString();\n });\n });\n\n return gisModels;\n }\n }\n\n function setStatusForImportedTimeStepsToLoaded(importedTimeSteps) {\n if (!(importedTimeSteps && importedTimeSteps.length)) {\n return;\n } // Note - this is an ideal candidate for currying, but currying is not good for unit testing (it\n // breaks if you try to spy on the function being curried).\n\n\n var setStatusToLoaded = function setStatusToLoaded(timeStep) {\n return modellingState.setModelLoadingStatusForSingleTimeStep(modelId, modelLoadingStatus.loaded, timeStep);\n };\n\n _.forEach(importedTimeSteps, setStatusToLoaded);\n }\n\n function processModelDataSetErrors() {\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.failed, fromMillis, toMillis);\n }\n }\n\n function addActiveJobsToJobState(activeJobs, modelId) {\n _.forEach(activeJobs, function (job) {\n // Sanity check that this job belongs to the nominated model\n if (job.requesterId !== modelId) {\n return;\n } // We also need to check if we are already tracking this job - depends on if the SignalR JobCreated\n // event was received before the call returned.\n\n\n var existingJob = _.find(jobState.jobs, {\n jobId: job.jobId\n });\n\n if (!existingJob) {\n jobState.jobs.push(job);\n }\n });\n }\n\n function getModelById(modelId) {\n // Most likely to be in the selected interval\n var model = _.find(modellingState.selectedInterval.models, {\n modelId: modelId\n }); // _.find returns undefined if not found.\n\n\n return model || null;\n }\n\n function onJobCompleted(job) {\n if (!(job && job.requesterId)) {\n return;\n }\n\n var modelId = job.requesterId;\n var model = getModelById(modelId);\n\n if (model === null) {\n return;\n }\n\n processJobCompleted(job, modelId, model);\n }\n\n function processJobCompleted(job, modelId, model) {\n var status = job.hasFailed ? modelLoadingStatus.failed : modelLoadingStatus.pending;\n modellingState.setModelLoadingStatus(modelId, status, job.fromMillis, job.toMillis);\n\n if (job.hasFailed) {\n return;\n }\n\n var dataSetDateRange = modellingState.getDataSetDateRange();\n var isJobForCurrentDateRange = dataSetDateRange.fromMillis <= job.fromMillis && dataSetDateRange.toMillis >= job.toMillis;\n\n if (!isJobForCurrentDateRange) {\n return;\n }\n\n var isModelStillSelected = model && _.find(modellingState.selectedModels, {\n modelId: modelId\n });\n\n if (!isModelStillSelected) {\n return;\n }\n\n loadDataForModels([modelId]);\n }\n\n function onJobDismissed(job) {\n if (!job.isStale) {\n return;\n }\n\n var modelId = job.requesterId;\n\n if (!modelId) {\n return;\n }\n\n var currentLoadingStatus = modellingState.getModelLoadingStatus(modelId, job.fromMillis, job.toMillis);\n\n if (currentLoadingStatus !== modelLoadingStatus.loading) {\n return;\n }\n\n var hasActiveJob = doesActiveJobExist(modelId, job.fromMillis, job.toMillis);\n\n if (!hasActiveJob) {\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.failed, job.fromMillis, job.toMillis);\n }\n }\n\n function resyncModelDataAvailability() {\n _.forEach(modellingState.selectedInterval.models, function (model) {\n updateModelDataAvailability(model.modelId);\n });\n }\n\n function updateModelDataAvailability(modelId) {\n var isSelected = _.find(modellingState.selectedModels, {\n modelId: modelId\n });\n\n if (!isSelected) {\n delete modellingState.modelDataAvailability[modelId];\n return;\n }\n\n var dateRange = modellingState.getDataSetDateRange();\n\n if (!dateRange) {\n return;\n }\n\n var availability = {};\n var tickStep = modellingState.selectedInterval.minutes * millisPerMinute;\n\n for (var tick = dateRange.fromMillis; tick <= dateRange.toMillis; tick += tickStep) {\n availability[tick] = modellingState.modellingDataStore.modelHasDataAt(modelId, tick);\n }\n\n modellingState.modelDataAvailability[modelId] = availability;\n }\n\n function onJobStale(job) {\n if (!(job && job.requesterId)) {\n return;\n }\n\n var modelId = job.requesterId;\n var model = getModelById(modelId);\n\n if (model === null) {\n return;\n } // Cater for SignalR crapping itself by manually checking the job status\n\n\n gisModelService.getStatus(job.jobId).then(function (status) {\n job.progress = status.progress;\n\n if (!status.hasCompleted) {\n job.completionStatus = jobCompletionStatus.incomplete;\n } else {\n job.completionStatus = jobCompletionStatus.calculate(status.jobSucceededCount, status.jobFailedCount);\n processJobCompleted(job, modelId, model);\n }\n });\n }\n\n function dispose() {\n _.invokeMap(subscriptions, \"unsubscribe\");\n }\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.modelling.state\"];\n\n function appRun(routeHelper, modellingState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.modelling\",\n abstract: true\n }, {\n state: \"app.modelling.gisModelling\",\n url: \"/modelling/{companyAlias}/{facilityAlias}?modelhash\",\n views: {\n 'actionsPanel@app': {\n templateUrl: \"/App/ui/features/modelling/ActionsPanel.html\",\n controller: \"app.ui.features.modelling.ActionsPanel as vm\"\n },\n 'leftPanel@app': {\n templateUrl: \"/App/ui/features/modelling/LeftPanel.html\",\n controller: \"app.ui.features.modelling.LeftPanel as vm\"\n },\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/modelling/ContentPanel.html\",\n controller: \"app.ui.features.modelling.ContentPanel as vm\"\n }\n },\n reloadOnSearch: false,\n // allows us to set the ?modelhash parameter without reloading the resolvers.\n data: {\n requiredAccessControl: \"app.modelling\"\n },\n settings: {\n i18n: [\"/App/ui/core/controls/i18n/esTimeSlider\", \"/App/ui/features/modelling/i18n/modelling\", \"/App/ui/features/modelling/controls/i18n/esModellingDurationSelect\", \"/App/ui/features/modelling/controls/i18n/esModellingModelSelect\", \"/App/ui/features/modelling/controls/i18n/esModellingTimeSlider\", \"/App/ui/core/mapping/controls/i18n/esMapCentre\", \"/App/ui/core/mapping/controls/i18n/esMapKml\", \"/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries\", \"/App/ui/core/mapping/controls/i18n/esMapEmissionSources\", \"/App/ui/core/mapping/controls/i18n/esMapCredits\", \"/App/ui/core/mapping/controls/i18n/esMapTiles\", \"/App/ui/core/mapping/controls/i18n/esMapType\"]\n },\n resolve: {\n modellingState: modellingState\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").factory(\"app.ui.features.modelling.state\", modellingStateFactory);\n modellingStateFactory.$inject = [\"$q\", \"lodash\", \"app.core.mapDefaults\", \"app.core.services.companyService\", \"app.core.services.gisModelService\", \"app.core.services.reportsService\", \"app.core.models.modelLoadingStatus\", \"app.ui.features.modelling.ModellingDataStore\"];\n\n function modellingStateFactory($q, _, mapDefaults, companyService, gisModelService, reportsService, modelLoadingStatus, ModellingDataStore) {\n function modellingStateFactoryResolver() {\n var facilityLocation = companyService.getFacilityLocation();\n var intervals = gisModelService.getIntervals();\n var alertPointReports = reportsService.getAlertPointReports();\n var domainBoundaries = companyService.getDomainBoundaries(true);\n return $q.all([facilityLocation, intervals, alertPointReports, domainBoundaries]).then(function (result) {\n var _result = _slicedToArray(result, 4),\n mapLocation = _result[0],\n intervals = _result[1],\n alertPointReports = _result[2],\n domainBoundaries = _result[3];\n\n var mappedIntervals = intervals.map(function (interval) {\n return {\n minutes: interval.durationInMinutes,\n durationRanges: interval.intervalOptionMinutes,\n models: interval.models\n };\n });\n return new ModellingState(mappedIntervals, mapLocation, alertPointReports, domainBoundaries);\n });\n }\n\n function ModellingState(mappedIntervals, mapLocation, alertPointReports, domainBoundaries) {\n var self = this;\n var millisPerMinute = 60 * 1000;\n this.intervals = mappedIntervals;\n this.autoUpdateEnabled = false;\n this.dataSetStartDate = null;\n this.dataSetEndDate = null;\n this.alertPointReports = alertPointReports;\n var selectedInterval;\n\n if (mappedIntervals.length > 0) {\n selectedInterval = mappedIntervals[0];\n } else {\n selectedInterval = {\n durationRanges: [],\n minutes: 60,\n models: []\n };\n }\n\n var selectedModels = [];\n var modellingDataStore = new ModellingDataStore();\n var modelDataAvailability = {};\n this.realTimeMode = false; // Contains the loading status for each model at the end-time of each interval\n // e.g:\n // {\n // \"model-1\": {\n // \"146000\": loading,\n // \"147000\": loaded\n // }\n // }\n\n var modelLoadingStatuses = {};\n this.map = {\n defaultCentre: mapLocation,\n centre: mapLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n isColor: false,\n bounds: getMapBounds(),\n layers: {\n baselayers: mapDefaults.baselayers,\n overlays: {\n discreteReceptor: {\n type: \"group\",\n visible: true,\n name: \"DiscreteReceptor\"\n }\n }\n }\n };\n Object.defineProperty(this, \"selectedInterval\", {\n get: function get() {\n return selectedInterval;\n },\n set: function set(value) {\n selectedInterval = value;\n clearData(self.modelDataAvailability);\n }\n });\n Object.defineProperty(this, \"selectedModels\", {\n get: function get() {\n return selectedModels;\n }\n });\n Object.defineProperty(this, \"modellingDataStore\", {\n get: function get() {\n return modellingDataStore;\n }\n });\n Object.defineProperty(this, \"modelLoadingStatuses\", {\n get: function get() {\n return modelLoadingStatuses;\n }\n });\n Object.defineProperty(this, \"modelDataAvailability\", {\n get: function get() {\n return modelDataAvailability;\n }\n });\n this.modelDurationWarning = null;\n this.getDataSetDateRange = getDataSetDateRange;\n this.getModelLoadingStatus = getModelLoadingStatus;\n this.setModelLoadingStatus = setModelLoadingStatus;\n this.setModelLoadingStatusForSingleTimeStep = setModelLoadingStatusForSingleTimeStep;\n this.setModelSelected = setModelSelected;\n\n this.clear = function () {\n clearData(self.modelDataAvailability);\n modellingDataStore = new ModellingDataStore();\n }; ////////////////////\n\n\n function clearData(dataObject) {\n _.forEach(dataObject, function (value, key) {\n return delete dataObject[key];\n });\n }\n\n function getModelLoadingStatus(modelId) {\n var fromMillis = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var toMillis = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n if (!_.has(modelLoadingStatuses, modelId)) {\n return modelLoadingStatus.pending;\n }\n\n if (!(fromMillis && toMillis)) {\n var dataSetDateRangeMillis = getDataSetDateRange();\n fromMillis = dataSetDateRangeMillis.fromMillis;\n toMillis = dataSetDateRangeMillis.toMillis;\n }\n\n var result = modelLoadingStatus.pending;\n var intervalStatuses = modelLoadingStatuses[modelId];\n var intervalStepMillis = selectedInterval.minutes * millisPerMinute;\n\n for (var stepMillis = toMillis; stepMillis > fromMillis; stepMillis -= intervalStepMillis) {\n var intervalStatus = _.has(intervalStatuses, stepMillis) ? intervalStatuses[stepMillis] : modelLoadingStatus.pending;\n\n if (intervalStatus === modelLoadingStatus.pending) {\n continue;\n } // The model is loading if even one interval is loading.\n\n\n if (intervalStatus === modelLoadingStatus.loading) {\n return intervalStatus;\n } // Always chose failed over loaded\n\n\n if (result !== modelLoadingStatus.failed) {\n result = intervalStatus;\n }\n }\n\n return result;\n }\n\n function setModelLoadingStatus(modelId, state) {\n var fromMillis = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n var toMillis = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n\n if (!(fromMillis && toMillis)) {\n var dataSetDateRangeMillis = getDataSetDateRange();\n fromMillis = dataSetDateRangeMillis.fromMillis;\n toMillis = dataSetDateRangeMillis.toMillis;\n }\n\n var modelLoadingStatusByTimeStep = getModelLoadingStatusByTimeStep(modelId);\n var intervalStepMillis = selectedInterval.minutes * millisPerMinute;\n\n for (var stepMillis = toMillis; stepMillis > fromMillis; stepMillis -= intervalStepMillis) {\n updateLoadingStatus(modelLoadingStatusByTimeStep, stepMillis, state);\n }\n }\n\n function setModelLoadingStatusForSingleTimeStep(modelId, state, timeStepEndMillis) {\n var modelLoadingStatusByTimeStep = getModelLoadingStatusByTimeStep(modelId);\n updateLoadingStatus(modelLoadingStatusByTimeStep, timeStepEndMillis, state);\n }\n\n function getModelLoadingStatusByTimeStep(modelId) {\n return _.has(modelLoadingStatuses, modelId) && modelLoadingStatuses[modelId] || (modelLoadingStatuses[modelId] = {});\n }\n\n function updateLoadingStatus(loadingStatusByTimeStep, timeStepMillis, state) {\n // Never overwrite `loaded`.\n if (loadingStatusByTimeStep[timeStepMillis] === modelLoadingStatus.loaded) {\n return;\n }\n\n loadingStatusByTimeStep[timeStepMillis] = state;\n }\n\n function getDataSetDateRange() {\n var toMillis = self.dataSetEndDate && self.dataSetEndDate.getTime();\n var fromMillis = self.dataSetStartDate && self.dataSetStartDate.getTime();\n\n if (!(toMillis && fromMillis)) {\n return null;\n }\n\n if (fromMillis === toMillis && selectedInterval && selectedInterval.minutes) {\n fromMillis -= selectedInterval.minutes * millisPerMinute;\n }\n\n return {\n fromMillis: fromMillis,\n toMillis: toMillis\n };\n }\n\n function setModelSelected(model, isSelected) {\n var modelId = model.modelId;\n\n if (isSelected) {\n // If the model previously loaded with an error, then reset it to allow the user to attempt loading it again.\n var dateRange = getDataSetDateRange();\n\n if (dateRange && getModelLoadingStatus(modelId, dateRange.fromMillis, dateRange.toMillis) === modelLoadingStatus.failed) {\n setModelLoadingStatus(modelId, modelLoadingStatus.pending, dateRange.fromMillis, dateRange.toMillis);\n }\n\n selectedModels.push(model);\n } else {\n _.remove(selectedModels, {\n modelId: modelId\n });\n\n delete modelDataAvailability[modelId];\n }\n }\n\n function getMapBounds() {\n return domainBoundaries && _.reduce(domainBoundaries, function (memo, boundary) {\n var coordinates = [boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight];\n return memo.concat(_.map(coordinates, function (coordinate) {\n return [coordinate.latitude, coordinate.longitude];\n }));\n }, []);\n }\n }\n\n return modellingStateFactoryResolver;\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.modelling\").factory(\"app.ui.features.modelling.timeStepCalculator\", timeStepCalculator);\n timeStepCalculator.$inject = [\"lodash\"];\n\n function timeStepCalculator(_) {\n var millisPerMinute = 60 * 1000;\n return {\n calculateTimeStepRange: calculateTimeStepRange,\n getLastIntervalMillis: getLastIntervalMillis\n }; ////////////////////\n\n function calculateTimeStepRange(baseDate, fromMinutes, toMinutes, intervalMinutes) {\n if (!isIntervalValid(intervalMinutes)) {\n throw new Error(\"The interval must be a divisor or multiple of one hour.\");\n }\n\n var baseDateMillis = getLastIntervalMillis(baseDate, intervalMinutes);\n var fromTicks = baseDateMillis - parseInt(fromMinutes) * millisPerMinute;\n var toTicks = baseDateMillis + parseInt(toMinutes) * millisPerMinute;\n var intervalMillis = parseInt(intervalMinutes) * millisPerMinute;\n var timeStepCount = Math.round((toTicks - fromTicks) / intervalMillis);\n return {\n timeStepCount: timeStepCount,\n fromDate: new Date(fromTicks),\n toDate: new Date(toTicks)\n };\n }\n\n function isIntervalValid(intervalMinutes) {\n if (intervalMinutes === 0) {\n return false;\n }\n\n var remainder = intervalMinutes < 60 ? 60 % intervalMinutes : intervalMinutes % 60;\n return remainder === 0;\n }\n\n function getLastIntervalMillis(date, intervalMinutes) {\n var intervalMillis = parseInt(intervalMinutes) * millisPerMinute;\n var baseDateMillis;\n\n if (date instanceof Date) {\n baseDateMillis = date.getTime();\n } else if (_.isNumber(date)) {\n baseDateMillis = date;\n } else {\n baseDateMillis = new Date(date).getTime();\n } //javascript.about.com/od/problemsolving/a/modulobug.htm\n\n\n var delta = (baseDateMillis % intervalMillis + intervalMillis) % intervalMillis;\n return baseDateMillis - delta;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").controller(\"app.ui.features.monitoring.ActionsPanel\", ActionsPanel);\n ActionsPanel.$inject = [\"monitoringState\"];\n\n function ActionsPanel(monitoringState) {\n var vm = this;\n vm.map = monitoringState.map;\n vm.actions = {\n fullScreen: {\n isEnabled: false\n }\n };\n activate(); /////////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").controller(\"app.ui.features.monitoring.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$scope\", \"$interval\", \"$q\", \"lodash\", \"promiseTracker\", \"app.core.appSettings\", \"app.core.services.monitoringService\", \"monitoringState\", \"app.core.states.monitoringTimeState\", \"app.core.services.mappingService\"];\n\n function ContentPanel($scope, $interval, $q, _, promiseTracker, appSettings, monitoringService, monitoringState, monitoringTimeState, mappingService) {\n var realTimeTickTimeout = 60000;\n var vm = this;\n var pollingMonitorsPromise = null;\n vm.isRealTime = false;\n vm.isLoading = promiseTracker();\n vm.map = monitoringState.map;\n vm.overlayProvider = {};\n vm.showControls = false;\n vm.temporalEventGroups = [];\n vm.state = monitoringState;\n activate(); /////////////////////\n\n function activate() {\n loadOverlays();\n var hasAccessToSourceIdentification = appSettings.site.accessControls[\"app.monitoring.source-identification\"];\n $scope.$watch(function () {\n return monitoringTimeState.dateTime;\n }, function (dateTime) {\n if (!dateTime) {\n return;\n }\n\n refreshDataForAllMonitors();\n\n if (hasAccessToSourceIdentification) {\n refreshDataForAllSourceAreas();\n }\n });\n\n _.forEach(monitoringState.monitorsByType, function (monitorGrouping) {\n $scope.$watch(function () {\n return monitorGrouping.selectedMeasurementGroupId;\n }, function (newValue, oldValue) {\n if (newValue && newValue !== oldValue) {\n refreshDataForMonitorType(monitorGrouping.monitorIds, newValue);\n }\n });\n });\n\n if (hasAccessToSourceIdentification) {\n $scope.$watch(function () {\n return vm.state.map.switches.sourceIdentification;\n }, function () {\n //temp workaround till the next ticket where this will move into its own widget.\n if (vm.state.map.layers && vm.state.map.layers.overlays.areaSources) {\n vm.state.map.layers.overlays.areaSources.visible = vm.state.map.switches.sourceIdentification;\n }\n });\n $scope.$watch(function () {\n return vm.state.map.switches.sourceIdentificationDebug;\n }, function () {\n $scope.$watch(function () {\n return monitoringTimeState.dateTime;\n }, refreshTemporalEventGroups);\n });\n } else if (appSettings.site.accessControls[\"app.monitoring.temporal-map-layers\"]) {\n $scope.$watch(function () {\n return monitoringTimeState.dateTime;\n }, refreshTemporalEventGroups);\n }\n\n addIsRealTimeWatcher();\n\n function refreshTemporalEventGroups(dateTime) {\n if (!dateTime) {\n return;\n }\n\n mappingService.getActiveTemporalEventGroups(dateTime).then(function (eventGroups) {\n // Include/exclude the source identification groups - we will use these fixed names initially.\n if (!vm.state.map.switches.sourceIdentificationDebug) {\n eventGroups = _.pickBy(eventGroups, function (group) {\n return group.name !== \"source-identification-debug\";\n });\n }\n\n vm.temporalEventGroups = eventGroups;\n });\n }\n }\n\n function loadOverlays() {\n mappingService.getKmls().then(function (overlays) {\n vm.overlayProvider = overlays;\n vm.showControls = overlays && overlays.length > 0;\n });\n }\n\n function getMonitorData() {\n if (!(monitoringState.monitorsByType && _.keys(monitoringState.monitorsByType).length)) {\n return $q.when([]);\n }\n\n var dataCalls = _.map(monitoringState.monitorsByType, function (monitorGrouping, monitorType) {\n return monitoringService.getMonitorData(monitorGrouping.monitorIds, monitoringState.monitorsByType[monitorType].selectedMeasurementGroupId, monitoringTimeState.dateTime);\n });\n\n return $q.all(dataCalls).then(_.flatten).catch(angular.noop);\n }\n\n function getSourceAreaData() {\n return monitoringService.getSourceAreaData(monitoringTimeState.dateTime);\n }\n\n function refreshDataForAllMonitors() {\n var getMonitorDataPromise = getMonitorData();\n var updatingPromise = getMonitorDataPromise.then(renderMonitorMapMarkers);\n vm.isLoading.addPromise(updatingPromise);\n }\n\n function refreshDataForMonitorType(monitorIds, measurementGroupId) {\n var getMonitorDataPromise = monitoringService.getMonitorData(monitorIds, measurementGroupId, monitoringTimeState.dateTime);\n var updatingPromise = getMonitorDataPromise.then(renderMonitorMapMarkers).catch(function () {});\n vm.isLoading.addPromise(updatingPromise);\n }\n\n function refreshDataForAllSourceAreas() {\n var updatingPromise = getSourceAreaData().then(renderAreaSources).catch(angular.noop);\n vm.isLoading.addPromise(updatingPromise);\n }\n\n function addIsRealTimeWatcher() {\n $scope.$watch(function () {\n return vm.isRealTime;\n }, function (isRealTime) {\n if (isRealTime && !isPolling()) {\n pollingMonitorsPromise = $interval(function () {\n monitoringTimeState.dateTime = new Date();\n monitoringTimeState.isRealTime = true;\n }, realTimeTickTimeout);\n } else {\n stopPollingMonitoringData();\n }\n });\n vm.isRealTime = true;\n }\n\n function isPolling() {\n return pollingMonitorsPromise !== null;\n }\n\n function stopPollingMonitoringData() {\n $interval.cancel(pollingMonitorsPromise);\n pollingMonitorsPromise = null;\n }\n\n function renderMonitorMapMarkers(monitors) {\n mergeResultsWithState(vm.state.monitors, monitors);\n monitoringState.map.renderMonitorMapMarkers();\n }\n\n function renderAreaSources(areaSources) {\n mergeResultsWithState(vm.state.areaSources, areaSources);\n monitoringState.map.renderSourceAreaSources();\n }\n\n function mergeResultsWithState(target, source) {\n _.forEach(source, function (item) {\n var exists = _.find(target, {\n id: item.id\n });\n\n if (exists) {\n _.merge(exists, item);\n } else {\n target.push(item);\n }\n });\n }\n\n $scope.$on(\"$destroy\", stopPollingMonitoringData);\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").directive(\"esMetSummary\", esMetSummary).controller(\"esMetSummaryController\", esMetSummaryController);\n esMetSummary.$inject = [];\n\n function esMetSummary() {\n return {\n scope: {},\n restrict: \"E\",\n controllerAs: \"vm\",\n bindToController: true,\n controller: esMetSummaryController,\n templateUrl: \"/App/ui/features/monitoring/controls/esMetSummary.html\"\n };\n }\n\n esMetSummaryController.$inject = [\"$scope\", \"lodash\", \"browserStorage\", \"promiseTracker\", \"app.core.services.monitoringService\", \"app.core.states.monitoringTimeState\", \"app.core.appSettings\"];\n\n function esMetSummaryController($scope, _, browserStorage, promiseTracker, monitoringService, monitoringTimeState, appSettings) {\n var vm = this;\n var storageKey = \"preferred-met-station\";\n var storageBucketKey = \"\".concat(appSettings.site.facility.alias, \"-\").concat(appSettings.userId);\n vm.busyLoading = promiseTracker();\n vm.metSummaries = [];\n vm.metSummary = getMetSummary();\n vm.changeSelectedMetStation = changeSelectedMetStation;\n activate();\n\n function activate() {\n $scope.$watch(function () {\n return monitoringTimeState.dateTime;\n }, getMetSummary);\n }\n\n function getMetSummary(dateTime) {\n var promise = monitoringService.getMetSummary(dateTime).then(function (metSummaries) {\n vm.metSummaries = metSummaries;\n vm.metSummary = _.find(vm.metSummaries, {\n metStation: {\n isDefault: true\n }\n }) || _.first(vm.metSummaries);\n var storedMetStationId = getPreferredMetStationStore();\n\n if (!!storedMetStationId) {\n var metSummary = _.find(vm.metSummaries, {\n metStation: {\n id: storedMetStationId\n }\n });\n\n if (!!metSummary) {\n vm.metSummary = metSummary;\n }\n }\n }).catch(function () {\n /* ignore requestManager rejections */\n });\n vm.busyLoading.addPromise(promise);\n }\n\n function changeSelectedMetStation(metStationId) {\n vm.metSummary = _.find(vm.metSummaries, {\n metStation: {\n id: metStationId\n }\n });\n browserStorage.persistBucket(storageKey, storageBucketKey, metStationId);\n }\n\n function getPreferredMetStationStore() {\n return browserStorage.getBucket(storageKey, storageBucketKey) || {};\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").directive(\"esMonitoringDateTimeSelector\", esMonitoringDateTimeSelector).controller(\"esMonitoringDateTimeSelectorController\", esMonitoringDateTimeSelectorController);\n esMonitoringDateTimeSelector.$inject = [\"app.core.services.dateTimeService\", \"moment\"];\n\n function esMonitoringDateTimeSelector(dateTimeService, moment) {\n //NOTE:\n // The number one gotcha with Kendo controls is that setting invalid values in a control does not give you an error message/indication by default.\n // If you set the value and it is invalid (e.g. greater than max date), you get no warning, the value just doesn't set.\n var directive = {\n restrict: \"E\",\n scope: {\n isRealTime: \"=\",\n isLoading: \"=\"\n },\n controller: \"esMonitoringDateTimeSelectorController\",\n controllerAs: \"vm\",\n bindToController: true,\n templateUrl: \"/App/ui/features/monitoring/controls/esMonitoringDateTimeSelector.html\",\n link: link\n };\n /* istanbul ignore next */\n\n function link($scope) {\n var vm = $scope.vm; // events\n\n $scope.$on(\"resizePage\", resize);\n $scope.$on(\"kendoWidgetCreated\", activate); /////////////////////////\n\n function activate() {\n if (!vm.timeSlider.kendoSlider) {\n return;\n }\n\n renameSliderStepLabels();\n }\n\n function renameSliderStepLabels() {\n var stepContainer = vm.timeSlider.kendoSlider.element.siblings(\".k-slider-items\")[0];\n\n if (!stepContainer) {\n return;\n }\n\n var steps = stepContainer.children;\n var startOfDay = moment().startOf(\"day\").valueOf();\n\n for (var i = 0; i < steps.length; i += 12) {\n var step = steps[i];\n\n if (step.title.length <= 2) {\n // dodgy workaround, to make sure we aren't updating, UPDATED, labels. this happens when the renameSliderStepLables() method is called multiple times due to a resize event.\n return;\n }\n\n var value = startOfDay + i / 12 * 60 * 60 * 1000;\n step.title = dateTimeService.formatAs.hour(value);\n angular.element(step).find(\"span\").text(step.title);\n }\n }\n\n function resize() {\n if (!vm.timeSlider.kendoSlider) {\n return;\n }\n\n vm.timeSlider.kendoSlider.resize();\n renameSliderStepLabels();\n }\n }\n\n return directive;\n }\n\n esMonitoringDateTimeSelectorController.$inject = [\"$scope\", \"$interval\", \"$timeout\", \"$state\", \"$log\", \"moment\", \"lodash\", \"i18n\", \"notifier\", \"app.ui.core.keyboardShortcuts\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.dateTimeService\", \"app.core.services.settingsService\", \"app.core.states.monitoringTimeState\"];\n\n function esMonitoringDateTimeSelectorController($scope, $interval, $timeout, $state, $log, moment, _, i18n, notifier, keyboardShortcuts, timeZoneDateTime, dateTimeService, settingsService, monitoringTimeState) {\n var vm = this;\n var millisPerMinute = 1000 * 60;\n var fiveMinuteInterval = 5 * millisPerMinute;\n var sixtyMinuteInterval = 60 * millisPerMinute;\n\n var debouncedTimeChanged = _.debounce(notifyTimeChanged, 100);\n\n var shortcutKeys = {\n forwardOneDay: \"k\",\n backwardOneDay: \"j\",\n focusDatePicker: \"g d\",\n focusTimeSlider: \"g t\"\n };\n var shortcuts = {};\n var shortcutBindings;\n var updateWidgetsInterval;\n vm.is24Hours = dateTimeService.formats.is24Hour;\n vm.isRealTime = false;\n vm.dateTime = new Date();\n vm.datePicker = getDatePicker();\n vm.timeSlider = getTimeSlider();\n vm.switchBackToRealTimeMode = enableRealTimeMode;\n activate();\n\n function activate() {\n bindKeyboardShortcuts();\n startClock();\n } //////////////////////////////////\n\n\n function startClock() {\n if ($state.params.dateTime) {\n try {\n enableHistoricalMode(settingsService.getSampleDateTime());\n } catch (error) {\n enableRealTimeMode();\n generateErrorMessage();\n }\n } else {\n enableRealTimeMode();\n }\n\n updateWidgetsInterval = $interval(setDateTimeToNow, 1000);\n\n function generateErrorMessage() {\n var message = i18n.i10n(\"esMonitoringDateTimeSelector.params.error.message\", {\n dateTime: $state.params.dateTime\n });\n var title = i18n.i10n(\"esMonitoringDateTimeSelector.params.error.title\");\n notifier.error(message, title);\n $log.warn(message);\n }\n\n function setDateTimeToNow() {\n if (vm.isRealTime) {\n vm.dateTime = new Date(); // this triggers the watch on vm.dateTime which updates widgets\n } else {\n setDatePickerMaxDate(); // as the time ticks over midnight we need to make sure the max. date a user can choose is updated.\n }\n }\n }\n\n function updateDateTimeUrlParameter(dateTime) {\n dateTime = dateTime && dateTimeService.formatAs.iso(timeZoneDateTime.convertDateTimeToFacilityTimeZone(dateTime));\n var toParams = {\n dateTime: dateTime\n };\n $state.go(\"app.monitoring\", toParams, {\n notify: false\n });\n }\n\n function enableRealTimeMode() {\n vm.datePicker.hasFocus = false;\n vm.dateTime = new Date();\n vm.isRealTime = true;\n updateDateTimeUrlParameter();\n debouncedTimeChanged(true);\n }\n\n function enableHistoricalMode(dateTime) {\n vm.dateTime = dateTime;\n vm.isRealTime = false;\n debouncedTimeChanged(false);\n }\n\n function getDatePicker() {\n var date = new Date();\n return {\n hasFocus: false,\n date: date,\n options: {\n // note: anything provided in here is angular bound. don't put an event handler in here otherwise you have to run $scope.$apply()\n max: moment(calculateFacilityLocalTime(new Date())).endOf(\"day\").toDate(),\n // evening midnight\n format: dateTimeService.formats.kendo.date\n },\n onChange: function onChange() {\n vm.datePicker.onBlur();\n $timeout(updateDateTimeFromWidgetValues);\n },\n onFocus: function onFocus() {\n vm.datePicker.hasFocus = true;\n },\n onBlur: function onBlur() {\n vm.datePicker.hasFocus = false;\n }\n };\n }\n\n function getTimeSlider() {\n var min = moment().startOf(\"day\"); // morning midnight - ticks value\n\n var max = moment(min).add(1, \"d\"); // 24 hours later\n\n return {\n time: max.valueOf(),\n options: {\n // note: anything provided in here is angular bound. don't put an event handler in here otherwise you have to run $scope.$apply()\n min: min.valueOf(),\n max: max.valueOf(),\n smallStep: fiveMinuteInterval,\n // arrow keys\n largeStep: sixtyMinuteInterval,\n // page up/down\n tooltip: {\n template: \"#= moment(value).format('\".concat(dateTimeService.formats.moment.timeWithSeconds, \"') #\")\n },\n tickPlacement: \"topLeft\"\n },\n onChange: function onChange() {\n $timeout(updateDateTimeFromWidgetValues);\n }\n };\n }\n\n function setDatePickerMaxDate() {\n var datePickerMax = moment(calculateFacilityLocalTime(new Date())).endOf(\"day\");\n\n if (vm.datePicker.kendoDatePicker && vm.datePicker.kendoDatePicker.max() < datePickerMax.toDate()) {\n vm.datePicker.kendoDatePicker.max(datePickerMax.toDate());\n }\n } // update our model using the latest widget values\n\n\n function updateDateTimeFromWidgetValues() {\n var dateTime = readDateTimeFromWidgets(); // append the relative ticks to the start of the selected date\n\n if (dateTime < new Date()) {\n enableHistoricalMode(dateTime);\n } else {\n enableRealTimeMode();\n }\n\n function readDateTimeFromWidgets() {\n var selectedDate = moment(vm.datePicker.date);\n var millisAtMorningMidnightOfSelectedDate = selectedDate.valueOf(); // the vm.datePicker.date has a 00:00:00 time.\n\n var timeMillis = vm.timeSlider.time - vm.timeSlider.options.min;\n var result = moment(millisAtMorningMidnightOfSelectedDate + timeMillis + -1 * timeZoneDateTime.getFacilityTimeZoneOffsetDifferenceFromLocal(selectedDate.toDate()) * 60 * 1000).toDate(); //eslint-disable-line no-extra-parens\n\n return result;\n }\n }\n\n function notifyTimeChanged() {\n var isRealTime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n monitoringTimeState.dateTime = vm.dateTime;\n monitoringTimeState.isRealTime = isRealTime;\n } // update widgets using our the latest model values\n\n\n $scope.$watch(function () {\n return vm.dateTime;\n }, function () {\n if (!vm.isRealTime) {\n updateDateTimeUrlParameter(vm.dateTime);\n }\n\n var facilityDateTime = calculateFacilityLocalTime(vm.dateTime);\n vm.digitalClockTime = dateTimeService.formatAs.timeWithSeconds(facilityDateTime);\n updateWidgets(); // the vm.dateTime was probably changed by the interval ticking over so we need to update the widgets; in historical mode the widget state is correct.\n\n function updateWidgets() {\n var dateTime = moment(facilityDateTime);\n var dateTimeMorningMidnight = moment(facilityDateTime).startOf(\"day\");\n updateDatePicker();\n updateTimeSlider();\n\n function updateDatePicker() {\n setDatePickerMaxDate();\n\n if (!vm.datePicker.hasFocus) {\n vm.datePicker.date = dateTimeMorningMidnight.toDate();\n\n if (vm.datePicker && vm.datePicker.kendoDatePicker) {\n vm.datePicker.kendoDatePicker.value(vm.datePicker.date);\n }\n }\n }\n\n function updateTimeSlider() {\n var millisSinceMorningMidnight = dateTime.valueOf() - dateTimeMorningMidnight.valueOf();\n vm.timeSlider.time = vm.timeSlider.options.min + millisSinceMorningMidnight;\n\n if (vm.timeSlider && vm.timeSlider.kendoSlider) {\n vm.timeSlider.kendoSlider.value(vm.timeSlider.time);\n }\n }\n }\n });\n\n function calculateFacilityLocalTime(date) {\n return timeZoneDateTime.convertDateTimeToFacilityTimeZone(date);\n }\n\n function bindKeyboardShortcuts() {\n shortcuts[shortcutKeys.focusDatePicker] = {\n description: i18n.i10n(\"esMonitoringDateTimeSelector.shortcuts.datepicker.focus\"),\n action: function action(evnt) {\n vm.datePicker.kendoDatePicker.open();\n vm.datePicker.kendoDatePicker.element.focus(); // We have to prevent the default behaviour for the combo, otherwise the date textbox\n // gets the letter 'd' appended to its date.\n\n evnt.preventDefault();\n }\n };\n shortcuts[shortcutKeys.focusTimeSlider] = {\n description: i18n.i10n(\"esMonitoringDateTimeSelector.shortcuts.timeslider.focus\"),\n action: focusTimeSlider\n };\n shortcuts[shortcutKeys.forwardOneDay] = {\n description: i18n.i10n(\"esMonitoringDateTimeSelector.shortcuts.datepicker.forward\"),\n action: function action() {\n return moveDateTimeBy(1, \"days\");\n }\n };\n shortcuts[shortcutKeys.backwardOneDay] = {\n description: i18n.i10n(\"esMonitoringDateTimeSelector.shortcuts.datepicker.backward\"),\n action: function action() {\n return moveDateTimeBy(-1, \"days\");\n }\n };\n shortcutBindings = keyboardShortcuts.add(i18n.i10n(\"esMonitoringDateTimeSelector.shortcuts.description\"), shortcuts); ////////////////////\n\n function moveDateTimeBy(delta, period) {\n if (!vm.dateTime) {\n return;\n }\n\n $scope.$apply(function () {\n var now = moment();\n var targetDate = moment(vm.dateTime).add(delta, period);\n\n if (targetDate.isSameOrAfter(now)) {\n if (vm.isRealTime) {\n return;\n }\n\n enableRealTimeMode();\n } else {\n enableHistoricalMode(targetDate.toDate());\n }\n\n focusTimeSlider();\n });\n }\n\n function focusTimeSlider() {\n if (!vm.timeSlider.kendoSlider) {\n return;\n }\n\n vm.timeSlider.kendoSlider.element.parent().find(\".k-draghandle\").focus();\n }\n }\n\n $scope.$on(\"$destroy\", function () {\n if (updateWidgetsInterval) {\n $interval.cancel(updateWidgetsInterval);\n updateWidgetsInterval = null;\n }\n\n if (vm.datePicker.kendoDatePicker) {\n vm.datePicker.kendoDatePicker.destroy();\n }\n\n if (vm.timeSlider.timeSlider) {\n vm.timeSlider.timeSlider.destroy();\n }\n\n shortcutBindings.remove();\n });\n }\n})();\n\n\n\"use strict\";\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").directive(\"esMonitoringPopups\", esMonitoringPopups).controller(\"esMonitoringPopupsController\", esMonitoringPopupsController);\n esMonitoringPopups.$inject = [];\n /* istanbul ignore next */\n\n function esMonitoringPopups() {\n var directive = {\n restrict: \"E\",\n scope: {\n mapId: \"@\"\n },\n require: \"^esLeaflet\",\n link: link,\n controller: \"esMonitoringPopupsController\",\n controllerAs: \"vm\",\n bindToController: true,\n templateUrl: \"/App/ui/features/monitoring/controls/esMonitoringPopup.html\"\n };\n return directive;\n\n function link($scope, $element, attrs, leafletController) {\n $scope.vm.subscribeToLeafletMarkerClick($scope, leafletController);\n }\n }\n\n esMonitoringPopupsController.$inject = [\"$rootScope\", \"$scope\", \"$compile\", \"$timeout\", \"$templateCache\", \"jQuery\", \"leafletLib\", \"esLeafletData\", \"lodash\", \"i18n\", \"app.ui.core.keyboardShortcuts\", \"app.core.appSettings\", \"app.core.states.monitoringTimeState\"];\n\n function esMonitoringPopupsController($rootScope, $scope, $compile, $timeout, $templateCache, $, L, esLeafletData, _, i18n, keyboardShortcuts, appSettings, monitoringTimeState) {\n var vm = this;\n var defaultSize = \"small\";\n var popupSizes = {\n small: {\n height: 280,\n width: 320\n },\n medium: {\n height: 280,\n width: 680\n },\n large: {\n height: 400,\n width: 840\n }\n };\n vm.companyAlias = appSettings.site.company.alias;\n vm.facilityAlias = appSettings.site.facility.alias;\n vm.canAccessConfiguration = appSettings.site.accessControls[\"app.config\"];\n vm.subscribeToLeafletMarkerClick = subscribeToLeafletMarkerClick;\n\n function subscribeToLeafletMarkerClick($scope, leafletController) {\n var openPopups = new Set([]);\n\n var _map;\n\n subscribeToLeafletClickEvents();\n setupKeyboardShortcuts(); ////////////////////\n\n function subscribeToLeafletClickEvents() {\n var unsubscribeFromMarkerClick = $rootScope.$on(\"leafletDirectiveMarker.\".concat(vm.mapId, \".click\"), onLeafletElementClick);\n var unsubscribeFromPathClick = $rootScope.$on(\"leafletDirectivePath.\".concat(vm.mapId, \".click\"), onLeafletElementClick);\n $scope.$on(\"$destroy\", function () {\n unsubscribeFromMarkerClick();\n unsubscribeFromPathClick();\n });\n\n function onLeafletElementClick(event, leafletElementEvent, popupToClone) {\n var marker = _.find(event.targetScope.markers, {\n monitorId: leafletElementEvent.model && leafletElementEvent.model.monitor.id\n }) || leafletElementEvent.leafletEvent.target.options;\n var $widgetScope = buildViewModel(marker, popupToClone && popupToClone.size || defaultSize);\n marker.monitor.getGraphProcessVariables().then(setGraphVariables);\n\n function setGraphVariables(variables) {\n $widgetScope.graphProcessVariables = variables;\n var $element = getCompiledElement($widgetScope);\n leafletController.getMap().then(setMapInstance).then(getPopup).then(enableFocus).then(enableDragAndDrop).then(setResizePopupMethod).then(setCloseMethod).then(setCloneMethod);\n\n function setMapInstance(map) {\n return _map = map;\n }\n\n function getPopup(map) {\n var offset = [100, -15];\n var latlng = [marker.lat, marker.lng];\n popupToClone = popupToClone || _.findLast(_toConsumableArray(openPopups), function (popup) {\n return popup.monitorId === marker.monitorId;\n });\n\n if (popupToClone) {\n var _popupToClone$options = _slicedToArray(popupToClone.options.offset, 2),\n left = _popupToClone$options[0],\n top = _popupToClone$options[1];\n\n offset = [left + $element.width() + 30, top];\n latlng = map.layerPointToLatLng(popupToClone._container._leaflet_pos);\n }\n\n var options = {\n closeOnClick: false,\n autoPan: true,\n autoPanPadding: L.point(50, 50),\n zoomAnimation: true,\n className: \"es-monitoring-graph-popup\",\n closeButton: false,\n autoClose: false,\n offset: offset\n };\n var popup = L.popup(options).setLatLng(latlng).setContent($element[0]);\n popup.monitorId = marker.monitorId;\n popup.size = $widgetScope.popupSize;\n map.addLayer(popup);\n $element.height(\"100%\");\n\n popup.removeTracking = function () {\n openPopups.delete(popup);\n };\n\n bringToFront(popup);\n return popup;\n }\n\n function enableFocus(popup) {\n var debouncedBringToFront = _.debounce(bringToFront, 50);\n\n $(popup._wrapper).on(\"mouseenter\", function () {\n return debouncedBringToFront(popup);\n }).on(\"click\", function () {\n return debouncedBringToFront(popup);\n });\n return popup;\n }\n\n function bringToFront(popup) {\n if (!!popup.isClosing) {\n return;\n }\n\n popup.bringToFront();\n openPopups.delete(popup);\n openPopups.add(popup);\n }\n\n function enableDragAndDrop(popup) {\n var draggable = new L.Draggable(popup._container, popup._wrapper);\n draggable.enable();\n return popup;\n }\n\n function setCloseMethod(popup) {\n $widgetScope.closePopup = function () {\n popup.isClosing = true;\n popup.removeTracking();\n\n _map.closePopup(popup);\n };\n\n return popup;\n }\n\n function setResizePopupMethod(popup) {\n $widgetScope.resizePopup = function (size) {\n var newContentBounds = getContentBounds(size);\n popup.size = size;\n $widgetScope.popupSize = size;\n $widgetScope.contentBounds = newContentBounds;\n $element.height(\"100%\");\n $element.width(newContentBounds.width);\n popup.update();\n };\n\n return popup;\n }\n\n function setCloneMethod(popup) {\n $widgetScope.clonePopup = function () {\n onLeafletElementClick(event, leafletElementEvent, popup);\n };\n\n return popup;\n }\n }\n }\n\n function buildViewModel(marker) {\n var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultSize;\n var monitor = marker.monitor;\n var $widgetScope = $scope.$new();\n $widgetScope.popupSize = size;\n $widgetScope.name = monitor.name;\n $widgetScope.monitorId = monitor.id;\n $widgetScope.processVariableId = monitor.processVariable && monitor.processVariable.id;\n $widgetScope.contentBounds = getContentBounds(size);\n $widgetScope.monitoringTimeState = monitoringTimeState;\n $widgetScope.showUnits = monitor.showUnitsOnPopup;\n $widgetScope.showConfigButton = vm.canAccessConfiguration && monitor.canAccessConfiguration;\n return $widgetScope;\n }\n\n function getCompiledElement($widgetScope) {\n var compiledTemplate = $compile($templateCache.get(\"esMonitoringPopupTemplate.html\"));\n var $element = compiledTemplate($widgetScope);\n $element.height(estimatePopupHeight());\n $element.width($widgetScope.contentBounds.width);\n return $element;\n\n function estimatePopupHeight() {\n var pvRowHeight = 30;\n var graphHeight = 200;\n var paddingHeight = 50;\n var chromeHeight = 40;\n var isPortrait = $widgetScope.contentBounds.width <= 320;\n return isPortrait ? chromeHeight + $widgetScope.graphProcessVariables.length * pvRowHeight + graphHeight + paddingHeight : $widgetScope.contentBounds.height;\n }\n }\n\n function getContentBounds() {\n var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultSize;\n return popupSizes[size];\n }\n }\n\n function setupKeyboardShortcuts() {\n var shortcuts = _defineProperty({}, \"esc\", {\n description: i18n.i10n(\"esMonitoringPopup.shortcuts.close\"),\n action: function action() {\n if (!openPopups.size) {\n return;\n }\n\n var lastOpenedPopup = _toConsumableArray(openPopups).pop();\n\n _map.closePopup(lastOpenedPopup);\n\n lastOpenedPopup.removeTracking();\n }\n });\n\n var shortcutBindings = keyboardShortcuts.add(i18n.i10n(\"esMonitoringPopup.shortcuts.description\"), shortcuts);\n $scope.$on(\"$destroy\", function () {\n shortcutBindings.remove();\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").directive(\"esMonitoringWidget\", directive).controller(\"esMonitoringWidgetController\", controller);\n directive.$inject = [];\n var palette = [\"#90c9da\", \"#ed7572\", \"#986fac\", \"#569176\", \"#849eae\", \"#f39e63\", \"#facd53\", \"#ae9dcc\", \"#526077\", \"#af4570\", \"#817f6f\", \"#91c58b\", \"#e895b1\", \"#ae9997\"];\n /* istanbul ignore next */\n\n function directive() {\n return {\n restrict: \"A\",\n scope: {\n monitorId: \"=\",\n contentBounds: \"=\",\n sampleDateTime: \"=\",\n showUnits: \"=\",\n selectedProcessVariableId: \"=\",\n processVariableIds: \"=\",\n isRealTime: \"=\",\n context: \"=\"\n },\n controller: controller,\n controllerAs: \"vm\",\n bindToController: true,\n templateUrl: \"/App/ui/features/monitoring/controls/esMonitoringWidget.html\"\n };\n }\n\n controller.$inject = [\"$scope\", \"$q\", \"$timeout\", \"promiseTracker\", \"notifier\", \"jQuery\", \"lodash\", \"d3\", \"moment\", \"i18n\", \"MG\", \"app.core.datetime.timeZoneDateTime\", \"app.core.services.monitoringService\", \"app.core.services.dateTimeService\", \"app.core.services.mathService\"];\n\n function controller($scope, $q, $timeout, promiseTracker, notifier, $, _, d3, moment, i18n, MG, timeZoneDateTime, monitoringService, dateTimeService, mathService) {\n var dblClickDelay = 400;\n var initialLoad = true;\n var abortSingleClick = false;\n var vm = this;\n vm.instanceId = new Date().getTime();\n vm.selectedProcessVariableIds = [];\n vm.onClickProcessVariable = debouncedOnClickProcessVariable;\n vm.onMultiSelectProcessVariable = onMultiSelectProcessVariable;\n vm.sensorData = [];\n vm.isPortrait = vm.contentBounds.width <= 320;\n vm.busyLoadingSensors = promiseTracker();\n vm.busyLoadingGraphDataSeries = promiseTracker();\n\n vm.selectedHighlight = function (pvId) {\n var isSelected = _.find(vm.selectedProcessVariableIds, function (sId) {\n return pvId === sId;\n });\n\n return isSelected ? palette[_.findIndex(vm.processVariableIds, function (id) {\n return id === pvId;\n }) % palette.length] : undefined;\n };\n\n var prevDataSeries = {};\n var graphsNeedRerendering;\n activate(); /////////////////////\n\n function activate() {\n $scope.$watch(function () {\n return vm.sampleDateTime;\n }, loadWidget);\n\n function loadWidget() {\n graphsNeedRerendering = !vm.currentlySelectedDateTime || // first render\n vm.isRealTime || hasChangedDays();\n vm.sampleTime = vm.currentlySelectedDateTime = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.sampleDateTime);\n var promise = monitoringService.getMonitorSensorData(vm.monitorId, vm.processVariableIds, vm.sampleDateTime).then(onSuccess, onFail);\n vm.busyLoadingSensors.addPromise(promise);\n\n function hasChangedDays() {\n var sampleDate = moment(timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.sampleDateTime)).startOf(\"d\");\n var currentDate = moment(vm.currentlySelectedDateTime).startOf(\"d\");\n return Math.abs(sampleDate.diff(currentDate, \"d\")) >= 1;\n }\n\n function onSuccess(sensorData) {\n if (!vm.sensorData.length) {\n vm.sensorData = sensorData;\n } else {\n _.forEach(vm.sensorData, function (pv) {\n _.merge(pv, _.find(sensorData, {\n id: pv.id\n }));\n });\n\n if (sensorData.length !== vm.sensorData.length) {\n graphsNeedRerendering = true;\n }\n }\n\n if (initialLoad) {\n var selectedProcessVariable = _.find(sensorData, {\n id: vm.selectedProcessVariableId\n });\n\n var defaultSensorId = selectedProcessVariable && selectedProcessVariable.id || vm.sensorData[0].id;\n onClickProcessVariable(defaultSensorId);\n $scope.$watch(function () {\n return vm.contentBounds;\n }, function () {\n vm.isPortrait = vm.contentBounds.width <= 320;\n vm.graphHeight = vm.contentBounds.height - 80;\n vm.graphWidth = vm.contentBounds.width <= 320 || vm.context === \"dashboard\" ? vm.contentBounds.width - 20 : vm.contentBounds.width - 340;\n renderSelectedSensorGraphs();\n }, true);\n } else {\n renderSelectedSensorGraphs();\n }\n\n initialLoad = false;\n }\n\n function onFail(response) {\n // Don't notify of a failure if the reason for failure is that the request expired or was cancelled\n // - this is a result of us buffering using the requestManager.\n if (response && response.reason && (response.reason === \"expired\" || response.reason === \"cancelled\")) {\n return;\n }\n\n notifier.error(i18n.i10n(\"esMonitoringWidget.graph.error.text\"), i18n.i10n(\"esMonitoringWidget.graph.error.heading\"));\n\n if (response) {\n response.handled = true;\n }\n }\n }\n\n function renderSelectedSensorGraphs() {\n ensureSensorAlwaysSelectedForLandscapeWidgets();\n var promise = $q.all(_.map(vm.processVariableIds, loadSensorDataSeries));\n vm.busyLoadingGraphDataSeries.addPromise(promise);\n promise.then(renderSensorGraphs);\n\n function ensureSensorAlwaysSelectedForLandscapeWidgets() {\n if (!vm.isPortrait && vm.selectedProcessVariableIds.length === 0) {\n onClickProcessVariable(vm.sensorData[0].id);\n }\n }\n }\n }\n\n function debouncedOnClickProcessVariable(processVariableId, event) {\n $timeout(function () {\n if (!abortSingleClick) {\n onClickProcessVariable(processVariableId, event);\n $timeout(renderSensorGraphs); // ensure graph container is mounted before rendering.\n }\n }, dblClickDelay);\n }\n\n function onClickProcessVariable(processVariableId, event) {\n if (event && event.ctrlKey) {\n onMultiSelectProcessVariable(processVariableId, event);\n } else {\n var isSelected = _.includes(vm.selectedProcessVariableIds, processVariableId);\n\n var processVariable = _.find(vm.sensorData, {\n id: processVariableId\n });\n\n processVariable.isSelected = !isSelected;\n\n if (isSelected && vm.isPortrait && vm.selectedProcessVariableIds.length === 1) {\n vm.selectedProcessVariableIds = [];\n } else {\n vm.selectedProcessVariableIds = [processVariableId];\n }\n\n _.forEach(vm.sensorData, function (pv) {\n pv.isSelected = pv.id === processVariableId;\n });\n }\n }\n\n function onMultiSelectProcessVariable(processVariableId) {\n abortSingleClick = true;\n $timeout(function () {\n return abortSingleClick = false;\n }, dblClickDelay);\n\n var isSelected = _.includes(vm.selectedProcessVariableIds, processVariableId);\n\n var processVariable = _.find(vm.sensorData, {\n id: processVariableId\n });\n\n processVariable.isSelected = !isSelected;\n\n if (isSelected && (vm.selectedProcessVariableIds.length === 1 && vm.isPortrait || vm.selectedProcessVariableIds.length > 1)) {\n _.pull(vm.selectedProcessVariableIds, processVariableId);\n } else if (!isSelected) {\n vm.selectedProcessVariableIds = [].concat(_toConsumableArray(vm.selectedProcessVariableIds), [processVariableId]);\n }\n\n _.forEach(vm.sensorData, function (pv) {\n pv.isSelected = _.includes(vm.selectedProcessVariableIds, pv.id);\n });\n\n $timeout(renderSensorGraphs); // ensure the graph container dom element is mounted first\n }\n\n function loadSensorDataSeries(processVariableId) {\n var processVariable = _.find(vm.sensorData, {\n id: processVariableId\n });\n\n if (!processVariable) {\n return $q.when();\n }\n\n if (!graphsNeedRerendering) {\n return updateGraphDetails(processVariable, prevDataSeries[processVariable.id]);\n }\n\n var windowStart = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(timeZoneDateTime.getFacilityStartOfDay(vm.sampleDateTime));\n var windowEnd = moment(windowStart).add(1, \"d\").toDate();\n return monitoringService.getSensorDataSeries(windowStart, windowEnd, processVariable.id).then(function (dataSeries) {\n prevDataSeries[processVariable.id] = dataSeries;\n return updateGraphDetails(processVariable, dataSeries);\n }).finally(function () {\n return graphsNeedRerendering = false;\n }); /////////////////\n\n function updateGraphDetails(processVariable, dataSet) {\n var pvThresholds = _.sortBy(dataSet.exceedanceThresholds, [\"valueInBaseUnit\"]);\n\n processVariable.graphDetails = {\n unit: dataSet.units,\n title: dataSet.processName,\n readings: [dataSet.processVariableName],\n data: dataSet.values.map(convertDatumToFacilityDateTime)\n };\n processVariable.graphDetails.markers = [{\n date: vm.currentlySelectedDateTime,\n label: dateTimeService.formatAs.time(vm.currentlySelectedDateTime)\n }];\n\n var _getMinMaxThresholdVa = getMinMaxThresholdValuesToShow(dataSet.values, pvThresholds),\n min = _getMinMaxThresholdVa.min,\n max = _getMinMaxThresholdVa.max;\n\n processVariable.graphDetails.baselines = _.chain(pvThresholds).filter(function (pvThreshold) {\n return pvThreshold.valueInDisplayUnit >= min && pvThreshold.valueInDisplayUnit <= max;\n }).map(function (pvThreshold) {\n // MetricGraphics library doesn't seem to handle numbers greater than a 32bit float.\n var baseLineValue = Math.min(mathService.floatMaxValue, Math.max(pvThreshold.valueInDisplayUnit, mathService.floatMinValue));\n return {\n value: baseLineValue,\n label: mathService.round(baseLineValue, 1),\n colour: intToHexColor(pvThreshold.color)\n };\n }).value();\n return processVariable;\n\n function intToHexColor(int) {\n /* eslint-disable no-bitwise */\n return \"#\" + (int >>> 0).toString(16).slice(-6);\n }\n\n function convertDatumToFacilityDateTime(dataPoint) {\n return {\n date: timeZoneDateTime.convertDateTimeToFacilityTimeZone(dataPoint.date),\n value: dataPoint.valueInDisplayUnit,\n thresholdColour: getThresholdColour(dataPoint.valueInBaseUnit)\n };\n }\n\n function getThresholdColour(value) {\n var matchingThreshold = _.findLast(pvThresholds, function (threshold) {\n return value >= threshold.valueInBaseUnit;\n });\n\n var defaultColor = \"#679B38\";\n\n if (matchingThreshold == null) {\n return defaultColor;\n }\n\n return intToHexColor(matchingThreshold.color);\n }\n\n function getMinMaxThresholdValuesToShow() {\n var pvValues = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n var pvThresholds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n // get the minimum and maximum pv data point values.\n var max = Number.MIN_SAFE_INTEGER;\n var min = Number.MAX_SAFE_INTEGER;\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = pvValues[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var pvValue = _step.value;\n max = Math.max(max, pvValue.valueInDisplayUnit);\n min = Math.min(min, pvValue.valueInDisplayUnit);\n } // now include all the thresholds within the min/max range and\n // ALSO include one extra on either side of min/max range\n // UNLESS those extraneous values are floatMinValue or floatMaxValue\n\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n var lower = min;\n var upper = max;\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = pvThresholds[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var pvThreshold = _step2.value;\n var thresholdValue = pvThreshold.valueInDisplayUnit;\n\n if (thresholdValue < min && thresholdValue > Number.MIN_SAFE_INTEGER) {\n lower = thresholdValue;\n } else if (thresholdValue > max && thresholdValue < Number.MAX_SAFE_INTEGER) {\n upper = thresholdValue;\n break;\n }\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return != null) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n return {\n min: lower,\n max: upper\n };\n }\n }\n }\n\n function renderSensorGraphs() {\n var targetAccessor = \"#o-\".concat(vm.instanceId, \" .es-monitoring-graph-content\");\n var $targetAccessor = $(targetAccessor); // if the widget has been removed from the DOM we don't need to render the graph.\n\n if (!$targetAccessor.length) {\n return;\n }\n\n var selectedSensors = _.filter(vm.sensorData, function (pv) {\n return pv.isSelected;\n });\n\n var isSingleSelectMode = selectedSensors.length === 1;\n\n var selectedGraphs = _.filter(selectedSensors, function (pv) {\n return pv.graphDetails;\n }).map(function (pv) {\n return pv.graphDetails;\n });\n\n var hasDstAdjustment = false;\n var data = selectedGraphs.map(function (graphDetails) {\n var seen = new Set();\n var data = graphDetails.data.filter(function (item) {\n // This is a hack to filter out duplicates due to DST adjustments - metrics-graphics doesn't like\n // duplicate datetimes.\n var key = item.date.toLocaleTimeString();\n return seen.has(key) ? false : seen.add(key);\n });\n\n if (data.length > 0) {\n var first = data[0].date.getTimezoneOffset();\n var last = data[data.length - 1].date.getTimezoneOffset();\n hasDstAdjustment = hasDstAdjustment || first !== last;\n }\n\n return data;\n });\n\n if (hasDstAdjustment) {\n // Second hack - shift everything back one so the data is not on a day that has a timezone adjustment.\n // The metrics-graphics chart cannot graph a time-series that crosses multiple timezones.\n data.forEach(function (series) {\n series.forEach(function (item) {\n item.date = moment(item.date).add(-1, \"day\").toDate();\n });\n });\n }\n\n if (isDataMissing()) {\n renderMissingData();\n } else {\n renderTrend();\n }\n\n function isDataMissing() {\n return !_.flatten(data).length;\n }\n\n function renderMissingData() {\n $targetAccessor.empty();\n var missingText = i18n.i10n(\"esMonitoringWidget.graph.labels.noDataAvailable\");\n\n if (isSingleSelectMode && selectedSensors[0].isValueStale) {\n missingText = \"\".concat(i18n.i10n(\"esMonitoringWidget.graph.labels.stale\"), \" \").concat(dateTimeService.formatAs.dateTime(timeZoneDateTime.convertDateTimeToFacilityTimeZone(selectedSensors[0].valueTime)));\n }\n /* eslint-disable camelcase */\n\n\n MG.data_graphic({\n chart_type: \"missing-data\",\n missing_text: missingText,\n target: targetAccessor,\n full_width: true,\n full_height: true\n });\n /* eslint-enable camelcase */\n }\n\n function renderTrend() {\n $targetAccessor.empty();\n var min = !hasDstAdjustment ? timeZoneDateTime.getFacilityStartOfDay(vm.sampleDateTime) : timeZoneDateTime.getFacilityStartOfDay(moment(vm.sampleDateTime).add(-1, \"day\").toDate());\n var max = moment(min).add(1, \"d\").toDate();\n var markers = selectedGraphs[0].markers;\n\n if (hasDstAdjustment) {\n markers.forEach(function (marker) {\n marker.date = moment(marker.date).add(-1, \"day\").toDate();\n });\n }\n\n var baselines = selectedGraphs.length === 1 ? selectedGraphs[0].baselines : null;\n\n var indices = _.sortBy(_.map(vm.selectedProcessVariableIds, function (sId) {\n return _.findIndex(vm.processVariableIds, function (pvId) {\n return pvId === sId;\n });\n }));\n\n var adjustedPalette = _.map(indices, function (index) {\n return palette[index % palette.length];\n });\n /* eslint-disable camelcase */\n\n\n MG.data_graphic({\n target: targetAccessor,\n animate_on_load: graphsNeedRerendering,\n min_x: min,\n max_x: max,\n x_accessor: \"date\",\n xax_format: dateTimeService.formatAs.hour,\n y_accessor: \"value\",\n yax_format: function yax_format(value) {\n return \"\".concat(value);\n },\n yax_count: 5,\n y_extended_ticks: true,\n show_secondary_x_label: false,\n show_rollover_text: false,\n interpolate: d3.curveMonotoneX,\n aggregate_rollover: !isSingleSelectMode,\n full_width: true,\n full_height: true,\n missing_is_zero: true,\n top: 20,\n bottom: 20,\n colors: adjustedPalette,\n area: true,\n flip_area_under_y_value: 0,\n data: data,\n markers: markers,\n baselines: baselines,\n mouseover: function mouseover(dataPoint, i) {\n var values = dataPoint.values || [dataPoint];\n vm.sampleTime = values[0].date;\n var millis = vm.sampleTime.getTime();\n $timeout(function () {\n _.forEach(vm.sensorData, function (sensor) {\n var selectedDataPoint = _.findLast(sensor.graphDetails.data, function (dataPoint) {\n return dataPoint.date.getTime() <= millis;\n });\n\n sensor.graphDetails.selectedDataPoint = selectedDataPoint;\n });\n });\n },\n mouseout: function mouseout() {\n vm.sampleTime = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.sampleDateTime);\n $timeout(function () {\n _.forEach(vm.sensorData, function (sensor) {\n sensor.graphDetails.selectedDataPoint = null;\n });\n });\n }\n });\n /* eslint-enable camelcase */\n // Some on-premise clients are reporting that the graphs are not appearing.\n // This may catch that situation and log an error to the console that can be reported.\n // This is very low level because the situation in which this might occur is vague.\n\n if ($targetAccessor.html().indexOf(\"es-monitoring-graph-content\") < 0) {\n throw \"The graph area does not contain the expected graph content. Content is:\\n\".concat($targetAccessor.html());\n }\n\n _.forEach(baselines, function (baseline, index) {\n var $baseline = $(\".mg-baselines line:nth-child(\".concat(index + 1, \")\"));\n $baseline.css(\"stroke\", baseline.colour).css(\"stroke-dasharray\", \"2,5\");\n });\n }\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").directive(\"esMonitorTypeSelectionCriteria\", directive);\n directive.$inject = [];\n\n function directive() {\n return {\n scope: {\n monitorType: \"@\",\n state: \"=\"\n },\n restrict: \"E\",\n controllerAs: \"vm\",\n bindToController: true,\n controller: controller,\n templateUrl: \"/App/ui/features/monitoring/controls/esMonitorTypeSelectionCriteria.html\",\n transclude: true\n };\n }\n\n controller.$inject = [\"app.core.services.configuration.monitoringService\"];\n\n function controller(monitoringService) {\n var vm = this;\n vm.icon = monitoringService.getMonitorTypeIcon(vm.monitorType);\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").directive(\"esSourceIdentificationPanel\", directive);\n directive.$inject = [];\n\n function directive() {\n return {\n scope: {\n state: \"=\"\n },\n restrict: \"E\",\n controllerAs: \"vm\",\n bindToController: true,\n controller: function controller() {},\n templateUrl: \"/App/ui/features/monitoring/controls/esSourceIdentificationPanel.html\"\n };\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").controller(\"app.ui.features.monitoring.LeftPanel\", LeftPanel);\n LeftPanel.$inject = [\"$scope\", \"lodash\", \"monitoringState\"];\n\n function LeftPanel($scope, _, monitoringState) {\n var vm = this;\n vm.state = monitoringState;\n activate(); /////////////////////\n\n function activate() {\n renderMarkers();\n addWatchersToDisplaySwitches();\n addWatchersToSensorSwitches();\n }\n\n function renderMarkers() {\n monitoringState.map.renderMonitorMapMarkers();\n }\n\n function addWatchersToDisplaySwitches() {\n $scope.$watch(function () {\n return vm.state.map.switches.display;\n }, function () {\n return renderMarkers();\n }, true);\n $scope.$watch(function () {\n return vm.state.map.switches.influenceArcs;\n }, function (newValue) {\n getSensorTypes().map(mapSensorNameToSensorArcTuple).forEach(toggleInfluenceArcVisibility);\n\n function mapSensorNameToSensorArcTuple(sensorType) {\n var influenceArcOverlayBySensor = getInfluenceArcsOverlayForSensor(sensorType);\n return {\n arc: influenceArcOverlayBySensor,\n sensor: vm.state.map.layers.overlays[sensorType]\n };\n }\n\n function toggleInfluenceArcVisibility(overlay) {\n if (!overlay.arc) {\n return;\n }\n\n overlay.arc.visible = newValue && overlay.sensor.visible;\n }\n });\n }\n\n function addWatchersToSensorSwitches() {\n var sensorTypes = getSensorTypes();\n\n _.forEach(sensorTypes, watchSensorVisibilityToggle);\n\n function watchSensorVisibilityToggle(sensorType) {\n $scope.$watch(function () {\n return vm.state.map.switches.sensorTypes[sensorType];\n }, toggleSensorVisibility);\n\n function toggleSensorVisibility(newValue) {\n vm.state.map.layers.overlays[sensorType].visible = newValue;\n getInfluenceArcsOverlayForSensor(sensorType).visible = newValue && vm.state.map.switches.influenceArcs;\n }\n }\n }\n\n function getSensorTypes() {\n return _.keys(vm.state.map.switches.sensorTypes);\n }\n\n function getInfluenceArcsOverlayForSensor(sensorType) {\n return vm.state.map.layers.overlays[\"influenceArcs-\".concat(sensorType)];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.monitoring.state\"];\n\n function appRun(routeHelper, monitoringState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.monitoring\",\n url: \"/monitoring/{companyAlias}/{facilityAlias}?dateTime&fullScreen\",\n views: {\n actionsPanel: {\n templateUrl: \"/App/ui/features/monitoring/ActionsPanel.html\",\n controller: \"app.ui.features.monitoring.ActionsPanel as vm\"\n },\n leftPanel: {\n templateUrl: \"/App/ui/features/monitoring/LeftPanel.html\",\n controller: \"app.ui.features.monitoring.LeftPanel as vm\"\n },\n contentPanel: {\n templateUrl: \"/App/ui/features/monitoring/ContentPanel.html\",\n controller: \"app.ui.features.monitoring.ContentPanel as vm\"\n }\n },\n reloadOnSearch: false,\n // allows us to set the ?dateTime parameter without reloading the resolvers.\n data: {\n requiredAccessControl: \"app.monitoring\"\n },\n settings: {\n i18n: [\"/App/ui/features/monitoring/i18n/monitoring\", \"/App/ui/features/monitoring/controls/i18n/esMonitoringDateTimeSelector\", \"/App/ui/features/monitoring/controls/i18n/esMonitoringWidget\", \"/App/ui/features/monitoring/controls/i18n/esMonitoringPopup\", \"/App/ui/features/monitoring/controls/i18n/esMonitorTypeSelectionCriteria\", \"/App/ui/features/monitoring/controls/i18n/esSourceIdentificationPanel\", \"/App/ui/core/mapping/controls/i18n/esMapCentre\", \"/App/ui/core/mapping/controls/i18n/esMapKml\", \"/App/ui/core/mapping/controls/i18n/esMapCredits\", \"/App/ui/core/mapping/controls/i18n/esMapTiles\", \"/App/ui/core/mapping/controls/i18n/esMapType\"]\n },\n resolve: {\n monitoringState: monitoringState\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.monitoring\").factory(\"app.ui.features.monitoring.state\", monitoringStateFactory);\n monitoringStateFactory.$inject = [\"$q\", \"lodash\", \"app.core.appSettings\", \"app.core.mapDefaults\", \"app.core.services.companyService\", \"app.core.services.monitoringService\", \"app.core.services.configuration.monitoringService\", \"app.core.models.monitoring.createMonitorMapMarker\", \"app.core.models.monitoring.createMonitorMapPath\", \"app.core.models.monitoring.createMonitorMapFenceline\"];\n\n function monitoringStateFactory($q, _, appSettings, mapDefaults, companyService, monitoringService, monitoringConfigurationService, createMonitorMapMarker, createMonitorMapPath, createMonitorMapFenceline) {\n return function () {\n var getFacilityLocation = companyService.getFacilityLocation();\n var getMonitorsByType = monitoringService.getMonitorsByType();\n var getMonitorTypes = monitoringConfigurationService.getMonitorTypes();\n return $q.all([getFacilityLocation, getMonitorsByType, getMonitorTypes]).then(function (result) {\n var _result = _slicedToArray(result, 3),\n facilityLocation = _result[0],\n monitorsByType = _result[1],\n monitorTypes = _result[2];\n\n var state = {\n accessControls: {\n sourceIdentification: !!appSettings.site.accessControls[\"app.monitoring.source-identification\"],\n sourceIdentificationDebug: !!appSettings.site.accessControls[\"app.monitoring.source-identification-debug\"]\n },\n monitorTypes: monitorTypes,\n monitorsByType: monitorsByType,\n monitors: [],\n areaSources: [],\n map: {\n defaultCentre: facilityLocation,\n centre: facilityLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n isColor: false,\n paths: {},\n layers: {\n baselayers: mapDefaults.baselayers,\n overlays: buildLayers(monitorTypes)\n }\n }\n };\n var sensorTypes = {};\n\n _.forEach(monitorTypes, function (monitorType) {\n sensorTypes[monitorType.type] = true;\n });\n\n state.map.switches = {\n boundaries: true,\n influenceArcs: true,\n sourceIdentification: true,\n sourceIdentificationDebug: false,\n display: {\n monitorNames: false,\n units: false,\n heroMode: false,\n thresholdExceeded: false,\n icons: true\n },\n sensorTypes: sensorTypes\n };\n\n state.map.renderMonitorMapMarkers = function () {\n state.map.markers = _.map(state.monitors, function (monitor) {\n return createMonitorMapMarker(monitor, _extends({}, state.map.switches.display, {\n dataValue: true\n }));\n });\n setInfluenceArcs();\n state.map.bounds = _.map(state.monitors, function (monitor) {\n return [monitor.latitude, monitor.longitude];\n });\n\n var fencelines = _.chain(state.monitors).filter(function (monitor) {\n return monitor.fencelineLocations && monitor.fencelineLocations.length >= 2;\n }).map(function (monitor) {\n return createMonitorMapFenceline(monitor, state.map.switches.display);\n }).flatten().reduce(function (obj, fenceline) {\n obj[fenceline.id] = fenceline;\n return obj;\n }, {}).value();\n\n state.map.paths = _extends({}, state.map.paths, fencelines);\n };\n\n if (state.accessControls.sourceIdentification) {\n var areaSourcesLayerName = \"areaSources\";\n state.map.layers.overlays[areaSourcesLayerName] = {\n type: \"group\",\n visible: true,\n name: areaSourcesLayerName\n };\n\n state.map.renderSourceAreaSources = function () {\n var areaSources = _.map(state.areaSources, function (process) {\n return createMonitorMapPath(process, {\n layer: areaSourcesLayerName,\n showUnitsOnPopup: false,\n graphProcessVariables: process.dataPoints.map(function (dp) {\n return dp.id;\n }),\n canAccessConfiguration: false\n });\n });\n\n areaSources = _.reduce(areaSources, function (obj, areaSource) {\n obj[areaSource.id] = areaSource;\n return obj;\n }, {});\n state.map.paths = _extends({}, state.map.paths, areaSources);\n };\n }\n\n function setInfluenceArcs() {\n state.map.influenceArcs = state.monitors.map(function (monitor) {\n var influenceArc = monitor.influenceArc || {};\n influenceArc.monitorId = monitor.id;\n influenceArc.latitude = monitor.latitude;\n influenceArc.longitude = monitor.longitude;\n influenceArc.monitorType = monitor.monitorType;\n influenceArc.thresholdColour = monitor.influenceArc ? monitor.influenceArc.thresholdColour : \"\";\n influenceArc.unrender = !monitor.influenceArc || state.map.switches.display.thresholdExceeded && !monitor.processVariable.hasValueExceededFirstThreshold;\n return influenceArc;\n });\n }\n\n return state;\n });\n };\n\n function buildLayers(monitorTypes) {\n var layers = {};\n\n _.forEach(monitorTypes, function (monitorType) {\n layers[monitorType.type] = {\n type: \"group\",\n visible: true,\n name: monitorType.name\n };\n layers[\"influenceArcs-\".concat(monitorType.type)] = {\n type: \"group\",\n visible: true,\n name: \"\".concat(monitorType.name, \" Influence Arcs\")\n };\n });\n\n return layers;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.reporting\").controller(\"app.ui.features.reporting.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$state\", \"$window\", \"$location\", \"promiseTracker\", \"app.core.services.reportsService\"];\n\n function ContentPanel($state, $window, $location, promiseTracker, reportsService) {\n var vm = this;\n vm.busyLoading = promiseTracker();\n activate(); //////////////////////////\n\n function activate() {\n vm.listOptions = getListOptions();\n loadReports().then(function (reports) {\n reports.filter(function (report) {\n return report.isEs2Report;\n }).forEach(function (report) {\n report.uri = $state.href(report.uri, report.params);\n });\n vm.listOptions.items = reports;\n }); //////////////////////////\n\n function loadReports() {\n var loadingPromise = reportsService.getListOfReports();\n vm.busyLoading.addPromise(loadingPromise);\n return loadingPromise;\n }\n\n function getListOptions() {\n return {\n columnDefs: [{\n heading: {\n i18n: {\n key: \"app.ui.features.reporting.ContentPanel.list.columns.name.heading\"\n }\n },\n field: \"name\"\n }, {\n heading: {\n i18n: {\n key: \"app.ui.features.reporting.ContentPanel.list.columns.description.heading\"\n }\n },\n field: \"description\"\n }],\n busyLoading: vm.busyLoading,\n onItemSelected: onReportSelected\n };\n }\n\n function onReportSelected(report) {\n window.location = report.uri;\n }\n }\n }\n})();\n\n\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.reporting\").controller(\"app.ui.features.reporting.reports.ProcessDataReport\", ProcessDataReport);\n ProcessDataReport.$inject = [\"$scope\", \"$state\", \"$q\", \"lodash\", \"i18n\", \"promiseTracker\", \"FileSaver\", \"notifier\", \"app.core.services.reportsService\", \"app.core.services.dateTimeService\", \"app.core.errorService\", \"app.core.datetime.timeZoneDateTime\"];\n\n function ProcessDataReport($scope, $state, $q, _, i18n, promiseTracker, saveFile, notifier, reportsService, dateTimeService, errorService, timeZoneDateTime) {\n var vm = this; // See: http://stackoverflow.com/a/18925211\n\n var utf8EncodingHeader = \"\\uFEFF\";\n var stateParamsKeys = {\n processId: \"processId\",\n startTime: \"start\",\n endTime: \"end\"\n };\n\n var hasAllStateParams = _.every(stateParamsKeys, function (key) {\n return _.has($state.params, key) && $state.params[key];\n });\n\n var lastProcessIdUsedToLoadColumns = null;\n var hasColumns = false;\n vm.busyLoading = promiseTracker();\n vm.reportId = $state.params.reportId;\n vm.parameters = {};\n vm.processes = [];\n vm.controls = {};\n vm.onRefreshed = onRefreshed;\n vm.export = exportReport;\n activate(); //////////////////////////\n\n function activate() {\n buildControls();\n revalidateStartAndEndTimeWhenParametersChange();\n var loadingPromise = loadLookupValues().then(loadReportDataIfParametersSpecified);\n vm.busyLoading.addPromise(loadingPromise); //////////////////////////\n\n function buildControls() {\n vm.controls = {\n startTime: buildDatePicker(),\n endTime: buildDatePicker(),\n dataGrid: buildDataGrid()\n }; //////////////////////////\n\n function buildDatePicker() {\n return {\n options: {\n format: dateTimeService.formats.kendo.dateTime,\n timeFormat: dateTimeService.formats.kendo.time\n }\n };\n }\n\n function buildDataGrid() {\n return {\n options: {\n dataProvider: loadReportData,\n filterable: false\n }\n };\n }\n }\n\n function loadLookupValues() {\n return reportsService.getProcessDataReportLookupValues(vm.reportId).then(importLookupValues).catch(redirectBackToReports); ////////////////////\n\n function importLookupValues(lookups) {\n vm.processes = lookups.processes;\n\n if (hasAllStateParams) {\n vm.parameters = {\n processId: $state.params[stateParamsKeys.processId],\n startTime: createDateModel($state.params[stateParamsKeys.startTime]),\n endTime: createDateModel($state.params[stateParamsKeys.endTime])\n };\n } else {\n vm.parameters = {\n processId: lookups.processes && lookups.processes.length && lookups.processes[0].id,\n startTime: createDateModel(lookups.utcStartTime),\n endTime: createDateModel(lookups.utcEndTime)\n };\n }\n\n lastProcessIdUsedToLoadColumns = null;\n } ////////////////////\n\n\n function createDateModel(utcTime) {\n var localDateTime = convertUtcToFacilityTime(utcTime);\n return {\n date: localDateTime,\n formattedString: dateTimeService.formatAs.dateTime(localDateTime)\n };\n }\n\n function redirectBackToReports(ex) {\n if (ex.status !== 404) {\n return;\n } // The reportId does not exist - most likely this is because the user changed facilities.\n\n\n ex.handled = true;\n $state.go(\"app.reporting\");\n }\n }\n\n function loadReportDataIfParametersSpecified() {\n if (!hasAllStateParams) {\n return;\n }\n\n var unsubscribe = $scope.$watch(function () {\n return vm.controls.dataGrid.grid;\n }, function (gridApi) {\n if (!gridApi) {\n return;\n }\n\n unsubscribe();\n updateGrid();\n });\n }\n }\n\n function revalidateStartAndEndTimeWhenParametersChange() {\n var watches = [function () {\n return vm.parameters.startTime && vm.parameters.startTime.date;\n }, function () {\n return vm.parameters.endTime && vm.parameters.endTime.date;\n }];\n $scope.$watchGroup(watches, function () {\n vm.$form.startTime.$validate();\n vm.$form.endTime.$validate();\n });\n }\n\n function onRefreshed() {\n updateStateParams();\n updateGrid();\n }\n\n function updateStateParams() {\n var _toParams;\n\n var toParams = (_toParams = {}, _defineProperty(_toParams, stateParamsKeys.processId, vm.parameters.processId), _defineProperty(_toParams, stateParamsKeys.startTime, convertFacilityDateTimeToShortISOString(vm.parameters.startTime.date)), _defineProperty(_toParams, stateParamsKeys.endTime, convertFacilityDateTimeToShortISOString(vm.parameters.endTime.date)), _toParams);\n $state.go(\"app.reporting.processData\", toParams, {\n notify: false\n });\n }\n\n function updateGrid() {\n // If the grid columns haven`t changed (i.e. the user hasn`t changed the process they want to\n // see the data for) then we only need to refresh the grid.\n if (vm.parameters.processId === lastProcessIdUsedToLoadColumns) {\n vm.controls.dataGrid.grid.refreshData();\n return;\n } // Otherwise we need to rebuild the grid with the columns for the new process id.\n\n\n var loadingColumnsPromise = reportsService.getProcessDataReportColumns(vm.parameters.processId).then(function (columns) {\n hasColumns = true; // Rebuilding the grid also causes the data to be refreshed.\n\n var gridColumns = buildGridColumns(columns);\n vm.controls.dataGrid.grid.rebuildGrid(gridColumns);\n lastProcessIdUsedToLoadColumns = vm.parameters.processId;\n });\n vm.busyLoading.addPromise(loadingColumnsPromise); ////////////////////\n\n function buildGridColumns(processVariables) {\n var timeColumn = {\n field: \"key\",\n title: i18n.i10n(\"app.ui.features.reporting.reports.processDataReport.date.label\"),\n format: \"{0:\".concat(dateTimeService.formats.kendo.dateTimeWithSeconds, \"}\"),\n dataType: \"date\"\n };\n\n var columns = _.map(processVariables, function (processVariable) {\n return {\n field: \"value[\\\"\".concat(processVariable.id, \"\\\"]\"),\n title: processVariable.name,\n format: \"{0:n1}\",\n dataType: \"number\"\n };\n });\n\n return [timeColumn].concat(_toConsumableArray(columns));\n }\n }\n\n function loadReportData(searchCriteria) {\n if (!hasColumns) {\n return $q.resolve();\n }\n\n return getParametersWithLocalTimes().then(function (parameters) {\n return reportsService.getProcessDataReport(parameters.processId, parameters.localStartTime, parameters.localEndTime, searchCriteria);\n }).then(function (report) {\n notifyIfNoDataAvailable(report && report.data);\n return report;\n }).catch(errorService.processError);\n }\n\n function exportReport() {\n getParametersWithLocalTimes().then(getReportDataAsCsv).then(notifyIfNoDataAvailable).then(saveCsvFile).catch(errorService.processError); ////////////////////\n\n function getReportDataAsCsv(parameters) {\n var searchCriteria = vm.controls.dataGrid.grid.getSearchCriteria();\n var getReportDataAsCsvPromise = reportsService.exportProcessDataReport(parameters.processId, parameters.localStartTime, parameters.localEndTime, searchCriteria);\n vm.busyLoading.addPromise(getReportDataAsCsvPromise);\n return getReportDataAsCsvPromise;\n }\n\n function saveCsvFile(csvData) {\n if (!csvData) {\n return;\n }\n\n var textBlob = new Blob([utf8EncodingHeader, csvData], {\n type: \"text/csv;charset=UTF8\"\n });\n\n var process = _.find(vm.processes, {\n id: vm.parameters.processId\n });\n\n var fileName = \"\".concat(dateTimeService.formatAs.iso(vm.parameters.startTime.date), \"-\").concat(dateTimeService.formatAs.iso(vm.parameters.endTime.date), \"-\").concat(process.name, \"-ProcessDataReport.csv\");\n saveFile(textBlob, fileName);\n }\n }\n\n function getParametersWithLocalTimes() {\n if (!(vm.parameters.processId && vm.parameters.startTime.date && vm.parameters.endTime.date)) {\n return $q.reject();\n }\n\n var localStartTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.parameters.startTime.date);\n var localEndTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.parameters.endTime.date);\n var parameters = {\n processId: vm.parameters.processId,\n localStartTime: localStartTime,\n localEndTime: localEndTime\n };\n return $q.resolve(parameters);\n }\n\n function convertUtcToFacilityTime(utcDateTimeString) {\n var localDateTime = new Date(utcDateTimeString);\n return timeZoneDateTime.convertDateTimeToFacilityTimeZone(localDateTime);\n }\n\n function convertFacilityDateTimeToShortISOString(dateTime) {\n var localDateTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(dateTime);\n var iso = localDateTime.toISOString(); // Chop off seconds and milliseconds\n\n return iso.replace(/:\\d{2}\\.\\d{3}Z$/, \"Z\");\n }\n\n function notifyIfNoDataAvailable(data) {\n var hasData = data && data.length;\n\n if (hasData) {\n return data;\n }\n\n var warning = \"app.ui.features.reporting.reports.processDataReport.warnings.noDataAvailable\";\n notifier.info(i18n.i10n(\"\".concat(warning, \".message\")), i18n.i10n(\"\".concat(warning, \".heading\")));\n return data;\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.reporting\").run(appRun);\n appRun.$inject = [\"routeHelper\"];\n\n function appRun(routeHelper) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: \"app.reporting\",\n url: \"/reporting/{companyAlias}/{facilityAlias}\",\n views: {\n contentPanel: {\n templateUrl: \"/App/ui/features/reporting/ContentPanel.html\",\n controller: \"app.ui.features.reporting.ContentPanel as vm\"\n }\n },\n data: {\n requiredAccessControl: \"app.reports\"\n },\n settings: {\n i18n: [\"/App/ui/features/reporting/i18n/reporting\", \"/App/ui/features/reporting/i18n/ContentPanel\"]\n }\n }, {\n state: \"app.reporting.processData\",\n url: \"/processData/{reportId}?processId&start&end\",\n views: {\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/reporting/reports/ProcessDataReport.html\",\n controller: \"app.ui.features.reporting.reports.ProcessDataReport as vm\"\n }\n },\n settings: {\n i18n: [\"/App/ui/features/reporting/i18n/reports/ProcessDataReport\"]\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.user\").controller(\"app.ui.features.user.profile.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"userTabs\"];\n\n function ContentPanel(userTabs) {\n var vm = this;\n vm.tabs = userTabs;\n activate(); //////////////////\n\n function activate() {}\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.user\").controller(\"app.ui.features.user.profile.PasswordTab\", PasswordTab);\n PasswordTab.$inject = [\"$scope\", \"$state\", \"$q\", \"promiseTracker\", \"notifier\", \"i18n\", \"app.core.appSettings\", \"app.core.services.userService\", \"userTabs\"];\n\n function PasswordTab($scope, $state, $q, promiseTracker, notifier, i18n, appSettings, userService, userTabs) {\n var vm = this;\n vm.busySaving = promiseTracker();\n vm.save = save;\n vm.cancel = clearForm;\n activate();\n\n function activate() {\n $scope.$watch(function () {\n return vm.$form.$dirty;\n }, function () {\n return userTabs.password.isDirty = vm.$form.$dirty;\n });\n }\n\n function save() {\n var savingPromise = updatePassword();\n savingPromise.then(saveSuccess);\n vm.busySaving.addPromise(savingPromise);\n\n function updatePassword() {\n return userService.updatePassword(appSettings.user.username, vm.currentPassword, vm.newPassword);\n }\n\n function saveSuccess() {\n clearForm();\n var title = i18n.i10n(\"app.ui.features.user.profile.passwordTab.notifications.passwordUpdated.heading\");\n var message = i18n.i10n(\"app.ui.features.user.profile.passwordTab.notifications.passwordUpdated.message\");\n notifier.info(message, title);\n }\n }\n\n function clearForm() {\n vm.$form.$setPristine();\n $state.go(\"app.user.profile.password\", {}, {\n reload: true\n });\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.user\").factory(\"app.ui.features.user.profile.state\", stateFactory);\n stateFactory.$inject = [\"$state\", \"app.ui.core.controls.Tab\"];\n\n function stateFactory($state, Tab) {\n return {\n userTabs: userTabs\n }; //////////////////\n\n function userTabs() {\n return {\n details: new Tab(\"app.ui.features.user.profile.contentPanel.tabs.profile.heading\", function () {\n return $state.href(\"app.user.profile.details\");\n }, function () {\n return $state.$current.name === \"app.user.profile.details\";\n }),\n password: new Tab(\"app.ui.features.user.profile.contentPanel.tabs.password.heading\", function () {\n return $state.href(\"app.user.profile.password\");\n }, function () {\n return $state.$current.name === \"app.user.profile.password\";\n })\n };\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.user\").controller(\"app.ui.features.user.profile.UserDetailsTab\", UserDetailsTab);\n UserDetailsTab.$inject = [\"$scope\", \"promiseTracker\", \"app.core.services.userService\", \"userTabs\"];\n\n function UserDetailsTab($scope, promiseTracker, userService, userTabs) {\n var vm = this;\n vm.busySaving = promiseTracker();\n vm.busyLoading = promiseTracker();\n vm.profile = {};\n vm.save = save;\n vm.cancel = cancel;\n activate(); //////////////////\n\n function activate() {\n var loadPromise = loadUserDetails();\n vm.busyLoading.addPromise(loadPromise);\n $scope.$watch(function () {\n return vm.$form.$dirty;\n }, function () {\n return userTabs.details.isDirty = vm.$form.$dirty;\n });\n $scope.$watch(function () {\n return vm.busyLoading.active();\n }, function (isBusyLoading) {\n return userTabs.details.isBusyLoading = isBusyLoading;\n });\n }\n\n function loadUserDetails() {\n var loadPromise = userService.getUserDetails(true).then(function (profile) {\n return vm.profile = profile;\n });\n return loadPromise;\n }\n\n function save() {\n var savingPromise = persistUserDetails();\n savingPromise.then(saveSuccess);\n vm.busySaving.addPromise(savingPromise);\n\n function persistUserDetails() {\n return userService.updateUserDetails(vm.profile);\n }\n\n function saveSuccess() {\n vm.$form.$setPristine();\n activate();\n }\n }\n\n function cancel() {\n activate();\n vm.$form.$setPristine();\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.user\").run(appRun);\n appRun.$inject = [\"routeHelper\", \"app.ui.features.user.profile.state\"];\n\n function appRun(routeHelper, userState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n abstract: true,\n state: \"app.user\",\n url: \"/user\"\n }, {\n // provides details panel responsible for managing the tabs.\n abstract: true,\n state: \"app.user.profile\",\n url: \"/profile\",\n views: {\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/user/profile/ContentPanel.html\",\n controller: \"app.ui.features.user.profile.ContentPanel as vm\"\n }\n },\n resolve: {\n userTabs: userState.userTabs\n },\n settings: {\n i18n: [\"/App/ui/features/user/profile/i18n/profile\"]\n }\n }, {\n state: \"app.user.profile.details\",\n url: \"/details\",\n views: {\n 'tab@app.user.profile': {\n templateUrl: \"/App/ui/features/user/profile/UserDetailsTab.html\",\n controller: \"app.ui.features.user.profile.UserDetailsTab as vm\"\n }\n }\n }, {\n state: \"app.user.profile.password\",\n url: \"/password\",\n views: {\n 'tab@app.user.profile': {\n templateUrl: \"/App/ui/features/user/profile/PasswordTab.html\",\n controller: \"app.ui.features.user.profile.PasswordTab as vm\"\n }\n }\n }, {\n state: \"app.user.settings\",\n url: \"/settings\",\n views: {\n 'contentPanel@app': {\n templateUrl: \"/App/ui/features/user/settings/ContentPanel.html\",\n controller: \"app.ui.features.user.settings.ContentPanel as vm\"\n }\n },\n settings: {\n i18n: [\"/App/ui/features/user/settings/i18n/settings\"]\n }\n }];\n }\n }\n})();\n\n\n\"use strict\";\n\n(function () {\n \"use strict\";\n\n angular.module(\"app.ui.features.user\").controller(\"app.ui.features.user.settings.ContentPanel\", ContentPanel);\n ContentPanel.$inject = [\"$window\", \"lodash\", \"app.core.services.settingsService\", \"app.core.appSettings\"];\n\n function ContentPanel($window, _, settingsService, appSettings) {\n var vm = this;\n vm.setLanguage = setLanguage;\n vm.appSettings = appSettings;\n activate(); //////////////////\n\n function activate() {\n vm.languages = settingsService.getSupportedLanguages();\n settingsService.getSelectedLanguage().then(function (selectedLanguage) {\n vm.selectedLanguage = selectedLanguage;\n });\n }\n\n function setLanguage(language) {\n settingsService.setLanguage(language).then(function () {\n $window.location.reload(true);\n });\n }\n }\n})();\n\n","`use strict`;\r\n\r\nangular\r\n .module(`app.ui.core`)\r\n .component(`esRouteSwitch`, {\r\n controller: esRouteSwitch,\r\n bindings: {\r\n routes: `<`,\r\n selectedRoute: `<`,\r\n onChange: `&`\r\n },\r\n transclude: true,\r\n templateUrl: `/App/ui/core/controls/esRouteSwitch.html`,\r\n controllerAs: `vm`\r\n });\r\n\r\nesRouteSwitch.$inject = [`$state`];\r\nfunction esRouteSwitch($state) {\r\n const vm = this;\r\n vm.changeRoute = changeRoute;\r\n\r\n vm.$onChanges = changes => {\r\n if (changes.selectedRoute) {\r\n vm.selectedRouteName = changes.selectedRoute.currentValue;\r\n }\r\n };\r\n\r\n //////////////////\r\n\r\n function changeRoute(routeName) {\r\n const oldRoute = vm.selectedRouteName;\r\n $state.go(routeName);\r\n vm.onChange({ newRoute : routeName, oldRoute : oldRoute });\r\n }\r\n}","(function () {\n `use strict`;\n\n angular.module(`blocks.browserStorage`, [`webStorageModule`]);\n\n})();","(function () {\n `use strict`;\n\n angular.module(`blocks.directives`, [`kendo.directives`]);\n})();\n","(function () {\n `use strict`;\n\n angular.module(`blocks.exception`, []);\n\n})();","(function () {\r\n `use strict`;\r\n\r\n angular.module(`blocks.i18n`, []);\r\n\r\n})();","(function () {\n `use strict`;\n\n angular.module(`blocks`, []);\n})();","(function () {\n `use strict`;\n\n angular.module(`blocks.notifier`, [`jlareau.pnotify`]);\n\n})();","(function () {\n `use strict`;\n\n angular.module(`blocks.router`, [`ui.router`]);\n\n})();","(function () {\n `use strict`;\n\n angular.module(`blocks.utils`, []);\n})();","(function () {\n `use strict`;\n\n angular.module(`blocks.validators`, []);\n})();","(function () {\r\n `use strict`;\r\n angular.module(`bootstrapper`, [`app.core`]);\r\n\r\n angular.module(`bootstrapper`)\r\n .config(BootstrapConfig)\r\n .run(BootstrapRun);\r\n\r\n BootstrapConfig.$inject = [\r\n `app.core.bootstrapper.configurators.stateReloadDecoratorProvider`,\r\n `app.core.bootstrapper.configurators.IE9BehaviorProvider`,\r\n `app.core.bootstrapper.configurators.notificationProvider`,\r\n `app.core.bootstrapper.configurators.httpProvider`,\r\n `app.core.bootstrapper.configurators.httpBatchProvider`,\r\n `app.core.bootstrapper.configurators.internationalizationProvider`,\r\n `app.core.bootstrapper.configurators.blockUIProvider`,\r\n `app.core.bootstrapper.configurators.localStorageProvider`,\r\n `app.core.bootstrapper.configurators.tooltipProvider`,\r\n `app.core.bootstrapper.configurators.dashboardProvider`\r\n ];\r\n\r\n function BootstrapConfig(...configurators) {\r\n configurators.forEach(configurator => configurator.configure());\r\n }\r\n\r\n BootstrapRun.$inject = [\r\n `app.core.bootstrapper.runners.routeHandler`,\r\n `app.core.bootstrapper.runners.dashboard`,\r\n `app.core.bootstrapper.runners.fileUploader`,\r\n `app.core.bootstrapper.runners.kendoCultures`,\r\n `app.core.bootstrapper.runners.internationalization`\r\n ];\r\n\r\n function BootstrapRun(...runners) {\r\n runners.forEach(run => run());\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`, [\r\n /*\r\n * Angular modules\r\n */\r\n `ngAnimate`, `ngSanitize`, `ngCookies`,\r\n\r\n /*\r\n * Our reusable cross app code modules\r\n */\r\n `blocks`,\r\n `blocks.directives`,\r\n `blocks.exception`,\r\n `blocks.router`,\r\n `blocks.notifier`,\r\n `blocks.i18n`,\r\n `blocks.validators`,\r\n `blocks.browserStorage`,\r\n `blocks.utils`,\r\n\r\n /*\r\n * 3rd Party modules\r\n */\r\n `kendo.directives`,\r\n `ngMessages`,\r\n `ui.router`,\r\n `ui.validate`,\r\n `SignalR`,\r\n `ui.bootstrap`,\r\n `ipCookie`,\r\n `ajoslin.promise-tracker`,\r\n `blockUI`,\r\n `jcs.angular-http-batch`,\r\n `angular-cache`,\r\n `ngclipboard`,\r\n `angularFileUpload`,\r\n `angular-loading-bar`,\r\n\r\n /*\r\n * Angular Dashboard\r\n */\r\n `adf`,\r\n `adf.provider`,\r\n\r\n /*\r\n * Angular translate dependencies\r\n */\r\n `pascalprecht.translate`,\r\n\r\n /*\r\n * Leaflet Angular directive\r\n */\r\n `es-leaflet-directive`,\r\n\r\n `app.legacy-adapter`\r\n ]).config([`$compileProvider`, $compileProvider =>\r\n $compileProvider.preAssignBindingsEnabled(true)\r\n ]);\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular.module(`app`, [\r\n /*\r\n * Order is not important. Angular makes a\r\n * pass to register all of the modules listed\r\n * and then when app.dashboard tries to use app.data,\r\n * its components are available.\r\n */\r\n `app.templates`,\r\n\r\n /*\r\n * Gulp bundled - Application Features\r\n */\r\n `app.ui.features.alerts`,\r\n `app.ui.features.blasting`,\r\n `app.ui.features.dashboard`,\r\n `app.ui.features.extras`,\r\n `app.ui.features.modelling`,\r\n `app.ui.features.monitoring`,\r\n `app.ui.features.reporting`,\r\n `app.ui.features.user`,\r\n\r\n `app.ui.features.configuration.company.blasting`,\r\n `app.ui.features.configuration.company.modelling`,\r\n `app.ui.features.configuration.company.monitoring`,\r\n\r\n `app.ui.features.configuration.system`,\r\n\r\n /*\r\n * WebPack bundled - Application Features\r\n * NOTE: add the module into App.Tests\\stubs\\webPackModules.stub.js\r\n */\r\n `app.ui.features.incidentIntelligence`,\r\n\r\n // This is the new stuff\r\n `app.parcel`\r\n ]);\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.ui.core`, [\r\n `app.core`\r\n ]);\r\n\r\n})();\r\n","(function () {\n `use strict`;\n\n angular.module(`app.ui.features.alerts`, [\n `app.ui.core`\n ]);\n})(); ","(function() {\n `use strict`;\n\n angular.module(`app.ui.features.blasting`, [\n `angularFileUpload`,\n `frapontillo.bootstrap-switch`,\n `app.ui.core`\n ]);\n})(); ","`use strict`;\r\n\r\n(function() {\r\n angular.module(`app.ui.features.configuration.company.blasting`, [\r\n `app.ui.features.configuration`,\r\n `app.ui.features.blasting`\r\n ]);\r\n})();","`use strict`;\r\n\r\n(function() {\r\n angular.module(`app.ui.features.configuration.company.modelling`, [\r\n `app.ui.core`\r\n ]);\r\n\r\n})();","`use strict`;\r\n\r\n(function() {\r\n angular.module(`app.ui.features.configuration.company.monitoring`, [\r\n `ui.sortable`,\r\n `app.ui.core`\r\n ]);\r\n})();","`use strict`;\r\n\r\n(function() {\r\n angular.module(`app.ui.features.configuration`, [\r\n `ui.bootstrap`,\r\n `angularFileUpload`,\r\n `app.ui.core`\r\n ]);\r\n})();\r\n","(function() {\r\n angular\r\n .module(`app.ui.features.configuration.system`, [`app.ui.core`]);\r\n})();\r\n","(function () {\n `use strict`;\n\n angular.module(`app.ui.features.dashboard`, [\n `ui.bootstrap`,\n `app.ui.features.modelling`,\n `app.ui.core`\n ]);\n\n})();","`use strict`;\r\n\r\n(function () {\r\n angular.module(`app.ui.features.extras`, [\r\n `app.ui.core`\r\n ]);\r\n})();","(function() {\n `use strict`;\n\n angular.module(`app.ui.features.incidentIntelligence`, [\n `frapontillo.bootstrap-switch`,\n `app.ui.core`\n ]);\n})(); ","(function () {\n `use strict`;\n\n angular.module(`app.ui.features.modelling`, [\n `app.ui.core`\n ]);\n})(); ","`use strict`;\n\n(function () {\n angular.module(`app.ui.features.monitoring`, [\n `frapontillo.bootstrap-switch`,\n `app.ui.core`\n ]);\n})();","`use strict`;\n\n(function () {\n angular.module(`app.ui.features.reporting`, [\n `app.ui.core`\n ]);\n})();","`use strict`;\r\n\r\n(function () {\r\n angular.module(`app.ui.features.user`, [\r\n `app.ui.core`\r\n ]);\r\n})();","(function () {\n `use strict`;\n\n angular\n .module(`blocks.browserStorage`)\n .factory(`browserStorage`, browserStorage);\n\n browserStorage.$inject = [`lodash`, `webStorage`];\n function browserStorage(_, webStorage) {\n\n return {\n persist,\n get : get,\n 'delete': deleteItem,\n\n persistBucket,\n getBucket,\n deleteBucket\n };\n\n /////////////////////\n function persist(storageKey, itemToPersist) {\n validateStorageKey(storageKey);\n let storageItem = webStorage.get(storageKey) || {};\n if (!_.isEqual(storageItem, itemToPersist)) {\n storageItem = itemToPersist;\n webStorage.add(storageKey, storageItem);\n }\n }\n\n function persistBucket(storageKey, bucketKey, itemToPersist) {\n validateBucketKey(storageKey, bucketKey);\n const storageItem = webStorage.get(storageKey) || {};\n if (!_.isEqual(storageItem[bucketKey], itemToPersist)) {\n storageItem[bucketKey] = itemToPersist;\n webStorage.add(storageKey, storageItem);\n }\n }\n\n function deleteItem(storageKey) {\n validateStorageKey(storageKey);\n webStorage.remove(storageKey);\n }\n\n function deleteBucket(storageKey, bucketKey) {\n validateBucketKey(storageKey, bucketKey);\n const storageItem = webStorage.get(storageKey) || {};\n delete storageItem[bucketKey];\n webStorage.add(storageKey, storageItem);\n }\n\n function get(storageKey) {\n validateStorageKey(storageKey);\n const storageItem = webStorage.get(storageKey);\n return storageItem;\n }\n\n function getBucket(storageKey, bucketKey) {\n validateBucketKey(storageKey, bucketKey);\n const storageItem = webStorage.get(storageKey) || {};\n return storageItem[bucketKey];\n }\n\n function validateStorageKey(storageKey) {\n if (!_.isString(storageKey)) {\n throw new Error(`The storage key must be a string with a value.`);\n }\n }\n\n function validateBucketKey(storageKey, bucketKey) {\n validateStorageKey(storageKey);\n if (!_.isString(bucketKey)) {\n throw new Error(`The bucket key must be a string with a value.`);\n }\n }\n }\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.directives`)\r\n .directive(`esDataGrid`, esDataGrid)\r\n .controller(`esDataGridController`, esDataGridController);\r\n\r\n esDataGrid.$inject = [`$window`, `lodash`];\r\n\r\n function esDataGrid($window, _) {\r\n return {\r\n scope: {\r\n options: `=`,\r\n grid: `=?`\r\n },\r\n restrict: `E`,\r\n templateUrl: `/App/blocks/directives/esDataGrid/esDataGrid.html`,\r\n controller: esDataGridController,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n const paddingBottom = 5;\r\n\r\n $scope.$on(`resizePage`, resizeGrid);\r\n $scope.$on(`grid.resize`, resizeGrid);\r\n\r\n function resizeGrid() {\r\n const container = $element.find(`.panel`),\r\n gridElement = $element.find(`.k-grid`),\r\n gridRows = gridElement.find(`.k-grid-content`),\r\n otherGridElements = gridElement.children().not(`.k-grid-content`),\r\n footer = $element.find(`.panel-footer`);\r\n\r\n let otherElementsHeight = footer && footer.length && footer[0].offsetHeight || 0;\r\n\r\n _.forEach(otherGridElements, element => {\r\n otherElementsHeight += element.offsetHeight;\r\n });\r\n\r\n const containerHeight = container[0].offsetHeight;\r\n\r\n const preferredHeight = containerHeight - otherElementsHeight - paddingBottom;\r\n const maxAllowedHeight = angular.element($window).height() - container.offset().top - otherElementsHeight - paddingBottom;\r\n gridRows.height(Math.min(preferredHeight, maxAllowedHeight));\r\n\r\n const buttons = gridRows.find(`.k-button`);\r\n _.forEach(buttons, button => {\r\n angular.element(button).removeClass(`k-button`);\r\n angular.element(button).removeClass(`k-button-icontext`);\r\n });\r\n }\r\n }\r\n }\r\n\r\n esDataGridController.$inject = [`$scope`, `lodash`, `app.core.services.dateTimeService`, `promiseTracker`];\r\n\r\n function esDataGridController($scope, _, dateTimeService, promiseTracker) {\r\n const vm = this;\r\n const clickableCells = [];\r\n const sorts = [];\r\n\r\n vm.busyLoading = promiseTracker();\r\n\r\n activate();\r\n\r\n function activate() {\r\n if (!vm.options.dataProvider) {\r\n throw new Error(`Data provider not defined. Please bind to a function that returns a promise for a DataSourceResult.`);\r\n }\r\n\r\n const preProcessedOptions = preProcessOptions(vm.options);\r\n const { onDataBound, ...rest } = preProcessedOptions;\r\n\r\n vm.kendoGridOptions = angular.merge(getDefaultOptions(onDataBound), getDefaultDataSourceOptions(), rest);\r\n vm.grid = buildGridApi();\r\n\r\n initGridAfterKendoGridCreated();\r\n\r\n ////////////////////\r\n\r\n // This builds an API that can be called by the consumer of the grid to force a refresh or update the\r\n // columns dynamically.\r\n function buildGridApi() {\r\n return {\r\n rebuildGrid,\r\n refreshData,\r\n getSearchCriteria\r\n };\r\n\r\n //////////////////////\r\n\r\n // Rebuild the grid, which will also refresh the data\r\n function rebuildGrid(columns) {\r\n const schemaAndColumns = buildSchemaAndColumns(columns);\r\n\r\n const options = {\r\n columns: schemaAndColumns.columns\r\n };\r\n\r\n vm.kendoGrid.setOptions(options);\r\n vm.kendoGrid.dataSource.reader.model.define(schemaAndColumns.schema.model);\r\n }\r\n\r\n // Refresh the data\r\n function refreshData() {\r\n vm.kendoGrid.dataSource.read();\r\n }\r\n\r\n function getSearchCriteria() {\r\n const dataSource = vm.kendoGrid.dataSource;\r\n\r\n return {\r\n columns: vm.kendoGrid.columns.filter(col => col.field).map(col => col.field),\r\n take: dataSource.take(),\r\n skip: dataSource.skip(),\r\n sort: dataSource.sort(),\r\n filter: dataSource.filter(),\r\n aggregates: dataSource.aggregates()\r\n };\r\n }\r\n }\r\n\r\n function initGridAfterKendoGridCreated() {\r\n $scope.$on(`kendoWidgetCreated`, () => {\r\n if (!vm.kendoGrid) {\r\n return;\r\n }\r\n\r\n vm.kendoGrid.pager.element.hide();\r\n\r\n $scope.$watch(\r\n () => vm.options.selectedId,\r\n selectedId => {\r\n if (selectedId) {\r\n return;\r\n }\r\n\r\n const $grid = angular.element(vm.kendoGrid.content);\r\n const row = $grid.find(`tbody>tr.k-state-selected`);\r\n row.removeClass(`k-state-selected`);\r\n });\r\n\r\n addClickHandler();\r\n });\r\n }\r\n }\r\n\r\n //////////////////////\r\n\r\n function getDefaultOptions(onDataBoundFromOptions) {\r\n const options = {\r\n selectable: `single row`,\r\n sortable: {\r\n mode: `multiple`,\r\n allowUnsort: true\r\n },\r\n columns: [],\r\n dataBound: onDataBound,\r\n change: onChange,\r\n resizable: true,\r\n reorderable: true\r\n };\r\n\r\n return options;\r\n\r\n ////////////////////\r\n\r\n function onChange(kendoEvent) {\r\n if (!vm.options.rowCallback) {\r\n return;\r\n }\r\n\r\n const grid = kendoEvent.sender;\r\n const item = grid.dataItem(grid.select());\r\n vm.options.rowCallback(item);\r\n }\r\n\r\n function onDataBound(event) {\r\n if (vm.kendoGrid.dataSource.totalPages() > 1) {\r\n vm.kendoGrid.pager.element.show();\r\n } else {\r\n vm.kendoGrid.pager.element.hide();\r\n }\r\n\r\n if (vm.options.selectedId) {\r\n highlightSelectedItem();\r\n }\r\n\r\n if (onDataBoundFromOptions) {\r\n onDataBoundFromOptions.call(this, event);\r\n }\r\n\r\n $scope.$broadcast(`grid.resize`);\r\n\r\n ///////////////////\r\n\r\n function highlightSelectedItem() {\r\n const item = vm.kendoGrid.dataSource.get(vm.options.selectedId);\r\n if (item) {\r\n const $grid = angular.element(vm.kendoGrid.content);\r\n const row = $grid.find(`tbody>tr[data-uid=${item.uid}]`);\r\n row.addClass(`k-state-selected`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n function getDefaultDataSourceOptions() {\r\n const options = {\r\n dataSource: {\r\n transport: {\r\n read: kendoEvent => {\r\n const queryObject = kendoEvent.data;\r\n if (vm.options.dataProvider) {\r\n const loadingPromise = vm.options.dataProvider(queryObject).then(kendoEvent.success);\r\n vm.busyLoading.addPromise(loadingPromise);\r\n }\r\n }\r\n },\r\n sort: null,\r\n schema: {\r\n data: response => response && response.data || [],\r\n total: response => response && response.total || 0,\r\n aggregates: response => response && response.aggregates || [],\r\n groups: response => response && response.groups || []\r\n },\r\n serverPaging: true,\r\n serverSorting: true,\r\n serverGrouping: false,\r\n serverFiltering: true,\r\n pageSize: 100\r\n },\r\n groupable: false,\r\n navigatable: true,\r\n scrollable: {\r\n virtual: false\r\n },\r\n pageable: {\r\n numeric: false,\r\n previousNext: true,\r\n refresh: true,\r\n input: true\r\n },\r\n filterable: {\r\n extra: false\r\n }\r\n };\r\n\r\n return options;\r\n }\r\n\r\n function preProcessOptions(options) {\r\n const schemaAndColumns = buildSchemaAndColumns(options.columns);\r\n\r\n options.columns = schemaAndColumns.columns;\r\n options.dataSource = _.extend({}, options.dataSource || {}, {\r\n schema: { ...schemaAndColumns.schema, ...(options.dataSource && options.dataSource.schema || {}) },\r\n sort: _.sortBy(sorts, `order`)\r\n });\r\n\r\n return options;\r\n }\r\n\r\n function buildSchemaAndColumns(columns) {\r\n const schemaFields = {};\r\n\r\n columns = _.map(columns, (column, columnIndex) => {\r\n\r\n if (column.dataType === `datetime`) {\r\n column.format = `{0:${dateTimeService.formats.kendo.dateTime}}`;\r\n column.type = `date`;\r\n if (typeof column.filterable === `undefined`) {\r\n column.filterable = {\r\n ui: `datetimepicker`,\r\n format: `{0:${dateTimeService.formats.kendo.dateTime}}`\r\n };\r\n }\r\n }\r\n\r\n if (column.dataType === `date`) {\r\n column.format = `{0:${dateTimeService.formats.kendo.dateTime}}`;\r\n column.type = `date`;\r\n if (typeof column.filterable === `undefined`) {\r\n column.filterable = {\r\n ui: `datepicker`,\r\n format: `{0:${dateTimeService.formats.kendo.dateTime}}`\r\n };\r\n }\r\n }\r\n\r\n if (column.dataType === `time`) {\r\n column.format = `{0:${dateTimeService.formats.kendo.dateTime}}`;\r\n column.type = `date`;\r\n if (typeof column.filterable === `undefined`) {\r\n column.filterable = {\r\n ui: `timepicker`,\r\n format: `{0:${dateTimeService.formats.kendo.dateTime}}`\r\n };\r\n }\r\n }\r\n\r\n // The default filterable ui works well for the remaining data types, so we don't need to set these explicitly.\r\n if (column.dataType === `number`) {\r\n column.type = `number`;\r\n }\r\n\r\n if (column.dataType === `boolean`) {\r\n column.type = `boolean`;\r\n }\r\n\r\n if (column.dataType === `string` || typeof column.dataType === `undefined`) {\r\n column.type = `string`;\r\n }\r\n\r\n if (column.sort) {\r\n sorts.push({\r\n field: column.field,\r\n dir: column.sort.dir,\r\n order: column.sort.order\r\n });\r\n }\r\n\r\n // NOTE: Order is important here! The click handler below must be the last item since the above are fixed once the template is set.\r\n if (column.click) {\r\n const fieldTemplate = column.template || column.format ? `#= kendo.format('${column.format}', ${column.field})#` : `#=${column.field}#`;\r\n\r\n const clickableCellSelector = `data-click-${columnIndex}`;\r\n clickableCells.push(`[${clickableCellSelector}]`);\r\n\r\n column.template = `${fieldTemplate}`;\r\n }\r\n\r\n if (column.field && column.type) {\r\n schemaFields[column.field] = { type: column.type };\r\n }\r\n\r\n return column;\r\n });\r\n\r\n // Add a slack column that does not have a fixed width to fill out the remainder of the grid width.\r\n // If this is not added resizing will not function correctly if all columns are set to fixed width as they will be implicitly (incorrectly) converted to variable width.\r\n // If only some of the columns are set then they will not be visible on smaller screen resolutions.\r\n // If every column does not have a width then we are assuming the user has opted for variable widths.\r\n if (columns.every(column => column.width && !isNaN(parseFloat(column.width)) && isFinite(column.width))) {\r\n columns.push({});\r\n }\r\n\r\n const schema = {\r\n model: {\r\n fields: schemaFields\r\n }\r\n };\r\n\r\n return { columns, schema };\r\n }\r\n\r\n function addClickHandler() {\r\n\r\n if (!clickableCells.length) {\r\n return;\r\n }\r\n\r\n const selector = clickableCells.join(`, `);\r\n const $grid = angular.element(vm.kendoGrid.content);\r\n\r\n // Note: DO NOT change this to an arrow function, it changes the scope of `this` and breaks.\r\n $grid.on(`click`, selector, function() {\r\n // Find the data record\r\n const $this = angular.element(this);\r\n const $row = $this.closest(`tr`);\r\n const rowData = vm.kendoGrid.dataItem($row);\r\n\r\n // Lookup the function from the parent scope\r\n const clickAttr = _.find(this.attributes, attr => attr.name.indexOf(`data-click-`) === 0);\r\n if (!clickAttr) {\r\n return;\r\n }\r\n\r\n const matches = clickAttr.name.match(/data-click-(\\d+)/);\r\n const columnIndex = parseInt(matches[1], 10);\r\n\r\n const column = vm.kendoGrid.columns[columnIndex];\r\n const clickHandler = column.click;\r\n\r\n if (clickHandler && _.isFunction(clickHandler)) {\r\n clickHandler(rowData);\r\n }\r\n });\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.directives`)\r\n .directive(`pelAutoFocus`, pelAutoFocus);\r\n\r\n pelAutoFocus.$inject = [];\r\n function pelAutoFocus() {\r\n\r\n return {\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n $element[0].focus();\r\n }\r\n }\r\n\r\n})();"," /* istanbul ignore next */\r\n\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.directives`)\r\n .directive(`pelMarkModelDirtyOnBlur`, pelMarkModelDirtyOnBlur);\r\n\r\n pelMarkModelDirtyOnBlur.$inject = [];\r\n\r\n function pelMarkModelDirtyOnBlur() {\r\n\r\n const directive = {\r\n restrict: `A`,\r\n compile: compiler\r\n };\r\n\r\n return directive;\r\n\r\n function compiler() {\r\n return function($scope, $element) {\r\n\r\n const delegatingEventSelector = $element.is(`input`) || $element.is(`select`) ? `` : `input, select`;\r\n $element.on(`blur`, delegatingEventSelector, event => {\r\n const ngModel = angular.element(event.currentTarget).data(`$ngModelController`);\r\n if (ngModel) {\r\n $scope.$apply(() => {\r\n ngModel.$$lastCommittedViewValue = ngModel.$$lastCommittedViewValue + ` `;\r\n ngModel.$dirty = true;\r\n ngModel.$commitViewValue();\r\n });\r\n }\r\n });\r\n };\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.directives`)\r\n .directive(`pelScrollToFirstError`, pelScrollToFirstError);\r\n\r\n pelScrollToFirstError.$inject = [];\r\n /* istanbul ignore next */\r\n function pelScrollToFirstError() {\r\n\r\n return {\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n /* istanbul ignore next */\r\n function link($scope, $elem) {\r\n $elem.on(`click`, () => {\r\n const $input = $elem.closest(`form`).find(`input.ng-invalid,textarea.ng-invalid,select.ng-invalid`).filter(`:first`);\r\n focus($input);\r\n });\r\n\r\n function focus($element) {\r\n if (!$element || !$element.length) {\r\n return;\r\n }\r\n\r\n const element = $element[0];\r\n if (\r\n element.clientWidth !== 0 &&\r\n element.clientHeight !== 0 &&\r\n element.style.opacity !== 0 &&\r\n element.style.visibility !== `hidden` &&\r\n element.style.display !== `none`) {\r\n $element.focus();\r\n return;\r\n }\r\n focus($element.parent());\r\n }\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.exception`)\r\n .config(decorateExceptionHandler);\r\n\r\n decorateExceptionHandler.$inject = [`$provide`];\r\n function decorateExceptionHandler($provide) {\r\n $provide.decorator(`$exceptionHandler`, exceptionHandlerDecorator);\r\n }\r\n\r\n exceptionHandlerDecorator.$inject = [`$log`, `$injector`, `$window`];\r\n function exceptionHandlerDecorator($log, $injector, $window) {\r\n\r\n const unhandledJavaScriptStatusCode = -999;\r\n let i18n, messageList, message, title, $timeout;\r\n const isUnhandledJavascriptError = error => error.type === `fatal` && error.status === unhandledJavaScriptStatusCode;\r\n\r\n window.addEventListener(`error`, addJavascriptErrorsToMessageList);\r\n\r\n return function(exception) {\r\n if (exception.handled) {\r\n return;\r\n }\r\n addJavascriptErrorsToMessageList({ message: exception.message, error: exception });\r\n if (angular.mock && exception.rethrow) {\r\n throw exception;\r\n }\r\n };\r\n\r\n ////////////////////////\r\n\r\n function addJavascriptErrorsToMessageList(event) {\r\n // these messages are 'fatal' in that they can prevent the application from running correctly but\r\n // refreshing the page for a javascript error will not result in any benefit to the user\r\n if (!i18n) {\r\n // Injector is used to get dependency because injecting these dependencies directly will result into circular dependency.\r\n i18n = $injector.get(`i18n`);\r\n $timeout = $injector.get(`$timeout`);\r\n\r\n messageList = $injector.get(`app.core.models.messages.messageList`);\r\n title = i18n.i10n(`errors.javascript.exception.title`);\r\n message = i18n.i10n(`errors.javascript.exception.message`);\r\n }\r\n\r\n $timeout(() => {\r\n messageList.update(isUnhandledJavascriptError) || messageList.addFatal(title, message, unhandledJavaScriptStatusCode);\r\n });\r\n\r\n if (event) {\r\n $log.fatal(event.message, event.error);\r\n $window.LogRocket && $window.LogRocket.captureException(event.error);\r\n }\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.i18n`, [`blocks.router`])\r\n .provider(`i18n`, i18nProvider);\r\n\r\n i18nProvider.$inject = [];\r\n function i18nProvider() {\r\n const self = this;\r\n self.settings = {};\r\n self.$get = i18n;\r\n\r\n i18n.$inject = [`$translatePartialLoader`, `$translate`, `$state`, `$q`, `$log`, `routeHelper`, `lodash`];\r\n function i18n($translatePartialLoader, $translate, $state, $q, $log, routeHelper, _) {\r\n\r\n const loaders = {};\r\n let addedResources = [];\r\n const resolvedPromise = $q.when(true);\r\n\r\n routeHelper.addStateChangeStartEventHandler((event, toState, toParams, fromState) => {\r\n return ensureTranslationsAreLoaded(fromState, toState);\r\n }, 99999); // make this the last step\r\n\r\n return {\r\n i10n: $translate.instant, // e.g. i10n(`resourceKey`) -> returns the localized value.\r\n loadTranslationsFor: loadTranslationsFor, // e.g. for example usage see -> app/core/services/jobService.js\r\n onTranslationsLoaded: onTranslationsLoaded, // used by blocks.router -> routeHelper.js\r\n unloadStates: unloadStates // used by bootstrapper in the $stateChangeSuccess event\r\n };\r\n\r\n ///////////////\r\n\r\n function buildUrl(...parts) {\r\n const url = [];\r\n const partCount = parts.length;\r\n\r\n for (let i = 0; i < partCount; i++) {\r\n let part = parts[i];\r\n\r\n // If this isn't the first part, and it STARTS with a slash, then strip it off\r\n if (i > 0 && part[0] === `/`) {\r\n part = part.substr(1);\r\n }\r\n\r\n // If this isn't the last part, and it ENDS with a slash, then strip it off.\r\n if (i < partCount - 1 && part[part.length - 1] === `/`) {\r\n part = part.substr(0, part.length - 1);\r\n }\r\n\r\n url.push(part);\r\n }\r\n\r\n return url.join(`/`);\r\n }\r\n\r\n function loadTranslationsFor(referenceUrl) {\r\n\r\n const resourceUrl = getResourceUrl(referenceUrl);\r\n $translatePartialLoader.addPart(resourceUrl);\r\n\r\n return $translate.refresh().then(() => {\r\n $log.debug(`loaded: ` + referenceUrl);\r\n return $translate.instant;\r\n });\r\n }\r\n\r\n function onTranslationsLoaded(state) {\r\n if (!state) {\r\n state = $state.current;\r\n }\r\n\r\n const loadedPromise = getTranslationsLoadedPromise(state);\r\n\r\n return loadedPromise.then(() => {\r\n return $translate.instant; // note: this promise can be accessed in the controller constructor as i10n [see: admin.js]\r\n });\r\n }\r\n\r\n function getTranslationsLoadedPromise(state) {\r\n if (state) {\r\n return loadStates(null, state);\r\n }\r\n\r\n if (_.isEmpty(loaders)) {\r\n return $q.when(true);\r\n }\r\n\r\n const allLoaders = _.values(loaders);\r\n return $q.all(allLoaders);\r\n }\r\n\r\n /// The reference url can have a .html suffix (for template urls) or not.\r\n function getResourceUrl(referenceUrl) {\r\n if (!referenceUrl) {\r\n return null;\r\n }\r\n\r\n let matches;\r\n // If the referenceUrl DOES NOT end with .html\r\n if (referenceUrl.indexOf(`.html`, referenceUrl.length - `.html`.length) === -1) {\r\n matches = referenceUrl.match(/(.+(?=\\/))(?:\\/)(.*)/);\r\n // Using this as an example: app/ui/monitoring/app.ui.monitoring.ContentPanel\r\n // matches[1]: (app/ui/monitoring/)\r\n // matches[2]: (app.ui.monitoring.ContentPanel)\r\n } else {\r\n matches = referenceUrl.match(/(.+(?=\\/))(?:\\/)(.*(?=.html))/);\r\n // Using this as an example: app/ui/monitoring/ContentPanel.html\r\n // matches[1]: (app/ui/monitoring/)\r\n // matches[2]: (ContentPanel)\r\n }\r\n\r\n const templateFolder = matches[1];\r\n const resourceName = matches[2];\r\n\r\n // Now we can compose the resource path: \"i18n/app/ui/monitoring/i18n/app.ui.monitoring.ContentPanel\".\r\n // The `i18n` at the start forces the correct resource to be loaded via the InternationalisationController.\r\n return buildUrl(`i18n`, templateFolder, `i18n`, resourceName);\r\n }\r\n\r\n function getResourceUrlsFromStateSettings(state) {\r\n let resourceUrls = [];\r\n\r\n if (!(state && state.settings && state.settings.i18n)) {\r\n return resourceUrls;\r\n }\r\n\r\n resourceUrls = state.settings.i18n;\r\n\r\n if (_.isString(resourceUrls)) {\r\n resourceUrls = [resourceUrls];\r\n }\r\n\r\n return resourceUrls.map(url => {\r\n if (url === null || url === undefined || !_.isString(url)) {\r\n return null;\r\n }\r\n\r\n // This regex tests if the url starts with /i18n/ or i18n/\r\n return /^[\\/]?i18n\\//i.test(url) ? url : buildUrl(`i18n`, url);\r\n });\r\n }\r\n\r\n function ensureTranslationsAreLoaded(fromState, toState) {\r\n return loadStates(fromState, toState);\r\n }\r\n\r\n function unloadStates(fromState, toState) {\r\n let ready = $q.when(true);\r\n if (!fromState) {\r\n return ready;\r\n }\r\n\r\n const toStatePath = toState && toState.name && getStatePath(toState.name) || [];\r\n const toStateResources = getResourceUrlsFromStateSettings(toState);\r\n\r\n let unloadedResources = false;\r\n for (let stateName = fromState.name; stateName !== null; stateName = getParentStateName(stateName)) {\r\n // Unload up to the part where resources are no longer common. e.g. if you are navigating via the following states:\r\n // From - agent.college.enrolments\r\n // To - agent.college.offers\r\n //\r\n // Then we only want to unload the \"enrolments\" resources\r\n if (isInPath(toStatePath, stateName)) {\r\n break;\r\n }\r\n\r\n const state = stateName === fromState.name ? fromState : $state.get(stateName);\r\n if (!state) {\r\n continue;\r\n }\r\n\r\n unloadedResources = true;\r\n\r\n // Unload explicitly defined resources that are no longer required\r\n const explicitResourcesForState = getResourceUrlsFromStateSettings(state);\r\n const explicitResourcesToUnload = _.filter(explicitResourcesForState, url => !_.includes(toStateResources, url));\r\n\r\n _.forEach(explicitResourcesToUnload, unloadResource);\r\n\r\n // Now check for a resource corresponding to all templates\r\n const templateResourceUrls = getTemplateResourceUrls(state);\r\n _.forEach(templateResourceUrls, unloadTemplateResource);\r\n }\r\n\r\n if (unloadedResources) {\r\n ready = $translate.refresh();\r\n ready.then(logReadyDebug);\r\n }\r\n\r\n return ready;\r\n\r\n function logReadyDebug() {\r\n $log.debug(`finished unloading translation files...`);\r\n }\r\n\r\n function unloadResource(resourcePath) {\r\n //// Don`t bother if the resource is null or hasn`t been loaded\r\n if (!(resourcePath && _.has(loaders, resourcePath))) {\r\n return;\r\n }\r\n\r\n // this line was added for the following scenario. we have a route called /add\r\n // it loads in a language file corresponding with a details.html template.\r\n // we then move to a route called /edit\r\n // it loads in a language file corresponding to the same details.html template - as both routes\r\n // are based on the same template.\r\n // usually we unload language files associated with templates from the previous route\r\n // but this time we want to keep it loaded as it's the same and required.\r\n if (!addedResources.length) {\r\n return;\r\n }\r\n\r\n $translatePartialLoader.deletePart(resourcePath, false);\r\n delete loaders[resourcePath];\r\n\r\n $log.debug(`unloading: ` + resourcePath);\r\n }\r\n\r\n function unloadTemplateResource(templateResourceUrl) {\r\n unloadResource(getResourceUrl(templateResourceUrl));\r\n }\r\n }\r\n\r\n function loadStates(fromState, toState) {\r\n if (!toState) {\r\n return resolvedPromise;\r\n }\r\n\r\n addedResources = [];\r\n const requiredResources = [];\r\n let refreshPromise;\r\n const fromStatePath = fromState && fromState.name && getStatePath(fromState.name) || [];\r\n\r\n // Load resources for this state as well as parent states\r\n for (let stateName = toState.name; stateName !== null; stateName = getParentStateName(stateName)) {\r\n // These states are already loaded by the parent path\r\n if (isInPath(fromStatePath, stateName)) {\r\n break;\r\n }\r\n\r\n const state = stateName === toState.name ? toState : $state.get(stateName);\r\n\r\n if (!state) {\r\n continue;\r\n }\r\n\r\n // Check for explicitly defined resources\r\n const resourceUrls = getResourceUrlsFromStateSettings(state);\r\n _.forEach(resourceUrls, loadResource);\r\n\r\n // Now check for a resource corresponding to all templates\r\n const templateResourceUrls = getTemplateResourceUrls(state);\r\n\r\n _.forEach(templateResourceUrls, loadTemplateResource);\r\n }\r\n\r\n if (addedResources.length) {\r\n // If we have requested any resources, then we return a new promise which will resolve when these\r\n // resources have been loaded.\r\n\r\n refreshPromise = $translate.refresh();\r\n\r\n _.forEach(addedResources, path => {\r\n loaders[path] = refreshPromise;\r\n });\r\n\r\n } else if (requiredResources.length) {\r\n // If no new resources have been requested, but there are resources which are required, then we return\r\n // a new promise which resolves when ALL of the required resource loaders are resolved.\r\n const requiredLoaders = _.map(requiredResources, requiredPath => {\r\n return _.has(loaders, requiredPath) && loaders[requiredPath] || resolvedPromise;\r\n });\r\n\r\n refreshPromise = $q.all(requiredLoaders);\r\n\r\n } else {\r\n // If there's nothing to load, well...\r\n refreshPromise = resolvedPromise;\r\n }\r\n\r\n if (refreshPromise !== resolvedPromise) {\r\n refreshPromise.then(() => {\r\n $log.debug(`finished loaded translation files...`);\r\n });\r\n }\r\n\r\n return refreshPromise;\r\n\r\n function loadResource(resourcePath) {\r\n requiredResources.push(resourcePath);\r\n\r\n // Don`t reload the resources if they`re already loading/loaded\r\n if (!resourcePath || _.has(loaders, resourcePath)) {\r\n return;\r\n }\r\n\r\n $translatePartialLoader.addPart(resourcePath);\r\n addedResources.push(resourcePath);\r\n $log.debug(`loading: ` + resourcePath);\r\n }\r\n\r\n function loadTemplateResource(templateResourceUrl) {\r\n loadResource(getResourceUrl(templateResourceUrl));\r\n }\r\n }\r\n\r\n function getTemplateResourceUrls(state) {\r\n let templateUrl;\r\n const templates = [];\r\n\r\n if (state.views) {\r\n const templateUrlValues = _.map(state.views, `templateUrl`);\r\n _.forEach(templateUrlValues, templateUrlValue => {\r\n if (_.isFunction(templateUrlValue)) {\r\n templateUrl = templateUrlValue(state.params);\r\n templates.push(templateUrl);\r\n } else { // string\r\n templates.push(templateUrlValue);\r\n }\r\n });\r\n\r\n } else {\r\n if (_.isFunction(state.templateUrl)) {\r\n templateUrl = state.templateUrl(state.params);\r\n } else {\r\n templateUrl = state.templateUrl;\r\n }\r\n templates.push(templateUrl);\r\n }\r\n\r\n return templates;\r\n }\r\n\r\n function getParentStateName(childStateName) {\r\n const matches = childStateName.match(/(.+)\\./);\r\n\r\n return matches && matches.length ? matches[1] : null;\r\n }\r\n\r\n // Breaks up a state path such as \"modelling.job.dashboard\" into [\"modelling\", \"job\", \"dashboard\"];\r\n function getStatePath(stateName) {\r\n return _.map(stateName.match(/[^.]+/g), path => {\r\n return path.toLowerCase();\r\n });\r\n }\r\n\r\n // Finds out if the given path (e.g. [\"modelling\", \"job\", \"dashboard\"]) contains the supplied path (e.g. \"modelling.job\")\r\n function isInPath(path, stateName) {\r\n const statePath = getStatePath(stateName);\r\n if (statePath.length > path.length) {\r\n return false;\r\n }\r\n\r\n for (let i = 0; i < statePath.length; i++) {\r\n if (path[i] !== statePath[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n }\r\n }\r\n})();","(function () {\n `use strict`;\n\n angular\n .module(`blocks.notifier`)\n .factory(`notifier`, notifier);\n\n notifier.$inject = [`notificationService`, `moment`];\n\n function notifier(notificationService, moment) {\n const service = {\n error: error,\n info: info,\n success: success,\n warning: warning\n };\n\n return service;\n\n /////////////////////\n\n function error(message, title, options = { hide: false }) {\n message += `${moment().format(`DD MMM YYYY hh:mm:ss A`)}`;\n return notify(message, title, `error`, options);\n }\n\n function info(message, title, options = {}) {\n return notify(message, title, `info`, options);\n }\n\n function success(message, title, options = {}) {\n return notify(message, title, `success`, options);\n }\n\n function warning(message, title, options = {}) {\n return notify(message, title, `notice`, options);\n }\n\n function notify(message, title, type, options) {\n /* eslint-disable camelcase */\n const defaultOptions = {\n title: title,\n text: message,\n type: type,\n hide: true,\n delay: 4000,\n mouse_reset: false,\n buttons: {\n closer: true,\n closer_hover: false,\n sticker: false\n }\n };\n /* eslint-enable camelcase */\n \n return notificationService.notifyWithDefaults(angular.extend(defaultOptions, options));\n }\n }\n})();","(function () {\r\n `use strict`;\r\n\r\n angular.module(`blocks.router`);\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.router`)\r\n .provider(`routeHelper`, routeHelperProvider)\r\n .config(setHtml5Mode);\r\n\r\n setHtml5Mode.$inject = [`$locationProvider`];\r\n function setHtml5Mode($locationProvider) {\r\n $locationProvider.html5Mode(true);\r\n }\r\n\r\n // This angular provider allows us to `carry` an angular.module.config() provider object into the angular.module.run() cycle of the lifecycle.\r\n routeHelperProvider.$inject = [`$stateProvider`];\r\n function routeHelperProvider($stateProvider) {\r\n\r\n this.$get = [`$rootScope`, `$state`, `$q`, `$translate`, `lodash`, routeHelper];\r\n\r\n function routeHelper($rootScope, $state, $q, $translate, _) {\r\n let routes = [];\r\n let stateChangeStartPromiseBuilders = [];\r\n let translationsLoadedPromise;\r\n\r\n subscribeToStateChangeStart();\r\n\r\n return {\r\n configureRoutes: configureRoutes,\r\n getNavigationRoutes: getNavigationRoutes,\r\n addStateChangeStartEventHandler: addStateChangeStartEventHandler\r\n };\r\n\r\n //////////////////\r\n\r\n // Call this method to add logic in the $stateChangeStart event handler.\r\n // If the promise returned is successful, the next event handler in the chain is executed (if one exists).\r\n // If the promise returned is rejected, the rejection function you provide is executed with the $state details.\r\n // When all event handlers pass the $stateChangeStart event is successful and the pipeline continues to $stateChangeSuccess.\r\n function addStateChangeStartEventHandler(fnThatReturnsAPromise, order = 0) {\r\n const prioritisedPromiseBuilder = { builder: fnThatReturnsAPromise, order: order };\r\n stateChangeStartPromiseBuilders.push(prioritisedPromiseBuilder);\r\n stateChangeStartPromiseBuilders = _.sortBy(stateChangeStartPromiseBuilders, item => item.order);\r\n\r\n return () => {\r\n stateChangeStartPromiseBuilders = _.without(stateChangeStartPromiseBuilders, prioritisedPromiseBuilder);\r\n };\r\n }\r\n\r\n function subscribeToStateChangeStart() {\r\n $rootScope.$on(`$stateChangeStart`, (event, toState, toParams, fromState, fromParams) => {\r\n // allow the event to pass through untouched if we don't have any logic to execute.\r\n if (!stateChangeStartPromiseBuilders || !stateChangeStartPromiseBuilders.length) {\r\n return;\r\n }\r\n\r\n // we have to prevent a stack overflow by continuously returning to the /oops page\r\n if (toState.state === `not-found`) {\r\n return ensureRootTranslationsAreLoaded();\r\n }\r\n\r\n // pause the progression of the route...\r\n event.preventDefault();\r\n\r\n return ensureRootTranslationsAreLoaded().then(() => {\r\n // progress through the event handlers, bailing out when an event handler rejection occurs\r\n // if all event handlers successful, continue the state/route change pipeline.\r\n const builders = _.map(stateChangeStartPromiseBuilders, `builder`);\r\n _.reduce(builders, chainHandlerPromise, null).then(onHandlersSuccessful, onHandlersFailed);\r\n });\r\n\r\n function chainHandlerPromise(promise, builder) {\r\n if (!promise) {\r\n return builder(event, toState, toParams, fromState, fromParams);\r\n }\r\n\r\n return promise.then(\r\n () => {\r\n return builder(event, toState, toParams, fromState, fromParams);\r\n },\r\n errorFn => {\r\n return _.isFunction(errorFn) && errorFn(event, toState, toParams, fromState, fromParams) || $q.reject(null);\r\n }\r\n );\r\n }\r\n\r\n function onHandlersSuccessful() {\r\n const reload = $state.$current.data && $state.$current.data.$reload;\r\n\r\n $state.go(toState.name, toParams, { notify: false, reload: reload }).then(() => {\r\n $rootScope.$broadcast(`$stateChangeSuccess`, toState, toParams, fromState, fromParams);\r\n });\r\n }\r\n\r\n function onHandlersFailed() {\r\n // rejection happens here.\r\n }\r\n });\r\n }\r\n\r\n function ensureRootTranslationsAreLoaded() {\r\n return translationsLoadedPromise || (translationsLoadedPromise = $translate.refresh());\r\n }\r\n\r\n function configureRoutes(routes) {\r\n routes.forEach(route => {\r\n $stateProvider.state(route.state, route);\r\n determinePageLayoutType(route);\r\n });\r\n\r\n function determinePageLayoutType(route) {\r\n if (route.views && (route.views.leftPanel || route.views[`leftPanel@app`])) {\r\n route.data = angular.extend(route.data || {}, { layoutType: `split` });\r\n }\r\n }\r\n }\r\n\r\n function getNavigationRoutes() {\r\n if (routes && routes.length) {\r\n return routes;\r\n }\r\n\r\n routes = _.chain($state.get())\r\n .filter(state => {\r\n return state.settings && state.settings.navigation && state.settings.navigation.group && state.settings.navigation.group === `application`;\r\n })\r\n .sortBy(state => {\r\n return state.settings.navigation.order ? state.settings.navigation.order : 1000;\r\n })\r\n .value();\r\n\r\n return routes;\r\n }\r\n\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`blocks.utils`)\r\n .factory(`utils`, getUtils);\r\n\r\n getUtils.$inject = [`lodash`];\r\n function getUtils(_) {\r\n\r\n return {\r\n freeze,\r\n arrToObj\r\n };\r\n\r\n ////////////////////\r\n\r\n function freeze(obj, deep = true) {\r\n if (deep) {\r\n Object\r\n .getOwnPropertyNames(obj)\r\n .forEach(function(propertyName) {\r\n const propertyValue = obj[propertyName];\r\n if (propertyValue === null || propertyValue === undefined) {\r\n return;\r\n }\r\n\r\n const valueType = typeof propertyValue;\r\n if (valueType !== `object` && valueType !== `function`) {\r\n return;\r\n }\r\n\r\n if (Object.isFrozen(propertyValue)) {\r\n return;\r\n }\r\n\r\n freeze(propertyValue);\r\n });\r\n }\r\n\r\n Object.freeze(obj);\r\n\r\n return obj;\r\n }\r\n\r\n // Use this function to use an immutable array in an ng-repeat loop.\r\n //\r\n // ng-repeat wants to adorn array elements with a $$hashKey property which isn't possible when using esStateStore\r\n // which freezes the state (including arrays). ng-repeat can loop through an object literal, treating the object keys as the $$hashKey.\r\n function arrToObj(arr) {\r\n let hashKey = 0;\r\n return _.reduce(arr, function(hash, value) {\r\n hash[hashKey++] = value;\r\n return hash;\r\n }, {});\r\n\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .provider(`app.core.appSettings`, appSettingsProvider);\r\n\r\n appSettingsProvider.$inject = [];\r\n function appSettingsProvider() {\r\n const self = this;\r\n\r\n self.settings = {\r\n appName: `Envirosuite`,\r\n pageTitle: ``,\r\n user: {},\r\n site: {\r\n company: {},\r\n facility: {}\r\n }\r\n };\r\n\r\n self.$get = appSettingsFactory;\r\n appSettingsFactory.$inject = [`$timeout`, `$log`, `webStorage`, `postal`, `app.core.events`];\r\n function appSettingsFactory($timeout, $log, webStorage, postal, coreEvents) {\r\n const channel = postal.channel(coreEvents.channelName);\r\n let accessControls = {};\r\n let user = {};\r\n\r\n Object.defineProperty(self.settings.site.company, `alias`, {\r\n get: () => getFromCache(`company-alias`),\r\n set: newValue => addToCache(`company-alias`, newValue),\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperty(self.settings.site.facility, `es1RouteName`, {\r\n get: () => getFromCache(`es1-route-name`),\r\n set: newValue => addToCache(`es1-route-name`, newValue),\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperty(self.settings.site.facility, `alias`, {\r\n get: () => getFromCache(`facility-alias`),\r\n set: newValue => {\r\n addToCache(`facility-alias`, newValue);\r\n if (newValue) {\r\n updateLoggingContext();\r\n }\r\n },\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperty(self.settings.site.facility, `ticketingSystem`, {\r\n get: () => {\r\n if (self.settings.site.facility.ticketingSystemType === `d522663f-75c2-4f7d-ba8d-81b90f93382a`) {\r\n const name = `JIRA Service Desk`;\r\n const baseUrl = `https://envirosuite.atlassian.net`;\r\n const ticketsUrl = `${baseUrl}/projects/${self.settings.site.facility.ticketingSystemTenantId}/queues`;\r\n return {\r\n name,\r\n baseUrl,\r\n ticketsUrl,\r\n ticketUrl: ticketId => `${baseUrl}/browse/${ticketId}`\r\n };\r\n }\r\n },\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperty(self.settings.site, `accessControls`, {\r\n get: () => accessControls,\r\n set: newValue => {\r\n accessControls = newValue;\r\n publish(coreEvents.topics.accessControlsUpdated, accessControls);\r\n }\r\n });\r\n\r\n Object.defineProperty(self.settings, `user`, {\r\n get: () => user,\r\n set: newValue => {\r\n if (user !== newValue) {\r\n user = newValue;\r\n addDisplayNameProperty();\r\n }\r\n }\r\n });\r\n\r\n self.settings.forgetCompanyAndFacility = function() {\r\n self.settings.site.company.alias = null;\r\n self.settings.site.facility.es1RouteName = null;\r\n self.settings.site.facility.alias = null;\r\n };\r\n\r\n function addDisplayNameProperty() {\r\n Object.defineProperty(self.settings.user, `displayName`, {\r\n get: () => user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : ``\r\n });\r\n }\r\n\r\n activate();\r\n\r\n function activate() {\r\n ensureSessionStorageHasFacilityDetails();\r\n\r\n $log.setLoggingContext(\r\n self.settings.webApiHostUri + `log`,\r\n null,\r\n null,\r\n `9B088CF9-C8BA-4F66-A462-7B1454BBA53C` // KnownCredentials.Guest\r\n );\r\n\r\n self.settings.user = {\r\n firstName: self.settings.firstName,\r\n lastName: self.settings.lastName\r\n };\r\n\r\n // ensure the web api url ends with a slash\r\n self.settings.zeusHostUri = self.settings.zeusHostUri && self.settings.zeusHostUri.replace(/\\/?$/, `/`);\r\n self.settings.mvcHostUri = self.settings.mvcHostUri && self.settings.mvcHostUri.replace(/\\/?$/, `/`);\r\n self.settings.webApiHostUri = self.settings.webApiHostUri && self.settings.webApiHostUri.replace(/\\/?$/, `/`);\r\n self.settings.eS2VersionedApiUri = self.settings.eS2VersionedApiUri && self.settings.eS2VersionedApiUri.replace(/\\/?$/, `/`);\r\n self.settings.reportsAppHostUri = self.settings.reportsAppHostUri && self.settings.reportsAppHostUri.replace(/\\/?$/, `/`);\r\n\r\n // transform icp registration configs\r\n self.settings.icpCertificate = self.settings[`china-IcpCertificate`];\r\n self.settings.internetSecurityNumberText = self.settings[`china-InternetSecurityNumberText`];\r\n self.settings.internetSecurityRegistrationLink = self.settings[`china-InternetSecurityNumber`]\r\n ? `http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=${self.settings[`china-InternetSecurityNumber`]}`\r\n : null;\r\n }\r\n\r\n return self.settings;\r\n\r\n ////////////////\r\n\r\n function addToCache(key, value) {\r\n webStorage.session.add(key, value);\r\n webStorage.local.add(key, value);\r\n }\r\n\r\n function getFromCache(key) {\r\n let value = webStorage.session.get(key);\r\n if (value === undefined || value === null) {\r\n value = webStorage.local.get(key);\r\n }\r\n return value;\r\n }\r\n\r\n function ensureSessionStorageHasFacilityDetails() {\r\n if (!isBrowserSessionPrimedWithFacilityDetails()) {\r\n // default the user to the first company/alias available to them.\r\n primeSessionStorageWithFacilityDetails();\r\n }\r\n // otherwise we use the company/facility stored in session previously (before hard-refresh)\r\n // see: routeHandler.js to see how the company/facility provided via the url route is used to override these session storage values.\r\n cleanupServerProvidedFacilityDetails();\r\n\r\n /////////////\r\n\r\n function isBrowserSessionPrimedWithFacilityDetails() {\r\n return self.settings.site.company.alias && self.settings.site.facility.alias;\r\n }\r\n\r\n function primeSessionStorageWithFacilityDetails() {\r\n self.settings.site.company.alias = self.settings.companyAlias;\r\n self.settings.site.facility.alias = self.settings.facilityAlias;\r\n }\r\n\r\n function cleanupServerProvidedFacilityDetails() {\r\n delete self.settings.facilityAlias;\r\n delete self.settings.companyAlias;\r\n }\r\n }\r\n\r\n function updateLoggingContext() {\r\n if (!(self.settings.site.company.id && self.settings.site.facility.id)) {\r\n return;\r\n }\r\n\r\n $log.setLoggingContext(\r\n self.settings.webApiHostUri + `log`,\r\n self.settings.site.company.id,\r\n self.settings.site.facility.id,\r\n self.settings.apiKey\r\n );\r\n }\r\n\r\n function publish(topic, payload) {\r\n $timeout(() => channel.publish(topic, payload));\r\n }\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.blockUI`, configureBlockUI);\r\n\r\n configureBlockUI.$inject = [`blockUIConfig`, `cfpLoadingBarProvider`];\r\n\r\n function configureBlockUI(blockUIConfig, loadingBarConfig) {\r\n this.configure = function () {\r\n blockUIConfig.autoBlock = false;\r\n blockUIConfig.autoInjectBodyBlock = false;\r\n blockUIConfig.delay = 150;\r\n blockUIConfig.templateUrl = `App/ui/core/layout/blockUI.html`;\r\n\r\n loadingBarConfig.includeSpinner = false;\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .config(configureCompileProvider);\r\n\r\n configureCompileProvider.$inject = [`$compileProvider`];\r\n\r\n function configureCompileProvider($compileProvider) {\r\n // See: https://docs.angularjs.org/guide/production\r\n $compileProvider.debugInfoEnabled(false);\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.dashboard`, configureDashboard);\r\n\r\n configureDashboard.$inject = [`dashboardProvider`];\r\n\r\n function configureDashboard(dashboardProvider) {\r\n this.configure = function() {\r\n if (screen.width < 992) {\r\n dashboardProvider\r\n .structure(`100`, {\r\n rows: [{\r\n columns: [{\r\n styleClass: `col-md-12`\r\n }]\r\n }]\r\n });\r\n } else {\r\n dashboardProvider\r\n .structure(`50-50`, {\r\n rows: [{\r\n columns: [{\r\n styleClass: `col-md-6`\r\n }, {\r\n styleClass: `col-md-6`\r\n }]\r\n }]\r\n })\r\n .structure(`40-60`, {\r\n rows: [{\r\n columns: [{\r\n styleClass: `col-md-4`\r\n }, {\r\n styleClass: `col-md-8`\r\n }]\r\n }]\r\n })\r\n .structure(`25-50-25`, {\r\n rows: [{\r\n columns: [{\r\n styleClass: `col-md-3`\r\n }, {\r\n styleClass: `col-md-6`\r\n }, {\r\n styleClass: `col-md-3`\r\n }]\r\n }]\r\n })\r\n .structure(`33-33-33`, {\r\n rows: [{\r\n columns: [{\r\n styleClass: `col-md-4`\r\n }, {\r\n styleClass: `col-md-4`\r\n }, {\r\n styleClass: `col-md-4`\r\n }]\r\n }]\r\n });\r\n }\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .constant(`environment`, { production: true, develop: false });\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.http`, configureHttp);\r\n\r\n configureHttp.$inject = [`$httpProvider`];\r\n\r\n function configureHttp($httpProvider) {\r\n this.configure = function () {\r\n $httpProvider.defaults.withCredentials = true; // this is needed to get cookies sent across the wire.\r\n /* eslint-disable dot-notation */\r\n $httpProvider.defaults.headers.common[`Content-Type`] = `application/json`; // used by post and put - telling the server that we're sending json content.\r\n $httpProvider.defaults.headers.post[`Accept`] = `application/json, text/plain`;\r\n /* eslint-enable dot-notation */\r\n\r\n $httpProvider.interceptors.push(`app.core.httpInterceptors`);\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.httpBatch`, configureHttpBatch);\r\n\r\n configureHttpBatch.$inject = [`httpBatchConfigProvider`, `app.core.appSettingsProvider`, `environment`];\r\n\r\n function configureHttpBatch(httpBatchConfigProvider, appSettings, environment) {\r\n this.configure = function() {\r\n\r\n // note: this is a workaround for when browser-sync strips the http:// from out appSettings objects when proxying to our real-url.\r\n if (appSettings.settings.webApiHostUri.indexOf(`//`) === 0) {\r\n appSettings.settings.webApiHostUri = `http:${appSettings.settings.webApiHostUri}`;\r\n appSettings.settings.signalRHostUri = `http:${appSettings.settings.signalRHostUri}`;\r\n }\r\n\r\n // ensure the webApiHostUri has a backslash on it\r\n appSettings.settings.webApiHostUri = appSettings.settings.webApiHostUri.replace(/\\/?$/, `/`);\r\n\r\n if (environment.production) {\r\n //http://www.jonsamwell.com/batching-http-requests-in-angular/\r\n httpBatchConfigProvider.setAllowedBatchEndpoint(\r\n appSettings.settings.webApiHostUri,\r\n appSettings.settings.webApiHostUri + `batch`,\r\n {\r\n maxBatchedRequestPerCall: 20\r\n }\r\n );\r\n }\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.IE9Behavior`, configureIE9Behavior);\r\n\r\n function configureIE9Behavior() {\r\n this.configure = function () {\r\n if (!(window.console && console.log)) {\r\n console = {\r\n log: function () {\r\n },\r\n debug: function () {\r\n },\r\n info: function () {\r\n },\r\n warn: function () {\r\n },\r\n error: function () {\r\n }\r\n };\r\n }\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.internationalization`, configureInternationalization);\r\n\r\n configureInternationalization.$inject = [`$translateProvider`, `$translatePartialLoaderProvider`, `app.core.appSettingsProvider`, `moment`, `kendo`];\r\n\r\n function configureInternationalization($translateProvider, $translatePartialLoaderProvider, appSettingsProvider, moment, kendo) {\r\n this.configure = function() {\r\n\r\n $translateProvider.useLoader(`$translatePartialLoader`, {\r\n urlTemplate: `{part}.{lang}.json`\r\n });\r\n\r\n $translatePartialLoaderProvider.addPart(`i18n/app/i18n/shared`);\r\n $translatePartialLoaderProvider.addPart(`i18n/app/ui/core/i18n/notFound`);\r\n $translatePartialLoaderProvider.addPart(`i18n/app/ui/core/i18n/forbidden`);\r\n\r\n $translateProvider.addInterpolation(`$translateMessageFormatInterpolation`);\r\n // null: does not sanitize and allows bad html (like )\r\n // sanitize: sanitizes HTML in the translation text using $sanitize\r\n // escape: escapes HTML in the translation\r\n // sanitizeParameters: sanitizes HTML in the values of the interpolation parameters using $sanitize\r\n // escapeParameters: escapes HTML in the values of the interpolation parameters\r\n // sce: wraps HTML in $sce.trustAsHtml(value)\r\n // sceParameters: wraps HTML in the values of the interpolation parameters in $sce.trustAsHtml(value)\r\n $translateProvider.useSanitizeValueStrategy(`escapeParameters`);\r\n\r\n // adding in some static translations needed to indicate that other translations are loading... :)\r\n if (!appSettingsProvider.settings.showEmptyTranslations) {\r\n $translateProvider.translations(`en`, { 'activityIndicator.default.label': `Please wait ...` });\r\n $translateProvider.translations(`es`, { 'activityIndicator.default.label': `Por favor espere ...` });\r\n $translateProvider.translations(`fr`, { 'activityIndicator.default.label': `S'il vous plaît, attendez ...` });\r\n $translateProvider.translations(`vi`, { 'activityIndicator.default.label': `Xin vui lòng chờ ...` });\r\n $translateProvider.translations(`zh`, { 'activityIndicator.default.label': `请稍候...` });\r\n $translateProvider.translations(`lt`, { 'activityIndicator.default.label': `Prašau palauk...` });\r\n }\r\n\r\n $translateProvider.preferredLanguage(appSettingsProvider.settings.locale);\r\n $translateProvider.fallbackLanguage(`en`);\r\n $translateProvider.use(appSettingsProvider.settings.locale);\r\n\r\n const locale = appSettingsProvider.settings.locale;\r\n kendo.culture(locale);\r\n moment.locale(locale.toLowerCase());\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.localStorage`, configureLocalStorage);\r\n\r\n configureLocalStorage.$inject = [`defaultSettings`];\r\n\r\n function configureLocalStorage(defaultSettings) {\r\n this.configure = function () {\r\n defaultSettings.prefix = `es.`;\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.notification`, configureNotification);\r\n\r\n configureNotification.$inject = [`notificationServiceProvider`, `PNotify`];\r\n\r\n function configureNotification(notificationServiceProvider, PNotify) {\r\n this.configure = function () {\r\n PNotify.defaults.styling = `bootstrap3`;\r\n\r\n notificationServiceProvider\r\n .setDefaults({\r\n delay: 8000,\r\n hide: true,\r\n buttons: {\r\n closer: false,\r\n sticker: false\r\n },\r\n history: {\r\n history: false\r\n }\r\n })\r\n .setStack(`top_right`, `stack-topright`, {\r\n dir1: `down`,\r\n dir2: `left`,\r\n firstpos1: 100,\r\n firstpos2: 30\r\n })\r\n .setDefaultStack(`top_right`);\r\n };\r\n this.$get = angular.noop;\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular.module(`app.core`).provider(`app.core.bootstrapper.configurators.tooltip`, configureTooltips);\r\n\r\n /* istanbul ignore next */\r\n configureTooltips.$inject = [`$tooltipProvider`];\r\n function configureTooltips($tooltipProvider) {\r\n this.configure = function () {\r\n const tooltipFactory = $tooltipProvider.$get[$tooltipProvider.$get.length - 1];\r\n\r\n // decorate the tooltip getter\r\n $tooltipProvider.$get = [\r\n `$window`,\r\n `$compile`,\r\n `$timeout`,\r\n `$document`,\r\n `$position`,\r\n `$interpolate`,\r\n `$rootScope`,\r\n function ( $window, $compile, $timeout, $document, $position, $interpolate, $rootScope) {\r\n // for touch devices, don't return tooltips\r\n if (`ontouchstart` in $window) {\r\n return () => {\r\n return {\r\n compile: function () { }\r\n };\r\n };\r\n } else {\r\n // run the default behavior\r\n return tooltipFactory($window, $compile, $timeout, $document, $position, $interpolate, $rootScope);\r\n }\r\n }\r\n ];\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();","//TODO: 12/01/2016 - Ben - This is a hack to overwrite the provided dashboard edit template until the library provides an override point like all the other templates.\r\n(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(`app.core.bootstrapper.runners.dashboard`, dashboard);\r\n\r\n dashboard.$inject = [\r\n `$templateCache`,\r\n `app.core.bootstrapper.runners.passwordExpirationValidator`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function dashboard($templateCache, passwordExpirationValidator) {\r\n passwordExpirationValidator();\r\n return function () {\r\n overrideDashboardEditTemplate();\r\n overrideWidgetEditTemplate();\r\n };\r\n\r\n function overrideDashboardEditTemplate() {\r\n $templateCache.put(\r\n `../src/templates/dashboard-edit.html`,\r\n `\r\n
      \r\n \r\n

      {{ 'adf.dashboard.actions.layout.modal.heading' | translate }}

      \r\n
      \r\n
      \r\n \r\n
      \r\n
      \r\n \r\n\r\n
      \r\n
      \r\n \r\n
      \r\n
      \r\n \r\n
      \r\n `\r\n );\r\n }\r\n\r\n function overrideWidgetEditTemplate() {\r\n $templateCache.put(\r\n `../src/templates/widget-edit.html`,\r\n `\r\n
      \r\n \r\n

      {{ widget.name | translate }}

      \r\n
      \r\n
      \r\n
      \r\n
      \r\n \r\n \r\n
      \r\n
      \r\n
      \r\n \r\n
      \r\n
      \r\n
      \r\n \r\n \r\n
      \r\n `\r\n );\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(`app.core.bootstrapper.runners.fileUploader`, configureFileUploader);\r\n\r\n configureFileUploader.$inject = [`FileUploader`];\r\n\r\n /* istanbul ignore next */\r\n function configureFileUploader(FileUploader) {\r\n return function () {\r\n\r\n // Adds a `validationErrors` property to the FileItem class on the file uploaders\r\n Object.defineProperty(FileUploader.FileItem.prototype, `validationErrors`, {\r\n get: function() {\r\n this._validationErrors = this._validationErrors || {};\r\n return this._validationErrors;\r\n },\r\n set: function(value) {\r\n this._validationErrors = value;\r\n }\r\n });\r\n };\r\n\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(`app.core.bootstrapper.runners.internationalization`, configure);\r\n\r\n configure.$inject = [\r\n `ipCookie`,\r\n `$window`,\r\n `$translate`,\r\n `app.core.appSettings`,\r\n `app.core.services.userService`,\r\n `app.core.services.settingsService`,\r\n `moment`,\r\n `kendo`\r\n ];\r\n\r\n function configure(cookie, $window, $translate, appSettings, userService, settingsService, moment, kendo) {\r\n const fallbackLanguage = `en`;\r\n const supportedLanguages = settingsService.getSupportedLanguages();\r\n\r\n function useLocale(locale) {\r\n $translate.use(locale);\r\n kendo.culture(locale);\r\n moment.locale(locale.toLowerCase());\r\n }\r\n\r\n return function () {\r\n userService.getLocale()\r\n .then(locale => useLocale(supportedLanguages.hasOwnProperty(locale) ? locale : fallbackLanguage))\r\n .catch(() => useLocale(fallbackLanguage));\r\n };\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(`app.core.bootstrapper.runners.kendoCultures`, configureKendoCultures);\r\n\r\n configureKendoCultures.$inject = [`$window`, `lodash`];\r\n\r\n /* istanbul ignore next */\r\n function configureKendoCultures($window, _) {\r\n return function () {\r\n overrideCultureVi();\r\n overrideCultureEs();\r\n };\r\n\r\n ////////////////////\r\n \r\n function overrideCultureVi() {\r\n // According to Vianna, there's not really a three-letter abbreviation for the days of the week, so\r\n // we use the same abbreviations for both namesAbbr and namesShort.\r\n const dayNamesShort = [`CN`, `TH`, `TB`, `TT`, `TN`, `TS`, `TB`];\r\n\r\n const overrides = {\r\n calendars: {\r\n standard: {\r\n days: {\r\n namesAbbr: dayNamesShort,\r\n namesShort: dayNamesShort\r\n }\r\n }\r\n }\r\n };\r\n\r\n overrideCultureIfExists(overrides, `vi`, `vi-VN`);\r\n }\r\n\r\n function overrideCultureEs() {\r\n // Abbreviations from Fernando - wanted to override the 'X' for Miércoles with another 'M'.\r\n const dayNamesShort = [`D`, `L`, `M`, `M`, `J`, `V`, `S`];\r\n\r\n // Also override the day names since it seems to fix an encoding issue for 'Miércoles'.\r\n const dayNames = [`Domingo`, `Lunes`, `Martes`, `Miércoles`, `Jueves`, `Viernes`, `Sábado`];\r\n\r\n const overrides = {\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: dayNames,\r\n namesAbbr: dayNamesShort,\r\n namesShort: dayNamesShort\r\n }\r\n }\r\n }\r\n };\r\n\r\n overrideCultureIfExists(overrides, `es`, `es-ES`);\r\n }\r\n\r\n function overrideCultureIfExists(overrides, ...cultures) {\r\n const kendoCultures = $window.kendo.cultures;\r\n\r\n _.forEach(cultures, culture => {\r\n const cultureInfo = kendoCultures[culture];\r\n if (cultureInfo) {\r\n _.merge(cultureInfo, overrides);\r\n }\r\n });\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n angular\r\n .module(`app.core`)\r\n .service(\r\n `app.core.bootstrapper.runners.passwordExpirationValidator`,\r\n passwordExpirationValidator\r\n );\r\n passwordExpirationValidator.$inject = [\r\n `app.core.services.securityService`,\r\n `i18n`,\r\n `app.core.models.messages.messageList`\r\n ];\r\n /* istanbul ignore next */\r\n function passwordExpirationValidator(securityService, i18n, messageList) {\r\n return function () {\r\n securityService.getPasswordExpirationStatus().then(data => {\r\n if (!data.shownNotification && data.daysBeforePasswordExpiration && data.daysBeforePasswordExpiration <= 7) {\r\n messageList.addWarning(i18n.i10n(`passwordExpirationValidator.notification.title`),\r\n i18n.i10n(`passwordExpirationValidator.notification.message`, { daysBeforePasswordExpiration: data.daysBeforePasswordExpiration }), 200);\r\n securityService.setPasswordExpirationConfirmed();\r\n }\r\n });\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular.module(`app.core`)\r\n .provider(`app.core.bootstrapper.configurators.stateReloadDecorator`, stateReloadDecorator)\r\n .service(`app.core.bootstrapper.runners.routeHandler`, runRouteHandler);\r\n\r\n\r\n stateReloadDecorator.$inject = [`$provide`, `lodash`];\r\n function stateReloadDecorator($provide, _) {\r\n this.configure = function configure() {\r\n $provide.decorator(`$state`, decorateTransitionTo);\r\n\r\n decorateTransitionTo.$inject = [`$delegate`];\r\n function decorateTransitionTo($delegate) {\r\n const original = $delegate.transitionTo;\r\n $delegate.transitionTo = transitionToWithReload;\r\n\r\n function transitionToWithReload(to, toParams, options) {\r\n const $state = this;\r\n $state.$current.data = _.extend($state.$current.data || {}, { $reload: options.reload });\r\n\r\n return original(to, toParams, options);\r\n }\r\n\r\n return $delegate;\r\n }\r\n };\r\n\r\n this.$get = angular.noop;\r\n }\r\n\r\n runRouteHandler.$inject = [\r\n `$rootScope`,\r\n `$window`,\r\n `$q`,\r\n `$log`,\r\n `$state`,\r\n `$location`,\r\n `lodash`,\r\n `blockUI`,\r\n `routeHelper`,\r\n `i18n`,\r\n `app.core.appSettings`,\r\n `app.core.services.userService`,\r\n `app.core.services.companyService`,\r\n `app.core.services.securityService`,\r\n `app.core.services.locationService`,\r\n `app.core.signalR.hubsConnector`\r\n ];\r\n function runRouteHandler($rootScope, $window, $q, $log, $state, $location, _, blockUI, routeHelper, i18n,\r\n appSettings, userService, companyService, securityService, locationService, hubsConnector) {\r\n\r\n return () => {\r\n const successPromise = $q.when(null);\r\n\r\n const busyMessage = i18n.i10n(`activityIndicator.default.label`);\r\n let handlingRouteChangeError = false;\r\n let lastCompanyFacilityRouted = null; // keep track of the last company/facility selected so we can route to different error pages under different conditions.\r\n\r\n onRouteChangeStart();\r\n onRouteChangeSuccess();\r\n onRouteChangeError();\r\n\r\n ////////////////////////////////\r\n\r\n function onRouteChangeStart() {\r\n routeHelper.addStateChangeStartEventHandler((event, toState, toParams) => {\r\n startNavigationTracker();\r\n\r\n if (toState.name === `not-found` || toState.name === `forbidden`) {\r\n return $q.when({ result: `not-found` });\r\n }\r\n\r\n const companyAlias = toParams.companyAlias || appSettings.site.company.alias;\r\n const facilityAlias = toParams.facilityAlias || appSettings.site.facility.alias;\r\n\r\n if (companyAlias && facilityAlias) {\r\n return companyService.getCompanyWithFacility(companyAlias, facilityAlias)\r\n .then(validateCompanyAndFacilityExist)\r\n .then(applySelectedCompanyFacilityDetailsToAppSettings)\r\n .then(refreshUserAndAccessControls)\r\n .then(redirectToOmnisCheck)\r\n .then(authorizeRouteAccess)\r\n .then(updateLastCompanyFacilityAccessed)\r\n .then(connectSignalRHubs)\r\n .catch(routeErrorHandler => {\r\n stopNavigationTracker();\r\n if (routeErrorHandler) {\r\n return $q.reject(routeErrorHandler);\r\n }\r\n // otherwise try and send them to dashboard\r\n $state.go(`app.dashboard`, { companyAlias, facilityAlias }, { reload: true });\r\n return $q.reject({});\r\n });\r\n }\r\n\r\n return successPromise;\r\n\r\n ////////////////////\r\n\r\n function validateCompanyAndFacilityExist(company) {\r\n return $q((resolve, reject) => {\r\n if (!company || !company.facility) {\r\n const errorHandler = createRoutingFailedErrorHandler(`not-found`, `no facility access`);\r\n reject(errorHandler);\r\n }\r\n else {\r\n resolve(company);\r\n }\r\n });\r\n }\r\n\r\n function applySelectedCompanyFacilityDetailsToAppSettings(company) {\r\n appSettings.site.company.id = company.id;\r\n appSettings.site.company.alias = company.alias;\r\n\r\n appSettings.site.facility.id = company.facility.id;\r\n appSettings.site.facility.alias = company.facility.alias;\r\n appSettings.site.facility.es1RouteName = company.facility.es1RouteName;\r\n appSettings.site.facility.ianaTimeZoneId = company.facility.ianaTimeZoneId;\r\n appSettings.site.facility.windowsTimeZoneId = company.facility.windowsTimeZoneId;\r\n appSettings.site.facility.ticketingSystemType = company.facility.ticketingSystemType;\r\n appSettings.site.facility.ticketingSystemTenantId = company.facility.ticketingSystemTenantId;\r\n appSettings.site.facility.facilityCode = company.facility.facilityCode;\r\n appSettings.site.facility.region = company.facility.region;\r\n\r\n return $q.when(company);\r\n }\r\n\r\n function refreshUserAndAccessControls(company) {\r\n return $q.all([refreshUser(), refreshAccessControls()]).then(() => company);\r\n\r\n function refreshUser() {\r\n return userService.getUserDetails().then(user => {\r\n appSettings.user = user;\r\n $window.ga && $window.ga(`set`, `userId`, user.username);\r\n $window.LogRocket && window.LogRocket.identify(`${user.displayName} (${user.username})`, {\r\n email: user.email && user.email.toLowerCase() || ``,\r\n userType: getUserType()\r\n });\r\n heapAnalytics(user);\r\n });\r\n\r\n function heapAnalytics(user) {\r\n if (!$window.heap) {\r\n return;\r\n }\r\n if (!user || !user.id || !user.email) {\r\n return;\r\n }\r\n const isInternal = user.email.indexOf(`@envirosuite`) !== -1;\r\n $window.heap.identify(user.id);\r\n $window.heap.addUserProperties({\r\n 'Is_Internal': isInternal,\r\n 'Region': appSettings.site.facility.region\r\n });\r\n }\r\n }\r\n\r\n function refreshAccessControls() {\r\n return securityService.getAccessControls(company.id, company.facility.id).then(accessControls => {\r\n appSettings.site.accessControls = accessControls;\r\n });\r\n }\r\n }\r\n\r\n function authorizeRouteAccess(company) {\r\n return $q((resolve, reject) => {\r\n if (!toState.data || !toState.data.requiredAccessControl) {\r\n // only check routes set up for checking\r\n resolve(company);\r\n return;\r\n }\r\n\r\n const requiredAccessControl = toState.data.requiredAccessControl;\r\n const accessControlCheck = appSettings.site.accessControls[requiredAccessControl];\r\n\r\n if (accessControlCheck) {\r\n resolve(company);\r\n } else {\r\n const errorHandler = createRoutingFailedErrorHandler(`forbidden`, `failed access control check`);\r\n reject(errorHandler);\r\n }\r\n });\r\n }\r\n function redirectToOmnisCheck(company) {\r\n return $q((resolve, reject) => {\r\n const enableEs2 = appSettings.site.accessControls[`app.es2`];\r\n const state = toState.state;\r\n const allowedStates = [`app.dashboard`, `app.reporting`];\r\n if (enableEs2) {return resolve(company);}\r\n if (allowedStates.includes(state)) {return resolve(company);}\r\n let redirectUrl = appSettings.omnisHostUri;\r\n if(state.startsWith(`app.monitoring`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/monitoring/real-time`;\r\n }else if (state.startsWith(`app.modelling.trajectory`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/trajectories`;\r\n } \r\n else if (state.startsWith(`app.modelling`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/modelling`;\r\n } \r\n else if (state.startsWith(`app.alerts`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/alerts`;\r\n }\r\n else if (state.startsWith(`app.incidentIntelligence`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/incident-intelligence`;\r\n }\r\n else if (state.startsWith(`app.configuration.company.modelling.models`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/configuration/modelling/models`;\r\n }\r\n else if (state.startsWith(`app.configuration.company.monitoring.monitors`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/configuration/monitoring/monitors`;\r\n }\r\n else if (state.startsWith(`app.configuration.company.monitoring.measurementGroups`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/configuration/monitoring/measurement-groups`;\r\n }\r\n else if (state.startsWith(`app.configuration.company.annotations.monitorPollutants`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/configuration/annotations/pollutant`;\r\n }\r\n else if (state.startsWith(`app.configuration`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/configuration`;\r\n }\r\n else if (state.startsWith(`app.user.profile`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/user/profile/details`;\r\n }\r\n else if (state.startsWith(`app.user.settings`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/user/profile/settings`;\r\n }\r\n else if (state.startsWith(`app.about`)){\r\n redirectUrl = redirectUrl + `/${companyAlias}/${facilityAlias}/user/profile/about`;\r\n }\r\n $window.location.replace(redirectUrl);\r\n });\r\n }\r\n function connectSignalRHubs(company) {\r\n return hubsConnector.connect().then(() => company);\r\n }\r\n\r\n function updateLastCompanyFacilityAccessed(company) {\r\n lastCompanyFacilityRouted = {\r\n companyAlias,\r\n facilityAlias\r\n };\r\n return $q.when(company);\r\n }\r\n\r\n function createRoutingFailedErrorHandler(route, detail) {\r\n return function errorHandler(event, toState, toParams) {\r\n if (hasTheCompanyFacilityChangedButTheRouteStayedTheSame()) {\r\n $state.go(`app.dashboard`, { companyAlias, facilityAlias }, { reload: true });\r\n return;\r\n }\r\n\r\n $state.go(route, toParams, { notify: false }).then(() => {\r\n $rootScope.$broadcast(`$stateChangeSuccess`, toState, toParams);\r\n const url = $state.href(toState, toParams);\r\n if (route === `not-found`) {\r\n $log.error(getInvalidRouteErrorMessage(`404`, url));\r\n $location.url(url);\r\n return;\r\n }\r\n if (route === `forbidden`) {\r\n $log.error(getInvalidRouteErrorMessage(`403`, url));\r\n return;\r\n }\r\n });\r\n\r\n return $q.reject({ status: route, detail });\r\n };\r\n\r\n function getInvalidRouteErrorMessage(errorCode, url) {\r\n return `${errorCode} trying to access ${url} with userId - ${appSettings.userId} and apiKey - ${appSettings.apiKey} and company/facility - [${companyAlias}/${facilityAlias}]`;\r\n }\r\n\r\n function hasTheCompanyFacilityChangedButTheRouteStayedTheSame() {\r\n return lastCompanyFacilityRouted !== null && (\r\n lastCompanyFacilityRouted.companyAlias !== companyAlias ||\r\n lastCompanyFacilityRouted.facilityAlias !== facilityAlias\r\n );\r\n }\r\n }\r\n });\r\n }\r\n\r\n function onRouteChangeError() {\r\n // Route cancellation:\r\n // On routing error, go to the dashboard.\r\n // Provide an exit clause if it tries to do it twice.\r\n $rootScope.$on(`$stateChangeError`, (event, toState, toParams, fromState, fromParams, error) => {\r\n stopNavigationTracker();\r\n\r\n if (handlingRouteChangeError) {\r\n return;\r\n }\r\n\r\n handlingRouteChangeError = true;\r\n const destination = toState !== null ? `${toState.name} - ${$state.href(toState, toParams)}` : `unknown target`;\r\n const msg = `Error routing to ${destination}. ${error && JSON.stringify(error.message) || ``}`;\r\n $log.error(msg, toState);\r\n $state.go(`app.dashboard`);\r\n });\r\n }\r\n\r\n function onRouteChangeSuccess() {\r\n $rootScope.$on(`$stateChangeSuccess`, (event, toState, toParams, fromState) => {\r\n handlingRouteChangeError = false;\r\n\r\n locationService.clearExitPoint();\r\n\r\n unloadPreviousPageTranslations(fromState, toState)\r\n .then(() => {\r\n updateGoogleAnalyticsPageValue(toState.name);\r\n locationService.bindPageHeading();\r\n })\r\n .finally(() => {\r\n stopNavigationTracker();\r\n });\r\n });\r\n\r\n function unloadPreviousPageTranslations(fromState, toState) {\r\n return i18n.unloadStates(fromState, toState);\r\n }\r\n\r\n function updateGoogleAnalyticsPageValue(stateName) {\r\n const page = $location.path();\r\n const userDescription = `${appSettings.user.displayName} (${appSettings.user.username})`;\r\n\r\n if ($window.ga) {\r\n $window.ga(`send`, `pageview`, {\r\n page: page,\r\n title: stateName,\r\n dimension1: getUserType(),\r\n dimension2: userDescription\r\n });\r\n\r\n $window.ga(`send`, `event`, `user-tracking`, userDescription, page);\r\n }\r\n }\r\n }\r\n\r\n function getUserType() {\r\n const emailAddress = appSettings.user.email && appSettings.user.email.toLowerCase() || ``;\r\n return _.endsWith(emailAddress, `envirosuite.com`) ? `internal` : `customer`;\r\n }\r\n\r\n function startNavigationTracker() {\r\n const blocker = blockUI.instances.get(`full-page`);\r\n blocker.start(busyMessage);\r\n }\r\n\r\n function stopNavigationTracker() {\r\n const blocker = blockUI.instances.get(`full-page`);\r\n blocker.stop();\r\n }\r\n };\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n const mapDefaults = {\r\n settings: {\r\n zoomControlPosition: `topright`,\r\n zoomAnimation: true,\r\n fadeAnimation: false,\r\n trackResize: false,\r\n attributionControl: false,\r\n worldCopyJump: true,\r\n controls: {\r\n layers: {\r\n visible: false,\r\n position: `topright`,\r\n collapsed: true\r\n }\r\n }\r\n },\r\n baselayers: {\r\n openStreetMap: {\r\n name: `Open Street Map`,\r\n type: `openstreetmap`,\r\n url: `http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`,\r\n layerOptions: {\r\n attribution: `© OpenStreetMap`,\r\n subdomains: [`a`,`b`,`c`]\r\n }\r\n },\r\n google: {\r\n name: `Google Hybrid`,\r\n layerType: `HYBRID`,\r\n type: `google`\r\n },\r\n gaode: {\r\n name: `Gaode`,\r\n type: `gaode`,\r\n url: `http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}`,\r\n layerOptions: {\r\n attribution: `© 高德地图`,\r\n subdomains: [`1`,`2`,`3`, `4`]\r\n }\r\n },\r\n baidu: {\r\n name: `Baidu`,\r\n type: `baidu`,\r\n url: `http://online{s}.map.bdimg.com/tile/?qt=vtile&x={x}&y={y}&z={z}&styles=pl&scaler=1&udt=20190929`,\r\n layerOptions: {\r\n attribution: `© 百度`,\r\n subdomains: [`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`]\r\n }\r\n },\r\n mapbox: {\r\n name: `Mapbox`,\r\n type: `mapbox`,\r\n url: `https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/{z}/{x}/{y}`,\r\n layerOptions: {\r\n style: `mapbox://styles/mapbox/satellite-v9`,\r\n attribution: `© Mapbox © OpenStreetMap`\r\n }\r\n }\r\n }\r\n };\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.mapDefaults`, mapConfiguredOptions);\r\n\r\n mapConfiguredOptions.$inject = [`app.core.appSettings`];\r\n function mapConfiguredOptions(appSettings) {\r\n const configuredLayer = getConfiguredBaseLayer();\r\n return {\r\n settings: mapDefaults.settings,\r\n baselayers: configuredLayer\r\n };\r\n\r\n function getConfiguredBaseLayer() {\r\n const layers = {};\r\n layers[appSettings.mapProvider] = mapDefaults.baselayers[appSettings.mapProvider] || mapDefaults.baselayers.google;\r\n if (appSettings.mapProvider === `mapbox`) {\r\n layers[appSettings.mapProvider].apiKey = appSettings.mapboxApiKey;\r\n }\r\n return layers;\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n /* eslint-disable no-undef */\r\n angular\r\n .module(`app.core`)\r\n .constant(`jQuery`, jQuery)\r\n .constant(`moment`, moment)\r\n .constant(`kendo`, kendo)\r\n .constant(`leafletLib`, L)\r\n .constant(`d3`, d3)\r\n .constant(`MG`, MG)\r\n .constant(`Mousetrap`, Mousetrap)\r\n .constant(`FileSaver`, saveAs)\r\n .constant(`Utm`, Utm)\r\n .constant(`LatLon`, LatLon)\r\n .constant(`log4javascript`, log4javascript)\r\n .constant(`PNotify`, PNotify)\r\n .constant(`google`, window.google)\r\n .constant(`d3`, d3)\r\n .constant(`anime`, anime);\r\n /* eslint-enable no-undef */\r\n})();\r\n","(function(){\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.events`, getEvents());\r\n\r\n function getEvents() {\r\n return {\r\n channelName: `app.core`,\r\n topics: {\r\n accessControlsUpdated: `accessControls.updated`\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .filter(`dateTimeFormat`, facilityTimezoneFilter);\r\n\r\n facilityTimezoneFilter.$inject = [\r\n `app.core.services.dateTimeService`,\r\n `lodash`\r\n ];\r\n\r\n function facilityTimezoneFilter(dateTimeService, _) {\r\n return (date, format) => {\r\n format = format || `dateTimeWithSeconds`;\r\n\r\n if (!_.has(dateTimeService.formatAs, format)) {\r\n return date;\r\n } else {\r\n return dateTimeService.formatAs[format](date);\r\n }\r\n };\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .filter(`facilityTimezone`, facilityTimezoneFilter);\r\n\r\n facilityTimezoneFilter.$inject = [`app.core.datetime.timeZoneDateTime`];\r\n\r\n function facilityTimezoneFilter(timeZoneDateTime) {\r\n function decorateFilter(input) {\r\n const parsedDate = new Date(input);\r\n if (isNaN(parsedDate.getTime())) {\r\n return input;\r\n }\r\n\r\n return timeZoneDateTime.convertDateTimeToFacilityTimeZone(parsedDate);\r\n }\r\n return decorateFilter;\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.httpInterceptors`, httpInterceptors);\r\n\r\n httpInterceptors.$inject = [`lodash`, `httpBatchConfig`, `$injector`, `$log`, `$q`, `app.core.appSettings`, `$timeout`, `app.core.errorService`, `app.core.appVersionService`];\r\n\r\n function httpInterceptors(_, httpBatchConfigProvider, $injector, $log, $q, appSettings, $timeout, errorService, appVersionService) {\r\n\r\n const unhandledErrorCodes = [0,500];\r\n const retryQueue = {};\r\n\r\n const interceptor = {\r\n request: requestInterceptor,\r\n response: responseInterceptor,\r\n responseError: responseErrorInterceptor\r\n };\r\n\r\n return interceptor;\r\n\r\n /////////////////////\r\n\r\n function requestInterceptor(httpConfig) {\r\n httpConfig.headers[`Authorization`] = `Token ${appSettings.apiKey}`;\r\n httpConfig.headers[`PEL-Company-Alias`] = appSettings.site.company.alias;\r\n httpConfig.headers[`PEL-Facility-Alias`] = appSettings.site.facility.alias;\r\n return httpConfig;\r\n }\r\n\r\n function responseInterceptor(response) {\r\n delete retryQueue[response.config.url];\r\n errorService.processSuccess(response);\r\n const appVersion = response.headers()[`pel-app-version`] || appSettings.appVersion;\r\n appVersionService.validate(appVersion);\r\n return response;\r\n }\r\n\r\n function responseErrorInterceptor(response) {\r\n const dfd = $q.defer();\r\n dfd.reject(response);\r\n\r\n if (_.includes(unhandledErrorCodes, response.status)) {\r\n if (/.*(batch[\\/]?)$/.test(response.config.url)) {\r\n $log.error(`A http batch request failed; turning off http batch requests. Perform a hard-refresh to re-enable.`);\r\n errorService.logResponse(response); // we don't want the usual error handling to occur here so we just log the response.\r\n httpBatchConfigProvider.getBatchConfig(appSettings.webApiHostUri).enabled = false;\r\n return dfd.promise;\r\n } else {\r\n const existsInRetryQueue = retryQueue[response.config.url];\r\n if (!existsInRetryQueue) {\r\n retryQueue[response.config.url] = response;\r\n return $injector.get(`$http`)(response.config);\r\n }\r\n delete retryQueue[response.config.url];\r\n }\r\n }\r\n\r\n // We have a bad state, but we want to give the developer a chance to handle it first. Run this on a later execution loop.\r\n // Effectively a last ditch catchall in case the developer forgets to handle their errors.\r\n $timeout(() => {\r\n if (!response.handled) {\r\n errorService.processError(response);\r\n }\r\n }, 1000);\r\n\r\n return dfd.promise;\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .provider(`app.core.leafletScopeDecoration`, leafletScopeDecoration);\r\n\r\n leafletScopeDecoration.$inject = [`$provide`];\r\n function leafletScopeDecoration($provide) {\r\n this.injectScopeProperty = function (property, attr) {\r\n $provide.decorator(`leafletDirective`, leafletDirectiveDecorator);\r\n\r\n leafletDirectiveDecorator.$inject = [`$delegate`];\r\n function leafletDirectiveDecorator($delegate) {\r\n const directive = $delegate[0];\r\n //http://www.ipreferjim.com/2014/11/decorating-directives-with-isolate-scope-in-angular-1-3/\r\n directive.$$isolateBindings[property] = {\r\n attrName: attr,\r\n mode: `=`,\r\n optional: true\r\n };\r\n\r\n return $delegate;\r\n }\r\n };\r\n this.$get = angular.noop;\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .provider(`log4j`, log4jProvider);\r\n\r\n log4jProvider.$inject = [`log4javascript`];\r\n function log4jProvider(log4javascript) {\r\n const self = this;\r\n\r\n let defaultAppender = null;\r\n let ajaxAppender = null;\r\n let ajaxAppenderEndpoint = null;\r\n\r\n log4javascript.logLog.setQuietMode(true);\r\n log4javascript.setShowStackTraces(true);\r\n\r\n self.logger = log4javascript.getNullLogger();\r\n self.$get = [() => {\r\n return {\r\n getLogger: () => self.logger,\r\n setLoggingContext,\r\n\r\n disableRemoteLogging,\r\n enableRemoteLogging\r\n };\r\n }];\r\n\r\n function disableRemoteLogging() {\r\n const logger = log4javascript.getDefaultLogger();\r\n if (ajaxAppender !== null) {\r\n logger.removeAppender(ajaxAppender);\r\n }\r\n }\r\n\r\n function enableRemoteLogging() {\r\n const logger = log4javascript.getDefaultLogger();\r\n if (ajaxAppender !== null) {\r\n logger.addAppender(ajaxAppender);\r\n }\r\n }\r\n\r\n function setLoggingContext(webApiHostUri, companyId, facilityId, apiKey) {\r\n const logger = log4javascript.getDefaultLogger();\r\n\r\n configureDefaultAppender(logger);\r\n configureAjaxAppender(logger, webApiHostUri, companyId, facilityId, apiKey);\r\n\r\n return self.logger = logger;\r\n }\r\n\r\n function configureDefaultAppender(logger) {\r\n if (defaultAppender) {\r\n return;\r\n }\r\n\r\n logger.removeAllAppenders();\r\n defaultAppender = new log4javascript.BrowserConsoleAppender();\r\n defaultAppender.setThreshold(log4javascript.Level.INFO);\r\n defaultAppender.setLayout(new log4javascript.PatternLayout(`%d{HH:mm:ss,SSS} %-5p - %m{1}`));\r\n\r\n logger.addAppender(defaultAppender);\r\n }\r\n\r\n function configureAjaxAppender(logger, webApiHostUri, companyId, facilityId, apiKey) {\r\n if (webApiHostUri !== ajaxAppenderEndpoint) {\r\n if (ajaxAppender !== null) {\r\n logger.removeAppender(ajaxAppender);\r\n }\r\n\r\n ajaxAppender = new log4javascript.AjaxAppender(webApiHostUri, true);\r\n ajaxAppender.setThreshold(log4javascript.Level.INFO);\r\n //logger.addAppender(ajaxAppender);\r\n\r\n ajaxAppenderEndpoint = webApiHostUri;\r\n }\r\n\r\n ajaxAppender.getHeaders().length = 0;\r\n ajaxAppender.addHeader(`Authorization`, `Token ${apiKey}`);\r\n ajaxAppender.addHeader(`PEL-Company-Id`, companyId);\r\n ajaxAppender.addHeader(`PEL-Facility-Id`, facilityId);\r\n return ajaxAppender;\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .config(decorateLog);\r\n\r\n decorateLog.$inject = [`$provide`];\r\n function decorateLog($provide) {\r\n $provide.decorator(`$log`, logDecorator);\r\n }\r\n\r\n logDecorator.$inject = [`$delegate`, `log4j`];\r\n function logDecorator($logDelegate, log4j) {\r\n\r\n // copies of original functions.\r\n const fatal = $logDelegate.fatal;\r\n const error = $logDelegate.error;\r\n const warn = $logDelegate.warn;\r\n const info = $logDelegate.info;\r\n const log = $logDelegate.log;\r\n\r\n // decorating the original log functions.\r\n $logDelegate.fatal = decorateLogFunction(logger => logger.fatal, fatal);\r\n $logDelegate.error = decorateLogFunction(logger => logger.error, error);\r\n $logDelegate.warn = decorateLogFunction(logger => logger.warn, warn);\r\n $logDelegate.info = decorateLogFunction(logger => logger.info, info);\r\n $logDelegate.log = decorateLogFunction(logger => logger.info, log);\r\n\r\n // Temporary hack to quiet down the leaflet directive logging\r\n // $logDelegate.debug = decorateLogFunction(logger => logger.debug, log);\r\n $logDelegate.debug = function(...args) {\r\n if (!(args && args.length)) {\r\n return;\r\n }\r\n\r\n const logMessage = args[0];\r\n if (logMessage && typeof logMessage === `string` && logMessage.indexOf(`leafletDirective`) === 0) {\r\n return;\r\n }\r\n\r\n const logger = log4j.getLogger();\r\n logger.debug.apply(logger, args);\r\n };\r\n\r\n $logDelegate.setLoggingContext = log4j.setLoggingContext;\r\n\r\n function decorateLogFunction(getLoggingFn) {\r\n return function(...args) {\r\n const logger = log4j.getLogger();\r\n const loggingFn = getLoggingFn(logger);\r\n loggingFn.apply(logger, args);\r\n };\r\n }\r\n\r\n return $logDelegate;\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.alerts.WebAlert`, alertFactory);\r\n\r\n alertFactory.$inject = [];\r\n function alertFactory() {\r\n\r\n return class WebAlert {\r\n\r\n constructor(id, alertEventSourceId, name, message, level, triggerTime, sentTime) {\r\n this.id = id;\r\n this.alertEventSourceId = alertEventSourceId;\r\n this.name = name;\r\n this.message = message;\r\n this.level = level;\r\n this.triggerTime = triggerTime;\r\n this.sentTime = sentTime;\r\n }\r\n\r\n get level() {\r\n return this._level;\r\n }\r\n\r\n set level(level) {\r\n if (this._level === level) {\r\n return;\r\n }\r\n\r\n this.previousLevel = this._level;\r\n this._level = level;\r\n }\r\n\r\n get hasLevelIncreased() {\r\n return this.previousLevel === undefined || this.level > this.previousLevel;\r\n }\r\n\r\n get hasLevelDecreased() {\r\n return this.previousLevel !== undefined && this.level < this.previousLevel;\r\n }\r\n };\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.BlastModel`, blastModelFactory);\r\n\r\n blastModelFactory.$inject = [\r\n `lodash`,\r\n `leafletLib`\r\n ];\r\n\r\n function blastModelFactory(_, L) {\r\n function BlastModel(modelId, modelType, modelCategory, blastModelLegends) {\r\n const self = this;\r\n\r\n this.id = modelId;\r\n this.modelType = modelType;\r\n this.modelCategory = modelCategory;\r\n this.blastModelLegends = blastModelLegends;\r\n\r\n const data = {};\r\n const dataPoints = {};\r\n Object.defineProperty(this, `data`, { get: () => data });\r\n\r\n this.getDataPoints = getDataPoints;\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n\r\n ////////////////////\r\n\r\n function getDataPoints(blastTimeMillis, map) {\r\n let dataPointsForBlastTime = _.has(dataPoints, blastTimeMillis) && dataPoints[blastTimeMillis] || null;\r\n if (dataPointsForBlastTime) {\r\n return dataPointsForBlastTime;\r\n }\r\n\r\n const modelData = self.data[blastTimeMillis];\r\n dataPointsForBlastTime = self.createDataPointsFromModelData(modelData, map);\r\n\r\n // Snapshot models only have one data point, but when it gets imported into the store, it needs to\r\n // pretend its part of a series of timestep data points.\r\n if (!_.isArray(dataPointsForBlastTime)) {\r\n dataPointsForBlastTime = [dataPointsForBlastTime];\r\n }\r\n\r\n return dataPoints[blastTimeMillis] = dataPointsForBlastTime;\r\n }\r\n\r\n function createDataPointsFromModelData() {\r\n throw new Error(`createDataPointsFromModelData has not been implemented.`);\r\n }\r\n }\r\n\r\n BlastModel.prototype.createCombinedDataPoint = function(offsetMinutes, ...constituentDataPoints) {\r\n const combinedDataPoint = {\r\n offsetMinutes,\r\n layerGroup: new L.LayerGroup()\r\n };\r\n\r\n _.flatten(constituentDataPoints).forEach(dataPoint => combinedDataPoint.layerGroup.addLayer(dataPoint.layerGroup));\r\n\r\n return combinedDataPoint;\r\n };\r\n\r\n return BlastModel;\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.blasting.blastModelCategory`, getBlastModelCategories());\r\n\r\n function getBlastModelCategories() {\r\n // Maps front-end model types to the equivalent back-end enum value.\r\n return {\r\n animated: `animated`,\r\n snapshot: `snapshot`\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.blasting.blastModelType`, getBlastModelTypes());\r\n\r\n function getBlastModelTypes() {\r\n // Maps front-end model types to the equivalent back-end enum value.\r\n return {\r\n path: `path`,\r\n dispersion: `dispersion`,\r\n fmz: `fumeManagementZone`,\r\n gain: `overpressureGain`,\r\n contour: `overpressureContour`,\r\n flyrock: `flyrock`,\r\n groundVibration : `groundVibration`\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.blasting.BlastScenario`, BlastScenario);\r\n\r\n function BlastScenario(scenarioId, scenarioAlias, name) {\r\n this.id = scenarioId;\r\n this.alias = scenarioAlias;\r\n this.name = name;\r\n\r\n this.models = [];\r\n this.blastTimesMillis = [];\r\n\r\n this.blastParameters = null;\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.blasting.blastSetup`, getBlastSetups());\r\n\r\n function getBlastSetups() {\r\n return {\r\n burden: `burden`,\r\n stemming: `stemming`\r\n };\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.DispersionModel`, DispersionModelFactory);\r\n\r\n DispersionModelFactory.$inject = [\r\n `lodash`,\r\n `app.core.models.blasting.BlastModel`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastModelCategory`,\r\n `app.ui.core.mapping.mapLayerRenderer`\r\n ];\r\n\r\n function DispersionModelFactory(_, BlastModel, blastModelType, blastModelCategory, mapLayerRenderer) {\r\n function DispersionModel(modelId, legends) {\r\n BlastModel.call(this, modelId, blastModelType.dispersion, blastModelCategory.animated, legends);\r\n\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n }\r\n\r\n DispersionModel.prototype = Object.create(BlastModel.prototype);\r\n\r\n return DispersionModel;\r\n\r\n ////////////////////\r\n\r\n function createDataPointsFromModelData(modelData) {\r\n const self = this;\r\n\r\n // Dispersion blasts contain plume and wind data, but when these get imported into the data store,\r\n // we need to represent them as a single data point.\r\n const windDataPoints = renderDataPoints(modelData.windData);\r\n const plumeDataPoints = renderDataPoints(modelData.plumes);\r\n\r\n return _.chain(windDataPoints.concat(plumeDataPoints))\r\n .groupBy(`offsetMinutes`)\r\n .map((dataPoints, offsetMinutes) => self.createCombinedDataPoint(offsetMinutes, dataPoints))\r\n .value();\r\n }\r\n\r\n function renderDataPoints(dataPoints) {\r\n if (!dataPoints) {\r\n return [];\r\n }\r\n\r\n dataPoints.forEach(dataPoint => {\r\n mapLayerRenderer.renderLayer(dataPoint);\r\n delete dataPoint.data;\r\n });\r\n\r\n return dataPoints;\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.FlyrockModel`, FlyrockModelFactory);\r\n\r\n FlyrockModelFactory.$inject = [\r\n `leafletLib`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.models.blasting.BlastModel`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastModelCategory`\r\n ];\r\n\r\n function FlyrockModelFactory(L, _, i18n, BlastModel, blastModelType, blastModelCategory) {\r\n function FlyrockModel(modelId, legends) {\r\n BlastModel.call(this, modelId, blastModelType.flyrock, blastModelCategory.snapshot, legends);\r\n\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n }\r\n\r\n FlyrockModel.prototype = Object.create(BlastModel.prototype);\r\n\r\n return FlyrockModel;\r\n\r\n ////////////////////\r\n\r\n function createDataPointsFromModelData(modelData) {\r\n const { flyrockBoundaries } = modelData;\r\n const startingPoint = new L.LatLng(modelData.location.latitude, modelData.location.longitude);\r\n const layerGroup = new L.LayerGroup();\r\n const azimuthBearingOffset = modelData.azimuth - 90;\r\n\r\n //calculate the points for the polygons\r\n _.map(flyrockBoundaries, boundary => boundary.points = createPolygonPoints(boundary));\r\n\r\n // the sort order is important here to get it to render correctly on the screen.\r\n const sortedData = _.sortBy(flyrockBoundaries, `frontFaceDistanceInMetres`).reverse();\r\n\r\n _.map(sortedData, (boundary, index) => {\r\n const polygonPoints = [];\r\n polygonPoints.push(boundary.points);\r\n if (index < sortedData.length - 1) {\r\n polygonPoints.push(sortedData[index + 1].points);\r\n }\r\n createPolygon(polygonPoints, boundary.color);\r\n });\r\n\r\n return {\r\n offsetMinutes: 0,\r\n layerGroup: layerGroup\r\n };\r\n\r\n function createPolygonPoints(values){\r\n const faceAngleStart = 45;\r\n const faceAngleStop = 135;\r\n const backAngleStop = 315;\r\n const backAngleStart = 225;\r\n const points = [];\r\n for (let angle = faceAngleStart; angle < faceAngleStop; angle++){\r\n const point = startingPoint.destinationPoint(angle + azimuthBearingOffset, values.frontFaceDistanceInMetres);\r\n points.push([point.lat, point.lng]);\r\n }\r\n for (let angle = backAngleStart; angle < backAngleStop; angle++){\r\n const point = startingPoint.destinationPoint(angle + azimuthBearingOffset, values.backFaceDistanceInMetres);\r\n points.push([point.lat, point.lng]);\r\n }\r\n return points;\r\n }\r\n\r\n function createPolygon(path, color){\r\n const polygon = L.polygon(path, { color: color, fillOpacity: 0.3, stroke:true, weight : 1, opacity: 0.4 });\r\n layerGroup.addLayer(polygon);\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.FumeManagementZoneModel`, FumeManagementZoneModelFactory);\r\n\r\n FumeManagementZoneModelFactory.$inject = [\r\n `app.core.models.blasting.BlastModel`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastModelCategory`,\r\n `app.ui.core.mapping.mapLayerRenderer`\r\n ];\r\n\r\n function FumeManagementZoneModelFactory(BlastModel, blastModelType, blastModelCategory, mapLayerRenderer) {\r\n function FumeManagementZoneModel(modelId, legends) {\r\n BlastModel.call(this, modelId, blastModelType.fmz, blastModelCategory.snapshot, legends);\r\n\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n }\r\n\r\n FumeManagementZoneModel.prototype = Object.create(BlastModel.prototype);\r\n\r\n return FumeManagementZoneModel;\r\n\r\n ////////////////////\r\n\r\n function createDataPointsFromModelData(modelData) {\r\n const dataPoint = modelData.plume;\r\n\r\n mapLayerRenderer.renderLayer(dataPoint);\r\n delete dataPoint.data;\r\n\r\n return dataPoint;\r\n }\r\n }\r\n})();\r\n","(function(){\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.GroundVibrationModel`, GroundVibrationModelFactory);\r\n\r\n\r\n GroundVibrationModelFactory.$inject = [\r\n `leafletLib`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.models.blasting.BlastModel`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastModelCategory`,\r\n `app.core.models.blasting.VibrationPointOfInterestMapMarker`\r\n ];\r\n\r\n function GroundVibrationModelFactory(L, _, i18n, BlastModel, blastModelType, blastModelCategory, VibrationPointOfInterestMapMarker) {\r\n function GroundVibrationModel(modelId, legends) {\r\n BlastModel.call(this, modelId, blastModelType.groundVibration, blastModelCategory.snapshot, legends);\r\n\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n }\r\n\r\n GroundVibrationModel.prototype = Object.create(BlastModel.prototype);\r\n\r\n return GroundVibrationModel;\r\n\r\n ////////////////////\r\n\r\n function createDataPointsFromModelData(modelData) {\r\n const { ppvThresholds, ppvReadings } = modelData;\r\n const layerGroup = new L.LayerGroup();\r\n const sortedThresholds = _.sortBy(ppvThresholds, `distanceInMetres`).reverse();\r\n\r\n renderThresholds();\r\n renderReadings();\r\n\r\n return {\r\n offsetMinutes: 0,\r\n layerGroup: layerGroup\r\n };\r\n\r\n function renderReadings(){\r\n _.forEach(ppvReadings, reading => {\r\n const thresholds = sortedThresholds.filter(ppv => ppv.ppvThreshold <= reading.value);\r\n const color = thresholds && thresholds.length\r\n ? thresholds[thresholds.length - 1].color\r\n : `white`;\r\n const vibrationMarker = new VibrationPointOfInterestMapMarker(reading.location, reading.value, color);\r\n const icon = L.divIcon(vibrationMarker.icon);\r\n layerGroup.addLayer(L.marker([reading.location.latitude, reading.location.longitude], { icon }));\r\n });\r\n }\r\n\r\n function renderThresholds(){\r\n const startingPoint = new L.LatLng(modelData.location.latitude, modelData.location.longitude);\r\n //calculate the points for the polygons\r\n _.forEach(sortedThresholds, boundary => boundary.points = createPolygonPoints(startingPoint, boundary));\r\n\r\n _.forEach(sortedThresholds, (boundary, index) => {\r\n const polygonPoints = [];\r\n polygonPoints.push(boundary.points);\r\n if (index < sortedThresholds.length - 1) {\r\n polygonPoints.push(sortedThresholds[index + 1].points);\r\n }\r\n createPolygon(polygonPoints, boundary.color);\r\n });\r\n\r\n function createPolygon(path, color){\r\n const polygon = L.polygon(path, { color: color, fillOpacity: 0.3, stroke:true, weight : 1, opacity: 0.4 });\r\n layerGroup.addLayer(polygon);\r\n }\r\n\r\n function createPolygonPoints(startingPoint, values){\r\n const points = [];\r\n for (let angle = 0; angle < 360; angle++){\r\n const point = startingPoint.destinationPoint(angle, values.distanceInMetres);\r\n points.push([point.lat, point.lng]);\r\n }\r\n return points;\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.OverpressureModel`, OverpressureModelFactory);\r\n\r\n OverpressureModelFactory.$inject = [\r\n `leafletLib`,\r\n `app.core.models.blasting.BlastModel`,\r\n `app.core.models.blasting.blastModelCategory`\r\n ];\r\n\r\n function OverpressureModelFactory(L, BlastModel, blastModelCategory) {\r\n \r\n function OverpressureModel(modelId, modelType, legends) {\r\n BlastModel.call(this, modelId, modelType, blastModelCategory.snapshot, legends);\r\n\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n }\r\n\r\n OverpressureModel.prototype = Object.create(BlastModel.prototype);\r\n\r\n return OverpressureModel;\r\n\r\n ////////////////////\r\n\r\n function createDataPointsFromModelData(modelData, map) {\r\n //todo kmcdonald 2015-08-19 add a mimetype field to the model returned by the service\r\n const imageUrl = `data:image/png;base64,${modelData.image}`;\r\n const layerGroup = new L.LayerGroup();\r\n\r\n const centreLatLng = L.latLng(modelData.latitude, modelData.longitude);\r\n const centrePoint = convertToCartesian(centreLatLng);\r\n\r\n // This is the number of pixels to crop off each edge of the raw Terrock image so that\r\n // what we are left with is simply the \"data\" part of the image overlay.\r\n const padding = {\r\n top: 10,\r\n left: 47,\r\n right: 5,\r\n bottom: 42\r\n };\r\n\r\n // The data part of the image is 468px square, which represents a 20 KM square area.\r\n const imageEdgeLengthPixels = 468;\r\n const imageEdgeLengthKm = 20;\r\n\r\n const imageRadius = imageEdgeLengthPixels / 2;\r\n const imageMetresPerPixel = 1000 / (imageEdgeLengthPixels / imageEdgeLengthKm);\r\n\r\n const mapMetresPerPixel = calculateScale();\r\n const multiplier = Math.abs(imageMetresPerPixel / mapMetresPerPixel);\r\n\r\n const top = centrePoint.y - (imageRadius + padding.top ) * multiplier;\r\n const left = centrePoint.x - (imageRadius + padding.left ) * multiplier;\r\n const bottom = centrePoint.y + (imageRadius + padding.bottom ) * multiplier;\r\n const right = centrePoint.x + (imageRadius + padding.right ) * multiplier;\r\n\r\n const imageSWLatLng = convertToLatLng(L.point(left, bottom));\r\n const imageNELatLng = convertToLatLng(L.point(right, top));\r\n layerGroup.addLayer(L.imageOverlay(imageUrl, L.latLngBounds(imageSWLatLng, imageNELatLng), { opacity: 0.15 }));\r\n\r\n delete modelData.image;\r\n\r\n return {\r\n offsetMinutes: 0,\r\n layerGroup: layerGroup\r\n };\r\n\r\n function calculateScale() {\r\n const referencePoint = convertToLatLng([centrePoint.x + 1000, centrePoint.y]);\r\n const metresToReferencePoint = centreLatLng.distanceTo(referencePoint);\r\n\r\n return Math.abs(metresToReferencePoint) / 1000;\r\n }\r\n\r\n function convertToCartesian(point) {\r\n return map.latLngToContainerPoint(point);\r\n }\r\n\r\n function convertToLatLng(point) {\r\n return map.containerPointToLatLng(point);\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.PathModel`, PathModelFactory);\r\n\r\n PathModelFactory.$inject = [\r\n `app.core.models.blasting.BlastModel`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastModelCategory`,\r\n `app.ui.core.mapping.mapLayerRenderer`\r\n ];\r\n\r\n function PathModelFactory(BlastModel, blastModelType, blastModelCategory, mapLayerRenderer) {\r\n function PathModel(modelId, legends) {\r\n BlastModel.call(this, modelId, blastModelType.path, blastModelCategory.snapshot, legends);\r\n\r\n this.createDataPointsFromModelData = createDataPointsFromModelData;\r\n }\r\n\r\n PathModel.prototype = Object.create(BlastModel.prototype);\r\n\r\n return PathModel;\r\n\r\n ////////////////////\r\n\r\n function createDataPointsFromModelData(modelData) {\r\n // Path models contain one track.\r\n const primaryTrackDataPoints = renderDataPoints(modelData.primaryTrack);\r\n\r\n return this.createCombinedDataPoint(0, primaryTrackDataPoints);\r\n }\r\n\r\n function renderDataPoints(dataPoint) {\r\n mapLayerRenderer.renderLayer(dataPoint);\r\n delete dataPoint.data;\r\n\r\n return dataPoint;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.blasting.VibrationPointOfInterestMapMarker`, factory);\r\n\r\n factory.$inject = [\r\n `app.core.services.configuration.monitoringService`];\r\n\r\n function factory(configMonitoringService) {\r\n function VibrationPointOfInterestMapMarker(location, value, backgroundColor) {\r\n this.lat = location.latitude;\r\n this.lng = location.longitude;\r\n this.layer = `VibrationPOILayer`;\r\n this.icon = {\r\n iconAnchor : [-11, 11],\r\n html : getHtml(),\r\n type: `div`\r\n };\r\n\r\n this.location = location;\r\n\r\n function getHtml() {\r\n const icon = configMonitoringService.getMonitorTypeIcon(`vibrationMonitor`);\r\n if (value){\r\n return `\r\n
      \r\n
      \r\n \r\n
      \r\n
      ${Math.round(value * 100) / 100} PPV mm/s
      \r\n
      \r\n `;\r\n }\r\n return ``;\r\n }\r\n }\r\n\r\n return VibrationPointOfInterestMapMarker;\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.jobs.Job`, jobFactory);\r\n\r\n jobFactory.$inject = [\r\n `$timeout`,\r\n `$log`,\r\n `i18n`,\r\n `lodash`,\r\n `postal`,\r\n `app.core.appSettings`,\r\n `app.core.signalR.jobs.events`,\r\n `app.core.models.jobs.jobCompletionStatus`\r\n ];\r\n\r\n function jobFactory($timeout, $log, i18n, _, postal, appSettings, jobEvents, jobCompletionStatus) {\r\n const jobRunningStaleTimeoutMillis = (appSettings.jobRunningStaleTimeoutSeconds || 60) * 1000;\r\n const jobQueuedStaleTimeoutMillis = (appSettings.jobQueuedStaleTimeoutSeconds || 300) * 1000;\r\n\r\n return function Job(jobId, name = `Unknown job`, description = null, progress = null, completionStatus = jobCompletionStatus.incomplete, lastUpdatedDateTime = null) {\r\n const self = this;\r\n const channel = postal.channel(jobEvents.channelName);\r\n\r\n let lastUpdatedMillis = (lastUpdatedDateTime || new Date()).getTime();\r\n let isStale = false;\r\n let isStaleTimeout = null;\r\n\r\n self.jobId = jobId;\r\n self.name = name;\r\n self.description = description;\r\n\r\n const progressMessages = [];\r\n const errorMessages = [];\r\n\r\n Object.defineProperty(self, `progressMessages`, { get: () => progressMessages });\r\n Object.defineProperty(self, `errorMessages`, { get: () => errorMessages });\r\n Object.defineProperty(self, `lastMessage`, { get: () => self.hasFailed ? _.last(errorMessages) : _.last(progressMessages) });\r\n\r\n Object.defineProperty(self, `hasCompleted`, { get: () => completionStatus !== jobCompletionStatus.incomplete });\r\n Object.defineProperty(self, `hasFailed`, { get: () => completionStatus === jobCompletionStatus.failure });\r\n\r\n Object.defineProperty(self, `hasStarted`, { get: () => _.isNumber(self.progress) });\r\n Object.defineProperty(self, `hasErrors`, { get: () => errorMessages.length > 0 });\r\n Object.defineProperty(self, `isQueued`, { get: () => !self.hasStarted });\r\n Object.defineProperty(self, `isRunning`, { get: () => self.hasStarted && !self.hasCompleted });\r\n Object.defineProperty(self, `isStale`, { get: () => isStale });\r\n\r\n Object.defineProperty(self, `progress`, {\r\n get: () => progress,\r\n set: value => {\r\n if (progress === value) {\r\n return;\r\n }\r\n\r\n progress = value;\r\n lastUpdatedMillis = new Date().getTime();\r\n\r\n scheduleIsStaleCheck();\r\n }\r\n });\r\n\r\n Object.defineProperty(self, `completionStatus`, {\r\n get: () => completionStatus,\r\n set: value => {\r\n if (completionStatus === value) {\r\n return;\r\n }\r\n\r\n completionStatus = value;\r\n cancelStaleTimeout();\r\n\r\n if (value === jobCompletionStatus.incomplete) {\r\n scheduleIsStaleCheck();\r\n }\r\n }\r\n });\r\n\r\n self.getJobType = () => `job`;\r\n self.addProgressMessage = messageKey => addMessage(progressMessages, `progress`, messageKey);\r\n self.addErrorMessage = messageKey => addMessage(errorMessages, `error`, messageKey);\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n scheduleIsStaleCheck();\r\n }\r\n\r\n function scheduleIsStaleCheck() {\r\n cancelStaleTimeout();\r\n\r\n if (self.hasCompleted || self.hasFailed) {\r\n return;\r\n }\r\n\r\n const timeoutMillis = self.hasStarted ? jobRunningStaleTimeoutMillis : jobQueuedStaleTimeoutMillis;\r\n const staleCutoffMillis = new Date().getTime() - timeoutMillis;\r\n isStale = lastUpdatedMillis <= staleCutoffMillis;\r\n\r\n if (isStale) {\r\n // signalR is down before starting the job, we can already publish the stale event directly (instead of waiting the timeout).\r\n channel.publish(jobEvents.topics.jobStale, self);\r\n } else {\r\n // we will send the notification in a few minutes, to let a chance for the job to finish processing\r\n isStaleTimeout = $timeout(() => {\r\n isStale = true;\r\n channel.publish(jobEvents.topics.jobStale, self);\r\n }, timeoutMillis);\r\n }\r\n }\r\n\r\n function cancelStaleTimeout() {\r\n if (isStaleTimeout) {\r\n $timeout.cancel(isStaleTimeout);\r\n }\r\n\r\n if (self.hasCompleted || self.hasFailed) {\r\n isStale = false;\r\n }\r\n }\r\n\r\n function addMessage(messages, messageType, messageKey) {\r\n if (!messageKey) {\r\n return;\r\n }\r\n\r\n const message = i10n(self.getJobType(), messageType, messageKey);\r\n messages.push(message);\r\n }\r\n\r\n function i10n(jobType, messageType, key) {\r\n if (!key) {\r\n return null;\r\n }\r\n\r\n const i18nKey = `app.core.models.jobs.${jobType}.${messageType}.${key}`;\r\n const i18nResult = i18n.i10n(i18nKey);\r\n\r\n if (i18nResult !== i18nKey) {\r\n return i18nResult;\r\n }\r\n\r\n $log.error(`Untranslated job status ${messageType} message detected: ${key}`);\r\n return key;\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.jobs.jobCompletionStatus`, getJobCompletionStatus());\r\n\r\n function getJobCompletionStatus() {\r\n const jobCompletionStatus = {\r\n incomplete: `incomplete`,\r\n success: `success`,\r\n partial: `partialSuccess`,\r\n failure: `failure`\r\n };\r\n\r\n return angular.extend(jobCompletionStatus, { calculate });\r\n\r\n ////////////////////\r\n\r\n function calculate(jobSucceededCount, jobFailedCount) {\r\n if (jobFailedCount) {\r\n return jobSucceededCount ? jobCompletionStatus.partial : jobCompletionStatus.failure;\r\n }\r\n\r\n return jobCompletionStatus.success;\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.jobs.ModellingJob`, ModellingJobFactory);\r\n\r\n ModellingJobFactory.$inject = [\r\n `app.core.models.jobs.Job`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.models.jobs.jobCompletionStatus`\r\n ];\r\n\r\n function ModellingJobFactory(Job, dateTimeService, timeZoneDateTime, jobCompletionStatus) {\r\n function ModellingJob(jobId, requesterId, fromMillis, toMillis, name = `Unknown job`, progress = null, completionStatus = jobCompletionStatus.incomplete, lastUpdatedDateTime = null) {\r\n const description = `${toFacilityDateTimeString(fromMillis)} - ${toFacilityDateTimeString(toMillis)}`;\r\n\r\n Job.call(this, jobId, name, description, progress, completionStatus, lastUpdatedDateTime);\r\n\r\n this.getJobType = () => `modellingJob`;\r\n this.requesterId = requesterId;\r\n this.fromMillis = fromMillis;\r\n this.toMillis = toMillis;\r\n }\r\n\r\n ModellingJob.prototype = Object.create(Job.prototype);\r\n ModellingJob.createFromJobData = createFromJobData;\r\n\r\n return ModellingJob;\r\n\r\n ////////////////////\r\n\r\n function createFromJobData(jobData) {\r\n const startDate = new Date(jobData.utcFromDateTime);\r\n const endDate = new Date(jobData.utcToDateTime);\r\n const lastUpdated = jobData.utcLastUpdatedDateTime ? new Date(jobData.utcLastUpdatedDateTime) : null;\r\n const progress = parseInt(jobData.progress) || null;\r\n const completionStatus = calculateCompletionStatus();\r\n\r\n const modellingJob = new ModellingJob(jobData.id, jobData.requesterId, startDate.getTime(), endDate.getTime(), jobData.requesterName, progress, completionStatus, lastUpdated);\r\n\r\n if (jobData.errors) {\r\n jobData.errors.forEach(modellingJob.addErrorMessage);\r\n }\r\n\r\n return modellingJob;\r\n\r\n ////////////////////\r\n\r\n function calculateCompletionStatus() {\r\n if (!jobData.hasCompleted) {\r\n return jobCompletionStatus.incomplete;\r\n }\r\n\r\n if (jobData.jobFailedCount) {\r\n return jobData.jobSucceededCount ? jobCompletionStatus.partial : jobCompletionStatus.failure;\r\n }\r\n\r\n return jobCompletionStatus.success;\r\n }\r\n }\r\n\r\n function toFacilityDateTimeString(millis) {\r\n const date = new Date(millis);\r\n\r\n const facilityTime = timeZoneDateTime.convertDateTimeToFacilityTimeZone(date);\r\n return dateTimeService.formatAs.dateTime(facilityTime);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.legends.ArrowLegend`, arrowLegendFactory);\r\n\r\n arrowLegendFactory.$inject = [`app.core.models.legends.Legend`];\r\n\r\n function arrowLegendFactory(Legend) {\r\n const template = `/App/ui/core/controls/esArrowLegend.html`;\r\n\r\n function ArrowLegend(legendData) {\r\n Legend.call(this, legendData, template);\r\n }\r\n\r\n ArrowLegend.prototype = Object.create(Legend.prototype);\r\n\r\n return ArrowLegend;\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.legends.CircleLegend`, circleLegendFactory);\r\n\r\n circleLegendFactory.$inject = [`app.core.models.legends.Legend`];\r\n\r\n function circleLegendFactory(Legend) {\r\n const template = `/App/ui/core/controls/esCircleLegend.html`;\r\n\r\n function CircleLegend(legendData) {\r\n Legend.call(this, legendData, template);\r\n }\r\n\r\n CircleLegend.prototype = Object.create(Legend.prototype);\r\n\r\n return CircleLegend;\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.legends.Legend`, legendFactory);\r\n\r\n legendFactory.$inject = [];\r\n\r\n function legendFactory() {\r\n function Legend(legendData, template) {\r\n this.title = legendData.title;\r\n this.description = legendData.description;\r\n this.items = legendData.items;\r\n this.template = template;\r\n }\r\n\r\n return Legend;\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.legends.legendFactory`, legendFactory);\r\n\r\n legendFactory.$inject = [\r\n `app.core.models.legends.ArrowLegend`,\r\n `app.core.models.legends.CircleLegend`,\r\n `app.core.models.legends.StrokeLegend`\r\n ];\r\n\r\n function legendFactory(ArrowLegend, CircleLegend, StrokeLegend) {\r\n return {\r\n create\r\n };\r\n\r\n ////////////////////\r\n\r\n function create(legend) {\r\n if (!legend) {\r\n throw new Error(`You must supply the legend.`);\r\n }\r\n\r\n switch (legend.legendType) {\r\n case `wind`:\r\n return new ArrowLegend(legend);\r\n\r\n case `path`:\r\n return new StrokeLegend(legend);\r\n\r\n default:\r\n return new CircleLegend(legend);\r\n }\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.legends.StrokeLegend`, strokeLegendFactory);\r\n\r\n strokeLegendFactory.$inject = [`app.core.models.legends.Legend`];\r\n\r\n function strokeLegendFactory(Legend) {\r\n const template = `/App/ui/core/controls/esStrokeLegend.html`;\r\n\r\n function StrokeLegend(legendData) {\r\n Legend.call(this, legendData, template);\r\n }\r\n\r\n StrokeLegend.prototype = Object.create(Legend.prototype);\r\n\r\n return StrokeLegend;\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.mapping.Boundary`, BoundaryFactory);\r\n\r\n BoundaryFactory.$inject = [];\r\n\r\n function BoundaryFactory() {\r\n function Boundary(bottomLeft, bottomRight, topLeft, topRight) {\r\n\r\n if (!(bottomLeft && bottomRight && topLeft && topRight)) {\r\n throw new Error(`You must provide four coordinates for a boundary.`);\r\n }\r\n\r\n if (!(isCoordinate(bottomLeft) && isCoordinate(bottomRight) && isCoordinate(topLeft) && isCoordinate(topRight))) {\r\n throw new Error(`all coordinates must each have a latitude and longitude property.`);\r\n }\r\n\r\n Object.defineProperties(this, {\r\n bottomLeft: { get: () => bottomLeft },\r\n bottomRight: { get: () => bottomRight },\r\n topLeft: { get: () => topLeft },\r\n topRight: { get: () => topRight }\r\n });\r\n\r\n }\r\n\r\n function isCoordinate(coord) {\r\n return coord.hasOwnProperty(`latitude`) && coord.hasOwnProperty(`longitude`);\r\n }\r\n\r\n Boundary.prototype.contains = function (latitude, longitude) {\r\n const bottomLeft = this.bottomLeft;\r\n const topRight = this.topRight;\r\n\r\n const isLatitudeInBoundary = isBetween(latitude, bottomLeft.latitude, topRight.latitude);\r\n if (!isLatitudeInBoundary) {\r\n return false;\r\n }\r\n\r\n const crossesAntimeridian = bottomLeft.longitude > topRight.longitude;\r\n\r\n return crossesAntimeridian ?\r\n isBetween(longitude, bottomLeft.longitude, 180) || isBetween(longitude, -180, topRight.longitude) :\r\n isBetween(longitude, bottomLeft.longitude, topRight.longitude);\r\n\r\n function isBetween(value, lowerBound, upperBound) {\r\n return value >= lowerBound && value <= upperBound;\r\n }\r\n };\r\n\r\n return Boundary;\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.mapping.DataPoint`, DataPointFactory);\r\n\r\n DataPointFactory.$inject = [`lodash`];\r\n\r\n function DataPointFactory(_) {\r\n return function DataPoint(dataPointType, data) {\r\n this.data = data;\r\n\r\n const isEmpty = !_.find(data, { isEmpty: false });\r\n\r\n Object.defineProperties(this, {\r\n type: { get: () => dataPointType },\r\n isEmpty: { get: () => isEmpty }\r\n });\r\n };\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.mapping.dataPointFactory`, dataPointFactory);\r\n\r\n dataPointFactory.$inject = [\r\n `lodash`,\r\n `app.core.models.mapping.dataPointType`,\r\n `app.core.models.mapping.PlumeDataPoint`,\r\n `app.core.models.mapping.WindDataPoint`,\r\n `app.core.models.mapping.PathDataPoint`\r\n ];\r\n\r\n function dataPointFactory(_, dataPointType, PlumeDataPoint, WindDataPoint, PathDataPoint) {\r\n return {\r\n create\r\n };\r\n\r\n ////////////////////\r\n\r\n function create(type, sourceData) {\r\n if (!_.isString(type)) {\r\n throw new Error(`You must specify the data point type.`);\r\n }\r\n\r\n switch (type.toLowerCase()) {\r\n case dataPointType.plume:\r\n return new PlumeDataPoint(sourceData);\r\n\r\n case dataPointType.wind:\r\n return new WindDataPoint(sourceData);\r\n\r\n case dataPointType.path:\r\n return new PathDataPoint(sourceData);\r\n }\r\n\r\n throw new Error(`Unknown data point type: ${type}`);\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.mapping.dataPointType`, getDataPointTypes());\r\n\r\n function getDataPointTypes() {\r\n return {\r\n plume: `plume`,\r\n wind: `wind`,\r\n path: `path`\r\n };\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.mapping.PathDataPoint`, PathDataPointFactory);\r\n\r\n PathDataPointFactory.$inject = [\r\n `lodash`,\r\n `app.core.models.mapping.DataPoint`,\r\n `app.core.models.mapping.dataPointType`\r\n ];\r\n\r\n function PathDataPointFactory(_, DataPoint, dataPointType) {\r\n function PathDataPoint(timeStepData) {\r\n DataPoint.call(this, dataPointType.path, processTimeStepData(timeStepData));\r\n }\r\n\r\n PathDataPoint.prototype = Object.create(DataPoint.prototype);\r\n\r\n return PathDataPoint;\r\n\r\n ////////////////////\r\n\r\n function processTimeStepData(timeStepData) {\r\n return _.chain(timeStepData)\r\n .map(point => {\r\n const gisPoint = point.gisPoint;\r\n const dataPoint = {\r\n latitude: gisPoint.latitude,\r\n longitude: gisPoint.longitude,\r\n timeMillis: new Date(point.utcEndTime).getTime()\r\n };\r\n if (point.latitudeStdDev && point.longitudeStdDev){\r\n return { latitudeStdDev : point.latitudeStdDev, longitudeStdDev: point.longitudeStdDev, ...dataPoint };\r\n }\r\n return dataPoint;\r\n\r\n })\r\n .sortBy(`timeMillis`)\r\n .value();\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.mapping.PlumeDataPoint`, PlumeDataPointFactory);\r\n\r\n PlumeDataPointFactory.$inject = [\r\n `app.core.models.mapping.DataPoint`,\r\n `app.core.models.mapping.dataPointType`\r\n ];\r\n\r\n function PlumeDataPointFactory(DataPoint, dataPointType) {\r\n function PlumeDataPoint(timeStepData) {\r\n DataPoint.call(this, dataPointType.plume, processTimeStepData(timeStepData));\r\n }\r\n\r\n PlumeDataPoint.prototype = Object.create(DataPoint.prototype);\r\n\r\n return PlumeDataPoint;\r\n\r\n ////////////////////\r\n\r\n function processTimeStepData(timeStepData) {\r\n return timeStepData.concentrations.map(processConcentration);\r\n\r\n ////////////////////\r\n\r\n function processConcentration(concentration) {\r\n const regionPoints = processRegions(concentration.regions);\r\n\r\n return {\r\n polygons: regionPoints,\r\n isEmpty: !regionPoints.length,\r\n color: concentration.displayColor,\r\n value: concentration.value\r\n };\r\n }\r\n\r\n function processRegions(regions) {\r\n return regions.map(region => {\r\n return region.gisPoints.map(point => ({\r\n lat: point.latitude,\r\n lng: point.longitude\r\n }));\r\n });\r\n }\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.mapping.WindDataPoint`, WindDataPointFactory);\r\n\r\n WindDataPointFactory.$inject = [\r\n `app.core.models.mapping.DataPoint`,\r\n `app.core.models.mapping.dataPointType`\r\n ];\r\n\r\n function WindDataPointFactory(DataPoint, dataPointType) {\r\n function WindDataPoint(timeStepData) {\r\n DataPoint.call(this, dataPointType.wind, processTimeStepData(timeStepData));\r\n }\r\n\r\n WindDataPoint.prototype = Object.create(DataPoint.prototype);\r\n\r\n return WindDataPoint;\r\n\r\n ////////////////////\r\n\r\n function processTimeStepData(timeStepData) {\r\n return timeStepData.windDataSpeedRanges.map(processWindDataSpeedRange);\r\n\r\n ////////////////////\r\n\r\n function processWindDataSpeedRange(speedRange) {\r\n const windVectors = speedRange.windVectors.map(vector => ({\r\n lat: vector.latitude,\r\n lng: vector.longitude,\r\n bearing: vector.windDirection,\r\n magnitude: vector.windSpeed\r\n }));\r\n\r\n return {\r\n windVectors,\r\n color: speedRange.displayColor,\r\n minimumSpeed: speedRange.minimumSpeed,\r\n maximumSpeed: speedRange.maximumSpeed,\r\n isEmpty: !windVectors.length\r\n };\r\n }\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.messages.messageList`, factory);\r\n\r\n factory.$inject = [`$injector`, `$rootScope`, `$window`, `lodash`, `moment`, `app.core.datetime.timeZoneDateTime`];\r\n\r\n function factory($injector, $scope, $window, _, moment, timeZoneDateTime) {\r\n let messages = [];\r\n let confirmationDialog;\r\n\r\n const presentDialogConfiguration = {\r\n numberOfMessages: 10,\r\n timePeriodSeconds: 300, // five minutes\r\n messageTimestamps: []\r\n };\r\n\r\n return {\r\n addFatal: (title, message, status) => addMessage(`fatal`, title, message, status),\r\n addError: (title, message, status) => {\r\n const msg = addMessage(`error`, title, message, status);\r\n if (status >= 500) {\r\n presentDialogConfiguration.messageTimestamps.push(msg.timestamp);\r\n processRecoverableErrorCountOverTime();\r\n }\r\n },\r\n addWarning: (title, message, status) => addMessage(`warning`, title, message, status),\r\n addInfo: (title, message, status) => addMessage(`info`, title, message, status),\r\n remove: predicate => {\r\n _.remove(messages, predicate);\r\n },\r\n removeStale: () => {\r\n const oneDayAgo = now().subtract(1, `days`);\r\n _.remove(messages, message => message.timestamp.isBefore(oneDayAgo));\r\n },\r\n removeAll: () => {\r\n messages = [];\r\n },\r\n update: predicate => {\r\n const message = _.find(messages, predicate);\r\n if (!message) {\r\n return false;\r\n }\r\n message.count++;\r\n if (message.type === `error` && message.status >= 500) {\r\n presentDialogConfiguration.messageTimestamps.push(now());\r\n processRecoverableErrorCountOverTime();\r\n }\r\n return true;\r\n },\r\n all: () => messages,\r\n count: (type = `all`) => {\r\n const filteredMessages = type === `all` ? messages : _.filter(messages, { type });\r\n return _.reduce(filteredMessages, (acc, val) => acc + val.count, 0);\r\n }\r\n };\r\n\r\n ////////////////////\r\n\r\n function now() {\r\n return moment(timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date()));\r\n }\r\n\r\n function addMessage(type, title, message, status) {\r\n const item = {\r\n type,\r\n status,\r\n title,\r\n message,\r\n timestamp: now(),\r\n count: 1\r\n };\r\n messages.push(item);\r\n return item;\r\n }\r\n\r\n function processRecoverableErrorCountOverTime() {\r\n const errorMessageCount = presentDialogConfiguration.messageTimestamps.length;\r\n if (errorMessageCount >= presentDialogConfiguration.numberOfMessages) {\r\n const comparisonTime = presentDialogConfiguration.messageTimestamps[errorMessageCount - presentDialogConfiguration.numberOfMessages];\r\n const earliestTime = now().subtract(presentDialogConfiguration.timePeriodSeconds, `seconds`);\r\n if (comparisonTime.isSameOrAfter(earliestTime)) {\r\n confirmationDialog = confirmationDialog || $injector.get(`confirmationDialog`);\r\n confirmationDialog.error();\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.models.modelLoadingStatus`, getModelLoadingStatuses());\r\n\r\n function getModelLoadingStatuses() {\r\n return {\r\n pending: `pending`,\r\n loading: `loading`,\r\n loaded: `loaded`,\r\n failed: `failed`\r\n };\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.monitoring.createMonitorMapFenceline`, factory);\r\n\r\n factory.$inject = [\r\n `$filter`,\r\n `lodash`,\r\n `$q`,\r\n `app.core.services.monitoringService`\r\n ];\r\n\r\n function factory($filter, _, $q, monitoringService) {\r\n\r\n function createMonitorMapFenceline(monitor, switches) {\r\n\r\n extendMonitorAttributes();\r\n return buildFenceline();\r\n\r\n ////////////////////\r\n\r\n function buildFenceline() {\r\n const processVariable = monitor.processVariable;\r\n const showMonitorsThatHaveExceededFirstThreshold = switches.thresholdExceeded;\r\n const isFocusedFenceline = processVariable && (!showMonitorsThatHaveExceededFirstThreshold || processVariable.hasValueExceededFirstThreshold);\r\n const latlngs = monitor.fencelineLocations.map(location => ({\r\n lat: location.latitude,\r\n lng: location.longitude\r\n }));\r\n\r\n const firstLatLng = { lat: monitor.fencelineLocations[0].latitude, lng: monitor.fencelineLocations[0].longitude };\r\n const last = monitor.fencelineLocations.length - 1;\r\n const lastLatLng = { lat: monitor.fencelineLocations[last].latitude, lng: monitor.fencelineLocations[last].longitude };\r\n\r\n const line = {\r\n id: `fenceline_${monitor.name.replace(/\\s/g, ``).toLowerCase()}`,\r\n monitor: monitor,\r\n filter: `fenceline`,\r\n latlngs: latlngs,\r\n lat: _.max(latlngs, monitor => monitor.lat).lat,\r\n lng: _.min(latlngs, monitor => monitor.lng).lng,\r\n type: `polyline`,\r\n layer: monitor.monitorType,\r\n color: isFocusedFenceline ? monitor.processVariable.thresholdColour : `#111`,\r\n weight: isFocusedFenceline ? 4 : 2\r\n };\r\n\r\n const circle1 = getCircle(firstLatLng, `one`);\r\n const circle2 = getCircle(lastLatLng, `two`);\r\n\r\n function getCircle(latlng, prefix) {\r\n return {\r\n id: `fenceline_${prefix}_${monitor.id.replace(/[\\s\\-\\d]/g, ``).toLowerCase()}`,\r\n monitor: monitor,\r\n filter: `fenceline`,\r\n latlngs: latlng,\r\n lat: latlng.lat,\r\n lng: latlng.lng,\r\n type: `circleMarker`,\r\n layer: monitor.monitorType,\r\n color: isFocusedFenceline ? monitor.processVariable.thresholdColour : `#111`,\r\n radius: isFocusedFenceline ? 4 : 2,\r\n weight: isFocusedFenceline ? 4 : 2\r\n };\r\n }\r\n\r\n return [circle1, line, circle2];\r\n }\r\n\r\n function extendMonitorAttributes() {\r\n monitor.showUnitsOnPopup = true;\r\n monitor.canAccessConfiguration = true;\r\n monitor.getGraphProcessVariables = () => monitoringService.getGraphVariables(monitor.id);\r\n }\r\n\r\n }\r\n\r\n return createMonitorMapFenceline;\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.monitoring.createMonitorMapMarker`, factory);\r\n\r\n factory.$inject = [\r\n `$filter`,\r\n `app.core.services.configuration.monitoringService`,\r\n `app.core.services.monitoringService`,\r\n `app.core.appSettings`,\r\n `esLeafletData`];\r\n\r\n function factory($filter, configMonitoringService, monitoringService, appSettings, esLeafletData) {\r\n\r\n const scaleFactor = 1.5;\r\n\r\n function createMonitorMapMarker(monitor, switches, link) {\r\n\r\n extendMonitorAttributes();\r\n return buildMarker();\r\n\r\n ////////////////////\r\n\r\n function buildMarker() {\r\n const showMonitorName = switches.monitorNames;\r\n const showUnits = switches.units;\r\n const showMonitorsThatHaveExceededFirstThreshold = switches.thresholdExceeded;\r\n const showInHeroMode = switches.heroMode;\r\n const showIcons = switches.icons;\r\n const showValue = switches.dataValue;\r\n const displayLocation = getMarkerDisplayLocation(monitor);\r\n\r\n const marker = {\r\n monitor: monitor,\r\n filter: `marker`,\r\n title: monitor.name,\r\n lat: displayLocation.latitude,\r\n lng: displayLocation.longitude,\r\n focus: false,\r\n draggable: false,\r\n riseOnHover: true,\r\n layer: monitor.monitorType,\r\n type: monitor.monitorType,\r\n link: link,\r\n zIndexOffset: 0\r\n };\r\n\r\n marker.icon = buildMarkerIcon();\r\n\r\n return marker;\r\n\r\n ////////////////////\r\n\r\n function buildMarkerIcon() {\r\n const isDiscreteReceptor = marker.type === `discreteReceptor`;\r\n const processVariable = marker.monitor.processVariable;\r\n const monitorTypeIcon = configMonitoringService.getMonitorTypeIcon(marker.type);\r\n\r\n if (isUnfocusedMonitor()) {\r\n return {\r\n type: `div`,\r\n className: `unfocused-monitor-container`,\r\n html: `
      `\r\n };\r\n }\r\n\r\n setZIndex();\r\n const backgroundColor = processVariable.thresholdColour;\r\n const textColor = getTextColor(processVariable);\r\n const sensorValueCssClasses = getSensorValueCssClasses(processVariable);\r\n\r\n const scaledMonitor = {\r\n type: `div`,\r\n className: `dots-on-a-plane`,\r\n html: `
      `\r\n };\r\n\r\n esLeafletData.getMap(`map-canvas`)\r\n .then(map => {\r\n renderScaledMonitor(map, scaledMonitor, isDiscreteReceptor);\r\n map.on(`zoomend`, () => renderScaledMonitor(map, scaledMonitor, isDiscreteReceptor));\r\n });\r\n\r\n return scaledMonitor;\r\n\r\n ////////////////////\r\n\r\n function isUnfocusedMonitor() {\r\n return !processVariable || showMonitorsThatHaveExceededFirstThreshold && !processVariable.hasValueExceededFirstThreshold;\r\n }\r\n\r\n function setZIndex() {\r\n if (processVariable) {\r\n if (processVariable.hasValueExceededFirstThreshold && !processVariable.isValueStale) {\r\n marker.zIndexOffset = 9999; // any threshold exceedances show on top\r\n } else if (!processVariable.hasDisplayableValue) {\r\n marker.zIndexOffset = 500; // then stale data monitors\r\n } else {\r\n marker.zIndexOffset = 9998; // then green monitors\r\n }\r\n } else {\r\n marker.zIndexOffset = 0; // unfocused etc.\r\n }\r\n }\r\n\r\n function getSensorValueCssClasses(processVariable) {\r\n const cssClassList = [`sensor-value`];\r\n\r\n if (showInHeroMode) {\r\n cssClassList.push(`hero-mode`);\r\n }\r\n\r\n if (showUnits) {\r\n cssClassList.push(`show-units`);\r\n }\r\n\r\n if (processVariable.hasDisplayableValue) {\r\n cssClassList.push(`has-displayable-value`);\r\n }\r\n\r\n if (processVariable.hasDisplayableValue && showValue) {\r\n cssClassList.push(`show-value`);\r\n }\r\n\r\n if (showIcons) {\r\n cssClassList.push(`show-icons`);\r\n }\r\n\r\n if (processVariable.hasValueFlatlined) {\r\n cssClassList.push(`flatlined`);\r\n }\r\n\r\n return cssClassList.join(` `);\r\n }\r\n\r\n function getTextColor(processVariable) {\r\n return processVariable.hasDisplayableValue ? `#fff` : `#444`;\r\n }\r\n\r\n function renderScaledMonitor(map, scaledMonitor, isDiscreteReceptor) {\r\n const currentZoom = map.getZoom();\r\n if (currentZoom >= 10 && !isDiscreteReceptor) {\r\n scaledMonitor.iconAnchor = [-11, 11];\r\n scaledMonitor.html = link ? wrapInsideLink(getHtml()) : getHtml();\r\n } else {\r\n const radius = Math.round(currentZoom * scaleFactor);\r\n const html = `
      `;\r\n scaledMonitor.iconSize = [radius, radius];\r\n delete scaledMonitor.iconAnchor;\r\n scaledMonitor.html = link ? wrapInsideLink(html) : html;\r\n }\r\n }\r\n\r\n function wrapInsideLink(html) {\r\n return `${html}`;\r\n }\r\n\r\n function getHtml() {\r\n return `\r\n
      \r\n
      \r\n ${buildIcon(monitorTypeIcon)}\r\n ${buildValue(processVariable)}\r\n ${buildUnits(processVariable)}\r\n
      \r\n ${buildMonitorName()}\r\n
      \r\n `;\r\n }\r\n\r\n function buildIcon() {\r\n return ``;\r\n }\r\n\r\n function buildValue(processVariable) {\r\n const valueRounded = $filter(`number`)(processVariable.valueInDisplayUnit, processVariable.numericScale);\r\n return `${valueRounded}`;\r\n }\r\n\r\n function buildUnits(processVariable) {\r\n return `${processVariable.units}`;\r\n }\r\n\r\n function buildMonitorName() {\r\n const monitorName = showMonitorName ? marker.title : null;\r\n return monitorName && monitorName.length\r\n ? `
      ${monitorName}
      `\r\n : ``;\r\n\r\n }\r\n }\r\n\r\n function getMarkerDisplayLocation(monitor) {\r\n // Apply special handling for placement of marker\r\n if (monitor.fencelineLocations && monitor.fencelineLocations.length > 1) {\r\n // If the marker is for a fenceline, position marker at the center of the first two fenceline points.\r\n const firstFenceSegment = monitor.fencelineLocations.slice(0, 2);\r\n const latitude = firstFenceSegment.map(c => c.latitude).reduce((a, b) => a + b, 0) / 2;\r\n const longitude = firstFenceSegment.map(c => c.longitude).reduce((a, b) => a + b, 0) / 2;\r\n return { latitude, longitude };\r\n }\r\n\r\n return { latitude: monitor.latitude, longitude: monitor.longitude };\r\n }\r\n }\r\n\r\n function extendMonitorAttributes() {\r\n monitor.showUnitsOnPopup = true;\r\n monitor.canAccessConfiguration = true;\r\n monitor.getGraphProcessVariables = () => monitoringService.getGraphVariables(monitor.id);\r\n }\r\n }\r\n return createMonitorMapMarker;\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.models.monitoring.createMonitorMapPath`, factory);\r\n\r\n factory.$inject = [`$filter`, `lodash`, `$q`];\r\n\r\n function factory($filter, _, $q) {\r\n\r\n function createMonitorMapPath(monitor, options) {\r\n\r\n extendMonitorAttributes();\r\n return buildPath();\r\n\r\n ////////////////////\r\n\r\n function buildPath() {\r\n return {\r\n id: `path_${monitor.id.replace(/[\\s\\-\\d]/g, ``).toLowerCase()}`,\r\n monitor: monitor,\r\n filter: options.layer,\r\n title: monitor.name,\r\n latlngs: monitor.latlngs,\r\n focus: false,\r\n draggable: false,\r\n riseOnHover: true,\r\n lat: _.max(monitor.latlngs, monitor => monitor.lat).lat,\r\n lng: _.min(monitor.latlngs, monitor => monitor.lng).lng,\r\n type: `polygon`,\r\n layer: options.layer,\r\n color: getPathColor(),\r\n weight: 1,\r\n fillOpacity: 0.5\r\n };\r\n }\r\n\r\n function getPathColor() {\r\n if (!monitor.dataPoints) {\r\n return null;\r\n }\r\n\r\n const dataPoint = monitor.dataPoints && monitor.dataPoints.find(dp => dp.valueInDisplayUnit !== null);\r\n return dataPoint && dataPoint.thresholdColour || _.get(monitor, `dataPoints[0].thresholdColour`, null);\r\n }\r\n\r\n function extendMonitorAttributes() {\r\n monitor.showUnitsOnPopup = options.showUnitsOnPopup;\r\n monitor.getGraphProcessVariables = () => $q.resolve(options.graphProcessVariables);\r\n monitor.canAccessConfiguration = options.canAccessConfiguration;\r\n }\r\n }\r\n\r\n return createMonitorMapPath;\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.alertDataProvider`, alertDataProvider);\r\n\r\n alertDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function alertDataProvider($http, appSettings) {\r\n\r\n return {\r\n getActiveWebAlerts,\r\n dismissWebAlert,\r\n getAlertsHistory\r\n };\r\n\r\n //////////////\r\n\r\n function buildUrl(url) {\r\n return appSettings.webApiHostUri + url;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getActiveWebAlerts() {\r\n const url = buildUrl(`alerts/web/active`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function dismissWebAlert(alertId) {\r\n const url = buildUrl(`alerts/web/dismiss/${alertId}`);\r\n return $http.delete(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getAlertsHistory(queryObject) {\r\n const url = buildUrl(`alerts/history`);\r\n return $http.post(url, queryObject).then(success).catch(angular.noop);\r\n }\r\n\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.blastingDataProvider`, blastingDataProvider);\r\n\r\n blastingDataProvider.$inject = [\r\n `$http`,\r\n `app.core.appSettings`\r\n ];\r\n\r\n function blastingDataProvider($http, appSettings) {\r\n return {\r\n getScenarios,\r\n getScenario,\r\n getBlastData,\r\n getOverlays\r\n };\r\n\r\n /////////////\r\n\r\n function buildUrl(url) {\r\n return `${appSettings.webApiHostUri}blasting/scenarios/${url}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getScenarios(queryObject) {\r\n const url = buildUrl(``);\r\n return $http.post(url, queryObject).then(success).catch(angular.noop);\r\n }\r\n\r\n function getScenario(scenarioAlias) {\r\n const url = buildUrl(`${scenarioAlias}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getBlastData(scenarioAlias, modelType, blastTimeMillis) {\r\n const url = buildUrl(`${scenarioAlias}/${modelType}`);\r\n\r\n const requestData = {\r\n params: {\r\n utcBlastTime: new Date(blastTimeMillis).toISOString()\r\n }\r\n };\r\n\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getOverlays(scenarioId) {\r\n const url = buildUrl(`${scenarioId}/overlays`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(`app.core.providers.companyDataProvider`, companyDataProvider);\r\n\r\n companyDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function companyDataProvider($http, appSettings) {\r\n return {\r\n getCompanies,\r\n getFacilityLocation,\r\n getDomainBoundaries\r\n };\r\n\r\n ////////////////////\r\n\r\n function buildUrl(path) {\r\n return `${appSettings.webApiHostUri}${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getCompanies(apiKey) {\r\n const url = buildUrl(`companies?apiKey=${apiKey}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getFacilityLocation() {\r\n const url = buildUrl(`facility/location`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getDomainBoundaries() {\r\n const url = buildUrl(`facility/boundaries`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .factory(`app.core.providers.configuration.blastingDataProvider`, blastingDataProvider);\n\n blastingDataProvider.$inject = [`$http`, `$q`, `app.core.appSettings`];\n\n function blastingDataProvider($http, $q, appSettings) {\n\n return {\n getScenario: () => $q.when({}),\n getValidScenarioAlias,\n getModelTypes,\n getAddOverlayUrl: getOverlayFilesUrl,\n getOverlayFiles,\n deleteOverlayFile,\n createScenario,\n getOverlayFile,\n deleteScenario,\n updateActualBlastTime\n };\n\n //////////////\n\n function buildUrl(path) {\n return `${appSettings.webApiHostUri}configuration/blasting/scenarios/${path}`;\n }\n\n function success(response) {\n return response.data.data;\n }\n\n function getModelTypes() {\n const url = `${appSettings.webApiHostUri}configuration/blasting/model-types`;\n return $http.get(url).then(success).catch(angular.noop);\n }\n\n function getOverlayFilesUrl() {\n return buildUrl(`overlays`);\n }\n\n function getOverlayFiles(scenarioId) {\n const requestConfig = {\n params: {\n scenarioId: scenarioId || null\n }\n };\n const url = getOverlayFilesUrl();\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function getOverlayFile(fileName) {\n const url = buildUrl(`overlay`);\n const requestConfig = {\n params: {\n fileName\n }\n };\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function deleteOverlayFile(scenarioId, fileName) {\n const requestConfig = {\n params: {\n scenarioId: scenarioId || null,\n fileName\n }\n };\n const url = getOverlayFilesUrl(scenarioId);\n return $http.delete(url, requestConfig).catch(angular.noop);\n }\n\n function getValidScenarioAlias(alias) {\n const requestConfig = {\n params: {\n alias: alias || null\n }\n };\n const url = buildUrl(`valid-alias`);\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\n }\n\n function createScenario(scenario) {\n const url = buildUrl(``);\n return $http.post(url, scenario).then(success).catch(angular.noop);\n }\n\n function deleteScenario(scenarioAlias) {\n const url = buildUrl(scenarioAlias);\n return $http.delete(url).then(success).catch(angular.noop);\n }\n\n function updateActualBlastTime(scenarioAlias, actualBlastTime) {\n const postData = {\n utcActualBlastTime: actualBlastTime.toISOString()\n };\n\n const url = buildUrl(`${scenarioAlias}/blast-time`);\n return $http.post(url, postData).then(success).catch(angular.noop);\n }\n }\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.configuration.gisModelDataProvider`, gisModelDataProvider);\r\n\r\n gisModelDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function gisModelDataProvider($http, appSettings) {\r\n\r\n return {\r\n getEmissionsDataFileUploadUrl,\r\n getExistingEmissionsDataFiles,\r\n getAll,\r\n getModel,\r\n getOptions,\r\n getCalpuffConfigs,\r\n remove,\r\n addPlume,\r\n addWind,\r\n importEmissionsData,\r\n updatePlume,\r\n updateWind,\r\n deleteEmissionsDataFiles\r\n };\r\n\r\n ////////////////\r\n\r\n function buildUrl(path) {\r\n return `${appSettings.webApiHostUri}configuration/gis-models/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getEmissionsDataFileUploadUrl() {\r\n return buildUrl(`emissions-data-file`);\r\n }\r\n\r\n // HTTP GETs\r\n\r\n function getExistingEmissionsDataFiles(calpuffConfigId) {\r\n const url = buildUrl(`emissions-data-file`);\r\n const requestData = {\r\n params: {\r\n calpuffConfigId\r\n }\r\n };\r\n\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getModel(modelId) {\r\n const url = buildUrl(`${modelId}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getAll() {\r\n const url = buildUrl(``);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getOptions() {\r\n const url = buildUrl(`options`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getCalpuffConfigs() {\r\n const url = buildUrl(`calpuff-configs`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP POSTS\r\n\r\n function addPlume(plumeData) {\r\n const url = buildUrl(`plume`);\r\n return $http.post(url, plumeData).then(success).catch(angular.noop);\r\n }\r\n\r\n function addWind(windData) {\r\n const url = buildUrl(`wind`);\r\n return $http.post(url, windData).then(success).catch(angular.noop);\r\n }\r\n\r\n function importEmissionsData(calpuffConfigId) {\r\n const url = buildUrl(`import-emissions-data`);\r\n return $http.post(url, { calpuffConfigId }).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP PUTs\r\n\r\n function updatePlume(plumeData) {\r\n const url = buildUrl(`plume`);\r\n return $http.put(url, plumeData).then(success).catch(angular.noop);\r\n }\r\n\r\n function updateWind(windData) {\r\n const url = buildUrl(`wind`);\r\n return $http.put(url, windData).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP DELETEs\r\n\r\n function remove(modelId) {\r\n const url = buildUrl(`${modelId}`);\r\n return $http.delete(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function deleteEmissionsDataFiles(calpuffConfigId, fileNames) {\r\n const requestData = {\r\n params: {\r\n calpuffConfigId,\r\n fileNames\r\n }\r\n };\r\n\r\n const url = buildUrl(`emissions-data-files`);\r\n return $http.delete(url, requestData).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.configuration.legacyLookupDataProvider`, lookupDataProvider);\r\n\r\n lookupDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function lookupDataProvider($http, appSettings) {\r\n\r\n return {\r\n getWindowsTimeZones\r\n };\r\n\r\n ////////////////\r\n\r\n function buildUrl(path = ``) {\r\n return `${appSettings.webApiHostUri}configuration/lookup/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n // HTTP GETs\r\n function getWindowsTimeZones() {\r\n const url = buildUrl(`windows-timezones`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.configuration.measurementGroupDataProvider`, measurementGroupDataProvider);\r\n\r\n measurementGroupDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function measurementGroupDataProvider($http, appSettings) {\r\n\r\n return {\r\n getAllMeasurementGroups,\r\n queryMeasurementGroups,\r\n getMeasurementGroup,\r\n isMeasurementGroupBeingUsed,\r\n getMeasurementGroupChildCount,\r\n createMeasurementGroup,\r\n updateMeasurementGroup,\r\n deleteMeasurementGroup\r\n };\r\n\r\n ////////////////\r\n\r\n function buildUrl(path = ``) {\r\n return `${appSettings.webApiHostUri}configuration/monitoring/measurement-groups/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n // HTTP GETs\r\n\r\n function getAllMeasurementGroups() {\r\n const url = buildUrl();\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMeasurementGroup(measurementGroupId) {\r\n const url = buildUrl(`${measurementGroupId}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function isMeasurementGroupBeingUsed(measurementGroupId) {\r\n const url = buildUrl(`${measurementGroupId}/is-in-use`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMeasurementGroupChildCount(measurementGroupId) {\r\n const url = buildUrl(`${measurementGroupId}/child-count`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP POSTs\r\n\r\n function queryMeasurementGroups(searchCriteria) {\r\n const url = buildUrl(`query`);\r\n return $http.post(url, searchCriteria).then(success).catch(angular.noop);\r\n }\r\n\r\n function createMeasurementGroup(measurementGroup) {\r\n const url = buildUrl();\r\n return $http.post(url, measurementGroup).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP PUTs\r\n \r\n function updateMeasurementGroup(measurementGroup) {\r\n const url = buildUrl();\r\n return $http.put(url, measurementGroup).then(success).catch(angular.noop);\r\n }\r\n \r\n // HTTP DELETEs\r\n\r\n function deleteMeasurementGroup(measurementGroupId) {\r\n const url = buildUrl(`${measurementGroupId}`);\r\n return $http.delete(url).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.configuration.modellingDataProvider`, modellingDataProvider);\r\n\r\n modellingDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function modellingDataProvider($http, appSettings) {\r\n\r\n return {\r\n getWrfConfiguration,\r\n runCalModelling,\r\n runAerModelling\r\n };\r\n\r\n ////////////////\r\n\r\n function buildUrl(path) {\r\n return `${appSettings.webApiHostUri}configuration/modelling/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n // HTTP GETs\r\n\r\n function getWrfConfiguration() {\r\n const url = buildUrl(`wrf-configuration`);\r\n return $http.get(url).then(success);\r\n }\r\n\r\n // HTTP POSTS\r\n\r\n function runCalModelling(wrfConfigurationName, forecastDate, forecastRun) {\r\n const url = buildUrl(`run-calmodelling`);\r\n const payload = {\r\n wrfConfigurationName: wrfConfigurationName,\r\n utcForecastDate: forecastDate, // no toISOString(); the date must be formatted without a time\r\n forecastRun: forecastRun\r\n };\r\n return $http.post(url, payload).then(success);\r\n }\r\n\r\n function runAerModelling(upperAirMetMonitorId, surfaceMetMonitorId, fromDate, toDate) {\r\n const url = buildUrl(`run-aermodelling`);\r\n const payload = {\r\n upperAirWeatherStationId: upperAirMetMonitorId,\r\n surfaceWeatherStationId: surfaceMetMonitorId,\r\n utcFromDate: fromDate.toISOString(),\r\n utcToDate: toDate.toISOString()\r\n };\r\n return $http.post(url, payload).then(success);\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.configuration.monitoringDataProvider`, monitoringDataProvider);\r\n\r\n monitoringDataProvider.$inject = [`$http`, `lodash`, `app.core.appSettings`];\r\n\r\n function monitoringDataProvider($http, _, appSettings) {\r\n\r\n return {\r\n getMonitors,\r\n getUpperAirWeatherStations,\r\n getSurfaceWeatherStations,\r\n getMonitorType,\r\n getMonitorTypes,\r\n getMonitor,\r\n getMonitorLocation,\r\n getMonitorDisplay,\r\n queryMonitors,\r\n getAllMetStations,\r\n\r\n setDefaultMetStation,\r\n updateMonitorDisplay,\r\n createMonitor,\r\n updateMonitor,\r\n\r\n getMeasurementType,\r\n getMeasurementTypeConfigurationOptions,\r\n queryMonitorMeasurementTypes,\r\n createMeasurementType,\r\n updateMeasurementType\r\n };\r\n\r\n ////////////////\r\n\r\n function buildUrl(path = ``) {\r\n return `${appSettings.webApiHostUri}configuration/monitoring/monitors/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function linqSuccess(response) {\r\n return response.data.data.data;\r\n }\r\n\r\n // HTTP GETs\r\n function getMonitorType(monitorId) {\r\n const url = buildUrl(`${monitorId}/monitor-type`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitorTypes() {\r\n const url = `${appSettings.webApiHostUri}configuration/monitoring/monitor-types`;\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitor(monitorType, monitorId) {\r\n const url = buildUrl(`${_.kebabCase(monitorType)}/${monitorId}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitors(whereVisible) {\r\n const url = buildUrl(``);\r\n const parameters = {\r\n params: {\r\n whereVisible\r\n }\r\n };\r\n\r\n return $http.get(url, parameters).then(success).catch(angular.noop);\r\n }\r\n\r\n function getSurfaceWeatherStations() {\r\n const url = buildUrl(`surface-weather-stations`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getUpperAirWeatherStations() {\r\n const url = buildUrl(`upper-air-weather-stations`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getAllMetStations() {\r\n const url = buildUrl(`met-stations`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitorLocation(monitorId) {\r\n const url = buildUrl(`${monitorId}/location`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n \r\n function getMonitorDisplay(monitorId) {\r\n const url = buildUrl(`${monitorId}/display`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMeasurementType(measurementTypeId) {\r\n const url = buildUrl(`measurement-types/${measurementTypeId}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMeasurementTypeConfigurationOptions() {\r\n const url = buildUrl(`measurement-types/options`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n\r\n // HTTP POSTs\r\n\r\n function queryMonitors(searchCriteria) {\r\n const url = buildUrl(`query`);\r\n return $http.post(url, searchCriteria).then(success).catch(angular.noop);\r\n }\r\n\r\n function setDefaultMetStation(monitorId) {\r\n const url = buildUrl(`${monitorId}/default-met-station`);\r\n return $http.post(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function createMonitor(monitorType, payload) {\r\n const url = buildUrl(`${_.kebabCase(monitorType)}`);\r\n return $http.post(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n function queryMonitorMeasurementTypes(monitorId, searchCriteria) {\r\n const url = buildUrl(`measurement-types/query?monitorId=${monitorId}`);\r\n return $http.post(url, searchCriteria).then(linqSuccess).catch(angular.noop);\r\n }\r\n\r\n function createMeasurementType(payload) {\r\n const url = buildUrl(`measurement-types`);\r\n return $http.post(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n\r\n // HTTP PUTs\r\n\r\n function updateMonitor(monitorType, payload) {\r\n const url = buildUrl(`${_.kebabCase(monitorType)}`);\r\n return $http.put(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n function updateMonitorDisplay(monitorId, payload) {\r\n const url = buildUrl(`${monitorId}/display`);\r\n return $http.put(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n function updateMeasurementType(payload) {\r\n const url = buildUrl(`measurement-types`);\r\n return $http.put(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP DELETEs\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.diagnosticsDataProvider`, diagnosticsDataProvider);\r\n\r\n diagnosticsDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function diagnosticsDataProvider($http, appSettings) {\r\n\r\n return {\r\n getUtcLatestProcessDataEndTime\r\n };\r\n\r\n //////////////\r\n\r\n function buildUrl(url) {\r\n return appSettings.webApiHostUri + url;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getUtcLatestProcessDataEndTime() {\r\n const url = buildUrl(`diagnostics/latest-process-data-time`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(`app.core.providers.errorThrowingDataProvider`, errorThrowingDataProvider);\r\n\r\n errorThrowingDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function errorThrowingDataProvider($http, appSettings) {\r\n\r\n return {\r\n getException,\r\n getFailedResult\r\n };\r\n\r\n /////////////\r\n\r\n function getException() {\r\n const webApiHostUri = appSettings.webApiHostUri;\r\n const url = `${webApiHostUri}error/exception`;\r\n return $http.get(url);\r\n }\r\n\r\n function getFailedResult() {\r\n const webApiHostUri = appSettings.webApiHostUri;\r\n const url = `${webApiHostUri}error/failed-result`;\r\n return $http.get(url);\r\n }\r\n\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.gisModelDataProvider`, gisModelDataProvider);\r\n\r\n gisModelDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function gisModelDataProvider($http, appSettings) {\r\n\r\n return {\r\n getIntervals,\r\n getModelDataSet,\r\n getModellingJobs,\r\n getModelDataAvailability,\r\n getDiscreteReceptorData,\r\n dismissJob,\r\n dismissJobs,\r\n getStatus,\r\n startTestJob\r\n };\r\n\r\n function buildUrl(url) {\r\n return appSettings.webApiHostUri + url;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getIntervals() {\r\n const url = buildUrl(`gis-models/intervals`);\r\n\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getModelDataSet(modelIds, startDate, endDate) {\r\n const postData = {\r\n modelIds: modelIds,\r\n utcFromDate : startDate.toISOString(),\r\n utcToDate: endDate.toISOString()\r\n };\r\n\r\n const url = buildUrl(`gis-models/model-data`);\r\n return $http.post(url, postData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getModellingJobs() {\r\n const url = buildUrl(`jobs/modelling`);\r\n\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getModelDataAvailability(modelId) {\r\n const url = buildUrl(`gis-models/model-data-availability/${modelId}`);\r\n\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getDiscreteReceptorData(modelId, fromTime, toTime) {\r\n const postData = {\r\n modelId,\r\n utcFromTime: fromTime.toISOString(),\r\n utcToTime: toTime.toISOString()\r\n };\r\n\r\n const url = buildUrl(`gis-models/discrete-receptor-data`);\r\n return $http.post(url, postData).then(success).catch(angular.noop);\r\n }\r\n\r\n function dismissJob(jobId) {\r\n const url = buildUrl(`jobs/modelling/${jobId}`);\r\n\r\n return $http.delete(url);\r\n }\r\n\r\n function dismissJobs(jobIds) {\r\n const url = buildUrl(`jobs/modelling/delete`);\r\n const postData = {\r\n jobBatchIds: jobIds\r\n };\r\n\r\n return $http.post(url, postData);\r\n }\r\n\r\n function getStatus(jobId) {\r\n const url = buildUrl(`jobs/modelling/${jobId}/status`);\r\n\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function startTestJob() {\r\n const url = buildUrl(`jobs/modelling/test`);\r\n const postData = {};\r\n\r\n return $http.post(url, postData).then(success).catch(angular.noop);\r\n }\r\n\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.incidentIntelligenceDataProvider`, incidentIntelligenceDataProvider);\r\n\r\n incidentIntelligenceDataProvider.$inject = [\r\n `$http`,\r\n `app.core.appSettings`\r\n ];\r\n\r\n function incidentIntelligenceDataProvider($http, appSettings) {\r\n return {\r\n getPathModel,\r\n getSummaryLookupValues,\r\n getTicketSummaryLocations\r\n };\r\n\r\n /////////////\r\n\r\n function buildUrl(url) {\r\n return `${appSettings.webApiHostUri}incident-intelligence/${url}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getPathModel(ticketId, ticketActivityId) {\r\n const url = buildUrl(`ticket/${ticketId}/path-model/${ticketActivityId}`);\r\n\r\n const requestData = {\r\n params: {\r\n ticketId,\r\n ticketActivityId\r\n }\r\n };\r\n\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getSummaryLookupValues() {\r\n const url = buildUrl(`tickets/summary-lookup-values`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getTicketSummaryLocations(criteria) {\r\n const payload = {\r\n params : {\r\n categoryTypes: [criteria.selectedCategoryId],\r\n resolutionTypes: criteria.selectedStatuses,\r\n issueTypes: criteria.selectedTypes,\r\n\r\n utcFromTime : criteria.fromDate.toISOString(),\r\n utcToTime: criteria.toDate.toISOString()\r\n }\r\n };\r\n\r\n const url = buildUrl(`tickets/summary-locations`);\r\n return $http.get(url, payload).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.mappingDataProvider`, mappingDataProvider);\r\n\r\n mappingDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function mappingDataProvider($http, appSettings) {\r\n\r\n return {\r\n getKmlDataSet,\r\n getTileLayers,\r\n getMapCredits,\r\n getElevationAtPoint,\r\n getActiveTemporalEventGroups\r\n };\r\n\r\n function buildUrl(url) {\r\n return appSettings.webApiHostUri + url;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getKmlDataSet(includeFiles, ignoreFiles) {\r\n const url = buildUrl(`map/kml-files`);\r\n\r\n const requestConfig = {\r\n params: {\r\n includeFiles,\r\n ignoreFiles\r\n }\r\n };\r\n\r\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\r\n }\r\n\r\n function getTileLayers() {\r\n const url = buildUrl(`map/tile-layers`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMapCredits() {\r\n const url = buildUrl(`map/credits`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getElevationAtPoint(latitude, longitude) {\r\n const url = buildUrl(`map/elevation`);\r\n\r\n const requestConfig = {\r\n params: {\r\n longitude,\r\n latitude\r\n }\r\n };\r\n\r\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\r\n }\r\n\r\n function getActiveTemporalEventGroups(activeAtDateTime) {\r\n const requestConfig = {\r\n params: {\r\n utcActiveAtDateTime: activeAtDateTime.toISOString()\r\n }\r\n };\r\n\r\n const url = buildUrl(`temporal-events/active-event-groups`);\r\n\r\n return $http.get(url, requestConfig).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.monitoringDataProvider`, monitoringDataProvider);\r\n\r\n monitoringDataProvider.$inject = [`$http`, `lodash`, `app.core.appSettings`];\r\n\r\n function monitoringDataProvider($http, _, appSettings) {\r\n\r\n return {\r\n getMonitorsByType,\r\n getMonitorData,\r\n getMetSummary,\r\n getGraphVariables,\r\n getMonitorSensorData,\r\n getSensorDataSeries,\r\n getMonitorTypes,\r\n getMonitorDataAlarms,\r\n getSourceAreaData\r\n };\r\n\r\n ////////////////////\r\n\r\n\r\n function buildUrl(template) {\r\n return `${appSettings.webApiHostUri}${template}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getMonitorsByType() {\r\n const url = buildUrl(`monitoring/monitors-by-type`);\r\n\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitorData(monitorIds, measurementGroupId, dateTime) {\r\n const postData = {\r\n monitorIds: monitorIds,\r\n measurementGroupId: measurementGroupId,\r\n utcDateTime: dateTime.toISOString()\r\n };\r\n\r\n const url = buildUrl(`monitoring/monitor-data`);\r\n return $http.post(url, postData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getSourceAreaData(dateTime) {\r\n const requestData = {\r\n params: {\r\n utcDateTime: dateTime.toISOString()\r\n }\r\n };\r\n\r\n const url = buildUrl(`monitoring/source-areas-data`);\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMetSummary(dateTime) {\r\n const requestData = {\r\n params: {\r\n utcDateTime: dateTime.toISOString()\r\n }\r\n };\r\n\r\n const url = buildUrl(`monitoring/met-summaries`);\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getGraphVariables(monitorId) {\r\n const requestData = {\r\n params: {\r\n monitorId\r\n }\r\n };\r\n\r\n const url = buildUrl(`monitoring/graph-variables`);\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitorSensorData(monitorId, processVariableIds, dateTime) {\r\n const requestData = {\r\n params: {\r\n monitorId,\r\n processVariableIds,\r\n utcDateTimeEnd: dateTime.toISOString()\r\n }\r\n };\r\n\r\n const url = buildUrl(`monitoring/graph-data`);\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getSensorDataSeries(dateTimeStart, dateTimeEnd, processVariableId) {\r\n const requestData = {\r\n params: {\r\n processVariableId,\r\n utcDateTimeStart: dateTimeStart.toISOString(),\r\n utcDateTimeEnd: dateTimeEnd.toISOString()\r\n }\r\n };\r\n\r\n const url = buildUrl(`monitoring/process-variable-trend`);\r\n return $http.get(url, requestData).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitorTypes() {\r\n const url = buildUrl(`monitoring/monitor-types`);\r\n\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getMonitorDataAlarms(monitorTypes, samplingTime = null) {\r\n const postData = {\r\n monitorTypes,\r\n utcSamplingTime: samplingTime.toISOString()\r\n };\r\n\r\n const url = buildUrl(`monitoring/monitor-data/alarms`);\r\n return $http.post(url, postData).then(success).catch(angular.noop);\r\n }\r\n\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.reportsDataProvider`, reportsDataProvider);\r\n\r\n reportsDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function reportsDataProvider($http, appSettings) {\r\n\r\n return {\r\n getListOfReports,\r\n getAlertPointReports,\r\n getProcessDataReportLookupValues,\r\n getProcessDataReportColumns,\r\n getProcessDataReport,\r\n exportProcessDataReport\r\n };\r\n\r\n //////////////\r\n\r\n function buildUrl(url) {\r\n return `${appSettings.webApiHostUri}reports/${url}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function getListOfReports() {\r\n const url = buildUrl(``);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getAlertPointReports() {\r\n const url = buildUrl(`alert-points`);\r\n return $http.get(url).then(success);\r\n }\r\n\r\n function getProcessDataReportLookupValues(reportId) {\r\n const url = buildUrl(`process-data/${reportId}/lookup-values`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getProcessDataReportColumns(processId) {\r\n const url = buildUrl(`process-data/columns?processId=${processId}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getProcessDataReport(processId, startTime, endTime, searchCriteria) {\r\n const path = `process-data`;\r\n return postProcessDataRequest(path, processId, startTime, endTime, searchCriteria);\r\n }\r\n\r\n function exportProcessDataReport(processId, startTime, endTime, searchCriteria) {\r\n const path = `process-data/export`;\r\n return postProcessDataRequest(path, processId, startTime, endTime, searchCriteria);\r\n }\r\n\r\n function postProcessDataRequest(path, processId, startTime, endTime, searchCriteria) {\r\n const queryString = `processId=${processId}&utcStartTime=${startTime.toISOString()}&utcEndTime=${endTime.toISOString()}`;\r\n const url = buildUrl(`${path}?${queryString}`);\r\n\r\n return $http.post(url, searchCriteria).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .service(\r\n `app.core.providers.securityDataProvider`,\r\n securityDataProvider\r\n );\r\n\r\n securityDataProvider.$inject = [\r\n `$http`,\r\n `app.core.appSettings`,\r\n `CacheFactory`\r\n ];\r\n\r\n function securityDataProvider($http, appSettings, cacheFactory) {\r\n const cacheName = `accessControlCache`;\r\n let accessControlCache = cacheFactory.get(cacheName);\r\n if (!accessControlCache) {\r\n accessControlCache = cacheFactory(cacheName, {\r\n maxAge: 5 * 60 * 1000, // Items added to this cache expire after 5 minutes\r\n cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour\r\n deleteOnExpire: `aggressive`, // Items will be deleted from this cache when they expire\r\n onExpire: function (url) {\r\n $http.get(url).then(response => {\r\n accessControlCache.put(url, response.data);\r\n });\r\n }\r\n });\r\n }\r\n\r\n return {\r\n getAccessControls,\r\n queryApiCredentials,\r\n getApiCredential,\r\n createApiCredential,\r\n updateApiCredential,\r\n getPasswordExpirationStatus,\r\n setPasswordExpirationConfirmed,\r\n logout\r\n };\r\n\r\n /////////////\r\n\r\n function buildUrl(path = ``) {\r\n return `${appSettings.webApiHostUri}security/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n function linqSuccess(response) {\r\n return response.data.data.data;\r\n }\r\n\r\n function getAccessControls(companyId, facilityId) {\r\n const url = buildUrl(\r\n `access-controls?companyId=${companyId}&facilityId=${facilityId}`\r\n );\r\n return $http\r\n .get(url, { cache: accessControlCache })\r\n .then(success)\r\n .catch(angular.noop);\r\n }\r\n\r\n function queryApiCredentials(monitorId, searchCriteria) {\r\n const url = buildUrl(`monitor/api-credentials/${monitorId}/query`);\r\n return $http\r\n .post(url, searchCriteria)\r\n .then(linqSuccess)\r\n .catch(angular.noop);\r\n }\r\n\r\n function getApiCredential(credentialId) {\r\n const url = buildUrl(`monitor/api-credentials/${credentialId}`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function createApiCredential(payload) {\r\n const url = buildUrl(`monitor/api-credentials`);\r\n return $http.post(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n function updateApiCredential(payload) {\r\n const url = buildUrl(`monitor/api-credentials`);\r\n return $http.put(url, payload).then(success).catch(angular.noop);\r\n }\r\n\r\n function getPasswordExpirationStatus() {\r\n const url = `${appSettings.webApiHostUri}user/passwordExpirationStatus`;\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function setPasswordExpirationConfirmed() {\r\n const url = `${appSettings.webApiHostUri}user/setPasswordExpirationConfirmation`;\r\n return $http.post(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function logout() {\r\n const url = buildUrl(`logout`);\r\n return $http.post(url).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.providers.userDataProvider`, userDataProvider);\r\n\r\n userDataProvider.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function userDataProvider($http, appSettings) {\r\n\r\n return {\r\n getUserDetails,\r\n getLocale,\r\n updatePassword,\r\n updateUserDetails\r\n };\r\n\r\n ////////////////\r\n\r\n function buildUrl(path) {\r\n return `${appSettings.webApiHostUri}user/${path}`;\r\n }\r\n\r\n function success(response) {\r\n return response.data.data;\r\n }\r\n\r\n // HTTP GETs\r\n\r\n function getUserDetails() {\r\n const url = buildUrl(``);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n function getLocale() {\r\n const url = buildUrl(`locale`);\r\n return $http.get(url).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP POSTS\r\n\r\n function updatePassword(username, currentPassword, newPassword) {\r\n const url = `${appSettings.webApiHostUri}security/authenticate-new-password`;\r\n const postData = {\r\n username,\r\n oldPassword: currentPassword,\r\n password: newPassword\r\n };\r\n\r\n return $http.post(url, postData).then(success).catch(angular.noop);\r\n }\r\n\r\n // HTTP PUTS\r\n\r\n function updateUserDetails(payload) {\r\n const url = buildUrl(`details`);\r\n return $http.put(url, payload).then(success).catch(angular.noop);\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.requestManager`, requestManager);\r\n\r\n requestManager.$inject = [`$q`, `$log`];\r\n\r\n function requestManager($q, $log) {\r\n\r\n return createQueuedRequestManager();\r\n\r\n function createQueuedRequestManager() {\r\n const queues = {};\r\n\r\n function createFetcher(fnPromise, queueName, options) {\r\n const queue = queues[queueName] || (queues[queueName] = []);\r\n const deferred = $q.defer();\r\n const fetcher = {\r\n fetch,\r\n cancel,\r\n promise: deferred.promise\r\n };\r\n\r\n queue.push(fetcher);\r\n\r\n if (queue.length === 1) {\r\n $log.debug(`fetching first request - ${queueName} - ${queue.length}`);\r\n fetcher.fetch();\r\n }\r\n\r\n return fetcher;\r\n\r\n ////////////////////\r\n\r\n function fetch() {\r\n fnPromise().then(postFetch, cancel);\r\n\r\n function postFetch(result) {\r\n queue.shift(); // remove the in-flight fetcher.\r\n const queueWasDrained = drainQueue();\r\n if (queueWasDrained && options.resolveLastFetchOnly) {\r\n $log.debug(`request rejected - ${queueName} - ${queue.length}`);\r\n\r\n // The package was actually fetched successfully, but since the options are configured to\r\n // only resolve the last fetch, we reject with a reason to say that the request expired.\r\n deferred.reject({\r\n reason: `expired`,\r\n result\r\n });\r\n\r\n return;\r\n }\r\n\r\n $log.debug(`request resolved - ${queueName} - ${queue.length}`);\r\n deferred.resolve(result);\r\n }\r\n }\r\n\r\n function cancel() {\r\n deferred.reject({\r\n reason: `cancelled`,\r\n result: {}\r\n });\r\n }\r\n\r\n function drainQueue() {\r\n if (queue.length === 0) {\r\n delete queues[queueName];\r\n return false; // didn't do anything\r\n }\r\n\r\n // cancel backlog of requests except for the last one\r\n while (queue.length > 1) {\r\n const fetchCount = queue.length;\r\n const nextFetcher = queue.shift();\r\n $log.debug(`cancelling - ${queueName} - fetcher ${fetchCount}`);\r\n nextFetcher.cancel();\r\n }\r\n\r\n // fetch latest pending request\r\n $log.debug(`fetching request - ${queueName} - ${queue.length}`);\r\n queue[0].fetch();\r\n\r\n return true; // queue was drained\r\n }\r\n }\r\n\r\n return {\r\n enqueue: (fnPromise, options = { resolveLastFetchOnly: true }) => {\r\n return {\r\n onQueue: function(queueName) {\r\n const fetcher = createFetcher(fnPromise, queueName, options);\r\n return fetcher.promise;\r\n }\r\n };\r\n }\r\n };\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.security.knownCredentials`, getKnownCredentials());\r\n\r\n function getKnownCredentials() {\r\n return {\r\n alertEngine: createCredential(`c33c0b79-6517-44f2-98bb-ad183eeb698d`, `Alert Engine`, `1c9b737d-b933-436f-97be-2c7946b2913d`),\r\n guest: createCredential(`d2d8c870-72a3-4dfb-bcc9-da64dc035f96`, `Guest`, `9b088cf9-c8ba-4f66-a462-7b1454bba53c`),\r\n jobProcessor: createCredential(`3bafdca3-4585-49a1-8ec4-547aca1db123`, `Job Processor`, `37d6157d-d8c4-4e45-919c-643beefafbb1`),\r\n messageBroker: createCredential(`f89c2a6a-46e2-4e0d-b17d-0d9bd4339b0e`, `Message Broker`, `b95fbe53-c5b9-4ad7-badc-4aee4b7c6ad9`),\r\n signalR: createCredential(`60f3fc47-7a75-4790-98f5-50b5717a5f97`, `SignalR`, `17a3c141-5541-40ff-adfe-0c3c9d257471`),\r\n jiraServiceDesk: createCredential(`2c15ab74-5d7b-4bbe-96f1-c6b54ef3b456`, `Jira Service Desk`, `47472d9a-5582-4dea-92f5-957e28a882eb`)\r\n };\r\n\r\n function createCredential(apiCredentialId, name, apiKey){\r\n return {\r\n apiCredentialId,\r\n name,\r\n apiKey\r\n };\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.alertService`, alertService);\r\n\r\n alertService.$inject = [`app.core.providers.alertDataProvider`, `app.core.models.alerts.WebAlert`, `lodash`, `app.core.datetime.timeZoneDateTime`];\r\n\r\n function alertService(endpointProvider, WebAlert, _, timeZoneDateTime) {\r\n\r\n return {\r\n getActiveWebAlerts,\r\n dismissWebAlert,\r\n getAlertsHistory\r\n };\r\n\r\n //////////////\r\n\r\n function getActiveWebAlerts() {\r\n return endpointProvider.getActiveWebAlerts().then(mapAlerts);\r\n }\r\n\r\n function dismissWebAlert(webAlertId) {\r\n return endpointProvider.dismissWebAlert(webAlertId);\r\n }\r\n\r\n function getAlertsHistory(queryObject) {\r\n\r\n const mappedQuery = queryObject && mapQueryObject(queryObject);\r\n return endpointProvider.getAlertsHistory(mappedQuery).then(success);\r\n\r\n function success(response) {\r\n response.data = _.map(response.alertLogHistory, datum => {\r\n return {\r\n dismissed: datum.utcDismissedTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(datum.utcDismissedTime)) : null,\r\n sentTime: timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(datum.utcTriggeredTime)),\r\n type: datum.alertDeliveryMethod,\r\n description: datum.description,\r\n message: datum.message\r\n };\r\n });\r\n return response;\r\n }\r\n }\r\n\r\n function mapQueryObject(queryObject) {\r\n const defaultQueryObject = {\r\n group: [],\r\n sort: [],\r\n filter: {\r\n filters: []\r\n }\r\n };\r\n\r\n defaultQueryObject.group = _.map(queryObject.group, group => {\r\n return {\r\n value: group.field === `sentTime` ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(group.value) : group.value,\r\n field: getFieldMapping(group.field)\r\n };\r\n });\r\n\r\n defaultQueryObject.sort = _.map(queryObject.sort, sort => {\r\n return {\r\n value: sort.field === `sentTime` ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(sort.value) : sort.value,\r\n field: getFieldMapping(sort.field)\r\n };\r\n });\r\n\r\n defaultQueryObject.filter.filters = _.map(queryObject.filter && queryObject.filter.filters, filter => {\r\n return {\r\n value: filter.field === `sentTime` ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(filter.value) : filter.value,\r\n field: getFieldMapping(filter.field)\r\n };\r\n });\r\n\r\n angular.merge(queryObject, defaultQueryObject);\r\n\r\n return queryObject;\r\n\r\n function getFieldMapping(field) {\r\n const fields = {\r\n dismissed: `UtcDismissedTime`,\r\n sentTime: `UtcTriggeredTime`,\r\n type: `AlertDeliveryMethod`,\r\n description: `Description`,\r\n message: `Message`\r\n };\r\n return _.get(fields, field);\r\n }\r\n }\r\n\r\n function mapAlerts(alerts) {\r\n if (!(alerts && alerts.length)) {\r\n return [];\r\n }\r\n\r\n return alerts.map(webAlert => {\r\n const triggerTime = new Date(webAlert.utcTriggeredTime);\r\n const sentTime = new Date(webAlert.utcSentTime);\r\n return new WebAlert(webAlert.id, webAlert.alertEventSourceId, webAlert.name, webAlert.message, webAlert.level, triggerTime, sentTime);\r\n });\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.appVersionService`, appVersionService);\r\n\r\n appVersionService.$inject = [`$log`, `$injector`, `notifier`, `app.core.appSettings`, `log4j`];\r\n\r\n function appVersionService($log, $injector, notifier, appSettings, log4j) {\r\n let notice, i18n;\r\n\r\n const service = {\r\n validate\r\n };\r\n\r\n return service;\r\n\r\n /////////////////////\r\n\r\n function validate(appVersion) {\r\n const isCurrentVersion = appSettings.appVersion === appVersion;\r\n const isNoticeDisplayed = notice && notice.state !== `closed`;\r\n\r\n if (isCurrentVersion || isNoticeDisplayed) {\r\n return;\r\n }\r\n\r\n // Injector was used to get dependency because injecting i18n directly will result into circular dependency.\r\n if (!i18n) {\r\n i18n = $injector.get(`i18n`);\r\n }\r\n\r\n $log.info(`EnviroSuite Application needs refreshing. Actual version: '${appSettings.appVersion}', expected version: '${appVersion}'.`);\r\n const msg = i18n.i10n(`version.message`);\r\n const title = i18n.i10n(`version.title`);\r\n\r\n if (msg !== `version.message` && title !== `version.title`) {\r\n notice = notifier.warning(msg, title, { hide: false } );\r\n }\r\n\r\n // disable the remote logging from the logger to avoid bombing the server with irrelevant log messages\r\n log4j.disableRemoteLogging();\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.blastingService`, blastingService);\r\n\r\n blastingService.$inject = [\r\n `lodash`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.providers.blastingDataProvider`,\r\n `app.core.providers.gisModelDataProvider`,\r\n `app.core.models.jobs.ModellingJob`,\r\n `app.core.models.mapping.dataPointType`,\r\n `app.core.models.mapping.dataPointFactory`,\r\n `app.core.models.legends.legendFactory`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.BlastScenario`,\r\n\r\n // Blast Models\r\n `app.core.models.blasting.DispersionModel`,\r\n `app.core.models.blasting.FumeManagementZoneModel`,\r\n `app.core.models.blasting.PathModel`,\r\n `app.core.models.blasting.OverpressureModel`,\r\n `app.core.models.blasting.FlyrockModel`,\r\n `app.core.models.blasting.GroundVibrationModel`\r\n ];\r\n\r\n function blastingService(_, timeZoneDateTime, dateTimeService, endpointProvider, jobDataProvider, ModellingJob,\r\n dataPointType, dataPointFactory, legendFactory, blastModelType, BlastScenario,\r\n DispersionModel, FumeManagementZoneModel, PathModel, OverpressureModel, FlyrockModel, GroundVibrationModel) {\r\n\r\n const millisPerMinute = 60 * 1000;\r\n\r\n return {\r\n getScenarios,\r\n getScenario,\r\n getBlastData,\r\n getOverlays,\r\n dismissJob: jobDataProvider.dismissJob,\r\n getStatus: jobDataProvider.getStatus\r\n };\r\n\r\n ////////////////////\r\n\r\n function getScenarios(queryObject = null) {\r\n const mappedQuery = mapQueryObject(queryObject);\r\n return endpointProvider.getScenarios(mappedQuery)\r\n .then(scenarios => {\r\n scenarios.data = _.map(scenarios.blastScenarioSummaries, scenario => {\r\n return {\r\n alias: scenario.alias,\r\n name: scenario.name,\r\n actualBlastTime: scenario.utcActualBlastTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(scenario.utcActualBlastTime)) : null,\r\n firstScenarioTime: scenario.utcFirstScenarioTime ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(scenario.utcFirstScenarioTime)) : null,\r\n lastUpdated: timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(scenario.utcLastUpdatedTime))\r\n };\r\n });\r\n return scenarios;\r\n })\r\n .catch(result => {\r\n throw new Error(result);\r\n });\r\n }\r\n \r\n function mapQueryObject(queryObject) {\r\n const defaultQueryObject = {\r\n group: [],\r\n sort: [],\r\n filter: {\r\n filters: []\r\n }\r\n };\r\n\r\n if (!queryObject) {\r\n return defaultQueryObject;\r\n }\r\n\r\n defaultQueryObject.group = _.map(queryObject.group, group => {\r\n return {\r\n value: group.field === `lastUpdated` ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(group.value) : group.value,\r\n field: getFieldMapping(group.field)\r\n };\r\n });\r\n\r\n defaultQueryObject.sort = _.map(queryObject.sort, sort => {\r\n return {\r\n value: sort.field === `lastUpdated` ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(sort.value) : sort.value,\r\n field: getFieldMapping(sort.field)\r\n };\r\n });\r\n\r\n defaultQueryObject.filter.filters = _.map(queryObject.filter && queryObject.filter.filters, filter => {\r\n return {\r\n value: filter.field === `lastUpdated` ? timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(filter.value) : filter.value,\r\n field: getFieldMapping(filter.field)\r\n };\r\n });\r\n\r\n angular.merge(queryObject, defaultQueryObject);\r\n\r\n return queryObject;\r\n\r\n function getFieldMapping(field) {\r\n const fields = {\r\n alias: `Alias`,\r\n name: `Name`,\r\n lastUpdated: `UtcLastUpdatedTime`\r\n };\r\n return _.get(fields, field);\r\n }\r\n }\r\n\r\n function getScenario(scenarioAlias) {\r\n return endpointProvider.getScenario(scenarioAlias).then(result => {\r\n const scenario = new BlastScenario(result.id, scenarioAlias, result.name);\r\n\r\n scenario.blastParameters = {\r\n latitude: result.latitude,\r\n longitude: result.longitude,\r\n\r\n blastWidth: result.width,\r\n blastLength: result.length,\r\n blastHeight: result.height,\r\n azimuth: result.azimuth,\r\n elevation: result.elevation,\r\n\r\n forwardTrajectoryScientificModel: result.forwardTrajectoryScientificModelDescription,\r\n windScientificModel: result.windScientificModelDescription,\r\n windScientificModelId: result.windScientificModelId,\r\n pollutant: result.pollutantDescription,\r\n pollutantId: result.modelPollutantId,\r\n pollutantScientificModel: result.pollutantScientificModelDescription,\r\n pollutantScientificModelId: result.pollutantScientificModelId,\r\n displayUnit: result.displayUnitDescription,\r\n displayUnitId: result.displayUnitId,\r\n initialConcentration: result.initialConcentrationGramsPerCubicMetre,\r\n\r\n blastSetup: result.blastSetup,\r\n chargeMass: result.chargeMass,\r\n chargeMassPerHole: result.chargeMassPerHole,\r\n holeDiameter: result.holeDiameter,\r\n burden: result.burden,\r\n stemmingHeight: result.stemmingHeight,\r\n frontFaceKFactor: result.frontFaceKFactor,\r\n backFaceKFactor: result.backFaceKFactor,\r\n\r\n flyrockSiteConstantKv: result.flyrockSiteConstantKv,\r\n holeAngle: result.holeAngle,\r\n dispersalAngle: result.dispersalAngle,\r\n\r\n groundVibrationSiteConstantKv: result.groundVibrationSiteConstantKv,\r\n groundVibrationSiteExponentKb: result.groundVibrationSiteExponentKb\r\n };\r\n\r\n scenario.models = _.chain(result.blastModels)\r\n .map(createBlastModel)\r\n .keyBy(`id`)\r\n .value();\r\n\r\n scenario.blastTimesMillis = result.utcBlastTimes.map(utcBlastTime => new Date(utcBlastTime).getTime());\r\n scenario.actualBlastTime = result.utcActualBlastTime\r\n ? timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(result.utcActualBlastTime))\r\n : null;\r\n\r\n return scenario;\r\n });\r\n\r\n ////////////////////\r\n\r\n function createBlastModel(blastModel) {\r\n const legends = blastModel.legends.map(legendFactory.create);\r\n switch (blastModel.modelType) {\r\n case blastModelType.path:\r\n return new PathModel(blastModel.id, legends);\r\n case blastModelType.dispersion:\r\n return new DispersionModel(blastModel.id, legends);\r\n case blastModelType.fmz:\r\n return new FumeManagementZoneModel(blastModel.id, legends);\r\n case blastModelType.gain:\r\n return new OverpressureModel(blastModel.id, blastModelType.gain, legends);\r\n case blastModelType.contour:\r\n return new OverpressureModel(blastModel.id, blastModelType.contour, legends);\r\n case blastModelType.flyrock:\r\n return new FlyrockModel(blastModel.id, legends);\r\n case blastModelType.groundVibration:\r\n return new GroundVibrationModel(blastModel.id, legends);\r\n }\r\n\r\n throw new Error(`Unsupported model type: ${blastModel.modelType}`);\r\n }\r\n }\r\n\r\n function getBlastData(scenarioAlias, modelType, blastTimeMillis) {\r\n return endpointProvider.getBlastData(scenarioAlias, modelType, blastTimeMillis).then(result => {\r\n return {\r\n activeJobForBlastModel: processActiveJob(result.activeJobBatch),\r\n availableBlastModelData: processAvailableData(result.modelData)\r\n };\r\n });\r\n\r\n ////////////////////\r\n\r\n function processActiveJob(jobData) {\r\n return jobData ? ModellingJob.createFromJobData(jobData) : null;\r\n }\r\n\r\n function processAvailableData(availableData) {\r\n if (!availableData) {\r\n return null;\r\n }\r\n\r\n switch (modelType) {\r\n case blastModelType.path:\r\n return processPathModelData(availableData);\r\n\r\n case blastModelType.dispersion:\r\n return processDispersionModelData(availableData);\r\n\r\n case blastModelType.fmz:\r\n return processFmzModelData(availableData);\r\n\r\n // No processing needed?\r\n case blastModelType.gain:\r\n case blastModelType.contour:\r\n case blastModelType.flyrock:\r\n case blastModelType.groundVibration:\r\n return availableData;\r\n }\r\n\r\n throw new Error(`Processing of ${modelType} model data is currently not supported.`);\r\n }\r\n\r\n function processPathModelData(availableData) {\r\n return {\r\n primaryTrack: createDataPoint(availableData.primaryTrack)\r\n };\r\n\r\n ////////////////////\r\n\r\n function createDataPoint(track) {\r\n return dataPointFactory.create(dataPointType.path, track.gisTrackDataTimeSteps);\r\n }\r\n }\r\n\r\n function processDispersionModelData(availableData) {\r\n return {\r\n plumes: createDataPoints(dataPointType.plume, availableData.plumes),\r\n windData: createDataPoints(dataPointType.wind, availableData.windData)\r\n };\r\n\r\n ////////////////////\r\n\r\n function createDataPoints(type, dataSet) {\r\n return dataSet.data.map(dataPointSource => {\r\n const dataPoint = dataPointFactory.create(type, dataPointSource);\r\n const offsetTimeMillis = new Date(dataPointSource.utcEndTime).getTime();\r\n dataPoint.offsetMinutes = (offsetTimeMillis - blastTimeMillis) / millisPerMinute;\r\n\r\n return dataPoint;\r\n });\r\n }\r\n }\r\n\r\n function processFmzModelData(availableData) {\r\n return {\r\n plume: createDataPoint(availableData.plumes)\r\n };\r\n\r\n ////////////////////\r\n\r\n function createDataPoint(dataSet) {\r\n // FMZ data looks like a dispersion with only a single time step. So even though the data is\r\n // an array, it should only contain a single element.\r\n if (dataSet.data.length !== 1) {\r\n throw new Error(`Unexpected data encountered when processing an FMZ model. Expected 1 data point, received ${dataSet.data.length}.`);\r\n }\r\n\r\n const dataPointSource = dataSet.data[0];\r\n const dataPoint = dataPointFactory.create(dataPointType.plume, dataPointSource);\r\n dataPoint.offsetMinutes = 0;\r\n\r\n return dataPoint;\r\n }\r\n }\r\n\r\n }\r\n\r\n function getOverlays(scenarioId) {\r\n return endpointProvider.getOverlays(scenarioId);\r\n }\r\n }\r\n})();\r\n","(function() {\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.companyService`, companyService);\r\n\r\n companyService.$inject = [\r\n `lodash`,\r\n `app.core.appSettings`,\r\n `app.core.providers.companyDataProvider`,\r\n `app.core.models.mapping.Boundary`\r\n ];\r\n\r\n function companyService(_, appSettings, companyDataProvider, Boundary) {\r\n let companiesPromise;\r\n\r\n return {\r\n getCompanies,\r\n getCompanyWithFacility,\r\n getFacilityDetails,\r\n getFacilityLocation,\r\n getDomainBoundaries,\r\n canAccessFacility\r\n };\r\n\r\n ////////////////////\r\n\r\n function getCompanies(options) {\r\n options = angular.extend({ refresh: false }, options || {});\r\n\r\n if (companiesPromise && !options.refresh) {\r\n return companiesPromise;\r\n }\r\n\r\n companiesPromise = companyDataProvider.getCompanies(appSettings.apiKey).then(companies => {\r\n const normalisedCompanies = {};\r\n\r\n _.forEach(companies, company => {\r\n const facilities = _.map(company.facilities, facility => angular.extend({},\r\n facility,\r\n {\r\n companyId: company.id,\r\n es1RouteName: facility.es1RouteName,\r\n searchTerms: `${company.name} ${company.alias} ${facility.name} ${facility.alias}`\r\n }\r\n ));\r\n\r\n delete company.es1RouteName;\r\n\r\n if (!_.has(normalisedCompanies, company.alias)) {\r\n normalisedCompanies[company.alias] = angular.extend({},\r\n company,\r\n { facilities }\r\n );\r\n\r\n } else {\r\n const existingFacilities = normalisedCompanies[company.alias].facilities;\r\n\r\n normalisedCompanies[company.alias] = angular.extend({},\r\n normalisedCompanies[company.alias],\r\n { facilities: [...existingFacilities, ...facilities] }\r\n );\r\n }\r\n });\r\n\r\n return _.values(normalisedCompanies);\r\n });\r\n\r\n return companiesPromise;\r\n }\r\n\r\n function getCompanyWithFacility(companyAlias, facilityAlias) {\r\n return getCompanies().then(companies => {\r\n return _.chain(companies)\r\n .filter(matchingCompany)\r\n .map(company => {\r\n const facility = _.find(company.facilities, matchingFacility);\r\n if (!facility) {\r\n return null;\r\n }\r\n\r\n const companyWithFacility = {\r\n ...company,\r\n facility,\r\n\r\n // Cater for the normalisation process where facilities from one company may have\r\n // been merged with the facilities from another company.\r\n id: facility.companyId\r\n };\r\n\r\n delete companyWithFacility.facilities;\r\n return companyWithFacility;\r\n })\r\n .find(company => company && company.facility)\r\n .value();\r\n });\r\n\r\n ////////////////////\r\n\r\n function matchingCompany(company) {\r\n return companyAlias && company.alias.toLowerCase() === companyAlias.toLowerCase();\r\n }\r\n\r\n function matchingFacility(facility) {\r\n return facilityAlias && facility.alias.toLowerCase() === facilityAlias.toLowerCase();\r\n }\r\n }\r\n\r\n function getFacilityDetails(companyAlias, facilityAlias) {\r\n return getCompanyWithFacility(companyAlias, facilityAlias).then(company => company && company.facility);\r\n }\r\n\r\n function getFacilityLocation() {\r\n return companyDataProvider.getFacilityLocation().then(location => {\r\n return {\r\n lat: location.latitude,\r\n lng: location.longitude,\r\n zoom: location.zoom\r\n };\r\n });\r\n }\r\n\r\n function getDomainBoundaries(showModelling, showBlasting, showIncidentIntelligence){\r\n return companyDataProvider.getDomainBoundaries().then(boundaries => {\r\n const filteredBoundaries = boundaries.filter(boundary => showModelling && boundary.isSourceForModelling\r\n || showBlasting && boundary.isSourceForBlasting\r\n || showIncidentIntelligence && boundary.isSourceForIncidentIntelligence\r\n );\r\n return filteredBoundaries.map(boundary => new Boundary(boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight));\r\n });\r\n }\r\n\r\n function canAccessFacility(companyAlias, facilityAlias) {\r\n return getCompanyWithFacility(companyAlias, facilityAlias).then(company => {\r\n return company != null && company.facility != null;\r\n });\r\n }\r\n\r\n }\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .factory(`app.core.services.configuration.blastingService`, blastingService);\n\n blastingService.$inject = [\n `lodash`,\n `app.core.models.blasting.blastModelType`,\n `app.core.models.blasting.blastSetup`,\n `app.core.providers.configuration.blastingDataProvider`,\n `app.core.providers.configuration.gisModelDataProvider`\n ];\n\n //TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\n /* istanbul ignore next */\n function blastingService(_, blastModelType, blastSetup, blastingDataProvider, gisModelDataProvider) {\n return {\n getAllScenarios,\n getScenario,\n deleteScenario,\n updateActualBlastTime,\n getModelTypes,\n getModelOptions,\n getAddOverlayUrl,\n getOverlayFiles,\n deleteOverlayFile,\n isNOxPollutant,\n getValidScenarioAlias,\n createScenario,\n getOverlayFile\n };\n\n ////////////\n\n function hashToNamedObjectArray(keyName = `id`) {\n return hash =>\n _.chain(hash)\n .map((name, id) => ({ name, [keyName]: id }))\n .sortBy(`name`)\n .value();\n }\n\n function getAllScenarios() {\n return blastingDataProvider.getAllScenarios().then(hashToNamedObjectArray(`scenarioId`));\n }\n\n function getScenario(scenarioAlias) {\n return blastingDataProvider.getScenario(scenarioAlias);\n }\n\n function deleteScenario(scenarioAlias) {\n return blastingDataProvider.deleteScenario(scenarioAlias);\n }\n\n function updateActualBlastTime(scenarioAlias, actualBlastTime) {\n return blastingDataProvider.updateActualBlastTime(scenarioAlias, actualBlastTime);\n }\n\n function getModelTypes() {\n return blastingDataProvider.getModelTypes()\n .then(modelTypes => {\n _.map(modelTypes, (config, key, source) => {\n source[key] = config && JSON.parse(config);\n });\n return modelTypes;\n });\n }\n\n function getDefaultConcentrations()\n {\n const defaultConcentrations = new Map();\n\n // Total Suspended Particulates (TSP)\n defaultConcentrations.set(`B8382C5A-AC52-4E67-93CA-755BF38F0295`, 0.054);\n\n // Particulate Matter 10 µm (PM10)\n defaultConcentrations.set(`106C9CC9-5C5E-4758-B384-1340DC93D578`, 0.054);\n\n return defaultConcentrations;\n }\n\n function getModelOptions() {\n return gisModelDataProvider.getOptions()\n .then(modelOptions => {\n\n const pollutantOptions = modelOptions.plumeGisModelOptions.pollutantOptions.map(pollutantOption => {\n pollutantOption.modelPollutantDisplayName = `${pollutantOption.modelPollutantName} (${pollutantOption.modelPollutantShortName})`;\n\n return pollutantOption;\n });\n\n return {\n windGisModelOptions: {\n displayUnitOptions : modelOptions.windGisModelOptions.displayUnitOptions,\n windScientificModels : modelOptions.windGisModelOptions.windScientificModels.filter(model => model.isSourceForBlasting)\n },\n forwardTrajectoryModelOptions: modelOptions.forwardTrajectoryModelOptions,\n pollutantGisModelOptions: {\n pollutantOptions,\n defaultConcentrations: getDefaultConcentrations(),\n noxScale: [\n //https://www.dnrm.qld.gov.au/__data/assets/pdf_file/0010/212500/qld-guidance-note-20-mgmt-oxides-nitrogen.pdf\n {\n level: 0,\n ppm: 2,\n gramsPerCubicMetre: 3.8e-3,\n description: `Level 0 - No fume`,\n colour: `#F4DED9`\n },\n {\n level: 1,\n ppm: 4,\n gramsPerCubicMetre: 7.5e-3,\n description: `Level 1 - Fume`,\n colour: `#F4DBAA`\n },\n {\n level: 2,\n ppm: 7,\n gramsPerCubicMetre: 1.32e-2,\n description: `Level 2 - Minor yellow / orange fume`,\n colour: `#EDA04F`\n },\n {\n level: 3,\n ppm: 17,\n gramsPerCubicMetre: 3.2e-2,\n description: `Level 3 - Moderate orange fume`,\n colour: `#E87511`\n },\n {\n level: 4,\n ppm: 70,\n gramsPerCubicMetre: 1.316e-1,\n description: `Level 4 - Significant orange fume`,\n colour: `#B55400`\n },\n {\n level: 5,\n ppm: 500,\n gramsPerCubicMetre: 0.94,\n description: `Level 5 - Major red / purple fume`,\n colour: `#633A11`\n }\n ]\n }\n };\n });\n }\n\n function getAddOverlayUrl(scenarioId) {\n return blastingDataProvider.getAddOverlayUrl(scenarioId);\n }\n\n function getOverlayFiles(scenarioId) {\n return blastingDataProvider.getOverlayFiles(scenarioId).then(response => {\n return _.map(response, overlayFile => {\n // See: https://github.com/nervgh/angular-file-upload/issues/211\n return {\n name: overlayFile.name,\n size: overlayFile.length,\n dateModified: new Date(overlayFile.utcLastModifiedDateTime),\n type: overlayFile.type\n };\n });\n });\n }\n\n function deleteOverlayFile(scenarioId, fileName) {\n return blastingDataProvider.deleteOverlayFile(scenarioId, fileName);\n }\n\n function getOverlayFile(fileName) {\n return blastingDataProvider.getOverlayFile(fileName);\n }\n\n function isNOxPollutant(pollutantId) {\n return pollutantId && pollutantId.toUpperCase() === `B183985A-F356-4204-87E7-246A95EC3315`;\n }\n\n function getValidScenarioAlias(alias) {\n return blastingDataProvider.getValidScenarioAlias(alias);\n }\n\n function createScenario(scenarioData) {\n const scenario = {\n name: scenarioData.name,\n alias: scenarioData.alias,\n latitude: scenarioData.latitude,\n longitude: scenarioData.longitude,\n\n utcBlastTimes: scenarioData.blastTimesMillis.map(blastTimeMillis => new Date(blastTimeMillis).toISOString()),\n modelTypes: _.chain(scenarioData.models)\n .pickBy(isSelected => isSelected)\n .map((isSelected, modelType) => blastModelType[modelType])\n .value(),\n\n // Path and pollutant model properties\n height: scenarioData.blastHeight,\n windScientificModelId: scenarioData.windScientificModelId,\n\n // Pollutant and overpressure model properties\n azimuth: scenarioData.azimuth,\n elevation: scenarioData.elevation,\n\n // Path model specific properties\n forwardTrajectoryScientificModelId: scenarioData.forwardTrajectoryScientificModelId,\n\n // Pollutant model specific properties\n modelPollutantId: scenarioData.modelPollutantId,\n pollutantScientificModelId: scenarioData.pollutantScientificModelId,\n displayUnitId: scenarioData.displayUnitId,\n initialConcentrationGramsPerCubicMetre: scenarioData.initialConcentration,\n length: scenarioData.blastLength,\n width: scenarioData.blastWidth,\n\n // Overpressure model specific properties\n blastSetup: scenarioData.blastSetup,\n holeDiameter: scenarioData.holeDiameter,\n frontFaceKFactor: scenarioData.frontFaceKFactor,\n backFaceKFactor: scenarioData.backFaceKFactor,\n chargeMass: scenarioData.chargeMass,\n\n // Flyrock\n holeAngle: scenarioData.holeAngle,\n dispersalAngle: scenarioData.dispersalAngle,\n flyrockSiteConstantKv: scenarioData.flyrockSiteConstantKv,\n\n // Overpressure & Flyrock properties\n burden: scenarioData.burden,\n stemmingHeight: scenarioData.stemmingHeight,\n\n // Ground Vibration\n chargeMassPerHole: scenarioData.chargeMassPerHole,\n groundVibrationSiteConstantKv: scenarioData.groundVibrationSiteConstantKv,\n groundVibrationSiteExponentKb: scenarioData.groundVibrationSiteExponentKb\n };\n\n if (scenarioData.isGroundVibrationSelected) {\n scenario.pointsOfInterest = scenarioData.groundVibrationPois;\n }\n\n if (scenarioData.blastSetup === blastSetup.stemming) {\n scenario.backFaceKFactor = scenario.frontFaceKFactor;\n }\n\n return blastingDataProvider.createScenario(scenario);\n }\n }\n})();\n","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .factory(`app.core.services.configuration.gisModelService`, gisModelService);\n\n gisModelService.$inject = [\n `lodash`,\n `i18n`,\n `app.core.providers.configuration.gisModelDataProvider`\n ];\n\n function gisModelService(_, i18n, gisModelDataProvider) {\n const service = {\n getEmissionsDataFileUploadUrl: gisModelDataProvider.getEmissionsDataFileUploadUrl,\n getExistingEmissionsDataFiles: gisModelDataProvider.getExistingEmissionsDataFiles,\n getAll: getAllModels,\n get: gisModelDataProvider.getModel,\n getOptions: getModellingOptions,\n getCalpuffConfigs: gisModelDataProvider.getCalpuffConfigs,\n remove: gisModelDataProvider.remove,\n addPlume: gisModelDataProvider.addPlume,\n addWind: gisModelDataProvider.addWind,\n importEmissionsData: gisModelDataProvider.importEmissionsData,\n updatePlume: updatePlume,\n updateWind: updateWind,\n deleteEmissionsDataFiles: gisModelDataProvider.deleteEmissionsDataFiles\n };\n\n return service;\n\n ////////////////////\n\n function getModellingOptions() {\n return gisModelDataProvider.getOptions().then(options => {\n const pollutants = _.chain(options.plumeGisModelOptions.pollutantOptions)\n .map(option => ({\n modelPollutantId: option.modelPollutantId,\n modelPollutantName: option.modelPollutantName,\n modelPollutantShortName: option.modelPollutantShortName,\n modelPollutantDisplayName: option.modelPollutantShortName\n ? `${option.modelPollutantName} (${option.modelPollutantShortName})`\n : option.modelPollutantName,\n displayUnits: option.displayUnitOptions,\n scientificModels: _.sortBy(option.associatedPlumeScientificModels, `name`)\n }))\n .sortBy(`modelPollutantName`)\n .value();\n\n const windScientificModels = _.chain(options.windGisModelOptions.windScientificModels.filter(model => model.isSourceForModelling))\n .map(windScientificModel => ({\n name: generateNameForScientificModel(windScientificModel),\n id: windScientificModel.id,\n intervalDurationInMinutes: windScientificModel.intervalDurationInMinutes\n }))\n .sortBy(`name`)\n .value();\n\n return {\n plumeOptions: {\n pollutants,\n windScientificModels: windScientificModels\n },\n windOptions: {\n displayUnits: options.windGisModelOptions.displayUnitOptions,\n scientificModels: windScientificModels\n }\n };\n });\n }\n\n function generateNameForScientificModel(windScientificModel) {\n const i10n = key => i18n.i10n(`app.core.services.configuration.gisModelService.scientificModelName.${key}`);\n return `${windScientificModel.name} - ${windScientificModel.intervalDurationInMinutes} ${i10n(`minutes`)} - ${i10n(windScientificModel.isPredictive ? `predictive` : `historical`)}`;\n }\n\n function getAllModels() {\n return gisModelDataProvider.getAll().then(hashToNamedObjectArray(`modelId`));\n }\n\n function hashToNamedObjectArray(keyName = `id`) {\n return hash =>\n _.chain(hash)\n .map((name, id) => ({ name, [keyName]: id }))\n .sortBy(`name`)\n .value();\n }\n\n function updatePlume(plumeData) {\n return gisModelDataProvider.updatePlume(plumeData).then(() => plumeData.id);\n }\n\n function updateWind(windData) {\n return gisModelDataProvider.updateWind(windData).then(() => windData.id);\n }\n }\n})();\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.configuration.legacyLookupService`, lookupService);\r\n\r\n lookupService.$inject =\r\n [\r\n `lodash`,\r\n `app.core.providers.configuration.legacyLookupDataProvider`\r\n ];\r\n\r\n function lookupService(_, lookupDataProvider) {\r\n return {\r\n getWindowsTimeZones\r\n };\r\n\r\n //////////////////\r\n\r\n function getWindowsTimeZones() {\r\n return lookupDataProvider.getWindowsTimeZones()\r\n .then(timeZones => {\r\n return _.map(timeZones, timeZone => {\r\n return {\r\n id: timeZone.Id,\r\n description: timeZone.DisplayName\r\n };\r\n });\r\n });\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.configuration.measurementGroupService`, measurementGroupService);\r\n\r\n measurementGroupService.$inject =\r\n [\r\n `lodash`,\r\n `app.core.providers.configuration.measurementGroupDataProvider`\r\n ];\r\n\r\n function measurementGroupService(_, measurementGroupDataProvider) {\r\n return {\r\n getMeasurementGroupsFlattened,\r\n getMeasurementGroupsNested,\r\n queryMeasurementGroups: measurementGroupDataProvider.queryMeasurementGroups,\r\n getMeasurementGroup: measurementGroupDataProvider.getMeasurementGroup,\r\n createMeasurementGroup: measurementGroupDataProvider.createMeasurementGroup,\r\n updateMeasurementGroup,\r\n isMeasurementGroupBeingUsed: measurementGroupDataProvider.isMeasurementGroupBeingUsed,\r\n getMeasurementGroupChildCount,\r\n deleteMeasurementGroup: measurementGroupDataProvider.deleteMeasurementGroup\r\n };\r\n\r\n function getMeasurementGroupsFlattened(sortBy = mg => mg.defaultOrder) {\r\n return measurementGroupDataProvider.getAllMeasurementGroups()\r\n .then(measurementGroups => _.sortBy(measurementGroups, sortBy));\r\n }\r\n\r\n function getMeasurementGroupsNested(sortBy = mg => mg.defaultOrder) {\r\n return measurementGroupDataProvider.getAllMeasurementGroups()\r\n .then(measurementGroups => {\r\n const byId = _.reduce(measurementGroups, (map, mg) => map.set(mg.id, mg), new Map());\r\n\r\n const parents = [];\r\n\r\n _.forEach(measurementGroups, mg => {\r\n if (!mg.parentId) {\r\n parents.push(mg);\r\n\r\n } else {\r\n const parent = byId.get(mg.parentId);\r\n parent.children = parent.children && [...parent.children, mg] || [mg];\r\n }\r\n });\r\n\r\n _.forEach(parents, parent => {\r\n if (parent.children) {\r\n parent.children = _.sortBy(parent.children, sortBy);\r\n }\r\n });\r\n\r\n return _.sortBy(parents, sortBy);\r\n });\r\n }\r\n\r\n function updateMeasurementGroup(measurementGroup) {\r\n return measurementGroupDataProvider.updateMeasurementGroup(measurementGroup).then(() => measurementGroup.id);\r\n }\r\n\r\n function getMeasurementGroupChildCount() {\r\n return measurementGroupDataProvider.getMeasurementGroupChildCount();\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.configuration.modellingService`, modellingService);\r\n\r\n modellingService.$inject = [\r\n `app.core.providers.configuration.modellingDataProvider`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function modellingService(modellingDataProvider, dateTimeService) {\r\n const service = {\r\n getWrfConfiguration: modellingDataProvider.getWrfConfiguration,\r\n runCalModelling: runCalModelling,\r\n runAerModelling: modellingDataProvider.runAerModelling\r\n };\r\n\r\n ////////////\r\n\r\n function runCalModelling(configurationName, forecastDate, forecastRun) {\r\n if (!configurationName) {\r\n throw new Error(`configurationName is not defined`);\r\n }\r\n\r\n if (!forecastRun) {\r\n throw new Error(`forecastRun is not defined`);\r\n }\r\n\r\n forecastDate = dateTimeService.formatAs.utcDate(forecastDate || new Date());\r\n\r\n return modellingDataProvider.runCalModelling(configurationName, forecastDate, forecastRun);\r\n }\r\n\r\n return service;\r\n }\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .factory(`app.core.services.configuration.monitoringService`, configurationMonitoringService);\n\n configurationMonitoringService.$inject = [\n `lodash`,\n `app.core.providers.configuration.monitoringDataProvider`\n ];\n\n function configurationMonitoringService(_, monitoringDataProvider) {\n const service = {\n // monitors\n getMonitorType: getMonitorType,\n getMonitorTypes: getMonitorTypes,\n getMonitorTypeIcon: getMonitorTypeIcon,\n getMonitor: monitoringDataProvider.getMonitor,\n getMonitors: getMonitors,\n getUpperAirWeatherStations: getUpperAirWeatherStations,\n getSurfaceWeatherStations: getSurfaceWeatherStations,\n getMonitorDisplay: getMonitorDisplay,\n getMonitorLocation: monitoringDataProvider.getMonitorLocation,\n queryMonitors: queryMonitors,\n\n updateMonitorDisplay: monitoringDataProvider.updateMonitorDisplay,\n setDefaultMetStation: monitoringDataProvider.setDefaultMetStation,\n getAllMetStations: monitoringDataProvider.getAllMetStations,\n\n createMonitor: monitoringDataProvider.createMonitor,\n updateMonitor: updateMonitor,\n\n // measurement types\n getMeasurementType: getMeasurementType,\n getMeasurementTypeConfigurationOptions: getMeasurementTypeConfigurationOptions,\n queryMonitorMeasurementTypes: monitoringDataProvider.queryMonitorMeasurementTypes,\n createMeasurementType: createMeasurementType,\n updateMeasurementType: updateMeasurementType,\n\n genericMeasurementTypeCategoryId: 4 // see Enum.cs -> VariableDataType\n };\n\n return service;\n\n ////////////\n function getMonitorType(monitorId) {\n return monitoringDataProvider.getMonitorType(monitorId).then(_.camelCase);\n }\n\n function getMonitorTypes() {\n // eg. response -> { type: `ambientMonitor`, name: `Ambient Monitor`, icon: `circle thin` }\n return monitoringDataProvider.getMonitorTypes().then(monitorTypes => {\n return _.map(hashToNamedObjectArray(`type`)(monitorTypes), monitorType => {\n monitorType.icon = service.getMonitorTypeIcon(monitorType.type);\n return monitorType;\n });\n });\n }\n\n function getMonitorTypeIcon(monitorType) {\n switch (monitorType) {\n case `ambientMonitor`:\n return `icon icons8-air-quality-filled`;\n case `noiseMonitor`:\n return `icon icons8-headphones-filled`;\n case `surfaceWeatherStation`:\n return `icon icons8-wind-gauge-filled`;\n case `upperAirWeatherStation`:\n return `icon icons8-wind-gauge-filled`;\n case `surfaceWaterMonitor`:\n return `icon icons8-water-filled`;\n case `groundWaterMonitor`:\n return `icon icons8-piping-filled`;\n case `soilMonitor`:\n return `icon icons8-sprout-filled`;\n case `discreteReceptor`:\n return `fa fa-cube`;\n case `vibrationMonitor`:\n return `fa fa-bullseye`;\n }\n }\n\n function getMonitors(whereVisible) {\n return monitoringDataProvider.getMonitors(whereVisible).then(hashToNamedObjectArray(`monitorId`));\n }\n\n function getUpperAirWeatherStations() {\n return monitoringDataProvider.getUpperAirWeatherStations().then(monitors => {\n return _.map(monitors, monitor => ({ name: monitor.name, id: monitor.id }));\n });\n }\n\n function getSurfaceWeatherStations() {\n return monitoringDataProvider.getSurfaceWeatherStations().then(monitors => {\n return _.map(monitors, monitor => ({ name: monitor.name, id: monitor.id }));\n });\n }\n\n function getMonitorDisplay(monitorId) {\n return monitoringDataProvider.getMonitorDisplay(monitorId).then(result => {\n _.forEach(result.availableVariables, pv => pv.measurementGroupId = null);\n return result;\n });\n }\n\n function queryMonitors(searchCriteria) {\n return monitoringDataProvider.queryMonitors(searchCriteria).then(mapResults);\n\n function mapResults(result) {\n result.data = _.map(result.data, monitor => {\n monitor.type = _.camelCase(monitor.type);\n monitor.icon = service.getMonitorTypeIcon(monitor.type);\n return monitor;\n });\n return result;\n }\n }\n\n function updateMonitor(monitorType, monitor) {\n return monitoringDataProvider.updateMonitor(monitorType, monitor).then(() => monitor.id);\n }\n\n function getMeasurementType(measurementTypeId) {\n return monitoringDataProvider\n .getMeasurementType(measurementTypeId)\n .then(result => fromConfigureProcessVariableRequest(result));\n }\n\n function getMeasurementTypeConfigurationOptions() {\n return monitoringDataProvider.getMeasurementTypeConfigurationOptions().then(result => {\n const aggregateTypeIds = _.keys(result.aggregateTypes);\n const aggregateTypes = _.map(aggregateTypeIds, aggregateTypeId => {\n return {\n type: parseInt(aggregateTypeId),\n name: result.aggregateTypes[aggregateTypeId]\n };\n });\n\n return {\n aggregateTypes: aggregateTypes,\n units: result.units,\n pollutants: result.pollutants,\n measurementTypeCategories: result.processVariableCategories\n };\n });\n }\n\n function updateMeasurementType(measurementType) {\n const payload = toConfigureProcessVariableRequest(measurementType);\n return monitoringDataProvider\n .updateMeasurementType(payload)\n .then(() => payload.processVariable.id);\n }\n\n function createMeasurementType(measurementType) {\n const payload = toConfigureProcessVariableRequest(measurementType);\n return monitoringDataProvider\n .createMeasurementType(payload)\n .then(result => result);\n }\n\n function hashToNamedObjectArray(keyName = `id`) {\n return hash =>\n _.chain(hash)\n .map((name, id) => ({ name, [keyName]: id }))\n .sortBy(`name`)\n .value();\n }\n\n function fromConfigureProcessVariableRequest(result) {\n const {\n pollutantId,\n defaultDisplayUnitId,\n defaultImportUnitId,\n dataType,\n samplingRateMillis,\n exceedanceThresholds,\n ...rest\n } = result;\n\n const mappedExceedanceThresholds = exceedanceThresholds\n .map(threshold => {\n const {\n color,\n ...rest\n } = threshold;\n\n return {\n ...rest,\n hexColor: intToHexColor(color)\n };\n });\n\n return {\n ...rest,\n exceedanceThresholds: mappedExceedanceThresholds,\n pollutantId: getGuid(pollutantId),\n defaultDisplayUnitId: getGuid(defaultDisplayUnitId),\n defaultImportUnitId: getGuid(defaultImportUnitId),\n categoryId: dataType || service.genericMeasurementTypeCategoryId,\n samplingRateSeconds: samplingRateMillis / 1000\n };\n\n function getGuid(guid) {\n return guid === `00000000-0000-0000-0000-000000000000` ? null : guid;\n }\n }\n\n function toConfigureProcessVariableRequest(measurementType) {\n const {\n monitorId,\n samplingRateSeconds,\n categoryId,\n exceedanceThresholds,\n ...rest\n } = measurementType;\n\n const mappedExceedanceThresholds = exceedanceThresholds\n .map(threshold => {\n const {\n hexColor,\n ...rest\n } = threshold;\n\n return {\n ...rest,\n color: hexColorToInt(hexColor)\n };\n });\n\n return {\n processVariable: {\n ...rest,\n exceedanceThresholds: mappedExceedanceThresholds,\n samplingRateMillis: samplingRateSeconds * 1000,\n dataType: categoryId,\n processId: monitorId\n }\n };\n }\n\n function hexColorToInt(hex) {\n return parseInt(hex.substr(1), 16);\n }\n\n function intToHexColor(int) {\n /* eslint-disable no-bitwise */\n return `#` + (int >>> 0).toString(16).slice(-6);\n }\n }\n})();\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`confirmationDialog`, confirmationDialog);\r\n\r\n confirmationDialog.$inject = [`$modal`, `i18n`, `lodash`];\r\n function confirmationDialog($modal, i18n, _) {\r\n\r\n const defaultOptions = {\r\n buttons: {\r\n cancel: {\r\n cssClass : `btn-default`,\r\n text: `buttons.cancel`\r\n },\r\n 'continue' : {\r\n text: `buttons.continue`\r\n }\r\n }\r\n };\r\n\r\n return {\r\n ask,\r\n notify,\r\n error\r\n };\r\n\r\n function ask(title, body, options = {}) {\r\n return buildDialog(title, body, options, `/App/core/services/confirmationDialog.html`);\r\n }\r\n\r\n function notify(title, body, options = {}) {\r\n return buildDialog(title, body, options, `/App/core/services/notifyDialog.html`);\r\n }\r\n\r\n function error() {\r\n const buttons = {\r\n reload: {\r\n text: i18n.i10n(`buttons.reload`),\r\n onClick: () => window.location.reload(true)\r\n },\r\n contactSupport: {\r\n text: i18n.i10n(`buttons.support`),\r\n onClick: () => window.location.href = `mailto:cms@envirosuite.com?subject=Envirosuite Application Errors`\r\n }\r\n };\r\n return buildDialog(\r\n i18n.i10n(`errors.fatal.title`),\r\n i18n.i10n(`errors.fatal.message`),\r\n { buttons },\r\n `/App/core/services/errorDialog.html`);\r\n }\r\n\r\n function buildDialog(title, body, options, templateUrl) {\r\n localiseDefaultOptionsButtonText();\r\n\r\n return $modal.open({\r\n templateUrl: templateUrl,\r\n backdrop: true,\r\n controller: getDialogController(title, body, Object.assign({}, defaultOptions, options)),\r\n size: `md`,\r\n animation: false\r\n }).result;\r\n\r\n //////////////////\r\n\r\n function localiseDefaultOptionsButtonText() {\r\n _.forEach(defaultOptions.buttons, value => {\r\n value.text = i18n.i10n(value.text);\r\n });\r\n }\r\n }\r\n\r\n function getDialogController(title, body, options) {\r\n\r\n confirmationDialogController.$inject = [`$scope`, `$modalInstance`];\r\n function confirmationDialogController($scope, $modalInstance) {\r\n $scope.title = title;\r\n $scope.body = body;\r\n $scope.$modalInstance = $modalInstance;\r\n $scope.options = options;\r\n }\r\n\r\n return confirmationDialogController;\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.dashboardService`, dashboardService);\r\n\r\n dashboardService.$inject = [\r\n `$log`,\r\n `$state`,\r\n `browserStorage`,\r\n `lodash`,\r\n `notifier`,\r\n `app.core.appSettings`,\r\n `i18n`,\r\n `dashboard`\r\n ];\r\n function dashboardService($log, $state, browserStorage, _, notifier, appSettings, i18n, dashboard) {\r\n const dashboardLayoutStorageKey = `dashboard-layout`;\r\n const accessibleWidgetStorageKey = `dashboard-widgets`;\r\n\r\n return {\r\n getDashboard,\r\n persistDashboard,\r\n deleteDashboard,\r\n canAccessWidget\r\n };\r\n\r\n //////////////\r\n\r\n function getDashboard() {\r\n const { accessibleWidgets, newWidgets } = getWidgets();\r\n\r\n const persistedDashboardConfiguration = browserStorage.getBucket(dashboardLayoutStorageKey, getStorageBucketKey());\r\n if (!persistedDashboardConfiguration) {\r\n return _.assign(buildDefaultDashboard(), { supportsLayouts: getDefaultNumberOfLayoutColumns() > 1 });\r\n }\r\n\r\n updateDeviceWidgets(persistedDashboardConfiguration);\r\n\r\n if (newWidgets.length) {\r\n persistedDashboardConfiguration.newWidgetsAreAvailable = {\r\n onUserHasViewed: () => {\r\n delete persistedDashboardConfiguration.newWidgetsAreAvailable;\r\n persistWidgetList(accessibleWidgets);\r\n }\r\n };\r\n }\r\n\r\n return _.assign(persistedDashboardConfiguration, { supportsLayouts: getDefaultNumberOfLayoutColumns() > 1 });\r\n\r\n //////////////\r\n\r\n function getWidgets() {\r\n const previousAccessibleWidgets = browserStorage.getBucket(accessibleWidgetStorageKey, getStorageBucketKey()) || [];\r\n\r\n const accessibleWidgets = _.chain(dashboard.widgets)\r\n .map(accessorizeWidget)\r\n .filter(canAccessWidget)\r\n .forEach(validate)\r\n .value();\r\n\r\n if (!previousAccessibleWidgets.length) { // first time this dashboard has been accessed\r\n persistWidgetList(accessibleWidgets);\r\n }\r\n\r\n return {\r\n accessibleWidgets,\r\n newWidgets: _.filter(accessibleWidgets, accessibleWidget => accessibleWidget.isNew)\r\n };\r\n\r\n //////////////\r\n\r\n function accessorizeWidget(widget, widgetType) {\r\n widget.type = widgetType;\r\n widget.isNew = previousAccessibleWidgets.length && !_.find(previousAccessibleWidgets, type => widget.type === type);\r\n widget.onClick = widget.route ? () => $state.go(widget.route, {\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias,\r\n dateTime: $state.params.dateTime\r\n }) : angular.noop;\r\n\r\n return widget;\r\n }\r\n\r\n function validate(widget) {\r\n validateMajorVersion();\r\n validateMinorVersion();\r\n\r\n ///////////\r\n\r\n function validateMajorVersion() {\r\n const majorVersion = widget.majorVersion;\r\n if (_.isNull(majorVersion) || _.isUndefined(majorVersion)) {\r\n widget.majorVersion = 1;\r\n } else {\r\n if (Number(majorVersion) !== parseInt(majorVersion) || parseInt(majorVersion, 10) < 1) {\r\n throw new Error(`The '${widget.type}' widget must have an integer major version greater than or equal to 1`);\r\n }\r\n widget.majorVersion = parseInt(majorVersion, 10);\r\n }\r\n }\r\n\r\n function validateMinorVersion() {\r\n const minorVersions = widget.minorVersions;\r\n if (!_.isObject(minorVersions) || _.isEmpty(minorVersions)) {\r\n return;\r\n }\r\n\r\n _.chain(_.keys(minorVersions))\r\n .map(mv => {\r\n const minorVersion = parseInt(mv, 10);\r\n if (_.isNaN(minorVersion)) {\r\n throw new Error(`The minor version key '${mv}' must be parsable to an integer`);\r\n }\r\n\r\n return minorVersion;\r\n })\r\n .sortBy(minorVersion => minorVersion)\r\n .tap(minorVersions => widget.minorVersionNumbers = minorVersions)\r\n .reduce((previous, current) => {\r\n if (previous + 1 !== current) {\r\n throw new Error(`The minor version is not the next in sequence - prev: ${previous} current: ${current}`);\r\n }\r\n if (!_.isFunction(minorVersions[current])) {\r\n throw new Error(`The minor version upgrader must be a function.`);\r\n }\r\n return current;\r\n }, 0)\r\n .value();\r\n }\r\n }\r\n }\r\n\r\n function buildDefaultDashboard() {\r\n return {\r\n isDefault: true,\r\n titleTemplateUrl: `/App/ui/features/dashboard/DashboardActions.html`,\r\n addTemplateUrl: `/App/ui/features/dashboard/WidgetAdd.html`,\r\n structure: `default`,\r\n rows: [\r\n {\r\n columns: getDefaultColumnLayout()\r\n }\r\n ]\r\n };\r\n\r\n ////////////////////\r\n\r\n function getDefaultColumnLayout() {\r\n if (getDefaultNumberOfLayoutColumns() === 1) {\r\n return [\r\n {\r\n styleClass: `col-md-12`,\r\n widgets: filterAccessibleWidgets()\r\n }\r\n ];\r\n } else {\r\n return [\r\n {\r\n styleClass: `col-md-6`,\r\n widgets: filterAccessibleWidgets((widget, index) => index % 2 === 0)\r\n },\r\n {\r\n styleClass: `col-md-6`,\r\n widgets: filterAccessibleWidgets((widget, index) => index % 2 !== 0)\r\n }];\r\n }\r\n }\r\n\r\n function filterAccessibleWidgets(filter = () => true) {\r\n return _.chain(accessibleWidgets)\r\n .filter(filter)\r\n .map(newWidget)\r\n .value();\r\n\r\n ////////////\r\n\r\n function newWidget(widget) {\r\n return {\r\n type: widget.type,\r\n config: {},\r\n titleTemplateUrl: `/App/ui/features/dashboard/WidgetHeader.html`,\r\n version: `1.0`\r\n };\r\n }\r\n }\r\n }\r\n\r\n function updateDeviceWidgets(persistedDashboardConfiguration) {\r\n let removedWidgets = [];\r\n\r\n _.forEach(persistedDashboardConfiguration.rows, row => {\r\n _.forEach(row.columns, column => {\r\n column.widgets = _.chain(column.widgets)\r\n .map(updateDeviceWidget)\r\n .filter(widget => widget)\r\n .value();\r\n });\r\n });\r\n\r\n persistDashboard(persistedDashboardConfiguration);\r\n\r\n if (removedWidgets.length) {\r\n notifyUserAboutTroublesomeWidgets(removedWidgets);\r\n }\r\n\r\n //////////////\r\n\r\n function updateDeviceWidget(deviceWidget) {\r\n const latestVersionOfWidget = _.find(accessibleWidgets, { type: deviceWidget.type });\r\n\r\n if (!latestVersionOfWidget) { // the widget is no longer accessible\r\n return removeFromDeviceDashboard();\r\n }\r\n\r\n deviceWidget.version = deviceWidget.version || `1.0`;\r\n const [currentMajor, currentMinor] = _.map(deviceWidget.version.split(`.`), number => parseInt(number));\r\n\r\n const latestMajor = latestVersionOfWidget.majorVersion;\r\n return latestMajor === currentMajor && upgradeConfiguration() || removeFromDeviceDashboard();\r\n\r\n ///////////\r\n\r\n function removeFromDeviceDashboard() {\r\n $log.info(`The '${deviceWidget.type}' was removed.
      Widget Details:
      ${JSON.stringify(deviceWidget) }`);\r\n removedWidgets = [...removedWidgets, deviceWidget];\r\n }\r\n\r\n function upgradeConfiguration() {\r\n try {\r\n deviceWidget.config = _.reduce(latestVersionOfWidget.minorVersionNumbers, executeMinorVersionUpgrade, deviceWidget.config);\r\n\r\n return deviceWidget;\r\n\r\n } catch (error) {\r\n return null;\r\n }\r\n\r\n ///////////\r\n\r\n function executeMinorVersionUpgrade(widgetConfig, minorVersionNumber) {\r\n if (minorVersionNumber <= currentMinor) {\r\n return widgetConfig;\r\n }\r\n\r\n try {\r\n const upgradeFunction = latestVersionOfWidget.minorVersions[minorVersionNumber];\r\n const upgradedConfig = upgradeFunction(widgetConfig);\r\n deviceWidget.version = `${currentMajor}.${minorVersionNumber}`;\r\n return upgradedConfig;\r\n\r\n } catch (error) {\r\n $log.error(`The '${widgetConfig.type}' widget failed the upgrade path.
      Initial version: ${currentMajor}.${currentMinor}
      Failed minor version upgrader: ${minorVersionNumber}
      error: ${error}`);\r\n removeFromDeviceDashboard();\r\n\r\n throw error;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function notifyUserAboutTroublesomeWidgets(removedWidgets) {\r\n const notificationTitle = i18n.i10n(`adf.notifications.widgetRemoval.title`);\r\n const widgetNames = _.reduce(removedWidgets, (list, removedWidget) => `${list}
    • ${i18n.i10n(removedWidget.type) }
    • `, ``);\r\n const notificationMessage = i18n.i10n(`adf.notifications.widgetRemoval.message`, { widgetNames });\r\n notifier.info(notificationMessage, notificationTitle);\r\n }\r\n }\r\n\r\n }\r\n\r\n function canAccessWidget(widget) {\r\n return _.reduce(widget.accessControls, (result, accessControl) => result && appSettings.site.accessControls[accessControl], true);\r\n }\r\n\r\n function persistDashboard(model) {\r\n delete model.isDefault;\r\n browserStorage.persistBucket(dashboardLayoutStorageKey, getStorageBucketKey(), model);\r\n }\r\n\r\n function persistWidgetList(accessibleWidgets) {\r\n browserStorage.persistBucket(accessibleWidgetStorageKey, getStorageBucketKey(), _.map(accessibleWidgets, accessibleWidget => accessibleWidget.type));\r\n }\r\n\r\n function deleteDashboard() {\r\n browserStorage.deleteBucket(dashboardLayoutStorageKey, getStorageBucketKey());\r\n }\r\n\r\n function getStorageBucketKey() {\r\n return `${appSettings.site.facility.alias}-${appSettings.userId}`;\r\n }\r\n\r\n function getDefaultNumberOfLayoutColumns() {\r\n return screen.width >= 992 ? 2 : 1;\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .provider(`app.core.services.dateTimeService`, dateTimeService);\n\n dateTimeService.$inject = [`lodash`];\n\n function dateTimeService(_) {\n this.$get = dateTimeServiceFactory;\n\n ////////////////////\n\n dateTimeServiceFactory.$inject = [\n `$filter`,\n `app.core.services.settingsService`\n ];\n\n function dateTimeServiceFactory($filter, settingsService) {\n const millisPerMinute = 1000 * 60;\n const cultureFormats = {};\n const service = {\n roundUpToClosestMinute\n };\n\n activate();\n\n return service;\n\n ////////////////////\n\n function activate() {\n setupCultureFormats();\n updateCurrentCultureFormats(cultureFormats.default);\n\n settingsService.getSelectedLanguage().then(culture => {\n culture = culture.toLowerCase();\n let formats = cultureFormats[culture];\n\n // Cater for a more generic version of the language, e.g. let `en-AU` fallback to `en`\n if (!formats) {\n const match = culture.match(/[^-]+/);\n if (match && match.length) {\n formats = cultureFormats[match[0]];\n }\n }\n\n if (formats && service.formats !== formats) {\n updateCurrentCultureFormats(formats);\n }\n });\n }\n\n function updateCurrentCultureFormats(formats) {\n service.formats = formats;\n service.formatAs = {\n date,\n utcDate,\n dateTime,\n dateTimeWithSeconds,\n hour,\n time,\n timeWithSeconds,\n iso\n };\n\n ////////////////////\n\n function date(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.date);\n }\n\n function utcDate(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.utcDate);\n }\n\n function dateTime(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.dateTime);\n }\n\n function dateTimeWithSeconds(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.dateTimeWithSeconds);\n }\n\n function hour(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.hour);\n }\n\n function time(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.time);\n }\n\n function timeWithSeconds(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.timeWithSeconds);\n }\n\n function iso(dateTime) {\n return $filter(`date`)(dateTime, formats.angular.iso);\n }\n }\n\n function roundUpToClosestMinute(dateTime) {\n const dateTimeMillis = dateTime.getTime();\n const delta = dateTimeMillis % millisPerMinute;\n if (delta === 0) {\n return dateTime;\n }\n\n const roundedEndTimeMillis = dateTimeMillis + millisPerMinute - delta;\n return new Date(roundedEndTimeMillis);\n }\n\n function setupCultureFormats() {\n addCultureFormats(getEnFormats(), `default`, `en`);\n addCultureFormats(getViFormats(), `vi`);\n addCultureFormats(get24HourFormats(), `fr`);\n addCultureFormats(get24HourFormats(), `es`);\n\n ////////////////////\n\n function addCultureFormats(formats, ...cultures) {\n _.forEach(cultures, culture => cultureFormats[culture.toLowerCase()] = formats);\n }\n\n function getEnFormats() {\n return {\n is24Hour: false,\n angular: {\n date: `dd MMM yyyy`,\n utcDate: `yyyy-MM-dd'Z'`,\n dateTime: `dd MMM yyyy hh:mm a`,\n dateTimeWithSeconds: `dd MMM yyyy hh:mm:ss a`,\n hour: `hh`,\n time: `hh:mm a`,\n timeWithSeconds: `hh:mm:ss a`,\n iso: `yyyy-MM-ddTHH:mm` // ISO8601\n },\n moment: {\n date: `DD MMM YYYY`,\n utcDate: `YYYY-MM-DD[Z]`,\n dateTime: `DD MMM YYYY hh:mm A`,\n dateTimeWithSeconds: `DD MMM YYYY hh:mm:ss A`,\n hour: `hh`,\n time: `hh:mm A`,\n timeWithSeconds: `hh:mm:ss A`,\n iso: `YYYY-MM-DDTHH:mm` // ISO8601\n },\n kendo: {\n date: `dd MMM yyyy`,\n utcDate: `yyyy-MM-dd'Z'`,\n dateTime: `dd MMM yyyy hh:mm tt`,\n dateTimeWithSeconds: `dd MMM yyyy hh:mm:ss tt`,\n hour: `hh`,\n time: `hh:mm tt`,\n timeWithSeconds: `hh:mm:ss tt`,\n iso: `yyyy-MMM-ddTHH:mm` // ISO8601\n }\n };\n }\n\n function getViFormats() {\n // According to Vianna, the Vietnamese don't really do \"12 hour\" time, so we always\n // use the 24 hour times below (even for 'hoursInDay12').\n return {\n is24Hour: true,\n angular: {\n date: `dd/MM/yyyy`,\n utcDate: `yyyy-MM-dd'Z'`,\n dateTime: `dd/MM/yyyy HH:mm`,\n dateTimeWithSeconds: `dd/MM/yyyy HH:mm:ss`,\n hoursInDay12: `HH`,\n time: `HH:mm`,\n timeWithSeconds: `HH:mm:ss`,\n iso: `yyyy-MM-ddTHH:mm` // ISO8601\n },\n moment: {\n date: `DD/MM/YYYY`,\n utcDate: `YYYY-MM-DD[Z]`,\n dateTime: `DD/MM/YYYY HH:mm`,\n dateTimeWithSeconds: `DD/MM/YYYY HH:mm:ss`,\n hour: `HH`,\n time: `HH:mm`,\n timeWithSeconds: `HH:mm:ss`,\n iso: `YYYY-MM-DDTHH:mm` // ISO8601\n },\n kendo: {\n date: `dd/MM/yyyy`,\n utcDate: `yyyy-MM-dd'Z'`,\n dateTime: `dd/MM/yyyy HH:mm`,\n dateTimeWithSeconds: `dd/MM/yyyy HH:mm:ss`,\n hour: `HH`,\n time: `HH:mm`,\n timeWithSeconds: `HH:mm:ss`,\n iso: `yyyy-MMM-ddTHH:mm` // ISO8601\n }\n };\n }\n\n function get24HourFormats() {\n return {\n is24Hour: true,\n angular: {\n date: `dd MMM yyyy`,\n utcDate: `yyyy-MM-dd'Z'`,\n dateTime: `dd MMM yyyy HH:mm`,\n dateTimeWithSeconds: `dd MMM yyyy HH:mm:ss`,\n hour: `HH`,\n time: `HH:mm a`,\n timeWithSeconds: `HH:mm:ss`,\n iso: `yyyy-MM-ddTHH:mm` // ISO8601\n },\n moment: {\n date: `DD MMM YYYY`,\n utcDate: `YYYY-MM-DD[Z]`,\n dateTime: `DD MMM YYYY HH:mm`,\n dateTimeWithSeconds: `DD MMM YYYY HH:mm:ss`,\n hour: `HH`,\n time: `HH:mm`,\n timeWithSeconds: `HH:mm:ss`,\n iso: `YYYY-MM-DDTHH:mm` // ISO8601\n },\n kendo: {\n date: `dd MMM yyyy`,\n utcDate: `yyyy-MM-dd'Z'`,\n dateTime: `dd MMM yyyy HH:mm`,\n dateTimeWithSeconds: `dd MMM yyyy HH:mm:ss`,\n hour: `HH`,\n time: `HH:mm`,\n timeWithSeconds: `HH:mm:ss`,\n iso: `yyyy-MMM-ddTHH:mm` // ISO8601\n }\n };\n }\n\n }\n }\n }\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.diagnosticsService`, diagnosticsService);\r\n\r\n diagnosticsService.$inject = [\r\n `app.core.providers.diagnosticsDataProvider`\r\n ];\r\n\r\n function diagnosticsService(diagnosticsDataProvider) {\r\n\r\n return {\r\n getLatestProcessDataEndTime\r\n };\r\n\r\n ////////////////////\r\n\r\n function getLatestProcessDataEndTime() {\r\n return diagnosticsDataProvider.getUtcLatestProcessDataEndTime().then(utcLatestEndTime => utcLatestEndTime && new Date(utcLatestEndTime));\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.errorService`, errorService);\r\n\r\n errorService.$inject = [\r\n `$log`,\r\n `notifier`,\r\n `$interval`,\r\n `$window`,\r\n `$injector`,\r\n `lodash`,\r\n `moment`,\r\n `app.core.appSettings`,\r\n `app.core.models.messages.messageList`\r\n ];\r\n function errorService($log, notifier, $interval, $window, $injector, _, moment, appSettings, messageList) {\r\n let i18n;\r\n\r\n const isOfflineError = error => error.status === 0;\r\n const isUnauthorised = error => error.status === 401;\r\n const isServerError = error => error.status === 500;\r\n\r\n addRemoveStaleMessagesAfterPeriodHandler();\r\n\r\n return {\r\n processSuccess,\r\n processError,\r\n logResponse\r\n };\r\n\r\n /////////////////////\r\n\r\n function addRemoveStaleMessagesAfterPeriodHandler() {\r\n const fiveMinutes = 1000 * 60 * 5;\r\n $interval(messageList.removeStale, fiveMinutes);\r\n }\r\n\r\n function processSuccess() {\r\n messageList.remove(isOfflineError);\r\n }\r\n\r\n function processError(response) {\r\n\r\n if (!i18n) {\r\n i18n = $injector.get(`i18n`);\r\n }\r\n\r\n // offline\r\n if (isOfflineError(response) || isNaN(response.status)) {\r\n const title = i18n.i10n(`errors.server.inaccessible.title`);\r\n const message = i18n.i10n(`errors.server.inaccessible.message`);\r\n const status = 0;\r\n messageList.update(isOfflineError) || messageList.addFatal(title, message, status);\r\n\r\n } // unexpected server error\r\n else if (isServerError(response)) {\r\n const title = i18n.i10n(`errors.server.exception.title`);\r\n const message = i18n.i10n(`errors.server.exception.message`);\r\n messageList.update(isServerError) || messageList.addError(title, message, response.status);\r\n } // unauthorised\r\n else if (isUnauthorised(response)) {\r\n appSettings.forgetCompanyAndFacility();\r\n $window.location.href = appSettings.loginUri;\r\n }\r\n // unhandled\r\n else {\r\n const title = i18n.i10n(`errors.server.error.title`);\r\n const errorWithStatus = ({ status }) => status === response.status;\r\n messageList.update(errorWithStatus) || messageList.addError(title, getErrorMessage(), response.status);\r\n\r\n function getErrorMessage() {\r\n if (response.data && _.isArray(response.data.messages) && response.data.messages.length) {\r\n const messages = _.map(response.data.messages, `content`);\r\n return messages.join(`
      `);\r\n }\r\n return i18n.i10n(`errors.server.error.message`);\r\n }\r\n }\r\n\r\n response.handled = true;\r\n logResponse(response);\r\n }\r\n\r\n function logResponse(response) {\r\n try {\r\n const statusText = response.statusText || `HTTP request status was not set.`;\r\n if (response.data !== null && typeof response.data === `object`) {\r\n response.data.stackTrace = response.data.stackTrace && response.data.stackTrace.replace(`\\r\\n`, `\\n`);\r\n }\r\n\r\n const error =\r\n `Unable to complete request:\r\n\"${response.config.method} ${response.config.url}\" | ${response.status} (${statusText})\r\n Request Headers:\r\n${JSON.stringify(response.config.headers, null, 4)}\r\n Request Data:\r\n${JSON.stringify(response.config.data, null, 4)}\r\n Response:\r\n${JSON.stringify(response.data, null, 4)}\r\n`;\r\n $log.fatal(error);\r\n $window.LogRocket && window.LogRocket.track(`on-screen-error`);\r\n $window.LogRocket && window.LogRocket.captureMessage(error);\r\n }\r\n catch (exception) {\r\n $log.fatal(exception);\r\n $window.LogRocket && window.LogRocket.captureException(exception);\r\n $window.LogRocket && window.LogRocket.track(`on-screen-error`);\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.exportService`, exportService);\r\n\r\n exportService.$inject = [`$http`, `app.core.appSettings`];\r\n\r\n function exportService($http, appSettings) {\r\n return {\r\n exportPdf,\r\n exportPng\r\n };\r\n\r\n ////////////\r\n\r\n function success(response) {\r\n return response;\r\n }\r\n\r\n function buildUrl(path) {\r\n return `${appSettings.webApiHostUri}export/${path}`;\r\n }\r\n\r\n /*\r\n options:\r\n waitTimeMs - how long to wait before a screenshot gets taken\r\n waitForSelector - selector to wait for.\r\n selectorTimeOutMs - time to wait for selector before assuming the process failed.\r\n isLandscape\r\n */\r\n\r\n function exportPdf(url, options) {\r\n const postUrl = buildUrl(`pdf`);\r\n let postData = {\r\n url: url,\r\n waitTimeMs : 1000,\r\n isLandscape : true\r\n };\r\n postData = { ...postData, ...options };\r\n return $http.post(postUrl, postData, { responseType: `blob` })\r\n .then(success)\r\n .catch(angular.noop);\r\n }\r\n\r\n /*\r\n options are:\r\n waitTimeMs - how long to wait before a screenshot gets taken\r\n waitForSelector - selector to wait for.\r\n selectorTimeOutMs - time to wait for selector before assuming the process failed.\r\n */\r\n\r\n function exportPng(url, options) {\r\n const postUrl = buildUrl(`png`);\r\n let postData = {\r\n url: url,\r\n waitTimeMs : 1000\r\n };\r\n postData = { ...postData, ...options };\r\n return $http.post(postUrl, postData, { responseType: `blob` })\r\n .then(success)\r\n .catch(angular.noop);\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.gisModelService`, gisModelService);\r\n\r\n gisModelService.$inject = [\r\n `lodash`,\r\n `$q`,\r\n `app.core.providers.gisModelDataProvider`,\r\n `app.core.models.jobs.ModellingJob`,\r\n `app.core.models.legends.legendFactory`\r\n ];\r\n\r\n function gisModelService(_, $q, gisModelDataProvider, ModellingJob, legendFactory) {\r\n return {\r\n getIntervals,\r\n getModelDataSet,\r\n getAllModels,\r\n getModellingJobs,\r\n getModelDataAvailability,\r\n getDiscreteReceptorData,\r\n dismissJob: gisModelDataProvider.dismissJob,\r\n dismissJobs: gisModelDataProvider.dismissJobs,\r\n getStatus: gisModelDataProvider.getStatus,\r\n startTestJob: gisModelDataProvider.startTestJob\r\n };\r\n\r\n function getIntervals() {\r\n return gisModelDataProvider.getIntervals()\r\n .then(intervals => {\r\n _.forEach(intervals, interval => {\r\n _.forEach(interval.models, model => {\r\n model.isSelected = false;\r\n model.legend = legendFactory.create(model.legend);\r\n });\r\n });\r\n\r\n return intervals;\r\n });\r\n }\r\n\r\n function getModelDataSet(models, dateFrom, dateTo) {\r\n return gisModelDataProvider.getModelDataSet(models, dateFrom, dateTo)\r\n .then(result => {\r\n const response = result;\r\n const activeJobs = {};\r\n\r\n _.forEach(response.activeJobsForGisModels, (job, modelId) => {\r\n activeJobs[modelId] = ModellingJob.createFromJobData(job);\r\n });\r\n\r\n response.activeJobsForGisModels = activeJobs;\r\n\r\n return response;\r\n });\r\n }\r\n\r\n function getAllModels() {\r\n return getIntervals()\r\n .then(intervals =>\r\n _.chain(intervals)\r\n .map(flattenModels)\r\n .flatten()\r\n .value()\r\n );\r\n }\r\n\r\n function flattenModels(interval) {\r\n return _.map(interval.models, model => {\r\n return {\r\n modelId: model.modelId,\r\n name: model.modelName,\r\n durationInMinutes: interval.durationInMinutes\r\n };\r\n });\r\n }\r\n\r\n function getModellingJobs() {\r\n return gisModelDataProvider.getModellingJobs()\r\n .then(result => {\r\n return _.chain(result)\r\n .map(job => ModellingJob.createFromJobData(job))\r\n .sortBy(job => {\r\n if (job.hasCompleted) {\r\n return job.fromMillis;\r\n\r\n } else if (job.isQueued) {\r\n return 0;\r\n }\r\n\r\n return 0 - job.progress;\r\n })\r\n .value();\r\n });\r\n }\r\n\r\n function getModelDataAvailability(modelId) {\r\n if (!modelId){\r\n throw new Error(`modelId is not defined`);\r\n }\r\n\r\n return gisModelDataProvider.getModelDataAvailability(modelId)\r\n .then(result => ({\r\n latestTime: new Date(result.utcLatestTime)\r\n }));\r\n }\r\n\r\n function getDiscreteReceptorData(modelId, fromDateTime, toDateTime) {\r\n if (!modelId){\r\n throw new Error(`modelId is not defined`);\r\n }\r\n\r\n return gisModelDataProvider.getDiscreteReceptorData(modelId, fromDateTime, toDateTime)\r\n .then(data => data && _.mapValues(data, item => item.map(mapDiscreteReceptorData)));\r\n\r\n ///////////////////\r\n\r\n function mapDiscreteReceptorData(discreteReceptorData) {\r\n const { monitor, processVariable } = discreteReceptorData;\r\n return {\r\n id: monitor.id,\r\n name: monitor.name,\r\n latitude: monitor.latitude,\r\n longitude: monitor.longitude,\r\n monitorType: monitor.monitorType && _.camelCase(monitor.monitorType) || null,\r\n processVariable: mapProcessVariableData(processVariable),\r\n modelId\r\n };\r\n }\r\n\r\n function mapProcessVariableData(processVariable) {\r\n if (!processVariable) {\r\n return null;\r\n }\r\n\r\n const result = {\r\n id: processVariable.id,\r\n name: processVariable.name,\r\n valueInDisplayUnit: getValue(processVariable),\r\n isValueStale: processVariable.isValueStale,\r\n hasValueFlatlined: processVariable.hasValueFlatlined,\r\n thresholdColour: getThresholdColour(processVariable),\r\n hasValueExceededFirstThreshold: processVariable.hasValueExceededFirstThreshold,\r\n units: processVariable.units,\r\n displayName: processVariable.displayName\r\n };\r\n\r\n result.hasDisplayableValue = !!(result.units && !result.isValueStale && _.isNumber(result.valueInDisplayUnit));\r\n return result;\r\n\r\n ////////////////////\r\n\r\n function getValue(processVariable) {\r\n if (!processVariable || processVariable.isValueStale || isNaN(processVariable.valueInDisplayUnit)) {\r\n return null;\r\n }\r\n\r\n return processVariable.valueInDisplayUnit;\r\n }\r\n\r\n function getThresholdColour(processVariable) {\r\n if (!processVariable || processVariable.isValueStale || processVariable.valueInDisplayUnit === null) {\r\n return `rgb(204, 204, 204)`;\r\n }\r\n\r\n return processVariable.thresholdColour;\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.incidentIntelligenceService`, incidentIntelligenceService);\r\n\r\n incidentIntelligenceService.$inject = [\r\n `$q`,\r\n `leafletLib`,\r\n `app.core.models.mapping.dataPointType`,\r\n `app.core.models.mapping.dataPointFactory`,\r\n `app.core.providers.incidentIntelligenceDataProvider`\r\n ];\r\n\r\n function incidentIntelligenceService($q, L, dataPointType, dataPointFactory, dataProvider) {\r\n\r\n return {\r\n getPathModel : getPathModel,\r\n getSummaryLookupValues : dataProvider.getSummaryLookupValues,\r\n getTicketSummaryLocations : dataProvider.getTicketSummaryLocations\r\n };\r\n\r\n ////////////////////\r\n\r\n function getPathModel(ticketId, ticketActivityId) {\r\n\r\n return dataProvider.getPathModel(ticketId, ticketActivityId).then(mapResult);\r\n\r\n function mapResult(pathData) {\r\n const result = {\r\n primaryTrack: createDataPoint(pathData.primaryTrack)\r\n };\r\n\r\n const firstStep = result.primaryTrack.data.length && result.primaryTrack.data[0];\r\n if (!firstStep) {\r\n return $q.when(result);\r\n }\r\n\r\n const firstPoint = new L.LatLng(firstStep.latitude, firstStep.longitude);\r\n const startPoint = new L.LatLng(pathData.startPoint.latitude, pathData.startPoint.longitude);\r\n\r\n result.isForwardTrajectory = firstPoint.equals(startPoint);\r\n\r\n const lastStep = result.primaryTrack.data[result.primaryTrack.data.length - 1];\r\n result.startTime = result.isForwardTrajectory\r\n ? new Date(firstStep.timeMillis)\r\n : new Date(lastStep.timeMillis);\r\n\r\n return $q.when(result);\r\n\r\n ////////////////////\r\n\r\n function createDataPoint(track) {\r\n const dataPoint = dataPointFactory.create(dataPointType.path, track.gisTrackDataTimeSteps);\r\n return dataPoint;\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.locationService`, locationService);\r\n\r\n locationService.$inject = [`$q`, `$window`, `$state`, `$log`, `lodash`, `i18n`,\r\n `app.core.appSettings`,\r\n `app.core.services.companyService`,\r\n `app.core.services.securityService`\r\n ];\r\n function locationService($q, $window, $state, $log, _, i18n, appSettings, companyService, securityService) {\r\n\r\n let pageHeading,\r\n pageHeadingParameters;\r\n\r\n let exitPoint = {};\r\n\r\n const service = {\r\n\r\n bindPageHeading: function() {\r\n pageHeading = i18n.i10n(`${$state.$current.name}.route.heading`, pageHeadingParameters || {});\r\n },\r\n\r\n updatePageHeading: function(pageHeadingParams = {}) {\r\n pageHeadingParameters = pageHeadingParams;\r\n service.bindPageHeading();\r\n },\r\n\r\n updateExitPoint: function(exitState, stateParameters, i18nParameters) {\r\n exitPoint = {\r\n exit: () => $state.go(exitState, stateParameters),\r\n text: i18n.i10n(`${$state.$current.name}.route.exitText`, i18nParameters)\r\n };\r\n $log.debug(`setting exit point - ${exitState} : ${exitPoint.text}`);\r\n },\r\n\r\n clearExitPoint: () => exitPoint = null,\r\n\r\n get pageHeading() {\r\n return pageHeading;\r\n },\r\n\r\n get exitPoint() {\r\n return exitPoint;\r\n },\r\n\r\n goHome: goHome,\r\n logout: logout\r\n };\r\n\r\n return service;\r\n\r\n //////////\r\n\r\n function goHome() {\r\n const companyAlias = appSettings.site.company.alias;\r\n const facilityAlias = appSettings.site.facility.alias;\r\n\r\n if (appSettings.isGuestUser) {\r\n return logout();\r\n }\r\n\r\n companyService.getCompanies({ refresh: true })\r\n .then(ensureCompanyExists)\r\n .then(goToCompanyHome)\r\n .catch(logout);\r\n\r\n function ensureCompanyExists(validCompanies) {\r\n return $q((resolve, reject) => {\r\n companyService.canAccessFacility(companyAlias, facilityAlias).then(canAccessFacility => {\r\n if (canAccessFacility) {\r\n return resolve({ companyAlias, facilityAlias });\r\n }\r\n\r\n const companyToSwitchTo = _.find(validCompanies, company => company.facilities.length);\r\n\r\n if (companyToSwitchTo) {\r\n return resolve({\r\n companyAlias: companyToSwitchTo.alias,\r\n facilityAlias: companyToSwitchTo.facilities[0].alias\r\n });\r\n }\r\n\r\n reject();\r\n });\r\n });\r\n }\r\n\r\n function goToCompanyHome(companyAndFacility) {\r\n $state.go(`app.dashboard`, companyAndFacility, { reload: true });\r\n }\r\n }\r\n\r\n function logout() {\r\n return securityService.logout();\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.mappingService`, mappingService);\r\n\r\n mappingService.$inject = [\r\n `lodash`,\r\n `app.core.providers.mappingDataProvider`,\r\n `app.core.appSettings`,\r\n `leafletLib`\r\n ];\r\n\r\n const sourcesKmlFileName = `sources.kml`;\r\n\r\n function mappingService(_, endpointProvider, appSettings, L) {\r\n\r\n return {\r\n getKmls,\r\n getEmissionSourceKml,\r\n getTileLayers,\r\n getMapCredits,\r\n getElevation,\r\n getActiveTemporalEventGroups\r\n };\r\n\r\n function getKmls() {\r\n return endpointProvider.getKmlDataSet(null, [sourcesKmlFileName]);\r\n }\r\n\r\n function getEmissionSourceKml() {\r\n return endpointProvider.getKmlDataSet([sourcesKmlFileName], null).then(\r\n kmls => {\r\n return kmls.length === 1 ? kmls[0] : null;\r\n });\r\n }\r\n\r\n function getTileLayers() {\r\n return endpointProvider.getTileLayers().then(data => {\r\n return _.map(data, config => {\r\n const mapBounds = new L.LatLngBounds(new L.LatLng(config.bounds[1], config.bounds[0]), new L.LatLng(config.bounds[3], config.bounds[2]));\r\n return {\r\n minZoom: config.minZoom,\r\n maxZoom: config.maxZoom,\r\n bounds: mapBounds,\r\n opacity: config.opacity,\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias,\r\n facilityCode: appSettings.site.facility.facilityCode,\r\n name: config.name\r\n };\r\n });\r\n });\r\n }\r\n\r\n function getMapCredits() {\r\n return endpointProvider.getMapCredits();\r\n }\r\n\r\n function getElevation(latitude, longitude) {\r\n return endpointProvider.getElevationAtPoint(latitude, longitude);\r\n }\r\n\r\n function getActiveTemporalEventGroups(activeAtDateTime) {\r\n if (!_.isDate(activeAtDateTime)) {\r\n throw new Error(`The activeAtDateTime must be a Date.`);\r\n }\r\n\r\n return endpointProvider.getActiveTemporalEventGroups(activeAtDateTime);\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n const module = angular.module(`app.core`);\r\n\r\n class MathService {\r\n\r\n constructor() {\r\n this.floatMaxValue = 3.4e+38;\r\n this.floatMinValue = -this.floatMaxValue; //corresponds to ProcessVariableThresholdEntityConverter.MinBaseThresholdValue\r\n }\r\n\r\n // this function rounds a number to at-most the provided number of decimal places.\r\n //\r\n // e.g. 2 decimal places\r\n //\r\n // 10 -> 10\r\n // 10.1 -> 10.1\r\n // 10.12 -> 10.12\r\n // 10.005 -> 10.01\r\n // 10.1234 -> 10.12\r\n\r\n round(number, decimalPlaces = 0) {\r\n return +(Math.round(`${number}e+${decimalPlaces}`) + `e-${decimalPlaces}`);\r\n }\r\n\r\n }\r\n\r\n MathService.$inject = [];\r\n module.service(`app.core.services.mathService`, MathService);\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.monitoringService`, monitoringService);\r\n\r\n monitoringService.$inject = [\r\n `$q`,\r\n `lodash`,\r\n `app.core.requestManager`,\r\n `app.core.providers.monitoringDataProvider`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.services.configuration.monitoringService`\r\n ];\r\n\r\n function monitoringService($q, _, requestManager, endpointProvider, dateTimeService, configurationMonitoringService) {\r\n\r\n return {\r\n getMonitorsByType,\r\n getMetSummary,\r\n getMonitorData,\r\n getMonitorSensorData,\r\n getSensorDataSeries,\r\n getGraphVariables,\r\n getMonitorTypes,\r\n getMonitorDataAlarms,\r\n getSourceAreaData\r\n };\r\n\r\n function getMonitorsByType() {\r\n return endpointProvider.getMonitorsByType().then(monitorsByType => {\r\n // For now, we don't want discrete receptors to show up in ES2, so we'll just pretend they don't exist...\r\n delete monitorsByType.discreteReceptor;\r\n\r\n _.forEach(monitorsByType, (monitorGrouping, monitorType) => {\r\n if (monitorGrouping.measurementGroups && monitorGrouping.measurementGroups.length > 1) {\r\n monitorGrouping.measurementGroups = _.chain(monitorGrouping.measurementGroups)\r\n .filter(mg => !mg.parentId)\r\n .sortBy(mg => mg.defaultOrder)\r\n .value();\r\n }\r\n\r\n const measurementGroup = _.head(monitorGrouping.measurementGroups);\r\n monitorsByType[monitorType].selectedMeasurementGroupId = measurementGroup ? measurementGroup.id : null;\r\n monitorsByType[monitorType].icon = configurationMonitoringService.getMonitorTypeIcon(monitorType);\r\n });\r\n return monitorsByType;\r\n });\r\n }\r\n\r\n function getMetSummary(dateTime) {\r\n dateTime = dateTime || new Date();\r\n\r\n return requestManager\r\n .enqueue(() => endpointProvider.getMetSummary(dateTime))\r\n .onQueue(getMetSummary.name);\r\n }\r\n\r\n function getSourceAreaData(dateTime) {\r\n dateTime = dateTime || new Date();\r\n\r\n return requestManager\r\n .enqueue(() => endpointProvider.getSourceAreaData(dateTime).then(processData => processData.map(mapSourceAreaData)))\r\n .onQueue(`${getSourceAreaData.name}`);\r\n\r\n function mapSourceAreaData(sourceAreaData) {\r\n const { process: { id, name, points }, dataPoints } = sourceAreaData;\r\n return {\r\n id,\r\n name,\r\n dataPoints: dataPoints.map(mapProcessVariableData),\r\n latlngs: _.map(points, point => ({\r\n lat: point.latitude, lng: point.longitude\r\n }))\r\n };\r\n }\r\n }\r\n\r\n function getMonitorData(monitorIds, measurementGroupId, dateTime) {\r\n if (!_.isArray(monitorIds)) {\r\n throw new Error(`monitorIds is not defined`);\r\n }\r\n\r\n dateTime = dateTime || new Date();\r\n\r\n return requestManager\r\n .enqueue(() => endpointProvider.getMonitorData(monitorIds, measurementGroupId, dateTime).then(monitorData => monitorData.map(mapMonitorData)))\r\n .onQueue(`${getMonitorData.name}-${measurementGroupId}`);\r\n\r\n ///////////////////\r\n\r\n function mapMonitorData(monitorData) {\r\n const monitor = monitorData.monitor;\r\n return {\r\n id: monitor.id,\r\n name: monitor.name,\r\n latitude: monitor.latitude,\r\n longitude: monitor.longitude,\r\n monitorType: monitor.monitorType && _.camelCase(monitor.monitorType) || null,\r\n processVariable: mapProcessVariableData(monitorData.processVariable),\r\n influenceArc: monitorData.influenceArc,\r\n fencelineLocations: monitor.fencelineLocations\r\n };\r\n }\r\n }\r\n\r\n function mapProcessVariableData(processVariable) {\r\n if (!processVariable) {\r\n return null;\r\n }\r\n\r\n const result = {\r\n id: processVariable.id,\r\n name: processVariable.name,\r\n valueInDisplayUnit: getValue(processVariable),\r\n valueTime: dateTimeService.roundUpToClosestMinute(new Date(processVariable.utcDateTimeEnd)),\r\n isValueStale: processVariable.isValueStale,\r\n hasValueFlatlined: processVariable.hasValueFlatlined,\r\n thresholdColour: getThresholdColour(processVariable),\r\n hasValueExceededFirstThreshold: processVariable.hasValueExceededFirstThreshold,\r\n units: processVariable.units,\r\n displayName: processVariable.displayName,\r\n numericScale: processVariable.numericScale\r\n };\r\n\r\n result.hasDisplayableValue = !!(result.units && !result.isValueStale && _.isNumber(result.valueInDisplayUnit));\r\n return result;\r\n\r\n /////////////\r\n\r\n function getValue(processVariable) {\r\n if (!processVariable || processVariable.isValueStale || isNaN(processVariable.valueInDisplayUnit)) {\r\n return null;\r\n }\r\n\r\n return processVariable.valueInDisplayUnit;\r\n }\r\n\r\n function getThresholdColour(processVariable) {\r\n if (!processVariable || processVariable.isValueStale || processVariable.valueInDisplayUnit === null) {\r\n return `rgb(204, 204, 204)`;\r\n }\r\n\r\n return processVariable.thresholdColour;\r\n }\r\n }\r\n\r\n function getGraphVariables(monitorId) {\r\n return endpointProvider.getGraphVariables(monitorId);\r\n }\r\n\r\n function getMonitorSensorData(monitorId, processVariables, dateTime) {\r\n return endpointProvider.getMonitorSensorData(monitorId, processVariables, dateTime)\r\n .then(graphVariables => graphVariables.map(mapProcessVariableData));\r\n }\r\n\r\n function getSensorDataSeries(startDateTime, endDateTime, processVariableId) {\r\n return endpointProvider.getSensorDataSeries(startDateTime, endDateTime, processVariableId).then(processResponse);\r\n\r\n function processResponse(dataSet) {\r\n dataSet.values = dataSet.values.map(value => {\r\n return {\r\n valueInDisplayUnit: value.valueInDisplayUnit,\r\n valueInBaseUnit: value.valueInBaseUnit,\r\n date: dateTimeService.roundUpToClosestMinute(new Date(value.utcDateTimeEnd))\r\n };\r\n });\r\n\r\n return dataSet;\r\n }\r\n }\r\n\r\n\r\n function getMonitorTypes() {\r\n return endpointProvider.getMonitorTypes().then(monitorTypes => monitorTypes.map(_.camelCase));\r\n }\r\n\r\n function getMonitorDataAlarms(monitorTypes = null, samplingTime = null) {\r\n if (!(_.isArray(monitorTypes) && monitorTypes.length)) {\r\n return $q.reject(`No monitor types specified.`);\r\n }\r\n\r\n const monitorTypesToRequest = monitorTypes.map(_.capitalize);\r\n\r\n return endpointProvider\r\n .getMonitorDataAlarms(monitorTypesToRequest, samplingTime)\r\n .then(processMonitorDataAlarms);\r\n\r\n ////////////////////\r\n function processMonitorDataAlarms(monitorDataAlarms) {\r\n const monitorsByType = _.chain(monitorDataAlarms)\r\n .groupBy(alarm => alarm.monitorType)\r\n .map(processMonitorsByType)\r\n .value();\r\n\r\n _.forEach(monitorTypes, monitorType => {\r\n const hasAlarms = _.find(monitorsByType, { monitorType });\r\n\r\n if (!hasAlarms) {\r\n monitorsByType.push({\r\n monitorType,\r\n monitors: []\r\n });\r\n }\r\n });\r\n\r\n return monitorsByType;\r\n\r\n ////////////////////\r\n\r\n function processMonitorsByType(monitors, monitorType) {\r\n return {\r\n monitorType: _.camelCase(monitorType),\r\n monitors: _.map(monitors, processMonitor)\r\n };\r\n }\r\n\r\n function processMonitor(monitor) {\r\n return {\r\n id: monitor.monitorId,\r\n name: monitor.monitorName,\r\n alarms: _.map(monitor.monitorData, processAlarm)\r\n };\r\n }\r\n\r\n function processAlarm(alarm) {\r\n return {\r\n id: alarm.id,\r\n name: alarm.displayName || alarm.name,\r\n isStale: alarm.isValueStale,\r\n valueInDisplayUnit: alarm.valueInDisplayUnit && alarm.valueInDisplayUnit.toFixed(1) || null,\r\n units: alarm.units,\r\n thresholdColour: alarm.thresholdColour\r\n };\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.reportsService`, reportsService);\r\n\r\n reportsService.$inject = [\r\n `lodash`,\r\n `app.core.appSettings`,\r\n `app.core.providers.reportsDataProvider`,\r\n `app.core.datetime.timeZoneDateTime`\r\n ];\r\n\r\n function reportsService(_, appSettings, dataProvider, timeZoneDateTime) {\r\n return {\r\n getListOfReports: getListOfReports,\r\n getAlertPointReports: getAlertPointReports,\r\n getProcessDataReportLookupValues: dataProvider.getProcessDataReportLookupValues,\r\n getProcessDataReportColumns: dataProvider.getProcessDataReportColumns,\r\n getProcessDataReport: getProcessDataReport,\r\n exportProcessDataReport: exportProcessDataReport\r\n };\r\n\r\n //////////////\r\n\r\n function getListOfReports() {\r\n return dataProvider.getListOfReports().then(collection => {\r\n\r\n const javaScriptReports = _.map(collection.javaScriptReports, mapJavaScriptReport);\r\n const powerBiReports = _.map(collection.powerBiReports, mapPowerBiReport);\r\n const legacyReports = _.chain(collection.legacyReports)\r\n .filter(report => report.name)\r\n .map(mapLegacyReport)\r\n .value();\r\n\r\n return javaScriptReports.concat(powerBiReports).concat(legacyReports);\r\n\r\n ////////////////////\r\n\r\n function mapLegacyReport(report) {\r\n\r\n // TODO: mcross (2016/07/01) - consider making this data driven\r\n const isProcessDataReport = report.reportType === `ProcessReport`;\r\n\r\n if (isProcessDataReport) {\r\n report.isEs2Report = true;\r\n report.uri = `app.reporting.processData`;\r\n report.params = { reportId: report.id };\r\n\r\n } else {\r\n const linkSafeName = report.name.replace(/\\s+/g, `_`);\r\n report.uri = `${appSettings.mvcHostUri}${appSettings.site.facility.es1RouteName}/Reports/_${linkSafeName}`;\r\n }\r\n\r\n return report;\r\n }\r\n });\r\n }\r\n\r\n function getAlertPointReports() {\r\n return dataProvider\r\n .getAlertPointReports()\r\n .then(reports => reports && reports.map(report => mapJavaScriptReport(report)))\r\n .catch(response => {\r\n response.handled = true;\r\n return null;\r\n });\r\n }\r\n\r\n function getProcessDataReport(processId, startTime, endTime, searchCriteria) {\r\n return dataProvider.getProcessDataReport(processId, startTime, endTime, searchCriteria).then(report => {\r\n _.forEach(report.data, dataForEndTime => {\r\n // Dates are returned as a string; we need to convert these to an actual date so that\r\n // kendo can render them properly.\r\n const localDateTime = new Date(dataForEndTime.key);\r\n dataForEndTime.key = timeZoneDateTime.convertDateTimeToFacilityTimeZone(localDateTime);\r\n\r\n // The data points themselves are returned unrounded; to maintain consistency with the old process\r\n // data report, we need to round the figures to 1 decimal place.\r\n _.forEach(dataForEndTime.valueInDisplayUnit, (value, processVariableId) => {\r\n // Use bitwise shift-left to cast to an int (see: http://stackoverflow.com/a/7343175/127497)\r\n dataForEndTime[processVariableId] = (value * 10 << 0) * 0.1; // eslint-disable-line no-bitwise\r\n });\r\n });\r\n\r\n return report;\r\n });\r\n }\r\n\r\n function exportProcessDataReport(processId, startTime, endTime, searchCriteria) {\r\n return dataProvider.exportProcessDataReport(processId, startTime, endTime, searchCriteria);\r\n }\r\n\r\n ////////////////////\r\n\r\n function mapPowerBiReport(report) {\r\n const { company, facility } = appSettings.site;\r\n report.uri = `${appSettings.reportsAppHostUri}${company.alias}/${facility.alias}/${report.reportAlias}`;\r\n return report;\r\n }\r\n\r\n function mapJavaScriptReport(report) {\r\n const { company, facility } = appSettings.site;\r\n report.uri = `${appSettings.reportsAppHostUri}${company.alias}/${facility.alias}/${report.reportAlias}`;\r\n return report;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.securityService`, securityService);\r\n\r\n securityService.$inject = [\r\n `$window`,\r\n `lodash`,\r\n `app.core.appSettings`,\r\n `app.core.providers.securityDataProvider`\r\n ];\r\n\r\n function securityService($window, _, appSettings, securityDataProvider) {\r\n let accessControlPromise;\r\n\r\n return {\r\n getAccessControls,\r\n queryApiCredentials,\r\n getApiCredential,\r\n createApiCredential,\r\n updateApiCredential,\r\n getPasswordExpirationStatus,\r\n setPasswordExpirationConfirmed,\r\n logout: logout\r\n };\r\n\r\n function getAccessControls(companyId, facilityId) {\r\n accessControlPromise = securityDataProvider\r\n .getAccessControls(companyId, facilityId)\r\n .then(response => response);\r\n return accessControlPromise;\r\n }\r\n\r\n function queryApiCredentials(monitorId, searchCriteria) {\r\n return securityDataProvider\r\n .queryApiCredentials(monitorId, searchCriteria)\r\n .then(result => {\r\n result.data = _.map(\r\n result.data,\r\n mapUtcDateTimesToDateTimes\r\n );\r\n return result;\r\n });\r\n }\r\n\r\n function getApiCredential(credentialId) {\r\n return securityDataProvider\r\n .getApiCredential(credentialId)\r\n .then(mapUtcDateTimesToDateTimes);\r\n }\r\n\r\n function createApiCredential(credential) {\r\n return securityDataProvider.createApiCredential(\r\n mapDateTimesToUtcDateTimes(credential)\r\n );\r\n }\r\n\r\n function updateApiCredential(credential) {\r\n return securityDataProvider\r\n .updateApiCredential(mapDateTimesToUtcDateTimes(credential))\r\n .then(() => credential.id);\r\n }\r\n\r\n function getPasswordExpirationStatus() {\r\n return securityDataProvider\r\n .getPasswordExpirationStatus();\r\n }\r\n\r\n function setPasswordExpirationConfirmed() {\r\n return securityDataProvider\r\n .setPasswordExpirationConfirmed();\r\n }\r\n\r\n function mapDateTimesToUtcDateTimes(credential) {\r\n credential.utcLastUsedTime =\r\n credential.lastUsedTime &&\r\n credential.lastUsedTime.toISOString();\r\n credential.utcGeneratedTime =\r\n credential.generatedTime &&\r\n credential.generatedTime.toISOString();\r\n credential.utcDeactivatedTime =\r\n credential.deactivatedTime &&\r\n credential.deactivatedTime.toISOString();\r\n\r\n delete credential.lastUsedTime;\r\n delete credential.generatedTime;\r\n delete credential.deactivatedTime;\r\n\r\n return credential;\r\n }\r\n\r\n function mapUtcDateTimesToDateTimes(credential) {\r\n credential.lastUsedTime =\r\n credential.utcLastUsedTime !== null\r\n ? new Date(credential.utcLastUsedTime)\r\n : null;\r\n credential.generatedTime =\r\n credential.utcGeneratedTime !== null\r\n ? new Date(credential.utcGeneratedTime)\r\n : null;\r\n credential.deactivatedTime =\r\n credential.utcDeactivatedTime !== null\r\n ? new Date(credential.utcDeactivatedTime)\r\n : null;\r\n\r\n delete credential.utcLastUsedTime;\r\n delete credential.utcGeneratedTime;\r\n delete credential.utcDeactivatedTime;\r\n\r\n return credential;\r\n }\r\n\r\n function logout() {\r\n return securityDataProvider.logout().then(loginUrl => {\r\n appSettings.forgetCompanyAndFacility();\r\n $window.location.href = loginUrl;\r\n });\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.settingsService`, settingsService);\r\n\r\n settingsService.$inject = [\r\n `ipCookie`,\r\n `lodash`,\r\n `$q`,\r\n `$state`,\r\n `app.core.appSettings`,\r\n `moment`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.userService`\r\n ];\r\n\r\n function settingsService(cookie, lodash, $q, $state, appSettings, moment, timeZoneDateTime, userService) {\r\n const validDateRegex = /(\\d{4})-(\\d{2})-(\\d{2})(T(\\d{2}):(\\d{2})){0,1}$/; // i.e. YYYY-MM-DDTHH:mm\r\n\r\n return {\r\n getSupportedLanguages: getSupportedLanguages,\r\n setLanguage: setLanguage,\r\n getSelectedLanguage: getSelectedLanguage,\r\n getSampleDateTime\r\n };\r\n\r\n function getSupportedLanguages() {\r\n const supported = {\r\n 'en': `English`,\r\n 'es': `Español`,\r\n 'fr': `Français`,\r\n 'vi': `Tiếng Việt`,\r\n 'zh': `中文`,\r\n 'lt': `Lietuvis`\r\n };\r\n\r\n const explicitlyAllowed = (appSettings.languagesExplicitlyAllowed || ``)\r\n .split(`,`)\r\n .filter(code => code !== ``)\r\n .map(code => code.trim().toLowerCase());\r\n // Either an explicit set of allowed languages is supplied, or we allow all supported\r\n if (explicitlyAllowed.length === 0) {\r\n return supported;\r\n } else {\r\n return lodash.pickBy(supported, (value, key) => explicitlyAllowed.indexOf(key) !== -1);\r\n }\r\n }\r\n\r\n function getSelectedLanguage() {\r\n return userService.getLocale();\r\n }\r\n\r\n function setLanguage(language) {\r\n return userService.getUserDetails().then(user => {\r\n user.locale = language;\r\n return userService.updateUserDetails(user);\r\n });\r\n }\r\n\r\n function getSampleDateTime() {\r\n if (!$state.params.dateTime) {\r\n return new Date();\r\n }\r\n\r\n if ($state.params.dateTime.match(validDateRegex)) {\r\n const dateTimeMoment = moment($state.params.dateTime);\r\n\r\n if (dateTimeMoment.isValid()) {\r\n return timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(dateTimeMoment.toDate());\r\n }\r\n }\r\n\r\n throw new Error(`The dateTime query parameter must be a valid date and time of the format: YYYY-MM-DDTHH:mm`);\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.services.userService`, userService);\r\n\r\n userService.$inject = [`app.core.providers.userDataProvider`, `app.core.appSettings`];\r\n\r\n function userService(userDataProvider, appSettings) {\r\n let userPromise;\r\n\r\n return {\r\n getUserDetails: getUserDetails,\r\n updatePassword: userDataProvider.updatePassword,\r\n updateUserDetails: updateUserDetails,\r\n getLocale: getLocale\r\n };\r\n\r\n function updateUserDetails(userDetails) {\r\n return userDataProvider.updateUserDetails(userDetails).then(() => {\r\n appSettings.user = userDetails;\r\n });\r\n }\r\n\r\n function getUserDetails(forceRefresh = false) {\r\n if (userPromise && !forceRefresh) {\r\n return userPromise;\r\n }\r\n\r\n return userPromise = userDataProvider.getUserDetails();\r\n }\r\n\r\n function getLocale() {\r\n return userDataProvider.getLocale();\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.signalR.alerts.alertStatusHub`, alertStatusHub);\r\n\r\n alertStatusHub.$inject = [\r\n `$timeout`,\r\n `postal`,\r\n `app.core.appSettings`,\r\n `app.core.signalR.Hub`,\r\n `app.core.models.alerts.WebAlert`,\r\n `app.core.signalR.alerts.events`\r\n ];\r\n function alertStatusHub($timeout, postal, appSettings, Hub, WebAlert, alertEvents) {\r\n const hubName = `alertStatusHub`;\r\n\r\n const channel = postal.channel(alertEvents.channelName);\r\n const hub = new Hub({\r\n hubName,\r\n canAccess: accessControls => accessControls[`app.alerts`],\r\n methods: [`subscribeAlerts`, `unsubscribeAlerts`],\r\n listeners: { notify: onNotify, dismiss: onDismiss },\r\n joinFacility,\r\n leaveFacility\r\n });\r\n\r\n return {\r\n name: hubName,\r\n connect: hub.connect\r\n };\r\n\r\n function onNotify(alert) {\r\n alert = new WebAlert(alert.id, alert.alertEventSourceId, alert.name, alert.message, alert.level, new Date(alert.utcTriggeredTime), new Date(alert.utcSentTime));\r\n publish(alertEvents.topics.notify, alert);\r\n }\r\n\r\n function onDismiss(alertId) {\r\n publish(alertEvents.topics.dismiss, alertId);\r\n }\r\n\r\n function publish(topic, payload) {\r\n $timeout(() => channel.publish(topic, payload));\r\n }\r\n\r\n function joinFacility(signalRHub, facility) {\r\n return signalRHub.subscribeAlerts(facility, appSettings.userId);\r\n }\r\n\r\n function leaveFacility(signalRHub, facility) {\r\n return signalRHub.unsubscribeAlerts(facility, appSettings.userId);\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .value(`app.core.signalR.alerts.events`, getEvents());\n\n function getEvents() {\n return {\n channelName: `app.core.signalR.alerts`,\n topics: {\n notify: `notify`,\n dismiss: `dismiss`\n }\n };\n }\n})();\n","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .value(`app.core.signalR.alerts.state`, {\n alerts: []\n });\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.signalR.Hub`, hubFactory)\r\n .factory(`app.core.signalR.HubReconnectionManager`, hubReconnectionManagerFactory);\r\n\r\n hubFactory.$inject = [`$log`, `$q`, `jQuery`, `lodash`, `postal`, `Hub`, `app.core.signalR.HubReconnectionManager`, `app.core.appSettings`, `app.core.events`];\r\n\r\n function hubFactory($logger, $q, $, _, postal, SignalRHub, HubReconnectionManager, appSettings, coreEvents) {\r\n return function Hub(configuration) {\r\n let hub, subscription;\r\n let subscribedFacility = null;\r\n let subscribedFacilityPromise = $q.when(true);\r\n\r\n let $log;\r\n let reconnectionManager = null;\r\n\r\n activate();\r\n\r\n ///////////////////\r\n\r\n function activate() {\r\n if (configuration === null || configuration === undefined) {\r\n throw new Error(`The hub configuration options must be provided.`);\r\n }\r\n\r\n if (configuration.hubName === null || configuration.hubName === undefined) {\r\n throw new Error(`The hub configuration \\`hubName\\` must be provided.`);\r\n }\r\n\r\n if (configuration.canAccess && !_.isFunction(configuration.canAccess)) {\r\n throw new Error(`The hub configuration \\`canAccess\\` must be a function.`);\r\n }\r\n\r\n configuration.canAccess = configuration.canAccess || (() => false);\r\n\r\n $log = new HubLogWrapper($logger, configuration.hubName);\r\n }\r\n\r\n this.connect = function() {\r\n if (subscription || hub) {\r\n return;\r\n }\r\n\r\n $log.debug(`Connecting: ${configuration.hubName}`);\r\n\r\n hub = new SignalRHub(configuration.hubName, {\r\n name: configuration.hubName,\r\n rootPath: appSettings.signalRHostUri,\r\n logging: false,\r\n useSharedConnection: true,\r\n stateChanged: onConnectionStateChanged,\r\n errorHandler: onError,\r\n methods: configuration.methods || [],\r\n listeners: configuration.listeners || {},\r\n queryParams : { apiKey: appSettings.apiKey }\r\n });\r\n\r\n subscription = postal.subscribe({\r\n channel: coreEvents.channelName,\r\n topic: coreEvents.topics.accessControlsUpdated,\r\n callback: updateSubscribedFacility\r\n });\r\n };\r\n\r\n this.invoke = function(method, ...args) {\r\n if (hub === null || hub === undefined || !_.isFunction(hub[method])) {\r\n throw new Error(`The hub method is not available.`);\r\n }\r\n\r\n hub.promise.then(() => {\r\n hub[method].apply(hub, args);\r\n });\r\n };\r\n\r\n /////////////////////\r\n\r\n function updateSubscribedFacility() {\r\n if (!isHubConnected()) {\r\n return;\r\n }\r\n\r\n const currentFacility = appSettings.site.facility.alias.toLowerCase();\r\n if (subscribedFacility === currentFacility) {\r\n return;\r\n }\r\n\r\n const updateSubscription = () => {\r\n return $q(resolve => {\r\n\r\n const facilityToLeave = subscribedFacility;\r\n const unsubscribe = $q.when(!facilityToLeave || configuration.leaveFacility(hub, facilityToLeave));\r\n\r\n unsubscribe.then(() => {\r\n if (facilityToLeave) {\r\n $log.debug(`Left facility ${facilityToLeave}`);\r\n }\r\n\r\n if (!isConnectionAllowedByAccessControl()) {\r\n subscribedFacility = null;\r\n resolve();\r\n\r\n } else {\r\n const facilityToJoin = currentFacility;\r\n\r\n configuration.joinFacility(hub, facilityToJoin).then(() => {\r\n $log.debug(`Joined facility ${facilityToJoin}`);\r\n subscribedFacility = currentFacility;\r\n resolve();\r\n });\r\n }\r\n });\r\n });\r\n };\r\n\r\n subscribedFacilityPromise = subscribedFacilityPromise.then(updateSubscription);\r\n }\r\n\r\n function isHubConnected() {\r\n if (hub === null || hub === undefined) {\r\n return false;\r\n }\r\n\r\n return hub.connection.state === $.signalR.connectionState.connected;\r\n }\r\n\r\n function isConnectionAllowedByAccessControl() {\r\n try {\r\n return configuration.canAccess(appSettings.site.accessControls) || false;\r\n\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n function onConnectionStateChanged(connectionState) {\r\n $log.debug(`State changed from '${getConnectionStateName(connectionState.oldState)}' to '${getConnectionStateName(connectionState.newState)}'.`);\r\n\r\n if (connectionState.newState === $.signalR.connectionState.disconnected) {\r\n // The only time that a hub connection goes directly from connected to disconnected is when it is explicitly closed\r\n // (e.g. the app is being torn down). In these cases, we don't want to reconnect.\r\n if (connectionState.oldState === $.signalR.connectionState.connected) {\r\n return;\r\n }\r\n\r\n reconnect();\r\n\r\n } else if (connectionState.newState === $.signalR.connectionState.connected) {\r\n if (reconnectionManager !== null) {\r\n reconnectionManager.reset();\r\n }\r\n\r\n updateSubscribedFacility();\r\n }\r\n }\r\n\r\n function reconnect() {\r\n if (reconnectionManager === null) {\r\n reconnectionManager = new HubReconnectionManager(hub);\r\n }\r\n\r\n reconnectionManager.reconnect();\r\n }\r\n\r\n function getConnectionStateName(state) {\r\n switch (state) {\r\n case $.signalR.connectionState.connecting: return `Connecting`;\r\n case $.signalR.connectionState.connected: return `Connected`;\r\n case $.signalR.connectionState.reconnecting: return `Reconnecting`;\r\n case $.signalR.connectionState.disconnected: return `Disconnected`;\r\n }\r\n\r\n throw new Error(`Unknown SignalR state: ${state}`);\r\n }\r\n\r\n function onError(error) {\r\n if (error.data) {\r\n $log.error(` Data - ${error.data && JSON.stringify(error.data)}`);\r\n }\r\n if (error.message) {\r\n const isTransient = /(websocket\\sclosed)|(No\\stransport\\scould\\sbe\\sinitialized\\ssuccessfully)/i.test(error.message) ;\r\n if (isTransient) {\r\n $log.warn(` Message - ${error.message}`);\r\n } else {\r\n $log.error(` Message - ${error.message}`, error);\r\n }\r\n }\r\n if (!isHubConnected()) {\r\n reconnect();\r\n }\r\n }\r\n };\r\n }\r\n\r\n hubReconnectionManagerFactory.$inject = [`$log`, `$timeout`];\r\n\r\n function hubReconnectionManagerFactory($logger, $timeout) {\r\n return function HubReconnectionManager(hub) {\r\n if (hub === null) {\r\n throw new Error(`You must provide the hub when creating a reconnection manager.`);\r\n }\r\n\r\n const millisPerMinute = 60 * 1000;\r\n const $log = new HubLogWrapper($logger, hub.name);\r\n\r\n const retryMinutes = [1, 2, 5, 10];\r\n let currentRetryMinutesIndex = null;\r\n let retryTimeout;\r\n\r\n ////////////////////\r\n\r\n this.reconnect = function() {\r\n currentRetryMinutesIndex = getNextRetryMinutesIndex();\r\n const minutes = retryMinutes[currentRetryMinutesIndex];\r\n\r\n $log.debug(`Retrying connection in ${minutes} min`);\r\n\r\n retryTimeout = $timeout(retryConnection, minutes * millisPerMinute);\r\n };\r\n\r\n function retryConnection() {\r\n retryTimeout = null;\r\n\r\n $log.debug(`Attempting to reconnect`);\r\n hub.connect();\r\n }\r\n\r\n function getNextRetryMinutesIndex() {\r\n if (currentRetryMinutesIndex === null) {\r\n return 0;\r\n }\r\n\r\n const nextIndex = currentRetryMinutesIndex + 1;\r\n return nextIndex < retryMinutes.length ? nextIndex : currentRetryMinutesIndex;\r\n }\r\n\r\n this.reset = function() {\r\n currentRetryMinutesIndex = null;\r\n\r\n if (retryTimeout) {\r\n $timeout.cancel(retryTimeout);\r\n retryTimeout = null;\r\n }\r\n };\r\n };\r\n }\r\n\r\n // Simple wrapper to prefix each log message with the hub that it originated from.\r\n // istanbul ignore next\r\n function HubLogWrapper($log, hubName) {\r\n const logPrefix = `SignalR Hub - ${hubName}`;\r\n\r\n function writeLog(logDelegate, messages) {\r\n logDelegate.apply(this, [logPrefix].concat(messages));\r\n }\r\n\r\n this.log = (...args) => writeLog($log.log, args);\r\n this.debug = (...args) => writeLog($log.debug, args);\r\n this.info = (...args) => writeLog($log.info, args);\r\n this.warn = (...args) => writeLog($log.warn, args);\r\n this.error = (...args) => writeLog($log.error, args);\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.signalR.hubsConnector`, hubsConnector);\r\n\r\n hubsConnector.$inject = [\r\n `$q`,\r\n `$log`,\r\n `lodash`,\r\n `app.core.signalR.jobs.jobStatusHub`,\r\n `app.core.signalR.alerts.alertStatusHub`\r\n ];\r\n\r\n function hubsConnector($q, $log, _, ...hubs) {\r\n let $connected$;\r\n\r\n return {\r\n connect\r\n };\r\n\r\n ////////////////////\r\n\r\n function connect() {\r\n if ($connected$) {\r\n return $connected$;\r\n }\r\n\r\n _.forEach(hubs, hub => {\r\n $log.debug(`Connecting to signalR hub: ${hub.name}`);\r\n hub.connect();\r\n });\r\n\r\n return $connected$ = $q.when(true);\r\n }\r\n }\r\n})();\r\n","//TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\r\n/* istanbul ignore next */\r\n(function(){\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.signalR.jobs.events`, getEvents());\r\n\r\n function getEvents() {\r\n return {\r\n channelName: `app.core.signalR.jobs`,\r\n topics: {\r\n progressUpdate: `progressUpdate`,\r\n jobStale: `jobStale`,\r\n jobCompleted: `jobCompleted`,\r\n jobDismissed: `jobDismissed`\r\n }\r\n };\r\n }\r\n})();\r\n","(function(){\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.signalR.jobs.jobStatusHub`, jobStatusHub);\r\n\r\n jobStatusHub.$inject = [\r\n `$log`,\r\n `$timeout`,\r\n `postal`,\r\n `lodash`,\r\n `app.core.appSettings`,\r\n `app.core.signalR.Hub`,\r\n `app.core.models.jobs.ModellingJob`,\r\n `app.core.models.jobs.jobCompletionStatus`,\r\n `app.core.signalR.jobs.events`,\r\n `app.core.signalR.jobs.state`\r\n ];\r\n function jobStatusHub($log, $timeout, postal, _, appSettings, Hub, ModellingJob, jobCompletionStatus, jobEvents, jobState) {\r\n const hubName = `jobStatusHub`;\r\n\r\n const channel = postal.channel(jobEvents.channelName);\r\n const hub = new Hub({\r\n hubName,\r\n canAccess: () => true,\r\n methods: [`subscribeJobStatus`, `unsubscribeJobStatus`],\r\n listeners: {\r\n jobBatchCreated: onJobBatchCreated,\r\n jobBatchUpdated: onJobBatchUpdated,\r\n jobBatchCompleted: onJobBatchCompleted,\r\n jobBatchDismissed: onJobBatchDismissed\r\n },\r\n joinFacility,\r\n leaveFacility\r\n });\r\n\r\n return {\r\n name: hubName,\r\n connect: hub.connect\r\n };\r\n\r\n ///////////////////\r\n\r\n function onJobBatchCreated(jobBatchId, requesterId, modelName, utcFromDateTime, utcToDateTime) {\r\n let job = getJobById(jobBatchId);\r\n if (job) {\r\n return;\r\n }\r\n\r\n const fromMillis = new Date(utcFromDateTime).getTime();\r\n const toMillis = new Date(utcToDateTime).getTime();\r\n\r\n job = new ModellingJob(jobBatchId, requesterId, fromMillis, toMillis, modelName);\r\n\r\n jobState.jobs.push(job);\r\n }\r\n\r\n function onJobBatchUpdated(jobBatchId, progress, progressMessage, errorMessage) {\r\n const job = getJobById(jobBatchId);\r\n if (!job) {\r\n return;\r\n }\r\n\r\n if (!job.hasStarted || job.progress < progress) {\r\n job.progress = parseInt(progress) || null;\r\n }\r\n\r\n job.addProgressMessage(progressMessage);\r\n job.addErrorMessage(errorMessage);\r\n\r\n publish(jobEvents.topics.progressUpdate, job);\r\n }\r\n\r\n function onJobBatchCompleted(jobBatchId, jobSucceededCount, jobFailedCount) {\r\n const completionStatus = jobCompletionStatus.calculate(jobSucceededCount, jobFailedCount);\r\n $log.debug(`Job ${jobBatchId} completed with ${jobSucceededCount} successful and ${jobFailedCount} failed constituents (overall status: ${completionStatus}).`);\r\n\r\n const job = getJobById(jobBatchId);\r\n if (!job) {\r\n return;\r\n }\r\n\r\n job.progress = 100;\r\n\r\n // cater for duplicate events which we seem to be getting now for some reason.\r\n if (completionStatus !== job.completionStatus) {\r\n job.completionStatus = completionStatus;\r\n publish(jobEvents.topics.jobCompleted, job);\r\n }\r\n }\r\n\r\n function onJobBatchDismissed(jobId) {\r\n const [job] = _.remove(jobState.jobs, { jobId });\r\n\r\n if (job) {\r\n publish(jobEvents.topics.jobDismissed, job);\r\n }\r\n }\r\n\r\n function joinFacility(signalRHub, facility) {\r\n return signalRHub.subscribeJobStatus(facility, appSettings.userId);\r\n }\r\n\r\n function leaveFacility(signalRHub, facility) {\r\n return signalRHub.unsubscribeJobStatus(facility, appSettings.userId);\r\n }\r\n\r\n function getJobById(jobId) {\r\n return _.find(jobState.jobs, { jobId });\r\n }\r\n\r\n function publish(topic, job) {\r\n $timeout(() => channel.publish(topic, job));\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .value(`app.core.signalR.jobs.state`, { jobs: [] });\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.core`)\n .factory(`app.core.states.monitoringTimeState`, monitoringTimeState);\n\n monitoringTimeState.$inject = [`app.core.datetime.timeZoneDateTime`];\n\n function monitoringTimeState(timeZoneDateTime) {\n\n let _dateTime = null;\n let _previousDateTime;\n\n const model = {\n isRealTime: false\n };\n\n Object.defineProperty(model, `dateTime`, {\n get: () => _dateTime,\n set: newValue => {\n _previousDateTime = _dateTime;\n _dateTime = newValue;\n },\n enumerable: true,\n configurable: true\n });\n\n model.facilityStartOfDay = () => timeZoneDateTime.getFacilityStartOfDay(_dateTime);\n model.facilityEndOfDay = () => timeZoneDateTime.getFacilityEndOfDay(_dateTime);\n model.dateTimeHasChangedDays = () => {\n if (!_previousDateTime || !_dateTime) {\n return false;\n }\n\n const previousStartOfDay = timeZoneDateTime.getFacilityStartOfDay(_previousDateTime);\n const currentStartOfDay = timeZoneDateTime.getFacilityStartOfDay(_dateTime);\n return previousStartOfDay.getTime() !== currentStartOfDay.getTime();\n };\n\n return model;\n }\n})();\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .factory(`app.core.datetime.timeZoneDateTime`, timeZoneDateTime);\r\n\r\n timeZoneDateTime.$inject = [`app.core.appSettings`, `moment`, `lodash`];\r\n\r\n function timeZoneDateTime(appSettings, moment, _) {\r\n\r\n const service = {\r\n getFacilityTimeZoneOffsetDifferenceFromLocal: getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes,\r\n convertDateTimeToFacilityTimeZone: convertDateTimeToFacilityTimeZone,\r\n convertFacilityDateTimeToLocalTimeZone : convertFacilityDateTimeToLocalTimeZone,\r\n\r\n getFacilityStartOfDay: getFacilityStartOfDay,\r\n getFacilityEndOfDay: getFacilityEndOfDay\r\n };\r\n\r\n return service;\r\n\r\n //////////////\r\n\r\n /*\r\n * e.g. 10 am in AEST (e.g. Brisbane) will give back 8am AWST (e.g. Perth) time.\r\n * e.g. 11am in AEDT (e.g. Sydney) will give back 8am AWST (e.g. Perth) time.\r\n */\r\n function convertDateTimeToFacilityTimeZone(localDateTime) {\r\n if (!localDateTime) {\r\n return null;\r\n }\r\n\r\n const offsetDifference = getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes(localDateTime);\r\n return moment(localDateTime).add(offsetDifference, `minute`).toDate();\r\n }\r\n\r\n function getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes(dateToOffset) {\r\n if (!_.isDate(dateToOffset)) {\r\n throw new Error(`A date must be supplied to get the offset. This is to cater for daylight savings time.`);\r\n }\r\n\r\n if (!appSettings.site.facility.ianaTimeZoneId) {\r\n // just use local time if not timezone is configured\r\n return 0;\r\n }\r\n\r\n return dateToOffset.getTimezoneOffset() - moment.tz.zone(appSettings.site.facility.ianaTimeZoneId).utcOffset(moment(dateToOffset).utc());\r\n }\r\n\r\n /*\r\n * e.g. 8am AWST (e.g. Perth) will give back 10am in AEST (e.g. Brisbane).\r\n * e.g. 8am AWST (e.g. Perth) will give back 11am in AEDT (e.g. Sydney).\r\n */\r\n function convertFacilityDateTimeToLocalTimeZone(facilityDateTime) {\r\n if (!facilityDateTime) {\r\n return null;\r\n }\r\n\r\n const offsetDifference = getFacilityTimeZoneOffsetDifferenceFromLocalInMinutes(facilityDateTime);\r\n return moment(facilityDateTime).add(-offsetDifference, `minute`).toDate();\r\n }\r\n\r\n\r\n // Given a local browser Date(); it offsets to the facility timezone before returning the midnight start of day.\r\n function getFacilityStartOfDay(localDateTime) {\r\n if (!localDateTime) {\r\n return null;\r\n }\r\n\r\n // e.g. it's 1am +10, November 2nd in Brisbane; the facility timezone is +8 (e.g. Western Australia)\r\n const facilityTime = convertDateTimeToFacilityTimeZone(localDateTime); // // returns 11pm +10, November 1st.\r\n return moment(facilityTime).startOf(`day`).toDate(); // 00:00:00 +10, November 1st\r\n }\r\n\r\n // Given a local browser Date(); it offsets to the facility timezone before return the midnight end of day.\r\n function getFacilityEndOfDay(localDateTime) {\r\n if (!localDateTime) {\r\n return null;\r\n }\r\n\r\n // e.g. it's 1am +10, November 2nd in Brisbane; the facility timezone is +8 (e.g. Western Australia)\r\n const facilityTime = convertDateTimeToFacilityTimeZone(localDateTime); // returns 11pm +10 November 1st.\r\n return moment(facilityTime).endOf(`day`).toDate(); // 23:59:59 +10 November 1st\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esAfterDate`, esAfterDate);\r\n\r\n esAfterDate.$inject = [\r\n `kendo`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function esAfterDate(kendo, dateTimeService) {\r\n return {\r\n require: `ngModel`,\r\n link: function($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.afterDate = (modelValue, viewValue) => {\r\n if (ngModel.$isEmpty(viewValue)) {\r\n return true;\r\n }\r\n const options = $scope.$eval(attrs.kOptions);\r\n const format = options && options.format && [options.format] || [dateTimeService.formats.kendo.dateTime, dateTimeService.formats.kendo.date];\r\n\r\n const viewDate = kendo.parseDate(viewValue, format);\r\n if (!viewDate) {\r\n return true;\r\n }\r\n\r\n const compareDateProperty = attrs.esAfterDate;\r\n const compareDate = $scope.$eval(compareDateProperty);\r\n\r\n return !compareDate || viewDate > compareDate;\r\n };\r\n }\r\n };\r\n }\r\n \r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esAngle`, esAngle);\r\n\r\n esAngle.$inject = [];\r\n\r\n function esAngle() {\r\n return {\r\n require: `ngModel`,\r\n link: function($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.angle = modelValue => {\r\n if (ngModel.$isEmpty(modelValue)) {\r\n return true;\r\n }\r\n\r\n const angle = parseInt(modelValue);\r\n return angle >= -360 && angle <= 360;\r\n };\r\n }\r\n };\r\n }\r\n \r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esBeforeDate`, esBeforeDate);\r\n\r\n esBeforeDate.$inject = [\r\n `kendo`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function esBeforeDate(kendo, dateTimeService) {\r\n return {\r\n require: `ngModel`,\r\n link: function ($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.beforeDate = (modelValue, viewValue) => {\r\n if (ngModel.$isEmpty(viewValue)) {\r\n return true;\r\n }\r\n\r\n const options = $scope.$eval(attrs.kOptions);\r\n const format = options && options.format && [options.format] || [dateTimeService.formats.kendo.dateTime, dateTimeService.formats.kendo.date];\r\n\r\n const viewDate = kendo.parseDate(viewValue, format);\r\n if (!viewDate) {\r\n return true;\r\n }\r\n\r\n const compareDateProperty = attrs.esBeforeDate;\r\n const compareDate = $scope.$eval(compareDateProperty);\r\n\r\n return !compareDate || viewDate < compareDate;\r\n };\r\n }\r\n };\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esDecimal`, esDecimal);\r\n\r\n esDecimal.$inject = [];\r\n\r\n function esDecimal() {\r\n return {\r\n require: `ngModel`,\r\n scope: {\r\n decimalPlaces : `=esDecimal`\r\n },\r\n link: function($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.decimal = modelValue => {\r\n if (ngModel.$isEmpty(modelValue)) {\r\n return true;\r\n }\r\n\r\n if (isNaN(Number(modelValue))) {\r\n return false;\r\n }\r\n\r\n let decimalPlaces = parseInt($scope.decimalPlaces);\r\n decimalPlaces = isNaN(decimalPlaces) ? 2 : decimalPlaces;\r\n\r\n const decimalValue = parseFloat(modelValue);\r\n return parseFloat(decimalValue.toFixed(decimalPlaces)) === decimalValue;\r\n };\r\n }\r\n };\r\n }\r\n \r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esLatitude`, esLatitude);\r\n\r\n esLatitude.$inject = [];\r\n\r\n function esLatitude() {\r\n return {\r\n require: `ngModel`,\r\n link: function($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.latitude = modelValue => {\r\n if (ngModel.$isEmpty(modelValue)) {\r\n return true;\r\n }\r\n\r\n const latitude = parseFloat(modelValue);\r\n return latitude >= -90 && latitude <= 90;\r\n };\r\n }\r\n };\r\n }\r\n \r\n})();","(function () {\n `use strict`;\n\n angular\n .module(`app.core`)\n .directive(`esLongitude`, esLongitude);\n\n esLongitude.$inject = [];\n\n function esLongitude() {\n return {\n require: `ngModel`,\n link: function($scope, $element, attrs, ngModel) {\n ngModel.$validators.longitude = modelValue => {\n if (ngModel.$isEmpty(modelValue)) {\n return true;\n }\n\n const longitude = parseFloat(modelValue);\n return longitude >= -180 && longitude <= 180;\n };\n }\n };\n }\n \n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esNoxScale`, esNoxScale);\r\n\r\n esNoxScale.$inject = [];\r\n\r\n function esNoxScale() {\r\n return {\r\n require: `ngModel`,\r\n scope: {\r\n },\r\n link: function($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.noxScale = modelValue => {\r\n if (ngModel.$isEmpty(modelValue)) {\r\n return true;\r\n }\r\n\r\n if (isNaN(Number(modelValue))) {\r\n return false;\r\n }\r\n\r\n const decimalValue = parseFloat(modelValue);\r\n const isValid = parseFloat(decimalValue.toFixed(6)) === decimalValue && decimalValue > 0;\r\n return isValid;\r\n };\r\n }\r\n };\r\n }\r\n \r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esPassword`, validator);\r\n\r\n validator.$inject = [`app.core.services.userService`];\r\n\r\n function validator(appSettings) {\r\n return {\r\n require: `ngModel`,\r\n link: function($scope, $element, $attrs, ctrl) {\r\n ctrl.$validators.password = modelValue => {\r\n if (modelValue === null || modelValue === undefined) {\r\n return true;\r\n }\r\n\r\n const { username } = appSettings.getUserDetails().$$state.value;\r\n const isPasswordValid =\r\n validateMinLength(modelValue) &&\r\n validateContainsLowercaseLetter(modelValue) &&\r\n validateContainsUppercaseLetter(modelValue) &&\r\n validateContainsNumber(modelValue) &&\r\n validateContainsSpecialCharacter(modelValue) &&\r\n validateUsernamePasswordNotTheSame(username, modelValue);\r\n\r\n return isPasswordValid;\r\n };\r\n }\r\n };\r\n }\r\n\r\n function validateMinLength(password) {\r\n return password.length >= 14;\r\n }\r\n\r\n function validateContainsLowercaseLetter(password) {\r\n return /[a-z]/.test(password);\r\n }\r\n\r\n function validateContainsUppercaseLetter(password) {\r\n return /[A-Z]/.test(password);\r\n }\r\n\r\n function validateContainsSpecialCharacter(password) {\r\n return /[\\s!'\"`#$%&*+-./\\\\:;<=>?@^_{}|~\\[\\]]/.test(password);\r\n }\r\n\r\n function validateContainsNumber(password) {\r\n return /\\d/.test(password);\r\n }\r\n\r\n function validateUsernamePasswordNotTheSame(username, password) {\r\n return !password.toUpperCase().includes(username.toUpperCase());\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esUnique`, validator);\r\n\r\n validator.$inject = [];\r\n\r\n function validator() {\r\n return {\r\n require: `ngModel`,\r\n link: function($scope, $element, $attrs, ngModel) {\r\n ngModel.$validators.unique = modelValue => {\r\n if (ngModel.$isEmpty(modelValue)) {\r\n return true;\r\n }\r\n\r\n const collection = $scope.$eval($attrs.esUnique);\r\n if (!(collection && collection.length)) {\r\n return true;\r\n }\r\n\r\n const matches = collection.filter(value => value === modelValue);\r\n return matches.length === 1;\r\n };\r\n }\r\n };\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .directive(`esValidDate`, esValidDate);\r\n\r\n esValidDate.$inject = [\r\n `kendo`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function esValidDate(kendo, dateTimeService) {\r\n return {\r\n require: `ngModel`,\r\n link: function($scope, $element, attrs, ngModel) {\r\n ngModel.$validators.validDate = (modelValue, viewValue) => {\r\n if (ngModel.$isEmpty(viewValue)) {\r\n return true;\r\n }\r\n const options = $scope.$eval(attrs.kOptions);\r\n const format = options && options.format && [options.format] || [dateTimeService.formats.kendo.dateTime, dateTimeService.formats.kendo.date];\r\n return kendo.parseDate(viewValue, format) !== null;\r\n };\r\n }\r\n };\r\n }\r\n \r\n})();","`use strict`;\r\n\r\nDate.equals = function(left, right) {\r\n if ((left === undefined || left === null) && (right === undefined || right === null)) {\r\n return true;\r\n }\r\n\r\n if (!(left instanceof Date && right instanceof Date)) {\r\n return false;\r\n }\r\n\r\n return left.getTime() === right.getTime();\r\n};","/**\r\n * Kendo UI v2019.1.220 (http://www.telerik.com/kendo-ui)\r\n * Copyright 2019 Progress Software Corporation and/or one of its subsidiaries or affiliates. All rights reserved.\r\n *\r\n * Kendo UI commercial licenses may be obtained at\r\n * http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\r\n * If you do not own a commercial license, this file shall be governed by the trial license terms.\r\n *\r\n * NOTE:\r\n *\r\n * This file was manually built by copy/pasting the files from the CDN -\r\n * e.g.\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.en.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.en-AU.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.es.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.fr.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.vi.min.js\r\n * http://kendo.cdn.telerik.com/2019.1.220/js/cultures/kendo.culture.zh.min.js\r\n *\r\n * NOTE:\r\n * This file has been extensively alterd to adjust special charactures from none english\r\n * alphabets to work with ES. The function layout remains identical to the CDN files but\r\n * contains formatting for readability. Updating with files listed above will loose these changes.\r\n */\r\n!function(e) {\r\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\r\n}(function() {\r\n !function(e, y) {\r\n kendo.cultures.en = {\r\n name: \"en\",\r\n numberFormat: {\r\n pattern: [\"-n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n percent: { pattern: [\"-n %\", \"n %\"], decimals: 2, \",\": \",\", \".\": \".\", groupSize: [3], symbol: \"%\" },\r\n currency: {\r\n name: \"\",\r\n abbr: \"\",\r\n pattern: [\"($n)\", \"$n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n symbol: \"$\"\r\n }\r\n },\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\r\n namesAbbr: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\r\n namesShort: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\r\n },\r\n months: {\r\n names: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\r\n namesAbbr: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\r\n },\r\n AM: [\"AM\", \"am\", \"AM\"],\r\n PM: [\"PM\", \"pm\", \"PM\"],\r\n patterns: {\r\n d: \"M/d/yyyy\",\r\n D: \"dddd, MMMM d, yyyy\",\r\n F: \"dddd, MMMM d, yyyy h:mm:ss tt\",\r\n g: \"M/d/yyyy h:mm tt\",\r\n G: \"M/d/yyyy h:mm:ss tt\",\r\n m: \"MMMM d\",\r\n M: \"MMMM d\",\r\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\r\n t: \"h:mm tt\",\r\n T: \"h:mm:ss tt\",\r\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\r\n y: \"MMMM yyyy\",\r\n Y: \"MMMM yyyy\"\r\n },\r\n \"/\": \"/\",\r\n \":\": \":\",\r\n firstDay: 0\r\n }\r\n }\r\n };\r\n }(this);\r\n});\r\n!function(e) {\r\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\r\n}(function() {\r\n !function(e, y) {\r\n kendo.cultures[\"en-AU\"] = {\r\n name: \"en-AU\",\r\n numberFormat: {\r\n pattern: [\"-n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n percent: { pattern: [\"-n%\", \"n%\"], decimals: 2, \",\": \",\", \".\": \".\", groupSize: [3], symbol: \"%\" },\r\n currency: {\r\n name: \"Australian Dollar\",\r\n abbr: \"AUD\",\r\n pattern: [\"-$n\", \"$n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n symbol: \"$\"\r\n }\r\n },\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\r\n namesAbbr: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\r\n namesShort: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\r\n },\r\n months: {\r\n names: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\r\n namesAbbr: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\r\n },\r\n AM: [\"AM\", \"am\", \"AM\"],\r\n PM: [\"PM\", \"pm\", \"PM\"],\r\n patterns: {\r\n d: \"d/MM/yyyy\",\r\n D: \"dddd, d MMMM yyyy\",\r\n F: \"dddd, d MMMM yyyy h:mm:ss tt\",\r\n g: \"d/MM/yyyy h:mm tt\",\r\n G: \"d/MM/yyyy h:mm:ss tt\",\r\n m: \"d MMMM\",\r\n M: \"d MMMM\",\r\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\r\n t: \"h:mm tt\",\r\n T: \"h:mm:ss tt\",\r\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\r\n y: \"MMMM yyyy\",\r\n Y: \"MMMM yyyy\"\r\n },\r\n \"/\": \"/\",\r\n \":\": \":\",\r\n firstDay: 1\r\n }\r\n }\r\n };\r\n }(this);\r\n});\r\n!function(e) {\r\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\r\n}(function() {\r\n !function(e, d) {\r\n kendo.cultures.es = {\r\n name: \"es\",\r\n numberFormat: {\r\n pattern: [\"-n\"],\r\n decimals: 2,\r\n \",\": \".\",\r\n \".\": \",\",\r\n groupSize: [3],\r\n percent: { pattern: [\"-n %\", \"n %\"], decimals: 2, \",\": \".\", \".\": \",\", groupSize: [3], symbol: \"%\" },\r\n currency: {\r\n name: \"\",\r\n abbr: \"\",\r\n pattern: [\"-n $\", \"n $\"],\r\n decimals: 2,\r\n \",\": \".\",\r\n \".\": \",\",\r\n groupSize: [3],\r\n symbol: \"€\"\r\n }\r\n },\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: [\"domingo\", \"lunes\", \"martes\", \"miércoles\", \"jueves\", \"viernes\", \"sábado\"],\r\n namesAbbr: [\"do.\", \"lu.\", \"ma.\", \"mi.\", \"ju.\", \"vi.\", \"sá.\"],\r\n namesShort: [\"D\", \"L\", \"M\", \"X\", \"J\", \"V\", \"S\"]\r\n },\r\n months: {\r\n names: [\"enero\", \"febrero\", \"marzo\", \"abril\", \"mayo\", \"junio\", \"julio\", \"agosto\", \"septiembre\", \"octubre\", \"noviembre\", \"diciembre\"],\r\n namesAbbr: [\"ene.\", \"feb.\", \"mar.\", \"abr.\", \"may.\", \"jun.\", \"jul.\", \"ago.\", \"sep.\", \"oct.\", \"nov.\", \"dic.\"]\r\n },\r\n AM: [\"\"],\r\n PM: [\"\"],\r\n patterns: {\r\n d: \"dd/MM/yyyy\",\r\n D: \"dddd, d' de 'MMMM' de 'yyyy\",\r\n F: \"dddd, d' de 'MMMM' de 'yyyy H:mm:ss\",\r\n g: \"dd/MM/yyyy H:mm\",\r\n G: \"dd/MM/yyyy H:mm:ss\",\r\n m: \"d 'de' MMMM\",\r\n M: \"d 'de' MMMM\",\r\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\r\n t: \"H:mm\",\r\n T: \"H:mm:ss\",\r\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\r\n y: \"MMMM' de 'yyyy\",\r\n Y: \"MMMM' de 'yyyy\"\r\n },\r\n \"/\": \"/\",\r\n \":\": \":\",\r\n firstDay: 1\r\n }\r\n }\r\n };\r\n }(this);\r\n});\r\n!function(e) {\r\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], e) : e();\r\n}(function() {\r\n !function(e, d) {\r\n kendo.cultures.fr = {\r\n name: \"fr\",\r\n numberFormat: {\r\n pattern: [\"-n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n percent: { pattern: [\"-n %\", \"n %\"], decimals: 2, \",\": \"Â \", \".\": \",\", groupSize: [3], symbol: \"%\" },\r\n currency: {\r\n name: \"\",\r\n abbr: \"\",\r\n pattern: [\"-n $\", \"n $\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n symbol: \"€\"\r\n }\r\n },\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: [\"dimanche\", \"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\", \"samedi\"],\r\n namesAbbr: [\"dim.\", \"lun.\", \"mar.\", \"mer.\", \"jeu.\", \"ven.\", \"sam.\"],\r\n namesShort: [\"di\", \"lu\", \"ma\", \"me\", \"je\", \"ve\", \"sa\"]\r\n },\r\n months: {\r\n names: [\"janvier\", \"février\", \"mars\", \"avril\", \"mai\", \"juin\", \"juillet\", \"août\", \"septembre\", \"octobre\", \"novembre\", \"décembre\"],\r\n namesAbbr: [\"janv.\", \"févr.\", \"mars\", \"avr.\", \"mai\", \"juin\", \"juil.\", \"août\", \"sept.\", \"oct.\", \"nov.\", \"déc.\"]\r\n },\r\n AM: [\"\"],\r\n PM: [\"\"],\r\n patterns: {\r\n d: \"dd/MM/yyyy\",\r\n D: \"dddd d MMMM yyyy\",\r\n F: \"dddd d MMMM yyyy HH:mm:ss\",\r\n g: \"dd/MM/yyyy HH:mm\",\r\n G: \"dd/MM/yyyy HH:mm:ss\",\r\n m: \"d MMMM\",\r\n M: \"d MMMM\",\r\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\r\n t: \"HH:mm\",\r\n T: \"HH:mm:ss\",\r\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\r\n y: \"MMMM yyyy\",\r\n Y: \"MMMM yyyy\"\r\n },\r\n \"/\": \"/\",\r\n \":\": \":\",\r\n firstDay: 1\r\n }\r\n }\r\n };\r\n }(this);\r\n});\r\n!function(n) {\r\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], n) : n();\r\n}(function() {\r\n !function(n, a) {\r\n kendo.cultures.vi = {\r\n name: \"vi\",\r\n numberFormat: {\r\n pattern: [\"-n\"],\r\n decimals: 2,\r\n \",\": \".\",\r\n \".\": \",\",\r\n groupSize: [3],\r\n percent: { pattern: [\"-n%\", \"n%\"], decimals: 2, \",\": \".\", \".\": \",\", groupSize: [3], symbol: \"%\" },\r\n currency: {\r\n name: \"\",\r\n abbr: \"\",\r\n pattern: [\"-n $\", \"n $\"],\r\n decimals: 2,\r\n \",\": \".\",\r\n \".\": \",\",\r\n groupSize: [3],\r\n symbol: \"₫\"\r\n }\r\n },\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: [\"Chủ nhật\", \"Thứ hai\", \"Thứ ba\", \"Thứ tư\", \"Thứ năm\", \"Thứ sáu\", \"Ngày thứ bảy\"],\r\n namesAbbr: [\"CN\", \"T2\", \"T3\", \"T4\", \"T5\", \"T6\", \"T7\"],\r\n namesShort: [\"C\", \"H\", \"B\", \"T\", \"N\", \"S\", \"B\"]\r\n },\r\n months: {\r\n names: [\"Tháng Giêng\", \"Tháng hai\", \"Tháng Ba\", \"Tháng tư\", \"Có thể\", \"Tháng sáu\", \"Tháng bảy\", \"Tháng Tám\", \"Tháng Chín\", \"Tháng Mười\", \"Tháng mười một\", \"Tháng mười hai\"],\r\n namesAbbr: [\"Thg1\", \"Thg2\", \"Thg3\", \"Thg4\", \"Thg5\", \"Thg6\", \"Thg7\", \"Thg8\", \"Thg9\", \"Thg10\", \"Thg11\", \"Thg12\"]\r\n },\r\n AM: [\"SA\", \"sa\", \"SA\"],\r\n PM: [\"CH\", \"ch\", \"CH\"],\r\n patterns: {\r\n d: \"dd/MM/yyyy\",\r\n D: \"dd MMMM yyyy\",\r\n F: \"dd MMMM yyyy h:mm:ss tt\",\r\n g: \"dd/MM/yyyy h:mm tt\",\r\n G: \"dd/MM/yyyy h:mm:ss tt\",\r\n m: \"dd MMMM\",\r\n M: \"dd MMMM\",\r\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\r\n t: \"h:mm tt\",\r\n T: \"h:mm:ss tt\",\r\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\r\n y: \"MMMM yyyy\",\r\n Y: \"MMMM yyyy\"\r\n },\r\n \"/\": \"/\",\r\n \":\": \":\",\r\n firstDay: 1\r\n }\r\n }\r\n };\r\n }(this);\r\n});\r\n!function(y) {\r\n \"function\" == typeof define && define.amd ? define([\"kendo.core.min\"], y) : y();\r\n}(function() {\r\n !function(y, n) {\r\n kendo.cultures.zh = {\r\n name: \"zh\",\r\n numberFormat: {\r\n pattern: [\"-n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n percent: { pattern: [\"-n%\", \"n%\"], decimals: 2, \",\": \",\", \".\": \".\", groupSize: [3], symbol: \"%\" },\r\n currency: {\r\n name: \"\",\r\n abbr: \"\",\r\n pattern: [\"$-n\", \"$n\"],\r\n decimals: 2,\r\n \",\": \",\",\r\n \".\": \".\",\r\n groupSize: [3],\r\n symbol: \"¥\"\r\n }\r\n },\r\n calendars: {\r\n standard: {\r\n days: {\r\n names: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"],\r\n namesAbbr: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"],\r\n namesShort: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"]\r\n },\r\n months: {\r\n names: [\"一月\", \"二月\", \"游行\", \"四月\", \"可以\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"],\r\n namesAbbr: [\"1月\", \"2月\", \"3月\", \"4月\", \"5月\", \"6月\", \"7月\", \"8月\", \"9月\", \"10月\", \"11月\", \"12月\"]\r\n },\r\n AM: [\"上午。\", \"上午。\", \"上午。\"],\r\n PM: [\"下午。\", \"下午。\", \"下午。\"],\r\n patterns: {\r\n d: \"yyyy/M/d\",\r\n D: \"yyyy'年'M'月'd'日'\",\r\n F: \"yyyy'年'M'月'd'日' H:mm:ss\",\r\n g: \"yyyy/M/d H:mm\",\r\n G: \"yyyy/M/d H:mm:ss\",\r\n m: \"M月d日\",\r\n M: \"M月d日\",\r\n s: \"yyyy'-'MM'-'dd'T'HH':'mm':'ss\",\r\n t: \"H:mm\",\r\n T: \"H:mm:ss\",\r\n u: \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\",\r\n y: \"yyyy'年'M'月'\",\r\n Y: \"yyyy'年'M'月'\"\r\n },\r\n \"/\": \"/\",\r\n \":\": \":\",\r\n firstDay: 1\r\n }\r\n }\r\n };\r\n }(this);\r\n});\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .config(ArrowMultiPolyLine);\r\n\r\n ArrowMultiPolyLine.$inject = [`lodash`, `leafletLib`];\r\n function ArrowMultiPolyLine(_, L) {\r\n const defaultArrowHeadFactor = 0.2;\r\n const defaultArrowHeadAngle = 25;\r\n const defaultScale = 200;\r\n L.es = L.es || {};\r\n\r\n L.es.ArrowMultiPolyLine = L.Polyline.extend({\r\n initialize: function(windArrows, options) {\r\n let arrowPointCollection = [];\r\n _.forEach(windArrows, windArrow => {\r\n const arrowPoints = this._getArrowPoints(windArrow.point, windArrow.bearing, windArrow.magnitude, options || {});\r\n arrowPointCollection = arrowPointCollection.concat(arrowPoints);\r\n });\r\n\r\n L.Polyline.prototype.initialize.call(this, arrowPointCollection, options);\r\n },\r\n\r\n _getArrowPoints: function(point, bearing, magnitude, options) {\r\n const\r\n arrowHeadFactor = options.arrowHeadFactor || defaultArrowHeadFactor,\r\n arrowHeadAngle = options.arrowHeadAngle || defaultArrowHeadAngle,\r\n scale = options.scale || defaultScale;\r\n\r\n const\r\n tail = point.destinationPoint(bearing, magnitude * scale),\r\n arrowBackTick1 = point.destinationPoint(bearing + arrowHeadAngle, magnitude * scale * arrowHeadFactor),\r\n arrowBackTick2 = point.destinationPoint(bearing - arrowHeadAngle, magnitude * scale * arrowHeadFactor);\r\n\r\n const points = [[point, tail], [point, arrowBackTick1], [point, arrowBackTick2]];\r\n return points;\r\n }\r\n\r\n });\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n angular\r\n .module(`app.core`)\r\n .config(corridorPlugin);\r\n\r\n /*\r\n Borrowed from https://github.com/mikhailshilkov/leaflet-corridor\r\n */\r\n corridorPlugin.$inject = [`leafletLib`];\r\n function corridorPlugin(L) {\r\n L.Corridor = L.Polyline.extend({\r\n initialize: function (latlngs, options) {\r\n const self = this;\r\n L.Polyline.prototype.initialize.call(this, latlngs, options);\r\n this.corridor = options.corridor;\r\n this.updateCallback = function() {\r\n self._updateWeight(this);\r\n };\r\n },\r\n\r\n onAdd: function(map) {\r\n L.Polyline.prototype.onAdd.call(this, map);\r\n map.on(`zoomend`, this.updateCallback);\r\n this._updateWeight(map);\r\n },\r\n\r\n onRemove: function(map) {\r\n map.off(`zoomend`, this.updateCallback);\r\n L.Polyline.prototype.onRemove.call(this, map);\r\n },\r\n\r\n _updateWeight: function(map) {\r\n this.setStyle({ weight : this._getWeight(map, this.corridor) });\r\n },\r\n\r\n _getWeight: function (map, corridor) {\r\n return corridor * 2 / this._getMetersPerPixel(map);\r\n },\r\n\r\n _getMetersPerPixel: function(map) {\r\n const centerLatLng = map.getCenter(); // get map center\r\n const pointC = map.latLngToContainerPoint(centerLatLng); // convert to containerpoint (pixels)\r\n const pointX = L.point(pointC.x + 10, pointC.y); // add 10 pixels to x\r\n\r\n // convert containerpoints to latlngs\r\n const latLngX = map.containerPointToLatLng(pointX);\r\n return centerLatLng.distanceTo(latLngX) / 10; // calculate distance between c and x (latitude)\r\n }\r\n });\r\n\r\n L.corridor = function (latlngs, options) {\r\n return new L.Corridor(latlngs, options || { corridor: 100 });\r\n };\r\n }\r\n})();\r\n","(function(L){\r\n `use strict`;\r\n\r\n L.Control.EasyButtons = L.Control.extend({\r\n\r\n initialize: function (options) {\r\n L.Control.prototype.initialize.call(this, options);\r\n },\r\n disable: function() {\r\n this.isEnabled = false;\r\n if (this.link) {\r\n L.DomUtil.addClass(this.link, `leaflet-disabled`);\r\n }\r\n },\r\n enable: function() {\r\n this.isEnabled = true;\r\n if (this.link) {\r\n L.DomUtil.removeClass(this.link, `leaflet-disabled`);\r\n }\r\n },\r\n onAdd: function () {\r\n const container = L.DomUtil.create(`div`, `leaflet-bar leaflet-control`);\r\n L.DomEvent.disableClickPropagation(container);\r\n\r\n this.link = L.DomUtil.create(`a`, `leaflet-bar-part`, container);\r\n this.link.href = `#`;\r\n this.link.title = this.options.title;\r\n L.DomEvent.on(this.link, `click`, this._click, this);\r\n if (!this.isEnabled){\r\n L.DomUtil.addClass(this.link, `leaflet-disabled`);\r\n }\r\n\r\n const icon = this.options.icon || `fa-lemon-o`;\r\n const extraClasses = icon.lastIndexOf(`fa`, 0) === 0 ? ` fa fa-lg` : ` glyphicon`;\r\n L.DomUtil.create(`i`, icon + extraClasses, this.link);\r\n\r\n return container;\r\n },\r\n onRemove: function(){\r\n L.DomEvent.off(this.link, `click`, this._click);\r\n },\r\n setActive: function(){\r\n if (this.link) {\r\n L.DomUtil.addClass(this.link, `leaflet-active`);\r\n }\r\n },\r\n setInactive: function(){\r\n if (this.link) {\r\n L.DomUtil.removeClass(this.link, `leaflet-active`);\r\n }\r\n },\r\n _click: function (e) {\r\n L.DomEvent.stop(e);\r\n\r\n if (this.options.click && this.isEnabled) {\r\n this.options.click(e);\r\n }\r\n }\r\n });\r\n\r\n})(L); // eslint-disable-line no-undef\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n /*\r\n Copied from https://github.com/shramov/leaflet-plugins/blob/1.9.3/layer/tile/Google.js - which doesn`t work with Leaflet 1.x.\r\n Looks like the Layer plugins now have to extend L.GridLayer/L.TileLayer where before they just extended L.Class\r\n */\r\n angular\r\n .module(`app.core`)\r\n .config(googlePlugin);\r\n\r\n googlePlugin.$inject = [`leafletLib`, `google`];\r\n function googlePlugin(L, google) {\r\n\r\n L.GoogleLayer = L.TileLayer.extend({\r\n options: {\r\n minZoom: 0,\r\n maxZoom: 18,\r\n tileSize: 256,\r\n subdomains: `abc`,\r\n errorTileUrl: ``,\r\n attribution: ``,\r\n opacity: 1,\r\n continuousWorld: false,\r\n noWrap: false,\r\n mapOptions: {\r\n backgroundColor: `#dddddd`\r\n }\r\n },\r\n\r\n initialize: function (type, options) {\r\n L.Util.setOptions(this, options);\r\n this._ready = L.GoogleLayer.isGoogleMapsReady();\r\n if (!this._ready) {\r\n L.GoogleLayer.asyncWait.push(this);\r\n }\r\n this._type = type || `SATELLITE`;\r\n },\r\n\r\n onAdd: function (map) {\r\n this._map = map;\r\n // create a container div for tiles\r\n this._initContainer();\r\n this._initMapObject();\r\n\r\n // set up events\r\n map.on(`viewreset`, this._reset, this);\r\n L.Util.throttle(this._update, 150, this);\r\n map.on(`move`, this._update, this);\r\n\r\n map.on(`zoomanim`, this._handleZoomAnim, this);\r\n\r\n //20px instead of 1em to avoid a slight overlap with google`s attribution\r\n map._controlCorners.bottomright.style.marginBottom = `20px`;\r\n\r\n this._reset();\r\n this._update();\r\n\r\n L.TileLayer.prototype.onAdd.apply(this, [map]);\r\n },\r\n\r\n onRemove: function (map) {\r\n map._container.removeChild(this._container);\r\n map.off(`viewreset`, this._reset, this);\r\n map.off(`move`, this._update, this);\r\n map.off(`zoomanim`, this._handleZoomAnim, this);\r\n if (map._controlCorners && map._controlCorners.bottomright){\r\n map._controlCorners.bottomright.style.marginBottom = `0em`;\r\n }\r\n\r\n L.TileLayer.prototype.onRemove.apply(this, [map]);\r\n },\r\n\r\n getAttribution: function () {\r\n return this.options.attribution;\r\n },\r\n\r\n setOpacity: function (opacity) {\r\n this.options.opacity = opacity;\r\n if (opacity < 1) {\r\n L.DomUtil.setOpacity(this._container, opacity);\r\n }\r\n },\r\n\r\n setElementSize: function (e, size) {\r\n e.style.width = size.x + `px`;\r\n e.style.height = size.y + `px`;\r\n },\r\n\r\n _initContainer: function () {\r\n const tilePane = this._map._container;\r\n const first = tilePane.firstChild;\r\n\r\n if (!this._container) {\r\n this._container = L.DomUtil.create(`div`, `leaflet-google-layer leaflet-top leaflet-left`);\r\n this._container.id = `_GMapContainer_` + L.Util.stamp(this);\r\n this._container.style.zIndex = `auto`;\r\n }\r\n\r\n tilePane.insertBefore(this._container, first);\r\n\r\n this.setOpacity(this.options.opacity);\r\n this.setElementSize(this._container, this._map.getSize());\r\n },\r\n _initMapObject: function () {\r\n if (!this._ready) {\r\n return;\r\n }\r\n this._googleCenter = new google.maps.LatLng(0, 0);\r\n const map = new google.maps.Map(this._container, {\r\n center: this._googleCenter,\r\n zoom: 0,\r\n tilt: 0,\r\n mapTypeId: google.maps.MapTypeId[this._type],\r\n disableDefaultUI: true,\r\n keyboardShortcuts: false,\r\n draggable: false,\r\n disableDoubleClickZoom: true,\r\n scrollwheel: false,\r\n streetViewControl: false,\r\n styles: this.options.mapOptions.styles,\r\n backgroundColor: this.options.mapOptions.backgroundColor\r\n });\r\n\r\n const self = this;\r\n google.maps.event.addListenerOnce(map, `center_changed`, function () { self.onReposition(); });\r\n this._google = map;\r\n\r\n google.maps.event.addListenerOnce(map, `idle`, function() { self._checkZoomLevels(); });\r\n google.maps.event.addListenerOnce(map, `tilesloaded`, function() { self.fire(`load`); } ) ;\r\n //Reporting that map-object was initialized.\r\n this.fire(`MapObjectInitialized`, { mapObject: map });\r\n },\r\n\r\n _checkZoomLevels: function () {\r\n //setting the zoom level on the Google map may result in a different zoom level than the one requested\r\n //(it won`t go beyond the level for which they have data).\r\n // verify and make sure the zoom levels on both Leaflet and Google maps are consistent\r\n if (this._map){\r\n if (this._map.getZoom() !== undefined && this._google.getZoom() !== this._map.getZoom()) {\r\n //zoom levels are out of sync. Set the leaflet zoom level to match the google one\r\n this._map.setZoom(this._google.getZoom());\r\n }\r\n }\r\n },\r\n\r\n _reset: function () {\r\n this._initContainer();\r\n },\r\n\r\n _update: function () {\r\n if (!this._google) {\r\n return;\r\n }\r\n this._resize();\r\n\r\n const center = this._map.getCenter();\r\n const centerLatLng = new google.maps.LatLng(center.lat, center.lng);\r\n\r\n this._google.setCenter(centerLatLng);\r\n if (this._map.getZoom() !== undefined){\r\n this._google.setZoom(Math.round(this._map.getZoom()));\r\n }\r\n this._checkZoomLevels();\r\n },\r\n\r\n _resize: function () {\r\n const size = this._map.getSize();\r\n if (this._container.style.width === size.x &&\r\n this._container.style.height === size.y){\r\n return;\r\n }\r\n this.setElementSize(this._container, size);\r\n this.onReposition();\r\n },\r\n\r\n _handleZoomAnim: function (e) {\r\n const center = e.center;\r\n const _center = new google.maps.LatLng(center.lat, center.lng);\r\n\r\n this._google.setCenter(_center);\r\n this._google.setZoom(Math.round(e.zoom));\r\n },\r\n\r\n onReposition: function () {\r\n if (!this._google) {\r\n return;\r\n }\r\n google.maps.event.trigger(this._google, `resize`);\r\n }\r\n\r\n });\r\n\r\n L.GoogleLayer.asyncWait = [];\r\n L.GoogleLayer.asyncInitialize = function () {\r\n for (let i = 0; i < L.GoogleLayer.asyncWait.length; i++) {\r\n const o = L.GoogleLayer.asyncWait[i];\r\n o._ready = true;\r\n if (o._container) {\r\n o._initMapObject();\r\n o._update();\r\n }\r\n }\r\n L.GoogleLayer.asyncWait = [];\r\n };\r\n L.GoogleLayer.isGoogleMapsReady = function () {\r\n return !!window.google && !!window.google.maps && !!window.google.maps.Map;\r\n };\r\n\r\n L.googleLayer = function (key, options) {\r\n return new L.GoogleLayer(key, options);\r\n };\r\n }\r\n})();","(function(L) {\r\n `use strict`;\r\n\r\n L.HtmlIcon = L.Icon.extend({\r\n options: {\r\n iconUrl: null,\r\n shadowUrl: null,\r\n content: `
      N/A
      `,\r\n className: `leaflet-html-icon`\r\n //iconSize: new L.Point(25, 41),\r\n //iconAnchor: new L.Point(13, 41),\r\n //popupAnchor: new L.Point(0, -33),\r\n },\r\n\r\n initialize: function(options) {\r\n L.Util.setOptions(this, options);\r\n },\r\n\r\n createIcon: function() {\r\n if (!this.options.content) {\r\n return;\r\n }\r\n const content = document.createElement(`div`);\r\n content.innerHTML = this.options.content;\r\n\r\n this._setIconStyles(content, `icon`);\r\n return content;\r\n },\r\n\r\n //you could change this to add a shadow like in the normal marker if you really wanted\r\n createShadow: function() {\r\n return null;\r\n }\r\n\r\n });\r\n\r\n L.htmlIcon = function (options) {\r\n return new L.HtmlIcon(options);\r\n };\r\n\r\n})(L); // eslint-disable-line no-undef\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .config(ImageOverlay);\r\n\r\n ImageOverlay.$inject = [`leafletLib`, `app.core.appSettingsProvider`];\r\n\r\n function ImageOverlay(L, appSettingsProvider) {\r\n const baseInitialize = L.ImageOverlay.prototype.initialize;\r\n\r\n L.ImageOverlay.prototype.initialize = function(url, bounds, options) {\r\n const isDataUrl = url.length > 4 && url.substr(0, 4).toLowerCase() === `data`;\r\n if (isDataUrl) {\r\n baseInitialize.call(this, url, bounds, options);\r\n\r\n } else {\r\n const separator = url.indexOf(`?`) === -1 ? `?` : `&`;\r\n const settings = appSettingsProvider.settings;\r\n const urlWithAuth = `${url}${separator}companyAlias=${settings.site.company.alias}&facilityAlias=${settings.site.facility.alias}&apiKey=${settings.apiKey}`;\r\n\r\n baseInitialize.call(this, urlWithAuth, bounds, options);\r\n }\r\n };\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.core`)\r\n .config(addInfluenceArcPolygon);\r\n\r\n addInfluenceArcPolygon.$inject = [`leafletLib`];\r\n\r\n function addInfluenceArcPolygon(L) {\r\n\r\n L.es = L.es || {};\r\n\r\n L.es.InfluenceArcs = L.Polygon.extend({\r\n initialize: function(map, arcsData, options) {\r\n this._buildArc(arcsData, options);\r\n },\r\n\r\n _buildArc: function(influenceArc, options) {\r\n options = options || {};\r\n\r\n // a windspeed of 1 (units?) will result in a 600m radius\r\n const _arcMultiplier = 600;\r\n\r\n //Set the center point for the arc\r\n const _centrePoint = new L.LatLng(influenceArc.latitude, influenceArc.longitude);\r\n\r\n //Determine the length of the arc\r\n const _arcLength = _arcMultiplier * influenceArc.windSpeed;\r\n\r\n\r\n const _arcColor = influenceArc ? influenceArc.thresholdColour : ``;\r\n\r\n //Draw the arc\r\n this._arcPts = this._drawArc(_centrePoint, influenceArc.windDirection - influenceArc.sigmaTheta, influenceArc.windDirection + influenceArc.sigmaTheta, _arcLength);\r\n\r\n\r\n this._arcPts.push(_centrePoint);\r\n this.setLatLngs(this._arcPts);\r\n //Apply the gradient to the arc\r\n options.fillColor = _arcColor;\r\n options.fillOpacity = 0.3;\r\n\r\n //border options\r\n options.color = _arcColor;\r\n options.weight = 2;\r\n options.opacity = 0.4;\r\n\r\n\r\n //Add the arc object as marker\r\n L.Polygon.prototype.initialize.call(this, [this._arcPts], options);\r\n\r\n this.setStyle(options);\r\n\r\n if (this._popup) {\r\n //set content while moving\r\n this._popup.setContent(this._getPopupContent(influenceArc.windDirection, influenceArc.windSpeed));\r\n } else {\r\n //Attach a popup\r\n this.bindPopup(this._getPopupContent(influenceArc.windDirection, influenceArc.windSpeed));\r\n }\r\n\r\n //Set the position of the popup to the center point in the event influence arcs rotates\r\n this._popup.setLatLng(_centrePoint);\r\n },\r\n\r\n _getPopupContent: function(direction, windSpeed) {\r\n return `Wind blowing from: ${direction} deg
      Wind Speed(m/s): ${windSpeed}`;\r\n },\r\n\r\n _drawInvArc: function(center, initialBearing, finalBearing, radius) {\r\n const _newcenter = center.destinationPoint((initialBearing + finalBearing) / 2, radius * 2);\r\n\r\n const _initialPoint = center.destinationPoint(initialBearing, radius);\r\n const _finalPoint = center.destinationPoint(finalBearing, radius);\r\n\r\n const _newFinalBearing = _newcenter.bearing(_initialPoint); // Reverse initial and final to avoid a \"speech-bubble\"\r\n const _newInitialBearing = _newcenter.bearing(_finalPoint);\r\n\r\n return this._drawArc(_newcenter, _newInitialBearing, _newFinalBearing, radius);\r\n },\r\n\r\n _drawArc: function(center, initialBearing, finalBearing, radius) {\r\n const _points = 32;\r\n const _extp = [];\r\n\r\n if (initialBearing > finalBearing) {\r\n finalBearing += 360;\r\n }\r\n\r\n let _deltaBearing = finalBearing - initialBearing;\r\n\r\n _deltaBearing = _deltaBearing / _points;\r\n\r\n for (let i = 0; i < _points + 1; i++) {\r\n _extp.push(center.destinationPoint(initialBearing + i * _deltaBearing, radius));\r\n }\r\n\r\n return _extp;\r\n },\r\n\r\n update: function(arcsData, options) {\r\n this._buildArc(arcsData, options);\r\n }\r\n\r\n });\r\n\r\n L.es.influenceArcs = function(map, arcsData, options) {\r\n return new L.es.InfluenceArcs(map, arcsData, options);\r\n };\r\n }\r\n})();","(function(L) {\r\n `use strict`;\r\n L.es = L.es || {};\r\n})(L); // eslint-disable-line no-undef\r\n","(function(L) {\r\n `use strict`;\r\n\r\n L.LatLng.prototype.latRadians = function() {\r\n return Math.PI * this.lat() / 180;\r\n };\r\n\r\n L.LatLng.prototype.lngRadians = function() {\r\n return Math.PI * this.lng() / 180;\r\n };\r\n\r\n L.LatLng.prototype.bearing = function(latLng) {\r\n const _from = this;\r\n const _to = latLng;\r\n\r\n if (_from.equals(_to)) {\r\n return 0;\r\n };\r\n\r\n const _lat1 = _from.lat.toRad();\r\n const _lon1 = _from.lng.toRad();\r\n\r\n const _lat2 = _to.lat.toRad();\r\n const _lon2 = _to.lng.toRad();\r\n\r\n let _angle = -Math.atan2(Math.sin(_lon1 - _lon2) * Math.cos(_lat2), Math.cos(_lat1) * Math.sin(_lat2) - Math.sin(_lat1) * Math.cos(_lat2) * Math.cos(_lon1 - _lon2));\r\n\r\n if (_angle < 0.0) {\r\n _angle += Math.PI * 2.0;\r\n }\r\n\r\n if (_angle > Math.PI) {\r\n _angle -= Math.PI * 2.0;\r\n }\r\n\r\n return parseFloat(_angle.toDeg());\r\n };\r\n\r\n L.LatLng.prototype.destinationPoint = function(bearing, distance) {\r\n const _earthRadiusMeters = 6378137.0;\r\n const _brng = bearing.toRad();\r\n\r\n const _lat1 = this.lat.toRad();\r\n const _lon1 = this.lng.toRad();\r\n\r\n const _lat2 = Math.asin(Math.sin(_lat1) * Math.cos(distance / _earthRadiusMeters) +\r\n Math.cos(_lat1) * Math.sin(distance / _earthRadiusMeters) * Math.cos(_brng));\r\n\r\n const _lon2 = _lon1 + Math.atan2(Math.sin(_brng) * Math.sin(distance / _earthRadiusMeters) * Math.cos(_lat1),\r\n Math.cos(distance / _earthRadiusMeters) - Math.sin(_lat1) * Math.sin(_lat2));\r\n\r\n return new L.LatLng(_lat2.toDeg(), _lon2.toDeg());\r\n };\r\n})(L); // eslint-disable-line no-undef","(function(L) {\r\n `use strict`;\r\n\r\n L.es.MapCredits = L.Control.extend({\r\n options: {\r\n position: `bottomleft`\r\n },\r\n onAdd: function() {\r\n const container = L.DomUtil.create(`div`, `leaflet-credits-control`);\r\n\r\n // make contents stack vertically\r\n container.style.width = `10px`;\r\n\r\n Object.defineProperty(this, `container`, {\r\n value: container\r\n });\r\n return container;\r\n },\r\n addCredit: function(imageUrl, imageClick) {\r\n const image = L.DomUtil.create(`img`, `leaflet-credit`, this.container);\r\n\r\n image.src = imageUrl;\r\n if (imageClick) {\r\n L.DomEvent\r\n .addListener(image, `mousedown`, L.DomEvent.stopPropagation)\r\n .addListener(image, `click`, L.DomEvent.stopPropagation)\r\n .addListener(image, `dblclick`, L.DomEvent.stopPropagation)\r\n .addListener(image, `click`, imageClick);\r\n }\r\n return image;\r\n }\r\n });\r\n})(L); // eslint-disable-line no-undef","/* istanbul ignore next */\r\n(function(){\r\n\r\n /*\r\n Mostly picked from https://raw.githubusercontent.com/tombatossals/angular-leaflet-directive/master/dist/angular-leaflet-directive.js\r\n */\r\n angular\r\n .module(`es-leaflet-directive`, [])\r\n .directive(`esLeaflet`, esLeaflet)\r\n .controller(`esLeafletController`, esLeafletController);\r\n\r\n esLeaflet.$inject = [`esLeafletData`, `esLeafletMapDefaults`, `esLeafletHelpers`, `esLeafletMapEvents`, `leafletLib`];\r\n function esLeaflet(esLeafletData, esLeafletMapDefaults, esLeafletHelpers, esLeafletMapEvents, L) {\r\n return {\r\n restrict: `EA`,\r\n replace: true,\r\n scope: {\r\n center: `=`,\r\n defaults: `=`,\r\n markers: `=`,\r\n layers: `=`,\r\n paths: `=`\r\n },\r\n transclude: true,\r\n template: `
      `,\r\n controller : esLeafletController,\r\n link\r\n };\r\n\r\n function link($scope, $element, attrs, controller) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const defaults = esLeafletMapDefaults.setDefaults($scope.defaults, attrs.id);\r\n const mapEvents = esLeafletMapEvents.getAvailableMapEvents();\r\n const addEvents = esLeafletMapEvents.addEvents;\r\n\r\n $scope.mapId = attrs.id;\r\n esLeafletData.setDirectiveControls({}, attrs.id);\r\n\r\n // Create the Leaflet Map Object with the options\r\n const map = new L.Map($element[0], esLeafletMapDefaults.getMapCreationDefaults(attrs.id));\r\n controller._leafletMap.resolve(map);\r\n\r\n if (!isDefined(attrs.center)){\r\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\r\n }\r\n\r\n if (!isDefined(attrs.layers)) {\r\n const tileLayerObj = L.tileLayer(defaults.tileLayer, defaults.tileLayerOptions);\r\n tileLayerObj.addTo(map);\r\n esLeafletData.setTiles(tileLayerObj, attrs.id);\r\n }\r\n // Set zoom control configuration\r\n if (isDefined(map.zoomControl) && isDefined(defaults.zoomControlPosition)) {\r\n map.zoomControl.setPosition(defaults.zoomControlPosition);\r\n }\r\n\r\n if (isDefined(map.zoomControl) && defaults.zoomControl === false) {\r\n map.zoomControl.removeFrom(map);\r\n }\r\n\r\n if (isDefined(map.zoomsliderControl) && isDefined(defaults.zoomsliderControl) && defaults.zoomsliderControl === false) {\r\n map.zoomsliderControl.removeFrom(map);\r\n }\r\n\r\n addEvents(map, mapEvents, `eventName`, $scope, `broadcast`);\r\n\r\n // Resolve the map object to the promises\r\n map.whenReady(function() {\r\n esLeafletData.setMap(map, attrs.id);\r\n });\r\n\r\n $scope.$on(`$destroy`, function() {\r\n esLeafletMapDefaults.reset();\r\n map.remove();\r\n esLeafletData.unresolveMap(attrs.id);\r\n });\r\n\r\n //Handle request to invalidate the map size\r\n //Up scope using $scope.$emit(`invalidateSize`)\r\n //Down scope using $scope.$broadcast(`invalidateSize`)\r\n $scope.$on(`invalidateSize`, function() {\r\n map.invalidateSize();\r\n });\r\n }\r\n }\r\n\r\n esLeafletController.$inject = [`$scope`, `$q`];\r\n function esLeafletController($scope, $q) {\r\n this._leafletMap = $q.defer();\r\n this.getMap = function() {\r\n return this._leafletMap.promise;\r\n };\r\n\r\n this.getLeafletScope = function() {\r\n return $scope;\r\n };\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletBoundsHelpers`, esLeafletBoundsHelpers);\r\n\r\n esLeafletBoundsHelpers.$inject = [`leafletLib`];\r\n function esLeafletBoundsHelpers (L) {\r\n\r\n return {\r\n createLeafletBounds,\r\n isValidBounds\r\n };\r\n\r\n function createLeafletBounds(bounds) {\r\n if (isValidBounds(bounds)) {\r\n return L.latLngBounds([bounds.southWest.lat, bounds.southWest.lng],\r\n [bounds.northEast.lat, bounds.northEast.lng]);\r\n }\r\n }\r\n\r\n function isValidBounds(bounds) {\r\n return angular.isDefined(bounds) && angular.isDefined(bounds.southWest) &&\r\n angular.isDefined(bounds.northEast) && angular.isNumber(bounds.southWest.lat) &&\r\n angular.isNumber(bounds.southWest.lng) && angular.isNumber(bounds.northEast.lat) &&\r\n angular.isNumber(bounds.northEast.lng);\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .directive(`center`, center)\r\n .controller(`centerController`, centerController);\r\n\r\n center.$inject = [`$log`, `$location`, `$timeout`, `esLeafletMapDefaults`, `esLeafletHelpers`, `esLeafletBoundsHelpers`, `esLeafletMapEvents`];\r\n function center($log, $location, $timeout, esLeafletMapDefaults, esLeafletHelpers, esLeafletBoundsHelpers, esLeafletMapEvents) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const isSameCenterOnMap = esLeafletHelpers.isSameCenterOnMap;\r\n const safeApply = esLeafletHelpers.safeApply;\r\n const isValidCenter = esLeafletHelpers.isValidCenter;\r\n const isValidBounds = esLeafletBoundsHelpers.isValidBounds;\r\n const isUndefinedOrEmpty = esLeafletHelpers.isUndefinedOrEmpty;\r\n const errorHeader = esLeafletHelpers.errorHeader;\r\n\r\n return {\r\n restrict: `A`,\r\n scope: false,\r\n replace: false,\r\n require: [`esLeaflet`, `center`],\r\n controller: centerController,\r\n link\r\n };\r\n\r\n function link($scope, $element, attrs, controllers){\r\n const controller = controllers[0];\r\n const centerController = controllers[1];\r\n const leafletScope = controller.getLeafletScope();\r\n let centerModel = leafletScope.center;\r\n\r\n controller.getMap().then(function(map) {\r\n const defaults = esLeafletMapDefaults.getDefaults(attrs.id);\r\n\r\n if (attrs.center.search(`-`) !== -1) {\r\n $log.error(`${errorHeader} The \"center\" variable can\\`t use a \"-\" on its key name: \"${attrs.center}\".`);\r\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\r\n return;\r\n } else if (shouldInitializeMapWithBounds(leafletScope.bounds, centerModel)) {\r\n map.fitBounds(esLeafletBoundsHelpers.createLeafletBounds(leafletScope.bounds), leafletScope.bounds.options);\r\n centerModel = map.getCenter();\r\n safeApply(leafletScope, scope => {\r\n angular.extend(scope.center, {\r\n lat: map.getCenter().lat,\r\n lng: map.getCenter().lng,\r\n zoom: map.getZoom(),\r\n autoDiscover: false\r\n });\r\n });\r\n\r\n safeApply(leafletScope, scope =>{\r\n const mapBounds = map.getBounds();\r\n scope.bounds = {\r\n northEast: {\r\n lat: mapBounds._northEast.lat,\r\n lng: mapBounds._northEast.lng\r\n },\r\n southWest: {\r\n lat: mapBounds._southWest.lat,\r\n lng: mapBounds._southWest.lng\r\n }\r\n };\r\n });\r\n } else if (!isDefined(centerModel)) {\r\n $log.error(errorHeader + ` The \"center\" property is not defined in the main scope`);\r\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\r\n return;\r\n } else if (!(isDefined(centerModel.lat) && isDefined(centerModel.lng)) && !isDefined(centerModel.autoDiscover)) {\r\n angular.copy(defaults.center, centerModel);\r\n }\r\n\r\n let urlCenterHash;\r\n let mapReady;\r\n if (attrs.urlHashCenter === `yes`) {\r\n const extractCenterFromUrl = () => {\r\n const search = $location.search();\r\n let centerParam;\r\n if (isDefined(search.c)) {\r\n const cParam = search.c.split(`:`);\r\n if (cParam.length === 3) {\r\n centerParam = {\r\n lat: parseFloat(cParam[0]),\r\n lng: parseFloat(cParam[1]),\r\n zoom: parseInt(cParam[2], 10)\r\n };\r\n }\r\n }\r\n\r\n return centerParam;\r\n };\r\n\r\n urlCenterHash = extractCenterFromUrl();\r\n\r\n leafletScope.$on(`$locationChangeSuccess`, event => {\r\n const scope = event.currentScope;\r\n const urlCenter = extractCenterFromUrl();\r\n if (isDefined(urlCenter) && !isSameCenterOnMap(urlCenter, map)) {\r\n angular.extend(scope.center, {\r\n lat: urlCenter.lat,\r\n lng: urlCenter.lng,\r\n zoom: urlCenter.zoom\r\n });\r\n }\r\n });\r\n }\r\n\r\n leafletScope.$watch(`center`, center => {\r\n if (leafletScope.settingCenterFromLeaflet) {\r\n return;\r\n }\r\n // The center from the URL has priority\r\n if (isDefined(urlCenterHash)) {\r\n angular.copy(urlCenterHash, center);\r\n urlCenterHash = undefined;\r\n }\r\n\r\n if (!isValidCenter(center) && center.autoDiscover !== true) {\r\n $log.warn(errorHeader + ` invalid \"center\"`);\r\n return;\r\n }\r\n\r\n if (center.autoDiscover === true) {\r\n if (!angular.isNumber(center.zoom)) {\r\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\r\n }\r\n\r\n if (angular.isNumber(center.zoom) && center.zoom > defaults.center.zoom) {\r\n map.locate({\r\n setView: true,\r\n maxZoom: center.zoom\r\n });\r\n } else if (isDefined(defaults.maxZoom)) {\r\n map.locate({\r\n setView: true,\r\n maxZoom: defaults.maxZoom\r\n });\r\n } else {\r\n map.locate({\r\n setView: true\r\n });\r\n }\r\n\r\n return;\r\n }\r\n\r\n if (mapReady && isSameCenterOnMap(center, map)) {\r\n return;\r\n }\r\n\r\n leafletScope.settingCenterFromScope = true;\r\n map.setView([center.lat, center.lng], center.zoom);\r\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\r\n $timeout(() => {\r\n leafletScope.settingCenterFromScope = false;\r\n });\r\n }, true);\r\n\r\n map.whenReady(() => {\r\n mapReady = true;\r\n });\r\n\r\n map.on(`moveend`, () => {\r\n // Resolve the center after the first map position\r\n centerController._leafletCenter.resolve();\r\n esLeafletMapEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search());\r\n\r\n if (isSameCenterOnMap(centerModel, map) || leafletScope.settingCenterFromScope) {\r\n return;\r\n }\r\n\r\n leafletScope.settingCenterFromLeaflet = true;\r\n safeApply(leafletScope, scope => {\r\n if (!leafletScope.settingCenterFromScope) {\r\n angular.extend(scope.center, {\r\n lat: map.getCenter().lat,\r\n lng: map.getCenter().lng,\r\n zoom: map.getZoom(),\r\n autoDiscover: false\r\n });\r\n }\r\n\r\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\r\n $timeout(() => {\r\n leafletScope.settingCenterFromLeaflet = false;\r\n });\r\n });\r\n });\r\n\r\n if (centerModel.autoDiscover === true) {\r\n map.on(`locationerror`, function() {\r\n $log.warn(errorHeader + ` The Geolocation API is unauthorized on this page.`);\r\n if (isValidCenter(centerModel)) {\r\n map.setView([centerModel.lat, centerModel.lng], centerModel.zoom);\r\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\r\n } else {\r\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\r\n esLeafletMapEvents.notifyCenterChangedToBounds(leafletScope, map);\r\n }\r\n });\r\n }\r\n });\r\n\r\n function shouldInitializeMapWithBounds(bounds, center) {\r\n return isDefined(bounds) && isValidBounds(bounds) && isUndefinedOrEmpty(center);\r\n }\r\n }\r\n }\r\n\r\n centerController.$inject = [`$q`];\r\n function centerController($q) {\r\n this._leafletCenter = $q.defer();\r\n this.getCenter = function() {\r\n return this._leafletCenter.promise;\r\n };\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletControlHelpers`, esLeafletControlHelpers);\r\n\r\n esLeafletControlHelpers.$inject = [`esLeafletHelpers`, `esLeafletMapDefaults`, `leafletLib`];\r\n function esLeafletControlHelpers(esLeafletHelpers, esLeafletMapDefaults, L) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const _controls = {};\r\n\r\n return {\r\n updateLayersControl\r\n };\r\n\r\n function updateLayersControl(map, mapId, loaded, baselayers, overlays, leafletLayers) {\r\n let layer;\r\n let _layersControl = _controls[mapId];\r\n const mustBeLoaded = layersControlMustBeVisible(baselayers, overlays, mapId);\r\n\r\n if (isDefined(_layersControl) && loaded) {\r\n for (layer in leafletLayers.baselayers) {\r\n if (layer){\r\n _layersControl.removeLayer(leafletLayers.baselayers[layer]);\r\n }\r\n }\r\n\r\n for (layer in leafletLayers.overlays) {\r\n if (layer){\r\n _layersControl.removeLayer(leafletLayers.overlays[layer]);\r\n }\r\n }\r\n\r\n map.removeControl(_layersControl);\r\n delete _controls[mapId];\r\n }\r\n\r\n if (mustBeLoaded) {\r\n _layersControl = createLayersControl(mapId);\r\n _controls[mapId] = _layersControl;\r\n for (layer in baselayers) {\r\n if (layer) {\r\n const hideOnSelector = isDefined(baselayers[layer].layerOptions) &&\r\n baselayers[layer].layerOptions.showOnSelector === false;\r\n if (!hideOnSelector && isDefined(leafletLayers.baselayers[layer])) {\r\n _layersControl.addBaseLayer(leafletLayers.baselayers[layer], baselayers[layer].name);\r\n }\r\n }\r\n }\r\n\r\n for (layer in overlays) {\r\n if (overlays.hasOwnProperty(layer)){\r\n const hideOverlayOnSelector = isDefined(overlays[layer].layerParams) &&\r\n overlays[layer].layerParams.showOnSelector === false;\r\n if (!hideOverlayOnSelector && isDefined(leafletLayers.overlays[layer])) {\r\n _layersControl.addOverlay(leafletLayers.overlays[layer], overlays[layer].name);\r\n }\r\n }\r\n\r\n }\r\n\r\n map.addControl(_layersControl);\r\n }\r\n\r\n return mustBeLoaded;\r\n }\r\n\r\n function layersControlMustBeVisible(baselayers, overlays, mapId) {\r\n const defaults = esLeafletMapDefaults.getDefaults(mapId);\r\n if (!defaults.controls.layers.visible) {\r\n return false;\r\n }\r\n\r\n let atLeastOneControlItemMustBeShown = false;\r\n\r\n if (angular.isObject(baselayers)) {\r\n Object.keys(baselayers).forEach(function(key) {\r\n const layer = baselayers[key];\r\n if (!isDefined(layer.layerOptions) || layer.layerOptions.showOnSelector !== false) {\r\n atLeastOneControlItemMustBeShown = true;\r\n }\r\n });\r\n }\r\n\r\n if (angular.isObject(overlays)) {\r\n Object.keys(overlays).forEach(function(key) {\r\n const layer = overlays[key];\r\n if (!isDefined(layer.layerParams) || layer.layerParams.showOnSelector !== false) {\r\n atLeastOneControlItemMustBeShown = true;\r\n }\r\n });\r\n }\r\n\r\n return atLeastOneControlItemMustBeShown;\r\n }\r\n\r\n function createLayersControl(mapId) {\r\n const defaults = esLeafletMapDefaults.getDefaults(mapId);\r\n const controlOptions = {\r\n collapsed: defaults.controls.layers.collapsed,\r\n position: defaults.controls.layers.position,\r\n autoZIndex: false\r\n };\r\n\r\n angular.extend(controlOptions, defaults.controls.layers.options);\r\n\r\n let control;\r\n if (defaults.controls.layers && isDefined(defaults.controls.layers.control)) {\r\n control = defaults.controls.layers.control.apply(this, [[], [], controlOptions]);\r\n } else {\r\n control = new L.control.Layers([], [], controlOptions);\r\n }\r\n\r\n return control;\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletData`, esLeafletData);\r\n\r\n esLeafletData.$inject = [`esLeafletHelpers`];\r\n function esLeafletData(esLeafletHelpers) {\r\n const getDefer = esLeafletHelpers.getDefer;\r\n const getUnresolvedDefer = esLeafletHelpers.getUnresolvedDefer;\r\n const setResolvedDefer = esLeafletHelpers.setResolvedDefer;\r\n\r\n const maps = {};\r\n const layers = {};\r\n const directiveControls = {};\r\n const tiles = {};\r\n const markers = {};\r\n const paths = {};\r\n\r\n return {\r\n setMap,\r\n getMap,\r\n getLayers,\r\n setLayers,\r\n setDirectiveControls,\r\n getDirectiveControls,\r\n getMarkers,\r\n setMarkers,\r\n getTiles,\r\n setTiles,\r\n unresolveMap,\r\n setPaths,\r\n getPaths\r\n };\r\n\r\n function setMap(leafletMap, scopeId) {\r\n const defer = getUnresolvedDefer(maps, scopeId);\r\n defer.resolve(leafletMap);\r\n setResolvedDefer(maps, scopeId);\r\n }\r\n\r\n function getMap(scopeId) {\r\n const defer = getDefer(maps, scopeId);\r\n return defer.promise;\r\n }\r\n\r\n function setMarkers(leafletMarkers, scopeId) {\r\n const defer = getUnresolvedDefer(markers, scopeId);\r\n defer.resolve(leafletMarkers);\r\n setResolvedDefer(markers, scopeId);\r\n }\r\n\r\n function getMarkers(scopeId) {\r\n const defer = getDefer(markers, scopeId);\r\n return defer.promise;\r\n }\r\n\r\n function setPaths(leafletMarkers, scopeId) {\r\n const defer = getUnresolvedDefer(paths, scopeId);\r\n defer.resolve(leafletMarkers);\r\n setResolvedDefer(paths, scopeId);\r\n }\r\n\r\n function getPaths(scopeId) {\r\n const defer = getDefer(paths, scopeId);\r\n return defer.promise;\r\n }\r\n\r\n function getLayers(scopeId){\r\n const defer = getDefer(layers, scopeId);\r\n return defer.promise;\r\n }\r\n\r\n function setLayers(leafletLayers, scopeId){\r\n const defer = getUnresolvedDefer(layers, scopeId);\r\n defer.resolve(leafletLayers);\r\n setResolvedDefer(layers, scopeId);\r\n }\r\n\r\n function getTiles(scopeId){\r\n const defer = getDefer(tiles, scopeId);\r\n return defer.promise;\r\n }\r\n\r\n function setTiles(leafletTiles, scopeId){\r\n const defer = getUnresolvedDefer(tiles, scopeId);\r\n defer.resolve(leafletTiles);\r\n setResolvedDefer(tiles, scopeId);\r\n }\r\n\r\n function setDirectiveControls(leafletControl, scopeId) {\r\n const defer = getUnresolvedDefer(directiveControls, scopeId);\r\n defer.resolve(leafletControl);\r\n setResolvedDefer(directiveControls, scopeId);\r\n }\r\n\r\n function getDirectiveControls(scopeId) {\r\n const defer = getDefer(directiveControls, scopeId);\r\n return defer.promise;\r\n }\r\n\r\n function unresolveMap(scopeId) {\r\n const id = esLeafletHelpers.obtainEffectiveMapId(maps, scopeId);\r\n maps[id] = undefined;\r\n }\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletDirectiveControlsHelpers`, esLeafletDirectiveControlsHelpers);\r\n\r\n esLeafletDirectiveControlsHelpers.$inject = [`$log`, `esLeafletData`, `esLeafletHelpers`];\r\n function esLeafletDirectiveControlsHelpers($log, esLeafletData, esLeafletHelpers) {\r\n return {\r\n extend\r\n };\r\n\r\n function extend(id, thingToAddName, createFn, cleanFn) {\r\n const _fnHeader = `${esLeafletHelpers.errorHeader}[leafletDirectiveControlsHelpers.extend] `;\r\n let extender = {};\r\n if (!esLeafletHelpers.isDefined(thingToAddName)) {\r\n $log.error(`${_fnHeader}thingToAddName cannot be undefined`);\r\n return;\r\n }\r\n\r\n if (angular.isString(thingToAddName) && esLeafletHelpers.isDefined(createFn) && esLeafletHelpers.isDefined(cleanFn)) {\r\n extender[thingToAddName] = {\r\n create: createFn,\r\n clean: cleanFn\r\n };\r\n }\r\n else if (angular.isObject(thingToAddName) && !esLeafletHelpers.isDefined(createFn) && !esLeafletHelpers.isDefined(cleanFn)) {\r\n extender = thingToAddName;\r\n }\r\n else {\r\n $log.error(`${_fnHeader}incorrect arguments`);\r\n return;\r\n }\r\n\r\n //add external control to create / destroy markers without a watch\r\n esLeafletData.getDirectiveControls().then(function(controls) {\r\n angular.extend(controls, extender);\r\n esLeafletData.setDirectiveControls(controls, id);\r\n });\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n angular.module(`es-leaflet-directive`)\r\n .factory(`esLeafletEventsHelpersFactory`, esLeafletEventsHelpersFactory)\r\n .service(`esLeafletEventsHelpers`, [`esLeafletEventsHelpersFactory`, function(EsLeafletEventsHelpersFactory) {\r\n return new EsLeafletEventsHelpersFactory();\r\n }]);\r\n\r\n esLeafletEventsHelpersFactory.$inject = [`$rootScope`, `$log`, `esLeafletHelpers`];\r\n function esLeafletEventsHelpersFactory($rootScope, $log, esLeafletHelpers) {\r\n const safeApply = esLeafletHelpers.safeApply;\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const errorHeader = esLeafletHelpers.errorHeader;\r\n\r\n const EventsHelper = function(rootBroadcastName, lObjectType) {\r\n this.rootBroadcastName = rootBroadcastName;\r\n $log.debug(`LeafletEventsHelpersFactory: lObjectType: ` + lObjectType + `rootBroadcastName: ` + rootBroadcastName);\r\n\r\n //used to path/key out certain properties based on the type , `markers`, `geojson`\r\n this.lObjectType = lObjectType;\r\n };\r\n\r\n EventsHelper.prototype.getAvailableEvents = function() {return [];};\r\n\r\n /*\r\n argument: name: Note this can be a single string or dot notation\r\n Example:\r\n markerModel : {\r\n m1: { lat:_, lon: _}\r\n }\r\n //would yield name of\r\n name = `m1`\r\n\r\n If nested:\r\n markerModel : {\r\n cars: {\r\n m1: { lat:_, lon: _}\r\n }\r\n }\r\n //would yield name of\r\n name = `cars.m1`\r\n */\r\n EventsHelper.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra) {\r\n const self = this;\r\n\r\n maybeMapId = maybeMapId || ``;\r\n if (maybeMapId){\r\n maybeMapId = `.` + maybeMapId;\r\n }\r\n\r\n return function(e) {\r\n const broadcastName = self.rootBroadcastName + maybeMapId + `.` + eventName;\r\n $log.debug(broadcastName);\r\n self.fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName, extra);\r\n };\r\n };\r\n\r\n EventsHelper.prototype.fire = function(scope, broadcastName, logic, event, lObject, model, modelName, layerName) {\r\n // Safely broadcast the event\r\n safeApply(scope, function() {\r\n const toSend = {\r\n leafletEvent: event,\r\n leafletObject: lObject,\r\n modelName: modelName,\r\n model: model\r\n };\r\n if (isDefined(layerName)) {\r\n angular.extend(toSend, { layerName: layerName } );\r\n }\r\n\r\n if (logic === `emit`) {\r\n scope.$emit(broadcastName, toSend);\r\n } else {\r\n $rootScope.$broadcast(broadcastName, toSend);\r\n }\r\n });\r\n };\r\n\r\n EventsHelper.prototype.bindEvents = function(maybeMapId, lObject, name, model, leafletScope, layerName, extra) {\r\n let events = [];\r\n const logic = `emit`;\r\n const self = this;\r\n\r\n if (!isDefined(leafletScope.eventBroadcast)) {\r\n // Backward compatibility, if no event-broadcast attribute, all events are broadcasted\r\n events = this.getAvailableEvents();\r\n } else if (!angular.isObject(leafletScope.eventBroadcast)) {\r\n // Not a valid object\r\n $log.error(errorHeader + `event-broadcast must be an object check your model.`);\r\n } else {\r\n // We have a possible valid object\r\n if (!isDefined(leafletScope.eventBroadcast[self.lObjectType])) {\r\n // We do not have events enable/disable do we do nothing (all enabled by default)\r\n events = this.getAvailableEvents();\r\n } else if (!angular.isObject(leafletScope.eventBroadcast[self.lObjectType])) {\r\n // Not a valid object\r\n $log.warn(errorHeader + `event-broadcast.` + [self.lObjectType] + ` must be an object check your model.`);\r\n } else {\r\n // We have a possible valid map object\r\n // Event propadation logic\r\n if (isDefined(leafletScope.eventBroadcast[this.lObjectType].logic)) {\r\n // We take care of possible propagation logic\r\n if (leafletScope.eventBroadcast[self.lObjectType].logic !== `emit` &&\r\n leafletScope.eventBroadcast[self.lObjectType].logic !== `broadcast`){\r\n $log.warn(errorHeader + `Available event propagation logic are: \\`emit\\` or \\`broadcast\\`.`);\r\n }\r\n }\r\n\r\n // Enable / Disable\r\n let eventsEnable = false;\r\n let eventsDisable = false;\r\n if (isDefined(leafletScope.eventBroadcast[self.lObjectType].enable) &&\r\n angular.isArray(leafletScope.eventBroadcast[self.lObjectType].enable)){\r\n eventsEnable = true;\r\n }\r\n\r\n if (isDefined(leafletScope.eventBroadcast[self.lObjectType].disable) &&\r\n angular.isArray(leafletScope.eventBroadcast[self.lObjectType].disable)){\r\n eventsDisable = true;\r\n }\r\n\r\n if (eventsEnable && eventsDisable) {\r\n // Both are active, this is an error\r\n $log.warn(errorHeader + `can not enable and disable events at the same time`);\r\n } else if (!eventsEnable && !eventsDisable) {\r\n // Both are inactive, this is an error\r\n $log.warn(errorHeader + `must enable or disable events`);\r\n } else {\r\n // At this point the object is OK, lets enable or disable events\r\n if (eventsEnable) {\r\n // Enable events\r\n leafletScope.eventBroadcast[this.lObjectType].enable.forEach(function(eventName) {\r\n // Do we have already the event enabled?\r\n if (events.indexOf(eventName) !== -1) {\r\n // Repeated event, this is an error\r\n $log.warn(errorHeader + `This event ` + eventName + ` is already enabled`);\r\n } else {\r\n // Does the event exists?\r\n if (self.getAvailableEvents().indexOf(eventName) === -1) {\r\n // The event does not exists, this is an error\r\n $log.warn(errorHeader + `This event ` + eventName + ` does not exist`);\r\n } else {\r\n // All ok enable the event\r\n events.push(eventName);\r\n }\r\n }\r\n });\r\n } else {\r\n // Disable events\r\n events = this.getAvailableEvents();\r\n leafletScope.eventBroadcast[self.lObjectType].disable.forEach(function(eventName) {\r\n const index = events.indexOf(eventName);\r\n if (index === -1) {\r\n // The event does not exist\r\n $log.warn(errorHeader + `This event ` + eventName + ` does not exist or has been already disabled`);\r\n\r\n } else {\r\n events.splice(index, 1);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n events.forEach(function(eventName) {\r\n lObject.on(eventName, self.genDispatchEvent(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra));\r\n });\r\n\r\n return logic;\r\n };\r\n\r\n return EventsHelper;\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletGeoJsonHelpers`, esLeafletGeoJsonHelpers);\r\n\r\n esLeafletGeoJsonHelpers.$inject = [`esLeafletHelpers`, `esLeafletIterators`];\r\n function esLeafletGeoJsonHelpers(esLeafletHelpers, esLeafletIterators) {\r\n return {\r\n validateCoords,\r\n getCoords\r\n };\r\n\r\n function Point(lat, lng) {\r\n this.lat = lat;\r\n this.lng = lng;\r\n return this;\r\n }\r\n\r\n function validateCoords(coords) {\r\n if (esLeafletHelpers.isUndefined(coords)) {\r\n return false;\r\n }\r\n\r\n if (angular.isArray(coords)) {\r\n if (coords.length === 2 && angular.isNumber(coords[0]) && angular.isNumber(coords[1])) {\r\n return true;\r\n }\r\n } else if (esLeafletHelpers.isDefined(coords.type)) {\r\n if (\r\n coords.type === `Point` && angular.isArray(coords.coordinates) &&\r\n coords.coordinates.length === 2 &&\r\n angular.isNumber(coords.coordinates[0]) &&\r\n angular.isNumber(coords.coordinates[1])) {\r\n return true;\r\n }\r\n }\r\n\r\n return esLeafletIterators.all([`lat`, `lng`],\r\n pos => esLeafletHelpers.isDefined(coords[pos]) && angular.isNumber(coords[pos]));\r\n }\r\n\r\n function getCoords(value) {\r\n if (!value || !validateCoords(value)) {\r\n return;\r\n }\r\n\r\n let p = null;\r\n if (Array.isArray(value) && value.length === 2) {\r\n p = new Point(value[1], value[0]);\r\n } else if (esLeafletHelpers.isDefined(value.type) && value.type === `Point`) {\r\n p = new Point(value.coordinates[1], value.coordinates[0]);\r\n } else {\r\n return value;\r\n }\r\n\r\n //note angular.merge is avail in angular 1.4.X we might want to fill it here\r\n return angular.extend(value, p);//tap on lat, lng if it doesnt exist\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletHelpers`, esLeafletHelpers);\r\n\r\n esLeafletHelpers.$inject = [`$q`, `$log`, `leafletLib`];\r\n function esLeafletHelpers($q, $log, L) {\r\n const _errorHeader = `[AngularJS - Leaflet] `;\r\n const SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\r\n const MOZ_HACK_REGEXP = /^moz([A-Z])/;\r\n\r\n return {\r\n errorHeader: _errorHeader,\r\n getObjectArrayPath,\r\n getObjectDotPath,\r\n defaultTo,\r\n isTruthy,\r\n isEmpty,\r\n isDefined,\r\n isUndefined,\r\n isFunction: angular.isFunction,\r\n isValidCenter,\r\n isSameCenterOnMap,\r\n safeApply,\r\n obtainEffectiveMapId,\r\n getUnresolvedDefer,\r\n getDefer,\r\n setResolvedDefer,\r\n isUndefinedOrEmpty,\r\n isValidPoint,\r\n FullScreenControlPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.Control.Fullscreen);\r\n }\r\n },\r\n MiniMapControlPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.Control.MiniMap);\r\n }\r\n },\r\n AwesomeMarkersPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.AwesomeMarkers) && angular.isDefined(L.AwesomeMarkers.Icon);\r\n },\r\n\r\n is: function(icon) {\r\n if (this.isLoaded()) {\r\n return icon instanceof L.AwesomeMarkers.Icon;\r\n } else {\r\n return false;\r\n }\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (!this.isLoaded()) {\r\n return false;\r\n }\r\n\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n VectorMarkersPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.VectorMarkers) && angular.isDefined(L.VectorMarkers.Icon);\r\n },\r\n\r\n is: function(icon) {\r\n if (this.isLoaded()) {\r\n return icon instanceof L.VectorMarkers.Icon;\r\n } else {\r\n return false;\r\n }\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (!this.isLoaded()) {\r\n return false;\r\n }\r\n\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n DomMarkersPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.DomMarkers) && angular.isDefined(L.DomMarkers.Icon);\r\n },\r\n\r\n is: function(icon) {\r\n if (this.isLoaded()) {\r\n return icon instanceof L.DomMarkers.Icon;\r\n } else {\r\n return false;\r\n }\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (!this.isLoaded()) {\r\n return false;\r\n }\r\n\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n PolylineDecoratorPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.PolylineDecorator);\r\n },\r\n\r\n is: function(decoration) {\r\n if (this.isLoaded()) {\r\n return decoration instanceof L.PolylineDecorator;\r\n } else {\r\n return false;\r\n }\r\n },\r\n\r\n equal: function(decorationA, decorationB) {\r\n if (!this.isLoaded()) {\r\n return false;\r\n }\r\n\r\n if (this.is(decorationA)) {\r\n return angular.equals(decorationA, decorationB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n MakiMarkersPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.MakiMarkers) && angular.isDefined(L.MakiMarkers.Icon);\r\n },\r\n\r\n is: function(icon) {\r\n if (this.isLoaded()) {\r\n return icon instanceof L.MakiMarkers.Icon;\r\n } else {\r\n return false;\r\n }\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (!this.isLoaded()) {\r\n return false;\r\n }\r\n\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n ExtraMarkersPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.ExtraMarkers) && angular.isDefined(L.ExtraMarkers.Icon);\r\n },\r\n\r\n is: function(icon) {\r\n if (this.isLoaded()) {\r\n return icon instanceof L.ExtraMarkers.Icon;\r\n } else {\r\n return false;\r\n }\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (!this.isLoaded()) {\r\n return false;\r\n }\r\n\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n LabelPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.Label);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.MarkerClusterGroup;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n MarkerClusterPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.MarkerClusterGroup);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.MarkerClusterGroup;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n GoogleLayerPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.GoogleLayer);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.GoogleLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n LeafletProviderPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.TileLayer.Provider);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.TileLayer.Provider;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n HeatLayerPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.heatLayer);\r\n }\r\n },\r\n WebGLHeatMapLayerPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.TileLayer.WebGLHeatMap);\r\n }\r\n },\r\n BingLayerPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.BingLayer);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.BingLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n AGSFeatureLayerPlugin: {\r\n isLoaded: function() {\r\n return L.esri !== undefined && L.esri.featureLayer !== undefined;\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.esri.featureLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n AGSTiledMapLayerPlugin: {\r\n isLoaded: function() {\r\n return L.esri !== undefined && L.esri.tiledMapLayer !== undefined;\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.esri.tiledMapLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n AGSDynamicMapLayerPlugin: {\r\n isLoaded: function() {\r\n return L.esri !== undefined && L.esri.dynamicMapLayer !== undefined;\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.esri.dynamicMapLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n AGSImageMapLayerPlugin: {\r\n isLoaded: function() {\r\n return L.esri !== undefined && L.esri.imageMapLayer !== undefined;\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.esri.imageMapLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n AGSClusteredLayerPlugin: {\r\n isLoaded: function() {\r\n return L.esri !== undefined && L.esri.clusteredFeatureLayer !== undefined;\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.esri.clusteredFeatureLayer;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n\r\n YandexLayerPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.Yandex);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.Yandex;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n GeoJSONPlugin: {\r\n isLoaded: function() {\r\n return angular.isDefined(L.TileLayer.GeoJSON);\r\n },\r\n\r\n is: function(layer) {\r\n if (this.isLoaded()) {\r\n return layer instanceof L.TileLayer.GeoJSON;\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n Leaflet: {\r\n DivIcon: {\r\n is: function(icon) {\r\n return icon instanceof L.DivIcon;\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n },\r\n Icon: {\r\n is: function(icon) {\r\n return icon instanceof L.Icon;\r\n },\r\n\r\n equal: function(iconA, iconB) {\r\n if (this.is(iconA)) {\r\n return angular.equals(iconA, iconB);\r\n } else {\r\n return false;\r\n }\r\n }\r\n }\r\n },\r\n /*\r\n watchOptions - object to set deep nested watches and turn off watches all together\r\n (rely on control / functional updates)\r\n watchOptions - Object\r\n doWatch:boolean\r\n isDeep:boolean (sets $watch(function,isDeep))\r\n individual\r\n doWatch:boolean\r\n isDeep:boolean\r\n */\r\n\r\n //legacy defaults\r\n watchOptions: {\r\n doWatch:true,\r\n isDeep: true,\r\n individual:{\r\n doWatch:true,\r\n isDeep: true\r\n }\r\n }\r\n };\r\n\r\n // BEGIN DIRECT PORT FROM AngularJS code base\r\n /**\r\n Converts snake_case to camelCase.\r\n Also there is special case for Moz prefix starting with upper case letter.\r\n @param name Name to normalize\r\n */\r\n\r\n function camelCase(name) {\r\n return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\r\n if (offset) {\r\n return letter.toUpperCase();\r\n } else {\r\n return letter;\r\n }\r\n }).replace(MOZ_HACK_REGEXP, `Moz$1`);\r\n }\r\n\r\n //Determine if a reference is undefined or {}\r\n function isUndefinedOrEmpty(value) {\r\n return angular.isUndefined(value) || value === null || Object.keys(value).length === 0;\r\n }\r\n\r\n /*\r\n Object Array Notation\r\n _getObjectArrayPath(\"bike.one.two\")\r\n returns:\r\n 'bike[\"one\"][\"two\"]'\r\n */\r\n function getObjectArrayPath(pathStr) {\r\n return pathStr.split(`.`).reduce(function(previous, current) {\r\n return `${previous}[\"${current}\"]`;\r\n });\r\n }\r\n\r\n /* Object Dot Notation\r\n _getObjectPath([\"bike\",\"one\",\"two\"])\r\n returns:\r\n \"bike.one.two\"\r\n */\r\n function getObjectDotPath(arrayOfStrings) {\r\n return arrayOfStrings.reduce(function(previous, current) {\r\n return `${previous}.${current}`;\r\n });\r\n }\r\n\r\n function defaultTo(val, _default) {\r\n return isDefined(val) ? val : _default;\r\n }\r\n function isDefined(value) {\r\n return angular.isDefined(value) && value !== null;\r\n }\r\n\r\n function isUndefined(value) {\r\n return !isDefined(value);\r\n }\r\n\r\n //mainly for checking attributes of directives lets keep this minimal (on what we accept)\r\n function isTruthy(val) {\r\n return val === `true` || val === true;\r\n }\r\n\r\n //Determine if a reference is {}\r\n function isEmpty(value) {\r\n return Object.keys(value).length === 0;\r\n }\r\n\r\n function isValidCenter(center) {\r\n return angular.isDefined(center) && angular.isNumber(center.lat) &&\r\n angular.isNumber(center.lng) && angular.isNumber(center.zoom);\r\n }\r\n\r\n function isSameCenterOnMap(centerModel, map) {\r\n const mapCenter = map.getCenter();\r\n const zoom = map.getZoom();\r\n return centerModel.lat && centerModel.lng &&\r\n mapCenter.lat.toFixed(4) === centerModel.lat.toFixed(4) &&\r\n mapCenter.lng.toFixed(4) === centerModel.lng.toFixed(4) &&\r\n zoom === centerModel.zoom;\r\n }\r\n\r\n function safeApply($scope, fn) {\r\n const phase = $scope.$root.$$phase;\r\n if (phase === `$apply` || phase === `$digest`) {\r\n $scope.$eval(fn);\r\n } else {\r\n $scope.$evalAsync(fn);\r\n }\r\n }\r\n\r\n function obtainEffectiveMapId(d, mapId) {\r\n let id;\r\n let i;\r\n if (!angular.isDefined(mapId)) {\r\n if (Object.keys(d).length === 0) {\r\n id = `main`;\r\n } else if (Object.keys(d).length >= 1) {\r\n for (i in d) {\r\n if (d.hasOwnProperty(i)) {\r\n id = i;\r\n }\r\n }\r\n } else {\r\n $log.error(`${_errorHeader}- You have more than 1 map on the DOM, you must provide the map ID to the leafletData.getXXX call`);\r\n }\r\n } else {\r\n id = mapId;\r\n }\r\n\r\n return id;\r\n }\r\n\r\n function getUnresolvedDefer(d, mapId) {\r\n const id = obtainEffectiveMapId(d, mapId);\r\n let defer;\r\n\r\n if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) {\r\n defer = $q.defer();\r\n d[id] = {\r\n defer: defer,\r\n resolvedDefer: false\r\n };\r\n } else {\r\n defer = d[id].defer;\r\n }\r\n\r\n return defer;\r\n }\r\n\r\n function getDefer(d, mapId) {\r\n const id = obtainEffectiveMapId(d, mapId);\r\n let defer;\r\n if (!angular.isDefined(d[id]) || d[id].resolvedDefer === false) {\r\n defer = getUnresolvedDefer(d, mapId);\r\n } else {\r\n defer = d[id].defer;\r\n }\r\n return defer;\r\n }\r\n\r\n function setResolvedDefer(d, mapId) {\r\n const id = obtainEffectiveMapId(d, mapId);\r\n d[id].resolvedDefer = true;\r\n }\r\n\r\n function isValidPoint(point) {\r\n if (!angular.isDefined(point)) {\r\n return false;\r\n }\r\n\r\n if (angular.isArray(point)) {\r\n return point.length === 2 && angular.isNumber(point[0]) && angular.isNumber(point[1]);\r\n }\r\n\r\n return angular.isNumber(point.lat) && angular.isNumber(point.lng);\r\n }\r\n\r\n\r\n // END AngularJS port\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletIterators`, esLeafletIterators);\r\n\r\n esLeafletIterators.$inject = [`$log`, `esLeafletHelpers`];\r\n function esLeafletIterators($log, esLeafletHelpers) {\r\n const errorHeader = esLeafletHelpers.errorHeader + `leafletIterators: `;\r\n //BEGIN COPY from underscore\r\n const _keys = Object.keys;\r\n\r\n // Helper for collection methods to determine whether a collection\r\n // should be iterated as an array or as an object\r\n // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength\r\n const MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;\r\n\r\n // Assigns a given object with all the own properties in the passed-in object(s)\r\n // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\r\n const _extendOwn = createAssigner(_keys);\r\n\r\n return {\r\n each,\r\n all\r\n };\r\n\r\n function _isArrayLike(collection) {\r\n const length = collection !== null && collection.length;\r\n return angular.isNumber(length) && length >= 0 && length <= MAX_ARRAY_INDEX;\r\n }\r\n\r\n // Keep the identity function around for default iteratees.\r\n function _identity(value) {\r\n return value;\r\n }\r\n\r\n function _property(key) {\r\n return function(obj) {\r\n return obj === null ? void 0 : obj[key];\r\n };\r\n }\r\n\r\n // Internal function that returns an efficient (for current engines) version\r\n // of the passed-in callback, to be repeatedly applied in other Underscore\r\n // functions.\r\n function optimizeCb(func, context, argCount) {\r\n if (context === void 0) {\r\n return func;\r\n }\r\n switch (argCount === null ? 3 : argCount) {\r\n case 1: return function(value) {\r\n return func.call(context, value);\r\n };\r\n\r\n case 2: return function(value, other) {\r\n return func.call(context, value, other);\r\n };\r\n\r\n case 3: return function(value, index, collection) {\r\n return func.call(context, value, index, collection);\r\n };\r\n\r\n case 4: return function(accumulator, value, index, collection) {\r\n return func.call(context, accumulator, value, index, collection);\r\n };\r\n }\r\n return function() {\r\n return func.apply(context, arguments);\r\n };\r\n }\r\n\r\n // An internal function for creating assigner functions.\r\n function createAssigner(keysFunc, undefinedOnly) {\r\n return function(obj) {\r\n const length = arguments.length;\r\n if (length < 2 || obj === null) {\r\n return obj;\r\n }\r\n for (let index = 1; index < length; index++) {\r\n const source = arguments[index];\r\n const keys = keysFunc(source);\r\n const l = keys.length;\r\n\r\n for (let i = 0; i < l; i++) {\r\n const key = keys[i];\r\n if (!undefinedOnly || obj[key] === void 0) {\r\n obj[key] = source[key];\r\n }\r\n }\r\n }\r\n\r\n return obj;\r\n };\r\n }\r\n\r\n // Returns whether an object has a given set of `key:value` pairs.\r\n function _isMatch(object, attrs) {\r\n const keys = _keys(attrs);\r\n const length = keys.length;\r\n if (object === null) {\r\n return !length;\r\n }\r\n const obj = Object(object);\r\n for (let i = 0; i < length; i++) {\r\n const key = keys[i];\r\n if (attrs[key] !== obj[key] || !(key in obj)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n // Returns a predicate for checking whether an object has a given set of\r\n // `key:value` pairs.\r\n function _matcher(attrs) {\r\n attrs = _extendOwn({}, attrs);\r\n return function(obj) {\r\n return _isMatch(obj, attrs);\r\n };\r\n }\r\n\r\n // A mostly-internal function to generate callbacks that can be applied\r\n // to each element in a collection, returning the desired result — either\r\n // identity, an arbitrary callback, a property matcher, or a property accessor.\r\n function cb(value, context, argCount) {\r\n if (value === null) {\r\n return _identity;\r\n }\r\n if (angular.isFunction(value)) {\r\n return optimizeCb(value, context, argCount);\r\n }\r\n if (angular.isObject(value)) {\r\n return _matcher(value);\r\n }\r\n return _property(value);\r\n }\r\n\r\n\r\n function all(obj, predicate, context) {\r\n predicate = cb(predicate, context);\r\n const keys = !_isArrayLike(obj) && _keys(obj);\r\n const length = (keys || obj).length;\r\n for (let index = 0; index < length; index++) {\r\n const currentKey = keys ? keys[index] : index;\r\n if (!predicate(obj[currentKey], currentKey, obj)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n //END COPY fron underscore\r\n\r\n function _hasErrors(collection, cb, ignoreCollection, cbName) {\r\n if (!ignoreCollection) {\r\n if (!esLeafletHelpers.isDefined(collection) || !esLeafletHelpers.isDefined(cb)) {\r\n return true;\r\n }\r\n }\r\n\r\n if (!esLeafletHelpers.isFunction(cb)) {\r\n cbName = esLeafletHelpers.defaultTo(cb, `cb`);\r\n $log.error(`${errorHeader}${cbName} is not a function`);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function _iterate(collection, externalCb, internalCb) {\r\n if (_hasErrors(undefined, internalCb, true, `internalCb`)) {\r\n return;\r\n }\r\n\r\n if (!_hasErrors(collection, externalCb)) {\r\n for (const key in collection) {\r\n if (collection.hasOwnProperty(key)) {\r\n internalCb(collection[key], key);\r\n }\r\n }\r\n }\r\n }\r\n\r\n //see http://jsperf.com/iterators/3\r\n //utilizing for in is way faster\r\n function each(collection, cb) {\r\n _iterate(collection, cb, function(val, key) {\r\n cb(val, key);\r\n });\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletLabelEvents`,esLeafletLabelEvents);\r\n\r\n esLeafletLabelEvents.$inject = [`esLeafletHelpers`, `esLeafletEventsHelpersFactory`];\r\n function esLeafletLabelEvents(esLeafletHelpers, EsLeafletEventsHelpersFactory) {\r\n\r\n const LabelEvents = function() {\r\n EsLeafletEventsHelpersFactory.call(this, `leafletDirectiveLabel`, `markers`);\r\n };\r\n\r\n LabelEvents.prototype = new EsLeafletEventsHelpersFactory();\r\n\r\n LabelEvents.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\r\n const markerName = name.replace(`markers.`, ``);\r\n return EsLeafletEventsHelpersFactory.prototype\r\n .genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, markerName, model, layerName);\r\n };\r\n\r\n LabelEvents.prototype.getAvailableEvents = function() {\r\n return [\r\n `click`,\r\n `dblclick`,\r\n `mousedown`,\r\n `mouseover`,\r\n `mouseout`,\r\n `contextmenu`\r\n ];\r\n };\r\n\r\n LabelEvents.prototype.genEvents = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\r\n const self = this;\r\n const labelEvents = this.getAvailableEvents();\r\n const scopeWatchName = esLeafletHelpers.getObjectArrayPath(`markers.` + name);\r\n labelEvents.forEach(function(eventName) {\r\n lObject.label.on(eventName, self.genDispatchEvent(\r\n maybeMapId, eventName, logic, leafletScope, lObject.label, scopeWatchName, model, layerName));\r\n });\r\n };\r\n\r\n LabelEvents.prototype.bindEvents = function() {};\r\n\r\n return new LabelEvents();\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletLayerHelpers`,esLeafletLayerHelpers);\r\n\r\n esLeafletLayerHelpers.$inject = [`$q`,`$log`, `leafletLib`, `esLeafletHelpers`, `esLeafletIterators`];\r\n function esLeafletLayerHelpers($q, $log, L, esLeafletHelpers, esLeafletIterators) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const IteratorHelper = esLeafletIterators;\r\n const errorHeader = `[esLeafletLayerHelpers`;\r\n const layerTypes = getLayerTypes();\r\n\r\n return {\r\n createLayer,\r\n safeAddLayer,\r\n safeRemoveLayer\r\n };\r\n\r\n function isValidLayerType(layerDefinition) {\r\n // Check if the baselayer has a valid type\r\n if (!angular.isString(layerDefinition.type)) {\r\n $log.error(`[AngularJS - Leaflet] A layer must have a valid type defined.`);\r\n return false;\r\n }\r\n\r\n if (Object.keys(layerTypes).indexOf(layerDefinition.type) === -1) {\r\n $log.error(`[AngularJS - Leaflet] A layer must have a valid type: ${Object.keys(layerTypes)}`);\r\n return false;\r\n }\r\n\r\n // Check if the layer must have an URL\r\n if (layerTypes[layerDefinition.type].mustHaveUrl && !angular.isString(layerDefinition.url)) {\r\n $log.error(`[AngularJS - Leaflet] A base layer must have an url`);\r\n return false;\r\n }\r\n\r\n if (layerTypes[layerDefinition.type].mustHaveData && !isDefined(layerDefinition.data)) {\r\n $log.error(`[AngularJS - Leaflet] The base layer must have a \"data\" array attribute`);\r\n return false;\r\n }\r\n\r\n if (layerTypes[layerDefinition.type].mustHaveLayer && !isDefined(layerDefinition.layer)) {\r\n $log.error(`[AngularJS - Leaflet] The type of layer ${layerDefinition.type} must have an layer defined`);\r\n return false;\r\n }\r\n\r\n if (layerTypes[layerDefinition.type].mustHaveBounds && !isDefined(layerDefinition.bounds)) {\r\n $log.error(`[AngularJS - Leaflet] The type of layer ${layerDefinition.type} must have bounds defined`);\r\n return false;\r\n }\r\n\r\n if (layerTypes[layerDefinition.type].mustHaveKey && !isDefined(layerDefinition.key)) {\r\n $log.error(`[AngularJS - Leaflet] The type of layer ${layerDefinition.type} must have key defined`);\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function createLayer(layerDefinition) {\r\n if (!isValidLayerType(layerDefinition)) {\r\n return;\r\n }\r\n\r\n if (!angular.isString(layerDefinition.name)) {\r\n $log.error(`[AngularJS - Leaflet] A base layer must have a name`);\r\n return;\r\n }\r\n\r\n if (!angular.isObject(layerDefinition.layerParams)) {\r\n layerDefinition.layerParams = {};\r\n }\r\n\r\n if (!angular.isObject(layerDefinition.layerOptions)) {\r\n layerDefinition.layerOptions = {};\r\n }\r\n\r\n // Mix the layer specific parameters with the general Leaflet options. Although this is an overhead\r\n // the definition of a base layers is more 'clean' if the two types of parameters are differentiated\r\n for (const attrname in layerDefinition.layerParams) {\r\n if (layerDefinition.layerParams.hasOwnProperty(attrname)){\r\n layerDefinition.layerOptions[attrname] = layerDefinition.layerParams[attrname];\r\n }\r\n }\r\n\r\n const params = {\r\n url: layerDefinition.url,\r\n data: layerDefinition.data,\r\n options: layerDefinition.layerOptions,\r\n layer: layerDefinition.layer,\r\n icon: layerDefinition.icon,\r\n type: layerDefinition.layerType,\r\n bounds: layerDefinition.bounds,\r\n key: layerDefinition.key,\r\n apiKey: layerDefinition.apiKey,\r\n pluginOptions: layerDefinition.pluginOptions,\r\n user: layerDefinition.user\r\n };\r\n\r\n //TODO Add $watch to the layer properties\r\n return layerTypes[layerDefinition.type].createLayer(params);\r\n }\r\n\r\n function safeAddLayer(map, layer) {\r\n if (layer && typeof layer.addTo === `function`) {\r\n layer.addTo(map);\r\n } else {\r\n map.addLayer(layer);\r\n }\r\n }\r\n\r\n function safeRemoveLayer(map, layer, layerOptions) {\r\n if (isDefined(layerOptions) && isDefined(layerOptions.loadedDefer)) {\r\n if (angular.isFunction(layerOptions.loadedDefer)) {\r\n const defers = layerOptions.loadedDefer();\r\n $log.debug(`Loaded Deferred`, defers);\r\n let count = defers.length;\r\n if (count > 0) {\r\n const resolve = function() {\r\n count--;\r\n if (count === 0) {\r\n map.removeLayer(layer);\r\n }\r\n };\r\n\r\n for (let i = 0; i < defers.length; i++) {\r\n defers[i].promise.then(resolve);\r\n }\r\n } else {\r\n map.removeLayer(layer);\r\n }\r\n } else {\r\n layerOptions.loadedDefer.promise.then(function() {\r\n map.removeLayer(layer);\r\n });\r\n }\r\n } else {\r\n map.removeLayer(layer);\r\n }\r\n }\r\n\r\n function getLayerTypes(){\r\n return {\r\n xyz: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer(params.url, params.options);\r\n }\r\n },\r\n __mapbox: { // original mapbox entry\r\n mustHaveKey: true,\r\n createLayer: function(params) {\r\n let version = 3;\r\n if (isDefined(params.options.version) && params.options.version === 4) {\r\n version = params.options.version;\r\n }\r\n\r\n const url = version === 3 ?\r\n `//{s}.tiles.mapbox.com/v3/${params.key}/{z}/{x}/{y}.png` :\r\n `//api.tiles.mapbox.com/v4/${params.key}/{z}/{x}/{y}.png?access_token=${params.apiKey}`;\r\n return L.tileLayer(url, params.options);\r\n }\r\n },\r\n mapbox: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n const url = `${params.url}?access_token=${params.apiKey}`;\r\n return L.tileLayer(url, params.options);\r\n }\r\n },\r\n geoJSON: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.GeoJSONPlugin.isLoaded()) {\r\n return;\r\n }\r\n return new L.TileLayer.GeoJSON(params.url, params.pluginOptions, params.options);\r\n }\r\n },\r\n geoJSONShape: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n return new L.GeoJSON(params.data,\r\n params.options);\r\n }\r\n },\r\n geoJSONAwesomeMarker: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n return new L.GeoJSON(params.data, {\r\n pointToLayer: function(feature, latlng) {\r\n return L.marker(latlng, { icon: L.AwesomeMarkers.icon(params.icon) });\r\n }\r\n });\r\n }\r\n },\r\n geoJSONVectorMarker: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n return new L.GeoJSON(params.data, {\r\n pointToLayer: function(feature, latlng) {\r\n return L.marker(latlng, { icon: L.VectorMarkers.icon(params.icon) });\r\n }\r\n });\r\n }\r\n },\r\n wms: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer.wms(params.url, params.options);\r\n }\r\n },\r\n wmts: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer.wmts(params.url, params.options);\r\n }\r\n },\r\n group: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n const lyrs = [];\r\n IteratorHelper.each(params.options.layers, function(l) {\r\n lyrs.push(createLayer(l));\r\n });\r\n\r\n params.options.loadedDefer = function() {\r\n const defers = [];\r\n if (isDefined(params.options.layers)) {\r\n for (let i = 0; i < params.options.layers.length; i++) {\r\n const d = params.options.layers[i].layerOptions.loadedDefer;\r\n if (isDefined(d)) {\r\n defers.push(d);\r\n }\r\n }\r\n }\r\n\r\n return defers;\r\n };\r\n\r\n return L.layerGroup(lyrs);\r\n }\r\n },\r\n featureGroup: {\r\n mustHaveUrl: false,\r\n createLayer: function() {\r\n return L.featureGroup();\r\n }\r\n },\r\n google: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n const type = params.type || `SATELLITE`;\r\n if (!esLeafletHelpers.GoogleLayerPlugin.isLoaded()) {\r\n return;\r\n }\r\n\r\n return new L.GoogleLayer(type, params.options);\r\n }\r\n },\r\n here: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n const provider = params.provider || `HERE.terrainDay`;\r\n if (!esLeafletHelpers.LeafletProviderPlugin.isLoaded()) {\r\n return;\r\n }\r\n return new L.TileLayer.Provider(provider, params.options);\r\n }\r\n },\r\n openstreetmap: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer(params.url, params.options);\r\n }\r\n },\r\n gaode: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer(params.url, params.options);\r\n }\r\n },\r\n baidu: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer(params.url, params.options);\r\n }\r\n },\r\n agsFeature: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.AGSFeatureLayerPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The esri plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n params.options.url = params.url;\r\n\r\n const layer = L.esri.featureLayer(params.options);\r\n const load = function() {\r\n if (isDefined(params.options.loadedDefer)) {\r\n params.options.loadedDefer.resolve();\r\n }\r\n };\r\n\r\n layer.on(`loading`, function() {\r\n params.options.loadedDefer = $q.defer();\r\n layer.off(`load`, load);\r\n layer.on(`load`, load);\r\n });\r\n\r\n return layer;\r\n }\r\n },\r\n agsTiled: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.AGSTiledMapLayerPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The esri plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n params.options.url = params.url;\r\n\r\n return L.esri.tiledMapLayer(params.options);\r\n }\r\n },\r\n agsDynamic: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.AGSDynamicMapLayerPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The esri plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n params.options.url = params.url;\r\n\r\n return L.esri.dynamicMapLayer(params.options);\r\n }\r\n },\r\n agsImage: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.AGSImageMapLayerPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The esri plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n params.options.url = params.url;\r\n\r\n return L.esri.imageMapLayer(params.options);\r\n }\r\n },\r\n agsClustered: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.AGSClusteredLayerPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The esri clustered layer plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n if (!esLeafletHelpers.MarkerClusterPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The markercluster plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n return L.esri.clusteredFeatureLayer(params.url, params.options);\r\n }\r\n },\r\n markercluster: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.MarkerClusterPlugin.isLoaded()) {\r\n $log.warn(`${errorHeader} The markercluster plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n return new L.MarkerClusterGroup(params.options);\r\n }\r\n },\r\n bing: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.BingLayerPlugin.isLoaded()) {\r\n return;\r\n }\r\n\r\n return new L.BingLayer(params.key, params.options);\r\n }\r\n },\r\n webGLHeatmap: {\r\n mustHaveUrl: false,\r\n mustHaveData: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.WebGLHeatMapLayerPlugin.isLoaded()) {\r\n return;\r\n }\r\n\r\n const layer = new L.TileLayer.WebGLHeatMap(params.options);\r\n if (isDefined(params.data)) {\r\n layer.setData(params.data);\r\n }\r\n\r\n return layer;\r\n }\r\n },\r\n heat: {\r\n mustHaveUrl: false,\r\n mustHaveData: true,\r\n createLayer: function(params) {\r\n if (!esLeafletHelpers.HeatLayerPlugin.isLoaded()) {\r\n return;\r\n }\r\n\r\n const layer = new L.HeatLayer();\r\n\r\n if (angular.isArray(params.data)) {\r\n layer.setLatLngs(params.data);\r\n }\r\n\r\n if (angular.isObject(params.options)) {\r\n layer.setOptions(params.options);\r\n }\r\n\r\n return layer;\r\n }\r\n },\r\n yandex: {\r\n mustHaveUrl: false,\r\n createLayer: function(params) {\r\n const type = params.type || `map`;\r\n if (!esLeafletHelpers.YandexLayerPlugin.isLoaded()) {\r\n return;\r\n }\r\n\r\n return new L.Yandex(type, params.options);\r\n }\r\n },\r\n imageOverlay: {\r\n mustHaveUrl: true,\r\n mustHaveBounds: true,\r\n createLayer: function(params) {\r\n return L.imageOverlay(params.url, params.bounds, params.options);\r\n }\r\n },\r\n iip: {\r\n mustHaveUrl: true,\r\n createLayer: function(params) {\r\n return L.tileLayer.iip(params.url, params.options);\r\n }\r\n },\r\n\r\n // This \"custom\" type is used to accept every layer that user want to define himself.\r\n // We can wrap these custom layers like heatmap or yandex, but it means a lot of work/code to wrap the world,\r\n // so we let user to define their own layer outside the directive,\r\n // and pass it on \"createLayer\" result for next processes\r\n custom: {\r\n createLayer: function(params) {\r\n if (params.layer instanceof L.Class) {\r\n return angular.copy(params.layer);\r\n }\r\n else {\r\n $log.error(`[AngularJS - Leaflet] A custom layer must be a leaflet Class`);\r\n }\r\n }\r\n }\r\n };\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n \r\n angular\r\n .module(`es-leaflet-directive`)\r\n .directive(`layers`, layers)\r\n .controller(`layersController`, controller);\r\n\r\n layers.$inject = [`esLeafletData`, `esLeafletHelpers`, `esLeafletLayerHelpers`, `esLeafletControlHelpers`];\r\n function layers(esLeafletData, esLeafletHelpers, esLeafletLayerHelpers, esLeafletControlHelpers) {\r\n return {\r\n restrict: `A`,\r\n scope: false,\r\n replace: false,\r\n require: `esLeaflet`,\r\n controller: controller,\r\n link\r\n };\r\n \r\n function link(scope, element, attrs, controller) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const leafletLayers = {};\r\n const leafletScope = controller.getLeafletScope();\r\n const layers = leafletScope.layers;\r\n const createLayer = esLeafletLayerHelpers.createLayer;\r\n const safeAddLayer = esLeafletLayerHelpers.safeAddLayer;\r\n const safeRemoveLayer = esLeafletLayerHelpers.safeRemoveLayer;\r\n const updateLayersControl = esLeafletControlHelpers.updateLayersControl;\r\n let isLayersControlVisible = false;\r\n\r\n controller.getMap().then(map => {\r\n\r\n // We have baselayers to add to the map\r\n scope._leafletLayers.resolve(leafletLayers);\r\n esLeafletData.setLayers(leafletLayers, attrs.id);\r\n\r\n leafletLayers.baselayers = {};\r\n leafletLayers.overlays = {};\r\n\r\n const mapId = attrs.id;\r\n\r\n // Setup all baselayers definitions\r\n let oneVisibleLayer = false;\r\n for (const layerName in layers.baselayers) {\r\n if (layerName){\r\n const newBaseLayer = createLayer(layers.baselayers[layerName]);\r\n if (!isDefined(newBaseLayer)) {\r\n delete layers.baselayers[layerName];\r\n continue;\r\n }\r\n\r\n leafletLayers.baselayers[layerName] = newBaseLayer;\r\n\r\n // Only add the visible layer to the map, layer control manages the addition to the map\r\n // of layers in its control\r\n if (layers.baselayers[layerName].top === true) {\r\n safeAddLayer(map, leafletLayers.baselayers[layerName]);\r\n oneVisibleLayer = true;\r\n }\r\n }\r\n }\r\n\r\n // If there is no visible layer add first to the map\r\n if (!oneVisibleLayer && Object.keys(leafletLayers.baselayers).length > 0) {\r\n safeAddLayer(map, leafletLayers.baselayers[Object.keys(layers.baselayers)[0]]);\r\n }\r\n\r\n // Setup the Overlays\r\n for (const layerName in layers.overlays) {\r\n if (layerName){\r\n //if (layers.overlays[layerName].type === `cartodb`) {\r\n //\r\n //}\r\n\r\n const newOverlayLayer = createLayer(layers.overlays[layerName]);\r\n if (!isDefined(newOverlayLayer)) {\r\n delete layers.overlays[layerName];\r\n continue;\r\n }\r\n\r\n leafletLayers.overlays[layerName] = newOverlayLayer;\r\n\r\n // Only add the visible overlays to the map\r\n if (layers.overlays[layerName].visible === true) {\r\n safeAddLayer(map, leafletLayers.overlays[layerName]);\r\n }\r\n }\r\n }\r\n\r\n // Watch for the base layers\r\n leafletScope.$watch(`layers.baselayers`, function(newBaseLayers, oldBaseLayers) {\r\n if (angular.equals(newBaseLayers, oldBaseLayers)) {\r\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers);\r\n return true;\r\n }\r\n\r\n // Delete layers from the array\r\n for (const name in leafletLayers.baselayers) {\r\n if (!isDefined(newBaseLayers[name]) || newBaseLayers[name].doRefresh) {\r\n // Remove from the map if it`s on it\r\n if (map.hasLayer(leafletLayers.baselayers[name])) {\r\n map.removeLayer(leafletLayers.baselayers[name]);\r\n }\r\n\r\n delete leafletLayers.baselayers[name];\r\n\r\n if (newBaseLayers[name] && newBaseLayers[name].doRefresh) {\r\n newBaseLayers[name].doRefresh = false;\r\n }\r\n }\r\n }\r\n\r\n // add new layers\r\n for (const newName in newBaseLayers) {\r\n if (!isDefined(leafletLayers.baselayers[newName])) {\r\n const testBaseLayer = createLayer(newBaseLayers[newName]);\r\n if (isDefined(testBaseLayer)) {\r\n leafletLayers.baselayers[newName] = testBaseLayer;\r\n\r\n // Only add the visible layer to the map\r\n if (newBaseLayers[newName].top === true) {\r\n safeAddLayer(map, leafletLayers.baselayers[newName]);\r\n }\r\n }\r\n } else {\r\n if (newBaseLayers[newName].top === true && !map.hasLayer(leafletLayers.baselayers[newName])) {\r\n safeAddLayer(map, leafletLayers.baselayers[newName]);\r\n } else if (newBaseLayers[newName].top === false && map.hasLayer(leafletLayers.baselayers[newName])) {\r\n map.removeLayer(leafletLayers.baselayers[newName]);\r\n }\r\n }\r\n }\r\n\r\n //we have layers, so we need to make, at least, one active\r\n let found = false;\r\n\r\n // search for an active layer\r\n for (const key in leafletLayers.baselayers) {\r\n if (map.hasLayer(leafletLayers.baselayers[key])) {\r\n found = true;\r\n break;\r\n }\r\n }\r\n\r\n // If there is no active layer make one active\r\n if (!found && Object.keys(leafletLayers.baselayers).length > 0) {\r\n safeAddLayer(map, leafletLayers.baselayers[Object.keys(leafletLayers.baselayers)[0]]);\r\n }\r\n\r\n // Only show the layers switch selector control if we have more than one baselayer + overlay\r\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers);\r\n }, true);\r\n\r\n // Watch for the overlay layers\r\n leafletScope.$watch(`layers.overlays`, function(newOverlayLayers, oldOverlayLayers) {\r\n if (angular.equals(newOverlayLayers, oldOverlayLayers)) {\r\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers);\r\n return true;\r\n }\r\n\r\n // Delete layers from the array\r\n for (const name in leafletLayers.overlays) {\r\n if (!isDefined(newOverlayLayers[name]) || newOverlayLayers[name].doRefresh) {\r\n // Remove from the map if it`s on it\r\n if (map.hasLayer(leafletLayers.overlays[name])) {\r\n // Safe remove when ArcGIS layers is loading.\r\n const options = isDefined(newOverlayLayers[name]) ?\r\n newOverlayLayers[name].layerOptions : null;\r\n safeRemoveLayer(map, leafletLayers.overlays[name], options);\r\n }\r\n\r\n // TODO: Depending on the layer type we will have to delete what`s included on it\r\n delete leafletLayers.overlays[name];\r\n\r\n if (newOverlayLayers[name] && newOverlayLayers[name].doRefresh) {\r\n newOverlayLayers[name].doRefresh = false;\r\n }\r\n }\r\n }\r\n\r\n // add new overlays\r\n for (const newName in newOverlayLayers) {\r\n if (!isDefined(leafletLayers.overlays[newName])) {\r\n const testOverlayLayer = createLayer(newOverlayLayers[newName]);\r\n if (!isDefined(testOverlayLayer)) {\r\n // If the layer creation fails, continue to the next overlay\r\n continue;\r\n }\r\n\r\n leafletLayers.overlays[newName] = testOverlayLayer;\r\n if (newOverlayLayers[newName].visible === true) {\r\n safeAddLayer(map, leafletLayers.overlays[newName]);\r\n }\r\n } else {\r\n // check for the .visible property to hide/show overLayers\r\n if (newOverlayLayers[newName].visible && !map.hasLayer(leafletLayers.overlays[newName])) {\r\n safeAddLayer(map, leafletLayers.overlays[newName]);\r\n } else if (newOverlayLayers[newName].visible === false && map.hasLayer(leafletLayers.overlays[newName])) {\r\n // Safe remove when ArcGIS layers is loading.\r\n safeRemoveLayer(map, leafletLayers.overlays[newName], newOverlayLayers[newName].layerOptions);\r\n }\r\n }\r\n\r\n //refresh heatmap data if present\r\n if (newOverlayLayers[newName].visible && map._loaded && newOverlayLayers[newName].data && newOverlayLayers[newName].type === `heatmap`) {\r\n leafletLayers.overlays[newName].setData(newOverlayLayers[newName].data);\r\n leafletLayers.overlays[newName].update();\r\n }\r\n }\r\n\r\n // Only add the layers switch selector control if we have more than one baselayer + overlay\r\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers);\r\n }, true);\r\n });\r\n }\r\n }\r\n\r\n controller.$inject = [`$scope`, `$q`];\r\n function controller($scope, $q){\r\n const self = this;\r\n $scope._leafletLayers = $q.defer();\r\n self.getLayers = function() {\r\n return $scope._leafletLayers.promise;\r\n };\r\n }\r\n\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletMapDefaults`, esLeafletMapDefaults);\r\n\r\n esLeafletMapDefaults.$inject = [`esLeafletHelpers`, `leafletLib`];\r\n function esLeafletMapDefaults(esLeafletHelpers, L) {\r\n\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const obtainEffectiveMapId = esLeafletHelpers.obtainEffectiveMapId;\r\n let defaults = {};\r\n\r\n // Get the _defaults dictionary, and override the properties defined by the user\r\n return {\r\n reset,\r\n getDefaults,\r\n getMapCreationDefaults,\r\n setDefaults\r\n };\r\n\r\n function reset() {\r\n defaults = {};\r\n }\r\n\r\n function getDefaults(scopeId) {\r\n const mapId = obtainEffectiveMapId(defaults, scopeId);\r\n return defaults[mapId];\r\n }\r\n\r\n function getMapCreationDefaults(scopeId) {\r\n const mapId = obtainEffectiveMapId(defaults, scopeId);\r\n const scopeDefaults = defaults[mapId];\r\n\r\n const mapDefaults = {\r\n maxZoom: scopeDefaults.maxZoom,\r\n keyboard: scopeDefaults.keyboard,\r\n dragging: scopeDefaults.dragging,\r\n zoomControl: scopeDefaults.zoomControl,\r\n doubleClickZoom: scopeDefaults.doubleClickZoom,\r\n scrollWheelZoom: scopeDefaults.scrollWheelZoom,\r\n tap: scopeDefaults.tap,\r\n touchZoom: scopeDefaults.touchZoom,\r\n attributionControl: scopeDefaults.attributionControl,\r\n worldCopyJump: scopeDefaults.worldCopyJump,\r\n crs: scopeDefaults.crs\r\n };\r\n\r\n if (isDefined(scopeDefaults.minZoom)) {\r\n mapDefaults.minZoom = scopeDefaults.minZoom;\r\n }\r\n\r\n if (isDefined(scopeDefaults.zoomAnimation)) {\r\n mapDefaults.zoomAnimation = scopeDefaults.zoomAnimation;\r\n }\r\n\r\n if (isDefined(scopeDefaults.fadeAnimation)) {\r\n mapDefaults.fadeAnimation = scopeDefaults.fadeAnimation;\r\n }\r\n\r\n if (isDefined(scopeDefaults.markerZoomAnimation)) {\r\n mapDefaults.markerZoomAnimation = scopeDefaults.markerZoomAnimation;\r\n }\r\n\r\n if (scopeDefaults.map) {\r\n for(const option in scopeDefaults.map) {\r\n if (option) {\r\n mapDefaults[option] = scopeDefaults.map[option];\r\n }\r\n }\r\n }\r\n\r\n return mapDefaults;\r\n }\r\n\r\n function setDefaults(userDefaults, scopeId) {\r\n const newDefaults = _getDefaults();\r\n\r\n if (isDefined(userDefaults)) {\r\n newDefaults.doubleClickZoom = isDefined(userDefaults.doubleClickZoom) ? userDefaults.doubleClickZoom : newDefaults.doubleClickZoom;\r\n newDefaults.scrollWheelZoom = isDefined(userDefaults.scrollWheelZoom) ? userDefaults.scrollWheelZoom : newDefaults.doubleClickZoom;\r\n newDefaults.tap = isDefined(userDefaults.tap) ? userDefaults.tap : newDefaults.tap;\r\n newDefaults.touchZoom = isDefined(userDefaults.touchZoom) ? userDefaults.touchZoom : newDefaults.doubleClickZoom;\r\n newDefaults.zoomControl = isDefined(userDefaults.zoomControl) ? userDefaults.zoomControl : newDefaults.zoomControl;\r\n newDefaults.zoomsliderControl = isDefined(userDefaults.zoomsliderControl) ? userDefaults.zoomsliderControl : newDefaults.zoomsliderControl;\r\n newDefaults.attributionControl = isDefined(userDefaults.attributionControl) ? userDefaults.attributionControl : newDefaults.attributionControl;\r\n newDefaults.tileLayer = isDefined(userDefaults.tileLayer) ? userDefaults.tileLayer : newDefaults.tileLayer;\r\n newDefaults.zoomControlPosition = isDefined(userDefaults.zoomControlPosition) ? userDefaults.zoomControlPosition : newDefaults.zoomControlPosition;\r\n newDefaults.keyboard = isDefined(userDefaults.keyboard) ? userDefaults.keyboard : newDefaults.keyboard;\r\n newDefaults.dragging = isDefined(userDefaults.dragging) ? userDefaults.dragging : newDefaults.dragging;\r\n\r\n if (isDefined(userDefaults.controls)) {\r\n angular.extend(newDefaults.controls, userDefaults.controls);\r\n }\r\n\r\n if (angular.isObject(userDefaults.crs)) {\r\n newDefaults.crs = userDefaults.crs;\r\n } else if (isDefined(L.CRS[userDefaults.crs])) {\r\n newDefaults.crs = L.CRS[userDefaults.crs];\r\n }\r\n\r\n if (isDefined(userDefaults.center)) {\r\n angular.copy(userDefaults.center, newDefaults.center);\r\n }\r\n\r\n if (isDefined(userDefaults.tileLayerOptions)) {\r\n angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions);\r\n }\r\n\r\n if (isDefined(userDefaults.maxZoom)) {\r\n newDefaults.maxZoom = userDefaults.maxZoom;\r\n }\r\n\r\n if (isDefined(userDefaults.minZoom)) {\r\n newDefaults.minZoom = userDefaults.minZoom;\r\n }\r\n\r\n if (isDefined(userDefaults.zoomAnimation)) {\r\n newDefaults.zoomAnimation = userDefaults.zoomAnimation;\r\n }\r\n\r\n if (isDefined(userDefaults.fadeAnimation)) {\r\n newDefaults.fadeAnimation = userDefaults.fadeAnimation;\r\n }\r\n\r\n if (isDefined(userDefaults.markerZoomAnimation)) {\r\n newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation;\r\n }\r\n\r\n if (isDefined(userDefaults.worldCopyJump)) {\r\n newDefaults.worldCopyJump = userDefaults.worldCopyJump;\r\n }\r\n\r\n if (isDefined(userDefaults.map)) {\r\n newDefaults.map = userDefaults.map;\r\n }\r\n\r\n if (isDefined(userDefaults.path)) {\r\n newDefaults.path = userDefaults.path;\r\n }\r\n }\r\n\r\n const mapId = obtainEffectiveMapId(defaults, scopeId);\r\n defaults[mapId] = newDefaults;\r\n return newDefaults;\r\n }\r\n\r\n function _getDefaults() {\r\n return {\r\n keyboard: true,\r\n dragging: true,\r\n worldCopyJump: false,\r\n doubleClickZoom: true,\r\n scrollWheelZoom: true,\r\n tap: true,\r\n touchZoom: true,\r\n zoomControl: true,\r\n zoomSliderControl: false, //changed casing\r\n zoomControlPosition: `topleft`,\r\n attributionControl: true,\r\n controls: {\r\n layers: {\r\n visible: true,\r\n position: `topright`,\r\n collapsed: true\r\n }\r\n },\r\n nominatim: {\r\n server: ` http://nominatim.openstreetmap.org/search`\r\n },\r\n crs: L.CRS.EPSG3857,\r\n tileLayer: `//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`,\r\n tileLayerOptions: {\r\n attribution: `© OpenStreetMap contributors`\r\n },\r\n path: {\r\n weight: 10,\r\n opacity: 1,\r\n color: `#0000ff`\r\n },\r\n center: {\r\n lat: 0,\r\n lng: 0,\r\n zoom: 1\r\n }\r\n };\r\n }\r\n }\r\n\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletMapEvents`,esLeafletMapEvents);\r\n\r\n esLeafletMapEvents.$inject = [`$log`, `esLeafletHelpers`, `esLeafletEventsHelpers`, `esLeafletIterators`];\r\n function esLeafletMapEvents($log, esLeafletHelpers, esLeafletEventsHelpers, esLeafletIterators) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const fire = esLeafletEventsHelpers.fire;\r\n\r\n return {\r\n getAvailableMapEvents,\r\n genDispatchMapEvent,\r\n notifyCenterChangedToBounds,\r\n notifyCenterUrlHashChanged,\r\n addEvents\r\n };\r\n\r\n function getAvailableMapEvents() {\r\n return [\r\n `click`,\r\n `dblclick`,\r\n `mousedown`,\r\n `mouseup`,\r\n `mouseover`,\r\n `mouseout`,\r\n `mousemove`,\r\n `contextmenu`,\r\n `focus`,\r\n `blur`,\r\n `preclick`,\r\n `load`,\r\n `unload`,\r\n `viewreset`,\r\n `movestart`,\r\n `move`,\r\n `moveend`,\r\n `dragstart`,\r\n `drag`,\r\n `dragend`,\r\n `zoomstart`,\r\n `zoomanim`,\r\n `zoomend`,\r\n `zoomlevelschange`,\r\n `resize`,\r\n `autopanstart`,\r\n `layeradd`,\r\n `layerremove`,\r\n `baselayerchange`,\r\n `overlayadd`,\r\n `overlayremove`,\r\n `locationfound`,\r\n `locationerror`,\r\n `popupopen`,\r\n `popupclose`,\r\n `draw:created`,\r\n `draw:edited`,\r\n `draw:deleted`,\r\n `draw:drawstart`,\r\n `draw:drawstop`,\r\n `draw:editstart`,\r\n `draw:editstop`,\r\n `draw:deletestart`,\r\n `draw:deletestop`\r\n ];\r\n }\r\n\r\n function genDispatchMapEvent(scope, eventName, logic, maybeMapId) {\r\n if (maybeMapId){\r\n maybeMapId = maybeMapId + `.`;\r\n }\r\n return function(e) {\r\n // Put together broadcast name\r\n const broadcastName = `leafletDirectiveMap.${maybeMapId}${eventName}`;\r\n $log.debug(broadcastName);\r\n\r\n // Safely broadcast the event\r\n fire(scope, broadcastName, logic, e, e.target, scope);\r\n };\r\n }\r\n\r\n function notifyCenterChangedToBounds(scope) {\r\n scope.$broadcast(`boundsChanged`);\r\n }\r\n\r\n function notifyCenterUrlHashChanged(scope, map, attrs, search) {\r\n if (!isDefined(attrs.urlHashCenter)) {\r\n return;\r\n }\r\n\r\n const center = map.getCenter();\r\n const centerUrlHash = center.lat.toFixed(4) + `:` + center.lng.toFixed(4) + `:` + map.getZoom();\r\n if (!isDefined(search.c) || search.c !== centerUrlHash) {\r\n //$log.debug(`notified new center...`);\r\n scope.$emit(`centerUrlHash`, centerUrlHash);\r\n }\r\n }\r\n\r\n function addEvents(map, mapEvents, contextName, scope, logic) {\r\n esLeafletIterators.each(mapEvents, function(eventName) {\r\n const context = {};\r\n context[contextName] = eventName;\r\n map.on(eventName, genDispatchMapEvent(scope, eventName, logic, map._container.id || ``), context);\r\n });\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletMarkerEvents`, esLeafletMarkerEvents);\r\n\r\n esLeafletMarkerEvents.$inject = [`$rootScope`, `esLeafletHelpers`, `esLeafletEventsHelpersFactory`, `esLeafletLabelEvents`];\r\n function esLeafletMarkerEvents($rootScope, esLeafletHelpers, esLeafletEventsHelpersFactory, esLeafletLabelEvents) {\r\n const safeApply = esLeafletHelpers.safeApply;\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const lblHelp = esLeafletLabelEvents;\r\n const EventsHelper = esLeafletEventsHelpersFactory;\r\n\r\n const MarkerEvents = function() {\r\n EventsHelper.call(this, `leafletDirectiveMarker`, `markers`);\r\n };\r\n\r\n MarkerEvents.prototype = new EventsHelper();\r\n\r\n MarkerEvents.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\r\n const handle = EventsHelper.prototype\r\n .genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName);\r\n return function(e) {\r\n // Broadcast old marker click name for backwards compatibility\r\n if (eventName === `click`) {\r\n safeApply(leafletScope, function() {\r\n $rootScope.$broadcast(`leafletDirectiveMarkersClick`, name);\r\n });\r\n } else if (eventName === `dragend`) {\r\n safeApply(leafletScope, function() {\r\n model.lat = lObject.getLatLng().lat;\r\n model.lng = lObject.getLatLng().lng;\r\n });\r\n\r\n if (model.message && model.focus === true) {\r\n lObject.openPopup();\r\n }\r\n }\r\n\r\n handle(e);\r\n };\r\n };\r\n\r\n MarkerEvents.prototype.getAvailableEvents = function() { return [\r\n `click`,\r\n `dblclick`,\r\n `mousedown`,\r\n `mouseover`,\r\n `mouseout`,\r\n `contextmenu`,\r\n `dragstart`,\r\n `drag`,\r\n `dragend`,\r\n `move`,\r\n `remove`,\r\n `popupopen`,\r\n `popupclose`,\r\n `touchend`,\r\n `touchstart`,\r\n `touchmove`,\r\n `touchcancel`,\r\n `touchleave`\r\n ];\r\n };\r\n\r\n MarkerEvents.prototype.bindEvents = function(maybeMapId, lObject, name, model, leafletScope, layerName) {\r\n const logic = EventsHelper.prototype.bindEvents.call(this, maybeMapId, lObject, name, model, leafletScope, layerName);\r\n\r\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) {\r\n lblHelp.genEvents(maybeMapId, name, logic, leafletScope, lObject, model, layerName);\r\n }\r\n };\r\n\r\n return new MarkerEvents();\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .directive(`markers`, markers);\r\n\r\n markers.$inject = [`$log`, `$q`, `esLeafletData`, `esLeafletHelpers`,\r\n `esLeafletMarkersHelpers`, `esLeafletMarkerEvents`, `esLeafletIterators`, `esLeafletWatchHelpers`,\r\n `esLeafletDirectiveControlsHelpers`, `leafletLib`];\r\n\r\n function markers($log, $q, esLeafletData, esLeafletHelpers,\r\n esLeafletMarkersHelpers, esLeafletMarkerEvents, esLeafletIterators, esLeafletWatchHelpers,\r\n esLeafletDirectiveControlsHelpers, L) {\r\n\r\n return {\r\n restrict: `A`,\r\n scope: false,\r\n replace: false,\r\n require: [`esLeaflet`, `?layers`],\r\n link\r\n };\r\n\r\n function link(scope, element, attrs, controllers) {\r\n //less terse vars to helpers\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const errorHeader = esLeafletHelpers.errorHeader;\r\n const addMarkerWatcher = esLeafletMarkersHelpers.addMarkerWatcher;\r\n const updateMarker = esLeafletMarkersHelpers.updateMarker;\r\n const listenMarkerEvents = esLeafletMarkersHelpers.listenMarkerEvents;\r\n const addMarkerToGroup = esLeafletMarkersHelpers.addMarkerToGroup;\r\n const createMarker = esLeafletMarkersHelpers.createMarker;\r\n const deleteMarker = esLeafletMarkersHelpers.deleteMarker;\r\n const _markersWatchOptions = esLeafletHelpers.watchOptions;\r\n const maybeWatch = esLeafletWatchHelpers.maybeWatch;\r\n const extendDirectiveControls = esLeafletDirectiveControlsHelpers.extend;\r\n const mapController = controllers[0];\r\n const leafletScope = mapController.getLeafletScope();\r\n\r\n mapController.getMap().then(function (map) {\r\n const leafletMarkers = {};\r\n let getLayers;\r\n\r\n // If the layers attribute is used, we must wait until the layers are created\r\n if (isDefined(controllers[1])) {\r\n getLayers = controllers[1].getLayers;\r\n } else {\r\n getLayers = function () {\r\n const deferred = $q.defer();\r\n deferred.resolve();\r\n return deferred.promise;\r\n };\r\n }\r\n\r\n const watchOptions = leafletScope.markersWatchOptions || _markersWatchOptions;\r\n\r\n // backwards compat\r\n if (isDefined(attrs.watchMarkers)) {\r\n watchOptions.doWatch = watchOptions.individual.doWatch =\r\n !isDefined(attrs.watchMarkers) || esLeafletHelpers.isTruthy(attrs.watchMarkers);\r\n }\r\n\r\n const isNested = isDefined(attrs.markersNested) && esLeafletHelpers.isTruthy(attrs.markersNested);\r\n\r\n getLayers().then(function (layers) {\r\n const _clean = function (models, oldModels) {\r\n if (isNested) {\r\n let oldModel;\r\n esLeafletIterators.each(models, function (markerToMaybeDel, layerName) {\r\n oldModel = isDefined(oldModel) ? oldModels[layerName] : undefined;\r\n destroy(markerToMaybeDel, oldModel, leafletMarkers[layerName], map, layers);\r\n });\r\n\r\n return;\r\n }\r\n\r\n destroy(models, oldModels, leafletMarkers, map, layers);\r\n };\r\n\r\n const _create = function (models, oldModels) {\r\n _clean(models, oldModels);\r\n let skips = null;\r\n if (isNested) {\r\n let oldModel;\r\n esLeafletIterators.each(models, function (markersToAdd, layerName) {\r\n oldModel = isDefined(oldModel) ? oldModels[layerName] : undefined;\r\n skips = getNewModelsToSkip(models[layerName], oldModel, leafletMarkers[layerName]);\r\n addMarkers(attrs.id, markersToAdd, oldModels, map, layers, leafletMarkers, leafletScope,\r\n watchOptions, layerName, skips);\r\n });\r\n\r\n return;\r\n }\r\n\r\n skips = getNewModelsToSkip(models, oldModels, leafletMarkers);\r\n addMarkers(attrs.id, models, oldModels, map, layers, leafletMarkers, leafletScope,\r\n watchOptions, undefined, skips);\r\n };\r\n\r\n extendDirectiveControls(attrs.id, `markers`, _create, _clean);\r\n esLeafletData.setMarkers(leafletMarkers, attrs.id);\r\n\r\n maybeWatch(leafletScope, `markers`, watchOptions, function (newMarkers, oldMarkers) {\r\n _create(newMarkers, oldMarkers);\r\n });\r\n });\r\n });\r\n\r\n function getLMarker(leafletMarkers, name, maybeLayerName) {\r\n if (!Object.keys(leafletMarkers).length){\r\n return;\r\n }\r\n if (maybeLayerName && angular.isString(maybeLayerName)) {\r\n if (!leafletMarkers[maybeLayerName] || !Object.keys(leafletMarkers[maybeLayerName]).length){\r\n return;\r\n }\r\n return leafletMarkers[maybeLayerName][name];\r\n }\r\n\r\n return leafletMarkers[name];\r\n }\r\n\r\n function setLMarker(lObject, leafletMarkers, name, maybeLayerName) {\r\n if (maybeLayerName && angular.isString(maybeLayerName)) {\r\n if (!isDefined(leafletMarkers[maybeLayerName])){\r\n leafletMarkers[maybeLayerName] = {};\r\n }\r\n leafletMarkers[maybeLayerName][name] = lObject;\r\n } else {\r\n leafletMarkers[name] = lObject;\r\n }\r\n return lObject;\r\n }\r\n\r\n function maybeAddMarkerToLayer(layerName, layers, model, marker, doIndividualWatch, map) {\r\n\r\n if (!angular.isString(layerName)) {\r\n $log.error(errorHeader + ` A layername must be a string`);\r\n return false;\r\n }\r\n\r\n if (!isDefined(layers)) {\r\n $log.error(errorHeader + ` You must add layers to the directive if the markers are going to use this functionality.`);\r\n return false;\r\n }\r\n\r\n if (!isDefined(layers.overlays) || !isDefined(layers.overlays[layerName])) {\r\n $log.error(errorHeader + ` A marker can only be added to a layer of type 'group'`);\r\n return false;\r\n }\r\n\r\n const layerGroup = layers.overlays[layerName];\r\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\r\n $log.error(errorHeader + ` Adding a marker to an overlay needs a overlay of the type 'group' or 'featureGroup'`);\r\n return false;\r\n }\r\n\r\n // The marker goes to a correct layer group, so first of all we add it\r\n layerGroup.addLayer(marker);\r\n\r\n // The marker is automatically added to the map depending on the visibility\r\n // of the layer, so we only have to open the popup if the marker is in the map\r\n if (!doIndividualWatch && map.hasLayer(marker) && model.focus === true) {\r\n marker.openPopup();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n //TODO: move to leafletMarkersHelpers??? or make a new class/function file (leafletMarkersHelpers is large already)\r\n function addMarkers(mapId, markersToRender, oldModels, map, layers, leafletMarkers, leafletScope,\r\n watchOptions, maybeLayerName, skips) {\r\n for (const newName in markersToRender) {\r\n if (skips[newName]) {\r\n continue;\r\n }\r\n\r\n if (newName.search(`-`) !== -1) {\r\n $log.error(`The marker can't use a '-' on his key name: ${newName}.`);\r\n continue;\r\n }\r\n\r\n const model = angular.copy(markersToRender[newName]);\r\n const pathToMarker = esLeafletHelpers.getObjectDotPath(maybeLayerName ? [maybeLayerName, newName] : [newName]);\r\n const maybeLMarker = getLMarker(leafletMarkers, newName, maybeLayerName);\r\n let oldModel;\r\n if (!isDefined(maybeLMarker)) {\r\n //(nmccready) very important to not have model changes when lObject is changed\r\n //this might be desirable in some cases but it causes two-way binding to lObject which is not ideal\r\n //if it is left as the reference then all changes from oldModel vs newModel are ignored\r\n //see _destroy (where modelDiff becomes meaningless if we do not copy here)\r\n const marker = createMarker(model);\r\n const layerName = (model ? model.layer : undefined) || maybeLayerName; //original way takes pref\r\n if (!isDefined(marker)) {\r\n $log.error(errorHeader + ` Received invalid data on the marker ${newName}.`);\r\n continue;\r\n }\r\n\r\n setLMarker(marker, leafletMarkers, newName, maybeLayerName);\r\n\r\n // Bind message\r\n if (isDefined(model.message)) {\r\n marker.bindPopup(model.message, model.popupOptions);\r\n }\r\n\r\n // Add the marker to a cluster group if needed\r\n if (isDefined(model.group)) {\r\n const groupOptions = isDefined(model.groupOption) ? model.groupOption : null;\r\n addMarkerToGroup(marker, model.group, groupOptions, map);\r\n }\r\n\r\n // Show label if defined\r\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(model.label) && isDefined(model.label.message)) {\r\n marker.bindTooltip(model.label.message, model.label.options);\r\n\r\n }\r\n\r\n // Check if the marker should be added to a layer\r\n if (isDefined(model) && (isDefined(model.layer) || isDefined(maybeLayerName))) {\r\n\r\n const pass = maybeAddMarkerToLayer(layerName, layers, model, marker,\r\n watchOptions.individual.doWatch, map);\r\n if (!pass) {\r\n continue; //something went wrong move on in the loop\r\n }\r\n } else if (!isDefined(model.group)) {\r\n // We do not have a layer attr, so the marker goes to the map layer\r\n map.addLayer(marker);\r\n if (!watchOptions.individual.doWatch && model.focus === true) {\r\n marker.openPopup();\r\n }\r\n }\r\n\r\n if (watchOptions.individual.doWatch) {\r\n addMarkerWatcher(marker, pathToMarker, leafletScope, layers, map,\r\n watchOptions.individual.isDeep);\r\n }\r\n\r\n listenMarkerEvents(marker, model, leafletScope, watchOptions.individual.doWatch, map);\r\n esLeafletMarkerEvents.bindEvents(mapId, marker, pathToMarker, model, leafletScope, layerName);\r\n }\r\n else {\r\n oldModel = isDefined(oldModel) ? oldModels[newName] : undefined;\r\n updateMarker(model, oldModel, maybeLMarker, pathToMarker, leafletScope, layers, map);\r\n }\r\n }\r\n };\r\n\r\n function seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, isEqual, cb) {\r\n let hasLogged = false;\r\n let equals = false;\r\n let oldMarker;\r\n let newMarker;\r\n\r\n const doCheckOldModel = isDefined(oldMarkerModels) && isDefined(markerModels);\r\n for (const name in lMarkers) {\r\n if (!hasLogged) {\r\n $log.debug(`${errorHeader}[markers] destroy: `);\r\n hasLogged = true;\r\n }\r\n\r\n if (doCheckOldModel) {\r\n //might want to make the option (in watch options) to disable deep checking\r\n //ie the options to only check !== (reference check) instead of angular.equals (slow)\r\n newMarker = markerModels[name];\r\n oldMarker = oldMarkerModels[name];\r\n equals = angular.equals(newMarker, oldMarker) && isEqual;\r\n }\r\n\r\n if (!isDefined(markerModels) ||\r\n !Object.keys(markerModels).length ||\r\n !isDefined(markerModels[name]) ||\r\n !Object.keys(markerModels[name]).length ||\r\n equals) {\r\n if (cb && esLeafletHelpers.isFunction(cb)){\r\n cb(newMarker, oldMarker, name);\r\n }\r\n }\r\n }\r\n };\r\n\r\n function destroy(markerModels, oldMarkerModels, lMarkers, map, layers) {\r\n seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, false,\r\n function(newMarker, oldMarker, lMarkerName) {\r\n $log.debug(`${errorHeader}[marker] is deleting marker: ` + lMarkerName);\r\n deleteMarker(lMarkers[lMarkerName], map, layers);\r\n delete lMarkers[lMarkerName];\r\n });\r\n };\r\n\r\n function getNewModelsToSkip(newModels, oldModels, lMarkers) {\r\n const skips = {};\r\n seeWhatWeAlreadyHave(newModels, oldModels, lMarkers, true,\r\n function(newMarker, oldMarker, lMarkerName) {\r\n $log.debug(`${errorHeader}[marker] is already rendered, marker: ${lMarkerName}`);\r\n skips[lMarkerName] = newMarker;\r\n });\r\n\r\n return skips;\r\n };\r\n }\r\n }\r\n\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletMarkersHelpers`,esLeafletMarkersHelpers);\r\n\r\n esLeafletMarkersHelpers.$inject = [`$rootScope`, `$timeout`, `esLeafletHelpers`, `$log`, `$compile`, `esLeafletGeoJsonHelpers`, `leafletLib`];\r\n function esLeafletMarkersHelpers($rootScope, $timeout, esLeafletHelpers, $log, $compile, esLeafletGeoJsonHelpers, L) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const defaultTo = esLeafletHelpers.defaultTo;\r\n const MarkerClusterPlugin = esLeafletHelpers.MarkerClusterPlugin;\r\n const AwesomeMarkersPlugin = esLeafletHelpers.AwesomeMarkersPlugin;\r\n const VectorMarkersPlugin = esLeafletHelpers.VectorMarkersPlugin;\r\n const MakiMarkersPlugin = esLeafletHelpers.MakiMarkersPlugin;\r\n const ExtraMarkersPlugin = esLeafletHelpers.ExtraMarkersPlugin;\r\n const DomMarkersPlugin = esLeafletHelpers.DomMarkersPlugin;\r\n const safeApply = esLeafletHelpers.safeApply;\r\n const groups = {};\r\n const errorHeader = esLeafletHelpers.errorHeader;\r\n\r\n\r\n return {\r\n deleteMarker,\r\n createMarker,\r\n addMarkerToGroup,\r\n listenMarkerEvents,\r\n updateMarker,\r\n addMarkerWatcher\r\n };\r\n\r\n function createLeafletIcon(iconData) {\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `awesomeMarker`) {\r\n if (!AwesomeMarkersPlugin.isLoaded()) {\r\n $log.error(errorHeader + ` The AwesomeMarkers Plugin is not loaded.`);\r\n }\r\n\r\n return new L.AwesomeMarkers.Icon(iconData);\r\n }\r\n\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `vectorMarker`) {\r\n if (!VectorMarkersPlugin.isLoaded()) {\r\n $log.error(errorHeader + ` The VectorMarkers Plugin is not loaded.`);\r\n }\r\n\r\n return new L.VectorMarkers.Icon(iconData);\r\n }\r\n\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `makiMarker`) {\r\n if (!MakiMarkersPlugin.isLoaded()) {\r\n $log.error(errorHeader + `The MakiMarkers Plugin is not loaded.`);\r\n }\r\n\r\n return new L.MakiMarkers.Icon(iconData);\r\n }\r\n\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `extraMarker`) {\r\n if (!ExtraMarkersPlugin.isLoaded()) {\r\n $log.error(errorHeader + `The ExtraMarkers Plugin is not loaded.`);\r\n }\r\n\r\n return new L.ExtraMarkers.Icon(iconData);\r\n }\r\n\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `div`) {\r\n return new L.DivIcon(iconData);\r\n }\r\n\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `dom`) {\r\n if (!DomMarkersPlugin.isLoaded()) {\r\n $log.error(errorHeader + `The DomMarkers Plugin is not loaded.`);\r\n }\r\n\r\n const markerScope = angular.isFunction(iconData.getMarkerScope) ? iconData.getMarkerScope() : $rootScope;\r\n const template = $compile(iconData.template)(markerScope);\r\n const iconDataCopy = angular.copy(iconData);\r\n iconDataCopy.element = template[0];\r\n return new L.DomMarkers.Icon(iconDataCopy);\r\n }\r\n\r\n // allow for any custom icon to be used... assumes the icon has already been initialized\r\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === `icon`) {\r\n return iconData.icon;\r\n }\r\n\r\n const base64icon = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAGmklEQVRYw7VXeUyTZxjvNnfELFuyIzOabermMZEeQC/OclkO49CpOHXOLJl/CAURuYbQi3KLgEhbrhZ1aDwmaoGqKII6odATmH/scDFbdC7LvFqOCc+e95s2VG50X/LLm/f4/Z7neY/ne18aANCmAr5E/xZf1uDOkTcGcWR6hl9247tT5U7Y6SNvWsKT63P58qbfeLJG8M5qcgTknrvvrdDbsT7Ml+tv82X6vVxJE33aRmgSyYtcWVMqX97Yv2JvW39UhRE2HuyBL+t+gK1116ly06EeWFNlAmHxlQE0OMiV6mQCScusKRlhS3QLeVJdl1+23h5dY4FNB3thrbYboqptEFlphTC1hSpJnbRvxP4NWgsE5Jyz86QNNi/5qSUTGuFk1gu54tN9wuK2wc3o+Wc13RCmsoBwEqzGcZsxsvCSy/9wJKf7UWf1mEY8JWfewc67UUoDbDjQC+FqK4QqLVMGGR9d2wurKzqBk3nqIT/9zLxRRjgZ9bqQgub+DdoeCC03Q8j+0QhFhBHR/eP3U/zCln7Uu+hihJ1+bBNffLIvmkyP0gpBZWYXhKussK6mBz5HT6M1Nqpcp+mBCPXosYQfrekGvrjewd59/GvKCE7TbK/04/ZV5QZYVWmDwH1mF3xa2Q3ra3DBC5vBT1oP7PTj4C0+CcL8c7C2CtejqhuCnuIQHaKHzvcRfZpnylFfXsYJx3pNLwhKzRAwAhEqG0SpusBHfAKkxw3w4627MPhoCH798z7s0ZnBJ/MEJbZSbXPhER2ih7p2ok/zSj2cEJDd4CAe+5WYnBCgR2uruyEw6zRoW6/DWJ/OeAP8pd/BGtzOZKpG8oke0SX6GMmRk6GFlyAc59K32OTEinILRJRchah8HQwND8N435Z9Z0FY1EqtxUg+0SO6RJ/mmXz4VuS+DpxXC3gXmZwIL7dBSH4zKE50wESf8qwVgrP1EIlTO5JP9Igu0aexdh28F1lmAEGJGfh7jE6ElyM5Rw/FDcYJjWhbeiBYoYNIpc2FT/SILivp0F1ipDWk4BIEo2VuodEJUifhbiltnNBIXPUFCMpthtAyqws/BPlEF/VbaIxErdxPphsU7rcCp8DohC+GvBIPJS/tW2jtvTmmAeuNO8BNOYQeG8G/2OzCJ3q+soYB5i6NhMaKr17FSal7GIHheuV3uSCY8qYVuEm1cOzqdWr7ku/R0BDoTT+DT+ohCM6/CCvKLKO4RI+dXPeAuaMqksaKrZ7L3FE5FIFbkIceeOZ2OcHO6wIhTkNo0ffgjRGxEqogXHYUPHfWAC/lADpwGcLRY3aeK4/oRGCKYcZXPVoeX/kelVYY8dUGf8V5EBRbgJXT5QIPhP9ePJi428JKOiEYhYXFBqou2Guh+p/mEB1/RfMw6rY7cxcjTrneI1FrDyuzUSRm9miwEJx8E/gUmqlyvHGkneiwErR21F3tNOK5Tf0yXaT+O7DgCvALTUBXdM4YhC/IawPU+2PduqMvuaR6eoxSwUk75ggqsYJ7VicsnwGIkZBSXKOUww73WGXyqP+J2/b9c+gi1YAg/xpwck3gJuucNrh5JvDPvQr0WFXf0piyt8f8/WI0hV4pRxxkQZdJDfDJNOAmM0Ag8jyT6hz0WGXWuP94Yh2jcfjmXAGvHCMslRimDHYuHuDsy2QtHuIavznhbYURq5R57KpzBBRZKPJi8eQg48h4j8SDdowifdIrEVdU+gbO6QNvRRt4ZBthUaZhUnjlYObNagV3keoeru3rU7rcuceqU1mJBxy+BWZYlNEBH+0eH4vRiB+OYybU2hnblYlTvkHinM4m54YnxSyaZYSF6R3jwgP7udKLGIX6r/lbNa9N6y5MFynjWDtrHd75ZvTYAPO/6RgF0k76mQla3FGq7dO+cH8sKn0Vo7nDllwAhqwLPkxrHwWmHJOo+AKJ4rab5OgrM7rVu8eWb2Pu0Dh4eDgXoOfvp7Y7QeqknRmvcTBEyq9m/HQQSCSz6LHq3z0yzsNySRfMS253wl2KyRDbcZPcfJKjZmSEOjcxyi+Y8dUOtsIEH6R2wNykdqrkYJ0RV92H0W58pkfQk7cKevsLK10Py8SdMGfXNXATY+pPbyJR/ET6n9nIfztNtZYRV9XniQu9IA2vOVgy4ir7GCLVmmd+zjkH0eAF9Po6K61pmCXHxU5rHMYd1ftc3owjwRSVRzLjKvqZEty6cRUD7jGqiOdu5HG6MdHjNcNYGqfDm5YRzLBBCCDl/2bk8a8gdbqcfwECu62Fg/HrggAAAABJRU5ErkJggg==`;\r\n const base64shadow = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAApCAYAAACoYAD2AAAC5ElEQVRYw+2YW4/TMBCF45S0S1luXZCABy5CgLQgwf//S4BYBLTdJLax0fFqmB07nnQfEGqkIydpVH85M+NLjPe++dcPc4Q8Qh4hj5D/AaQJx6H/4TMwB0PeBNwU7EGQAmAtsNfAzoZkgIa0ZgLMa4Aj6CxIAsjhjOCoL5z7Glg1JAOkaicgvQBXuncwJAWjksLtBTWZe04CnYRktUGdilALppZBOgHGZcBzL6OClABvMSVIzyBjazOgrvACf1ydC5mguqAVg6RhdkSWQFj2uxfaq/BrIZOLEWgZdALIDvcMcZLD8ZbLC9de4yR1sYMi4G20S4Q/PWeJYxTOZn5zJXANZHIxAd4JWhPIloTJZhzMQduM89WQ3MUVAE/RnhAXpTycqys3NZALOBbB7kFrgLesQl2h45Fcj8L1tTSohUwuxhy8H/Qg6K7gIs+3kkaigQCOcyEXCHN07wyQazhrmIulvKMQAwMcmLNqyCVyMAI+BuxSMeTk3OPikLY2J1uE+VHQk6ANrhds+tNARqBeaGc72cK550FP4WhXmFmcMGhTwAR1ifOe3EvPqIegFmF+C8gVy0OfAaWQPMR7gF1OQKqGoBjq90HPMP01BUjPOqGFksC4emE48tWQAH0YmvOgF3DST6xieJgHAWxPAHMuNhrImIdvoNOKNWIOcE+UXE0pYAnkX6uhWsgVXDxHdTfCmrEEmMB2zMFimLVOtiiajxiGWrbU52EeCdyOwPEQD8LqyPH9Ti2kgYMf4OhSKB7qYILbBv3CuVTJ11Y80oaseiMWOONc/Y7kJYe0xL2f0BaiFTxknHO5HaMGMublKwxFGzYdWsBF174H/QDknhTHmHHN39iWFnkZx8lPyM8WHfYELmlLKtgWNmFNzQcC1b47gJ4hL19i7o65dhH0Negbca8vONZoP7doIeOC9zXm8RjuL0Gf4d4OYaU5ljo3GYiqzrWQHfJxA6ALhDpVKv9qYeZA8eM3EhfPSCmpuD0AAAAASUVORK5CYII=`;\r\n\r\n if (!isDefined(iconData) || !isDefined(iconData.iconUrl)) {\r\n return new L.Icon.Default({\r\n iconUrl: base64icon,\r\n shadowUrl: base64shadow,\r\n iconSize: [25, 41],\r\n iconAnchor: [12, 41],\r\n popupAnchor: [1, -34],\r\n shadowSize: [41, 41]\r\n });\r\n }\r\n\r\n return new L.Icon(iconData);\r\n }\r\n\r\n function deleteMarker(marker, map, layers) {\r\n marker.closePopup();\r\n\r\n // There is no easy way to know if a marker is added to a layer, so we search for it\r\n // if there are overlays\r\n if (isDefined(layers) && isDefined(layers.overlays)) {\r\n for (const key in layers.overlays) {\r\n if (layers.overlays[key] instanceof L.LayerGroup || layers.overlays[key] instanceof L.FeatureGroup) {\r\n if (layers.overlays[key].hasLayer(marker)) {\r\n layers.overlays[key].removeLayer(marker);\r\n return;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (isDefined(groups)) {\r\n for (const groupKey in groups) {\r\n if (groups[groupKey].hasLayer(marker)) {\r\n groups[groupKey].removeLayer(marker);\r\n }\r\n }\r\n }\r\n\r\n if (map.hasLayer(marker)) {\r\n map.removeLayer(marker);\r\n }\r\n }\r\n\r\n function adjustPopupPan(marker, map) {\r\n const containerHeight = marker._popup._container.offsetHeight;\r\n const layerPos = new L.Point(marker._popup._containerLeft, -containerHeight - marker._popup._containerBottom);\r\n const containerPos = map.layerPointToContainerPoint(layerPos);\r\n if (containerPos !== null) {\r\n marker._popup._adjustPan();\r\n }\r\n }\r\n\r\n function compilePopup(marker, markerScope) {\r\n $compile(marker._popup._contentNode)(markerScope);\r\n }\r\n\r\n function updatePopup(marker, markerScope, map) {\r\n //The innerText should be more than 1 once angular has compiled.\r\n //We need to keep trying until angular has compiled before we _updateLayout and _updatePosition\r\n //This should take care of any scenario , eg ngincludes, whatever.\r\n //Is there a better way to check for this?\r\n const innerText = marker._popup._contentNode.innerText || marker._popup._contentNode.textContent;\r\n if (innerText.length < 1) {\r\n $timeout(function() {\r\n updatePopup(marker, markerScope, map);\r\n });\r\n }\r\n\r\n //cause a reflow - this is also very important - if we don`t do this then the widths are from before $compile\r\n const reflow = marker._popup._contentNode.offsetWidth;\r\n\r\n marker._popup._updateLayout();\r\n marker._popup._updatePosition();\r\n\r\n if (marker._popup.options.autoPan) {\r\n adjustPopupPan(marker, map);\r\n }\r\n\r\n //using / returning reflow so jshint doesn`t moan\r\n return reflow;\r\n }\r\n\r\n function manageOpenPopup(marker, markerData, map) {\r\n // The marker may provide a scope returning function used to compile the message\r\n // default to $rootScope otherwise\r\n const markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope;\r\n const compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true;\r\n\r\n if (compileMessage) {\r\n if (!isDefined(marker._popup) || !isDefined(marker._popup._contentNode)) {\r\n $log.error(errorHeader + `Popup is invalid or does not have any content.`);\r\n return false;\r\n }\r\n\r\n compilePopup(marker, markerScope);\r\n updatePopup(marker, markerData, map);\r\n }\r\n }\r\n\r\n function manageOpenLabel(marker, markerData) {\r\n const markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope;\r\n const labelScope = angular.isFunction(markerData.getLabelScope) ? markerData.getLabelScope() : markerScope;\r\n const compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true;\r\n\r\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(markerData.label)) {\r\n if (isDefined(markerData.label.options) && markerData.label.options.noHide === true) {\r\n marker.showLabel();\r\n }\r\n\r\n if (compileMessage && isDefined(marker.label)) {\r\n $compile(marker.label._container)(labelScope);\r\n }\r\n }\r\n }\r\n\r\n function updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map) {\r\n if (!isDefined(oldMarkerData)) {\r\n return;\r\n }\r\n\r\n // Update the lat-lng property (always present in marker properties)\r\n if (!esLeafletGeoJsonHelpers.validateCoords(markerData)) {\r\n $log.warn(`There are problems with lat-lng data, please verify your marker model`);\r\n deleteMarker(marker, map, layers);\r\n return;\r\n }\r\n\r\n // watch is being initialized if old and new object is the same\r\n const isInitializing = markerData === oldMarkerData;\r\n\r\n // Update marker rotation\r\n if (isDefined(markerData.iconAngle) && oldMarkerData.iconAngle !== markerData.iconAngle) {\r\n marker.setIconAngle(markerData.iconAngle);\r\n }\r\n\r\n // It is possible that the layer has been removed or the layer marker does not exist\r\n // Update the layer group if present or move it to the map if not\r\n if (!angular.isString(markerData.layer)) {\r\n // There is no layer information, we move the marker to the map if it was in a layer group\r\n if (angular.isString(oldMarkerData.layer)) {\r\n // Remove from the layer group that is supposed to be\r\n if (isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) {\r\n layers.overlays[oldMarkerData.layer].removeLayer(marker);\r\n marker.closePopup();\r\n }\r\n\r\n // Test if it is not on the map and add it\r\n if (!map.hasLayer(marker)) {\r\n map.addLayer(marker);\r\n }\r\n }\r\n }\r\n\r\n if ((angular.isNumber(markerData.opacity) || angular.isNumber(parseFloat(markerData.opacity))) && markerData.opacity !== oldMarkerData.opacity) {\r\n // There was a different opacity so we update it\r\n marker.setOpacity(markerData.opacity);\r\n }\r\n\r\n if (angular.isString(markerData.layer) && oldMarkerData.layer !== markerData.layer) {\r\n // If it was on a layer group we have to remove it\r\n if (angular.isString(oldMarkerData.layer) && isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) {\r\n layers.overlays[oldMarkerData.layer].removeLayer(marker);\r\n }\r\n\r\n marker.closePopup();\r\n\r\n // Remove it from the map in case the new layer is hidden or there is an error in the new layer\r\n if (map.hasLayer(marker)) {\r\n map.removeLayer(marker);\r\n }\r\n\r\n // The markerData.layer is defined so we add the marker to the layer if it is different from the old data\r\n if (!isDefined(layers.overlays[markerData.layer])) {\r\n $log.error(errorHeader + `You must use a name of an existing layer`);\r\n return;\r\n }\r\n\r\n // Is a group layer?\r\n const layerGroup = layers.overlays[markerData.layer];\r\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\r\n $log.error(errorHeader + `A marker can only be added to a layer of type 'group' or 'featureGroup'`);\r\n return;\r\n }\r\n\r\n // The marker goes to a correct layer group, so first of all we add it\r\n layerGroup.addLayer(marker);\r\n\r\n // The marker is automatically added to the map depending on the visibility\r\n // of the layer, so we only have to open the popup if the marker is in the map\r\n if (map.hasLayer(marker) && markerData.focus === true) {\r\n marker.openPopup();\r\n }\r\n }\r\n\r\n // Update the draggable property\r\n if (markerData.draggable !== true && oldMarkerData.draggable === true && isDefined(marker.dragging)) {\r\n marker.dragging.disable();\r\n }\r\n\r\n if (markerData.draggable === true && oldMarkerData.draggable !== true) {\r\n // The markerData.draggable property must be true so we update if there wasn't a previous value or it wasn't true\r\n if (marker.dragging) {\r\n marker.dragging.enable();\r\n } else {\r\n if (L.Handler.MarkerDrag) {\r\n marker.dragging = new L.Handler.MarkerDrag(marker);\r\n marker.options.draggable = true;\r\n marker.dragging.enable();\r\n }\r\n }\r\n }\r\n\r\n // Update the icon property\r\n if (!angular.isObject(markerData.icon)) {\r\n // If there is no icon property or it`s not an object\r\n if (angular.isObject(oldMarkerData.icon)) {\r\n // If there was an icon before restore to the default\r\n marker.setIcon(createLeafletIcon());\r\n marker.closePopup();\r\n marker.unbindPopup();\r\n if (angular.isString(markerData.message)) {\r\n marker.bindPopup(markerData.message, markerData.popupOptions);\r\n }\r\n }\r\n }\r\n\r\n if (angular.isObject(markerData.icon) && angular.isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) {\r\n let dragG = false;\r\n if (marker.dragging) {\r\n dragG = marker.dragging.enabled();\r\n }\r\n\r\n marker.setIcon(createLeafletIcon(markerData.icon));\r\n if (dragG) {\r\n marker.dragging.enable();\r\n }\r\n\r\n marker.closePopup();\r\n marker.unbindPopup();\r\n if (angular.isString(markerData.message)) {\r\n marker.bindPopup(markerData.message, markerData.popupOptions);\r\n\r\n // if marker has been already focused, reopen popup\r\n if (map.hasLayer(marker) && markerData.focus === true) {\r\n marker.openPopup();\r\n }\r\n }\r\n }\r\n\r\n // Update the Popup message property\r\n if (!angular.isString(markerData.message) && angular.isString(oldMarkerData.message)) {\r\n marker.closePopup();\r\n marker.unbindPopup();\r\n }\r\n\r\n // Update the label content or bind a new label if the old one has been removed.\r\n if (esLeafletHelpers.LabelPlugin.isLoaded()) {\r\n if (isDefined(markerData.label) && isDefined(markerData.label.message)) {\r\n if (`label` in oldMarkerData && `message` in oldMarkerData.label && !angular.equals(markerData.label.message, oldMarkerData.label.message)) {\r\n marker.updateLabelContent(markerData.label.message);\r\n } else if (!angular.isFunction(marker.getLabel) || angular.isFunction(marker.getLabel) && !isDefined(marker.getLabel())) {\r\n marker.bindTooltip(markerData.label.message, markerData.label.options);\r\n manageOpenLabel(marker, markerData);\r\n } else {\r\n manageOpenLabel(marker, markerData);\r\n }\r\n } else if (!(`label` in markerData && !(`message` in markerData.label))) {\r\n if (angular.isFunction(marker.unbindLabel)) {\r\n marker.unbindLabel();\r\n }\r\n }\r\n }\r\n\r\n // There is some text in the popup, so we must show the text or update existing\r\n if (angular.isString(markerData.message) && !angular.isString(oldMarkerData.message)) {\r\n // There was no message before so we create it\r\n marker.bindPopup(markerData.message, markerData.popupOptions);\r\n }\r\n\r\n if (angular.isString(markerData.message) && angular.isString(oldMarkerData.message) && markerData.message !== oldMarkerData.message) {\r\n // There was a different previous message so we update it\r\n marker.setPopupContent(markerData.message);\r\n }\r\n\r\n // Update the focus property\r\n let updatedFocus = false;\r\n if (markerData.focus !== true && oldMarkerData.focus === true) {\r\n // If there was a focus property and was true we turn it off\r\n marker.closePopup();\r\n updatedFocus = true;\r\n }\r\n\r\n // The markerData.focus property must be true so we update if there wasn`t a previous value or it wasn`t true\r\n if (markerData.focus === true && (!isDefined(oldMarkerData.focus) || oldMarkerData.focus === false) || isInitializing && markerData.focus === true) {\r\n // Reopen the popup when focus is still true\r\n marker.openPopup();\r\n updatedFocus = true;\r\n }\r\n\r\n // zIndexOffset adjustment\r\n if (oldMarkerData.zIndexOffset !== markerData.zIndexOffset) {\r\n marker.setZIndexOffset(markerData.zIndexOffset);\r\n }\r\n\r\n const markerLatLng = marker.getLatLng();\r\n const isCluster = angular.isString(markerData.layer) && esLeafletHelpers.MarkerClusterPlugin.is(layers.overlays[markerData.layer]);\r\n\r\n // If the marker is in a cluster it has to be removed and added to the layer when the location is changed\r\n if (isCluster) {\r\n // The focus has changed even by a user click or programatically\r\n if (updatedFocus) {\r\n // We only have to update the location if it was changed programatically, because it was\r\n // changed by a user drag the marker data has already been updated by the internal event\r\n // listened by the directive\r\n if (markerData.lat !== oldMarkerData.lat || markerData.lng !== oldMarkerData.lng) {\r\n layers.overlays[markerData.layer].removeLayer(marker);\r\n marker.setLatLng([markerData.lat, markerData.lng]);\r\n layers.overlays[markerData.layer].addLayer(marker);\r\n }\r\n } else {\r\n // The marker has possibly moved. It can be moved by a user drag (marker location and data are equal but old\r\n // data is diferent) or programatically (marker location and data are diferent)\r\n if (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) {\r\n // The marker was moved by a user drag\r\n layers.overlays[markerData.layer].removeLayer(marker);\r\n marker.setLatLng([markerData.lat, markerData.lng]);\r\n layers.overlays[markerData.layer].addLayer(marker);\r\n } else if (markerData.lat !== oldMarkerData.lat || markerData.lng !== oldMarkerData.lng) {\r\n // The marker was moved programatically\r\n layers.overlays[markerData.layer].removeLayer(marker);\r\n marker.setLatLng([markerData.lat, markerData.lng]);\r\n layers.overlays[markerData.layer].addLayer(marker);\r\n } else if (angular.isObject(markerData.icon) && angular.isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) {\r\n layers.overlays[markerData.layer].removeLayer(marker);\r\n layers.overlays[markerData.layer].addLayer(marker);\r\n }\r\n }\r\n } else if (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) {\r\n marker.setLatLng([markerData.lat, markerData.lng]);\r\n }\r\n }\r\n\r\n function createMarker(markerData) {\r\n if (!isDefined(markerData) || !esLeafletGeoJsonHelpers.validateCoords(markerData)) {\r\n $log.error(errorHeader + `The marker definition is not valid.`);\r\n return;\r\n }\r\n\r\n const coords = esLeafletGeoJsonHelpers.getCoords(markerData);\r\n\r\n if (!isDefined(coords)) {\r\n $log.error(errorHeader + `Unable to get coordinates from markerData.`);\r\n return;\r\n }\r\n\r\n const markerOptions = {\r\n icon: createLeafletIcon(markerData.icon),\r\n title: isDefined(markerData.title) ? markerData.title : ``,\r\n draggable: isDefined(markerData.draggable) ? markerData.draggable : false,\r\n clickable: isDefined(markerData.clickable) ? markerData.clickable : true,\r\n riseOnHover: isDefined(markerData.riseOnHover) ? markerData.riseOnHover : false,\r\n zIndexOffset: isDefined(markerData.zIndexOffset) ? markerData.zIndexOffset : 0,\r\n iconAngle: isDefined(markerData.iconAngle) ? markerData.iconAngle : 0\r\n };\r\n\r\n // Add any other options not added above to markerOptions\r\n for (const markerDatum in markerData) {\r\n if (markerData.hasOwnProperty(markerDatum) && !markerOptions.hasOwnProperty(markerDatum)) {\r\n markerOptions[markerDatum] = markerData[markerDatum];\r\n }\r\n }\r\n\r\n const marker = new L.Marker(coords, markerOptions);\r\n\r\n if (!angular.isString(markerData.message)) {\r\n marker.unbindPopup();\r\n }\r\n\r\n return marker;\r\n }\r\n\r\n function addMarkerToGroup(marker, groupName, groupOptions, map) {\r\n if (!angular.isString(groupName)) {\r\n $log.error(errorHeader + `The marker group you have specified is invalid.`);\r\n return;\r\n }\r\n\r\n if (!MarkerClusterPlugin.isLoaded()) {\r\n $log.error(errorHeader + `The MarkerCluster plugin is not loaded.`);\r\n return;\r\n }\r\n\r\n if (!isDefined(groups[groupName])) {\r\n groups[groupName] = new L.MarkerClusterGroup(groupOptions);\r\n map.addLayer(groups[groupName]);\r\n }\r\n\r\n groups[groupName].addLayer(marker);\r\n }\r\n\r\n function listenMarkerEvents(marker, markerData, leafletScope, doWatch, map) {\r\n marker.on(`popupopen`, function(/* event */) {\r\n safeApply(leafletScope, function() {\r\n if (isDefined(marker._popup) || isDefined(marker._popup._contentNode)) {\r\n markerData.focus = true;\r\n manageOpenPopup(marker, markerData, map);//needed since markerData is now a copy\r\n }\r\n });\r\n });\r\n\r\n marker.on(`popupclose`, function(/* event */) {\r\n safeApply(leafletScope, function() {\r\n markerData.focus = false;\r\n });\r\n });\r\n\r\n marker.on(`add`, function(/* event */) {\r\n safeApply(leafletScope, function() {\r\n if (`label` in markerData){\r\n manageOpenLabel(marker, markerData);\r\n }\r\n });\r\n });\r\n }\r\n\r\n function addMarkerWatcher(marker, name, leafletScope, layers, map, isDeepWatch) {\r\n const markerWatchPath = esLeafletHelpers.getObjectArrayPath(`markers.` + name);\r\n isDeepWatch = defaultTo(isDeepWatch, true);\r\n\r\n const clearWatch = leafletScope.$watch(markerWatchPath, function(markerData, oldMarkerData) {\r\n if (!isDefined(markerData)) {\r\n deleteMarker(marker, map, layers);\r\n clearWatch();\r\n return;\r\n }\r\n\r\n updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map);\r\n }, isDeepWatch);\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function () {\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletPathEvents`, esLeafletPathEvents);\r\n\r\n esLeafletPathEvents.$inject = [`$rootScope`, `$q`, `$log`, `esLeafletHelpers`, `esLeafletLabelEvents`, `esLeafletEventsHelpers`];\r\n\r\n function esLeafletPathEvents($rootScope, $q, $log, esLeafletHelpers, esLeafletLabelEvents, esLeafletEventsHelpers) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const isObject = angular.isObject;\r\n const Helpers = esLeafletHelpers;\r\n const errorHeader = esLeafletHelpers.errorHeader;\r\n const lblHelp = esLeafletLabelEvents;\r\n const fire = esLeafletEventsHelpers.fire;\r\n\r\n const _genDispatchPathEvent = function (maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) {\r\n maybeMapId = maybeMapId || ``;\r\n\r\n if (maybeMapId){\r\n maybeMapId = `.` + maybeMapId;\r\n }\r\n\r\n return function (e) {\r\n const broadcastName = `leafletDirectivePath` + maybeMapId + `.` + eventName;\r\n $log.debug(broadcastName);\r\n fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName);\r\n };\r\n };\r\n\r\n const _bindPathEvents = function (maybeMapId, lObject, name, model, leafletScope) {\r\n let pathEvents = [];\r\n let i;\r\n let eventName;\r\n let logic = `broadcast`;\r\n\r\n if (!isDefined(leafletScope.eventBroadcast)) {\r\n // Backward compatibility, if no event-broadcast attribute, all events are broadcasted\r\n pathEvents = _getAvailablePathEvents();\r\n } else if (!isObject(leafletScope.eventBroadcast)) {\r\n // Not a valid object\r\n $log.error(errorHeader + `event-broadcast must be an object check your model.`);\r\n } else {\r\n // We have a possible valid object\r\n if (!isDefined(leafletScope.eventBroadcast.path)) {\r\n // We do not have events enable/disable do we do nothing (all enabled by default)\r\n pathEvents = _getAvailablePathEvents();\r\n } else if (isObject(leafletScope.eventBroadcast.paths)) {\r\n // Not a valid object\r\n $log.warn(errorHeader + `event-broadcast.path must be an object check your model.`);\r\n } else {\r\n // We have a possible valid map object\r\n // Event propadation logic\r\n if (leafletScope.eventBroadcast.path.logic !== undefined && leafletScope.eventBroadcast.path.logic !== null) {\r\n // We take care of possible propagation logic\r\n if (leafletScope.eventBroadcast.path.logic !== `emit` && leafletScope.eventBroadcast.path.logic !== `broadcast`) {\r\n // This is an error\r\n $log.warn(errorHeader + `Available event propagation logic are: \\`emit\\` or \\`broadcast\\`.`);\r\n } else if (leafletScope.eventBroadcast.path.logic === `emit`) {\r\n logic = `emit`;\r\n }\r\n }\r\n\r\n // Enable / Disable\r\n let pathEventsEnable = false;\r\n let pathEventsDisable = false;\r\n if (leafletScope.eventBroadcast.path.enable !== undefined && leafletScope.eventBroadcast.path.enable !== null) {\r\n if (typeof leafletScope.eventBroadcast.path.enable === `object`) {\r\n pathEventsEnable = true;\r\n }\r\n }\r\n\r\n if (leafletScope.eventBroadcast.path.disable !== undefined && leafletScope.eventBroadcast.path.disable !== null) {\r\n if (typeof leafletScope.eventBroadcast.path.disable === `object`) {\r\n pathEventsDisable = true;\r\n }\r\n }\r\n\r\n if (pathEventsEnable && pathEventsDisable) {\r\n // Both are active, this is an error\r\n $log.warn(errorHeader + `can not enable and disable events at the same time`);\r\n } else if (!pathEventsEnable && !pathEventsDisable) {\r\n // Both are inactive, this is an error\r\n $log.warn(errorHeader + `must enable or disable events`);\r\n } else {\r\n // At this point the path object is OK, lets enable or disable events\r\n if (pathEventsEnable) {\r\n // Enable events\r\n for (i = 0; i < leafletScope.eventBroadcast.path.enable.length; i++) {\r\n eventName = leafletScope.eventBroadcast.path.enable[i];\r\n\r\n // Do we have already the event enabled?\r\n if (pathEvents.indexOf(eventName) !== -1) {\r\n // Repeated event, this is an error\r\n $log.warn(errorHeader + `This event ` + eventName + ` is already enabled`);\r\n } else {\r\n // Does the event exists?\r\n if (_getAvailablePathEvents().indexOf(eventName) === -1) {\r\n // The event does not exists, this is an error\r\n $log.warn(errorHeader + `This event ` + eventName + ` does not exist`);\r\n } else {\r\n // All ok enable the event\r\n pathEvents.push(eventName);\r\n }\r\n }\r\n }\r\n } else {\r\n // Disable events\r\n pathEvents = _getAvailablePathEvents();\r\n for (i = 0; i < leafletScope.eventBroadcast.path.disable.length; i++) {\r\n eventName = leafletScope.eventBroadcast.path.disable[i];\r\n const index = pathEvents.indexOf(eventName);\r\n if (index === -1) {\r\n // The event does not exist\r\n $log.warn(errorHeader + `This event ` + eventName + ` does not exist or has been already disabled`);\r\n\r\n } else {\r\n pathEvents.splice(index, 1);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (i = 0; i < pathEvents.length; i++) {\r\n eventName = pathEvents[i];\r\n lObject.on(eventName, _genDispatchPathEvent(maybeMapId, eventName, logic, leafletScope, pathEvents, name));\r\n }\r\n\r\n if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) {\r\n lblHelp.genEvents(maybeMapId, name, logic, leafletScope, lObject, model);\r\n }\r\n };\r\n\r\n const _getAvailablePathEvents = function () {\r\n return [\r\n `click`,\r\n `dblclick`,\r\n `mousedown`,\r\n `mouseover`,\r\n `mouseout`,\r\n `contextmenu`,\r\n `add`,\r\n `remove`,\r\n `popupopen`,\r\n `popupclose`\r\n ];\r\n };\r\n\r\n return {\r\n getAvailablePathEvents: _getAvailablePathEvents,\r\n bindPathEvents: _bindPathEvents\r\n };\r\n }\r\n})();","/* istanbul ignore next */\r\n(function () {\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .directive(`paths`, paths);\r\n\r\n paths.$inject = [`$log`, `$q`, `leafletLib`, `esLeafletData`, `esLeafletMapDefaults`, `esLeafletHelpers`, `esLeafletPathsHelpers`, `esLeafletPathEvents`];\r\n\r\n function paths($log, $q, L, esLeafletData, esLeafletMapDefaults, esLeafletHelpers, esLeafletPathsHelpers, esLeafletPathEvents) {\r\n\r\n return {\r\n restrict: `A`,\r\n scope: false,\r\n replace: false,\r\n require: [`esLeaflet`, `?layers`],\r\n link\r\n };\r\n\r\n function link(scope, element, attrs, controller) {\r\n const mapController = controller[0];\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const isString = angular.isString;\r\n const leafletScope = mapController.getLeafletScope();\r\n const createPath = esLeafletPathsHelpers.createPath;\r\n const bindPathEvents = esLeafletPathEvents.bindPathEvents;\r\n const setPathOptions = esLeafletPathsHelpers.setPathOptions;\r\n\r\n mapController.getMap().then(function (map) {\r\n const defaults = esLeafletMapDefaults.getDefaults(attrs.id);\r\n let getLayers;\r\n\r\n // If the layers attribute is used, we must wait until the layers are created\r\n if (isDefined(controller[1])) {\r\n getLayers = controller[1].getLayers;\r\n } else {\r\n getLayers = function () {\r\n const deferred = $q.defer();\r\n deferred.resolve();\r\n return deferred.promise;\r\n };\r\n }\r\n\r\n getLayers().then(function (layers) {\r\n const leafletPaths = {};\r\n esLeafletData.setPaths(leafletPaths, attrs.id);\r\n\r\n // Should we watch for every specific marker on the map?\r\n const shouldWatch = !isDefined(attrs.watchPaths) || attrs.watchPaths === `true`;\r\n\r\n // Function for listening every single path once created\r\n const watchPathFn = function (leafletPath, name) {\r\n const clearWatch = leafletScope.$watch(`paths[\"` + name + `\"]`, function (pathData, old) {\r\n if (!isDefined(pathData)) {\r\n if (isDefined(old.layer)) {\r\n for (const i in layers.overlays) {\r\n if (layers.overlays.hasOwnProperty(i)) {\r\n const overlay = layers.overlays[i];\r\n overlay.removeLayer(leafletPath);\r\n }\r\n }\r\n }\r\n\r\n map.removeLayer(leafletPath);\r\n clearWatch();\r\n return;\r\n }\r\n\r\n setPathOptions(leafletPath, pathData.type, pathData);\r\n }, true);\r\n };\r\n\r\n leafletScope.$watchCollection(`paths`, function (newPaths) {\r\n\r\n // Delete paths (by name) from the array\r\n for (const name in leafletPaths) {\r\n if (!isDefined(newPaths[name])) {\r\n map.removeLayer(leafletPaths[name]);\r\n delete leafletPaths[name];\r\n }\r\n }\r\n\r\n // Create the new paths\r\n for (const newName in newPaths) {\r\n if (newName.search(`\\\\$`) === 0) {\r\n continue;\r\n }\r\n\r\n if (newName.search(`-`) !== -1) {\r\n $log.error(`[AngularJS - Leaflet] The path name \"` + newName + `\" is not valid. It must not include \"-\" and a number.`);\r\n continue;\r\n }\r\n\r\n if (!isDefined(leafletPaths[newName])) {\r\n const pathData = newPaths[newName];\r\n const newPath = createPath(newName, newPaths[newName], defaults);\r\n\r\n // bind popup if defined\r\n if (isDefined(newPath) && isDefined(pathData.message)) {\r\n newPath.bindPopup(pathData.message, pathData.popupOptions);\r\n }\r\n\r\n // Show label if defined\r\n if (esLeafletHelpers.LabelPlugin.isLoaded() && isDefined(pathData.label) && isDefined(pathData.label.message)) {\r\n newPath.bindLabel(pathData.label.message, pathData.label.options);\r\n }\r\n\r\n // Check if the marker should be added to a layer\r\n if (isDefined(pathData) && isDefined(pathData.layer)) {\r\n\r\n if (!isString(pathData.layer)) {\r\n $log.error(`[AngularJS - Leaflet] A layername must be a string`);\r\n continue;\r\n }\r\n\r\n if (!isDefined(layers)) {\r\n $log.error(`[AngularJS - Leaflet] You must add layers to the directive if the markers are going to use this functionality.`);\r\n continue;\r\n }\r\n\r\n if (!isDefined(layers.overlays) || !isDefined(layers.overlays[pathData.layer])) {\r\n $log.error(`[AngularJS - Leaflet] A path can only be added to a layer of type \"group\"`);\r\n continue;\r\n }\r\n\r\n const layerGroup = layers.overlays[pathData.layer];\r\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\r\n $log.error(`[AngularJS - Leaflet] Adding a path to an overlay needs a overlay of the type \"group\" or \"featureGroup\"`);\r\n continue;\r\n }\r\n\r\n // Listen for changes on the new path\r\n leafletPaths[newName] = newPath;\r\n\r\n // The path goes to a correct layer group, so first of all we add it\r\n layerGroup.addLayer(newPath);\r\n\r\n if (shouldWatch) {\r\n watchPathFn(newPath, newName);\r\n } else {\r\n setPathOptions(newPath, pathData.type, pathData);\r\n }\r\n } else if (isDefined(newPath)) {\r\n // Listen for changes on the new path\r\n leafletPaths[newName] = newPath;\r\n map.addLayer(newPath);\r\n\r\n if (shouldWatch) {\r\n watchPathFn(newPath, newName);\r\n } else {\r\n setPathOptions(newPath, pathData.type, pathData);\r\n }\r\n }\r\n\r\n bindPathEvents(attrs.id, newPath, newName, pathData, leafletScope);\r\n }\r\n }\r\n });\r\n });\r\n });\r\n };\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function () {\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .factory(`esLeafletPathsHelpers`, esLeafletPathsHelpers);\r\n\r\n esLeafletPathsHelpers.$inject = [`$rootScope`, `$log`, `leafletLib`, `esLeafletHelpers`];\r\n\r\n function esLeafletPathsHelpers($rootScope, $log, L, esLeafletHelpers) {\r\n const isDefined = esLeafletHelpers.isDefined;\r\n const isArray = angular.isArray;\r\n const isNumber = angular.isNumber;\r\n const isValidPoint = esLeafletHelpers.isValidPoint;\r\n\r\n const availableOptions = [\r\n\r\n // Path options\r\n `stroke`, `weight`, `color`, `opacity`,\r\n `fill`, `fillColor`, `fillOpacity`,\r\n `dashArray`, `lineCap`, `lineJoin`, `clickable`,\r\n `pointerEvents`, `className`,\r\n\r\n // Polyline options\r\n `smoothFactor`, `noClip`\r\n ];\r\n\r\n function _convertToLeafletLatLngs(latlngs) {\r\n return latlngs.filter(function (latlng) {\r\n return isValidPoint(latlng);\r\n }).map(function (latlng) {\r\n return _convertToLeafletLatLng(latlng);\r\n });\r\n }\r\n\r\n function _convertToLeafletLatLng(latlng) {\r\n if (isArray(latlng)) {\r\n return new L.LatLng(latlng[0], latlng[1]);\r\n } else {\r\n return new L.LatLng(latlng.lat, latlng.lng);\r\n }\r\n }\r\n\r\n function _convertToLeafletMultiLatLngs(paths) {\r\n return paths.map(function (latlngs) {\r\n return _convertToLeafletLatLngs(latlngs);\r\n });\r\n }\r\n\r\n function _getOptions(path, defaults) {\r\n const options = {};\r\n for (let i = 0; i < availableOptions.length; i++) {\r\n const optionName = availableOptions[i];\r\n\r\n if (isDefined(path[optionName])) {\r\n options[optionName] = path[optionName];\r\n } else if (isDefined(defaults.path[optionName])) {\r\n options[optionName] = defaults.path[optionName];\r\n }\r\n }\r\n\r\n return options;\r\n }\r\n\r\n const _updatePathOptions = function (path, data) {\r\n const updatedStyle = {};\r\n for (let i = 0; i < availableOptions.length; i++) {\r\n const optionName = availableOptions[i];\r\n if (isDefined(data[optionName])) {\r\n updatedStyle[optionName] = data[optionName];\r\n }\r\n }\r\n\r\n path.setStyle(data);\r\n };\r\n\r\n const _isValidPolyline = function (latlngs) {\r\n if (!isArray(latlngs)) {\r\n return false;\r\n }\r\n\r\n for (let i = 0; i < latlngs.length; i++) {\r\n const point = latlngs[i];\r\n if (!isValidPoint(point)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const pathTypes = {\r\n polyline: {\r\n isValid: function (pathData) {\r\n const latlngs = pathData.latlngs;\r\n return _isValidPolyline(latlngs);\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.Polyline([], options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setLatLngs(_convertToLeafletLatLngs(data.latlngs));\r\n _updatePathOptions(path, data);\r\n }\r\n },\r\n multiPolyline: {\r\n isValid: function (pathData) {\r\n const latlngs = pathData.latlngs;\r\n if (!isArray(latlngs)) {\r\n return false;\r\n }\r\n\r\n for (const i in latlngs) {\r\n if (latlngs.hasOwnProperty(i)) {\r\n const polyline = latlngs[i];\r\n if (!_isValidPolyline(polyline)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.MultiPolyline([[[0, 0], [1, 1]]], options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs));\r\n _updatePathOptions(path, data);\r\n }\r\n },\r\n polygon: {\r\n isValid: function (pathData) {\r\n const latlngs = pathData.latlngs;\r\n return _isValidPolyline(latlngs);\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.Polygon([], options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setLatLngs(_convertToLeafletLatLngs(data.latlngs));\r\n _updatePathOptions(path, data);\r\n }\r\n },\r\n multiPolygon: {\r\n isValid: function (pathData) {\r\n const latlngs = pathData.latlngs;\r\n\r\n if (!isArray(latlngs)) {\r\n return false;\r\n }\r\n\r\n for (const i in latlngs) {\r\n if (latlngs.hasOwnProperty(i)) {\r\n const polyline = latlngs[i];\r\n if (!_isValidPolyline(polyline)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.MultiPolygon([[[0, 0], [1, 1], [0, 1]]], options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs));\r\n _updatePathOptions(path, data);\r\n }\r\n },\r\n rectangle: {\r\n isValid: function (pathData) {\r\n const latlngs = pathData.latlngs;\r\n\r\n if (!isArray(latlngs) || latlngs.length !== 2) {\r\n return false;\r\n }\r\n\r\n for (const i in latlngs) {\r\n if (latlngs.hasOwnProperty(i)) {\r\n const point = latlngs[i];\r\n if (!isValidPoint(point)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.Rectangle([[0, 0], [1, 1]], options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setBounds(new L.LatLngBounds(_convertToLeafletLatLngs(data.latlngs)));\r\n _updatePathOptions(path, data);\r\n }\r\n },\r\n circle: {\r\n isValid: function (pathData) {\r\n const point = pathData.latlngs;\r\n return isValidPoint(point) && isNumber(pathData.radius);\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.Circle([0, 0], 1, options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setLatLng(_convertToLeafletLatLng(data.latlngs));\r\n if (isDefined(data.radius)) {\r\n path.setRadius(data.radius);\r\n }\r\n\r\n _updatePathOptions(path, data);\r\n }\r\n },\r\n circleMarker: {\r\n isValid: function (pathData) {\r\n const point = pathData.latlngs;\r\n return isValidPoint(point) && isNumber(pathData.radius);\r\n },\r\n\r\n createPath: function (options) {\r\n return new L.CircleMarker([0, 0], options);\r\n },\r\n\r\n setPath: function (path, data) {\r\n path.setLatLng(_convertToLeafletLatLng(data.latlngs));\r\n if (isDefined(data.radius)) {\r\n path.setRadius(data.radius);\r\n }\r\n\r\n _updatePathOptions(path, data);\r\n }\r\n }\r\n };\r\n\r\n const _getPathData = function (path) {\r\n const pathData = {};\r\n if (path.latlngs) {\r\n pathData.latlngs = path.latlngs;\r\n }\r\n\r\n if (path.radius) {\r\n pathData.radius = path.radius;\r\n }\r\n\r\n return pathData;\r\n };\r\n\r\n return {\r\n setPathOptions: function (leafletPath, pathType, data) {\r\n if (!isDefined(pathType)) {\r\n pathType = `polyline`;\r\n }\r\n\r\n pathTypes[pathType].setPath(leafletPath, data);\r\n },\r\n\r\n createPath: function (name, path, defaults) {\r\n if (!isDefined(path.type)) {\r\n path.type = `polyline`;\r\n }\r\n\r\n const options = _getOptions(path, defaults);\r\n const pathData = _getPathData(path);\r\n\r\n if (!pathTypes[path.type].isValid(pathData)) {\r\n $log.error(`[AngularJS - Leaflet] Invalid data passed to the ` + path.type + ` path`);\r\n return;\r\n }\r\n\r\n return pathTypes[path.type].createPath(options);\r\n }\r\n };\r\n }\r\n})();","/* istanbul ignore next */\r\n(function(){\r\n\r\n angular\r\n .module(`es-leaflet-directive`)\r\n .service(`esLeafletWatchHelpers`, esLeafletWatchHelpers);\r\n\r\n function esLeafletWatchHelpers() {\r\n return {\r\n maybeWatch\r\n };\r\n /*\r\n @name: maybeWatch\r\n @description: Utility to watch something once or forever.\r\n @returns unWatch function\r\n @param watchOptions - see markersWatchOptions and or derrivatives. This object is used\r\n to set watching to once and its watch depth.\r\n */\r\n function maybeWatch(scope, thingToWatchStr, watchOptions, initCb) {\r\n return maybe(scope, `$watch`, thingToWatchStr, watchOptions, initCb);\r\n }\r\n\r\n function maybe(scope, watchFunctionName, thingToWatchStr, watchOptions, initCb) {\r\n //watchOptions.isDeep is/should be ignored in $watchCollection\r\n const unWatch = scope[watchFunctionName](thingToWatchStr, function(newValue, oldValue) {\r\n initCb(newValue, oldValue);\r\n if (!watchOptions.doWatch){\r\n unWatch();\r\n }\r\n }, watchOptions.isDeep);\r\n return unWatch;\r\n }\r\n }\r\n})();","`use strict`;\r\n\r\n/* eslint-disable no-extend-native */\r\n\r\nNumber.prototype.toRad = function () { return this * Math.PI / 180; };\r\nNumber.prototype.toDeg = function () { return this * 180 / Math.PI; };\r\nNumber.prototype.toBrng = function () { return (this.toDeg() + 360) % 360; };\r\n\r\n/* eslint-enable no-extend-native */","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module(`app`)\r\n .config(configureRouteAliases)\r\n .run(appRun);\r\n\r\n configureRouteAliases.$inject = [`$urlRouterProvider`];\r\n function configureRouteAliases($urlRouterProvider) {\r\n\r\n $urlRouterProvider.when(`/`, redirectToDashboard);\r\n\r\n redirectToDashboard.$inject = [`$state`, `app.core.appSettings`];\r\n function redirectToDashboard($state, appSettings) {\r\n if ($state.current.name === `not-found`) {\r\n return;\r\n }\r\n $state.go(`app.dashboard`, { companyAlias: appSettings.site.company.alias, facilityAlias: appSettings.site.facility.alias });\r\n }\r\n }\r\n\r\n appRun.$inject = [`routeHelper`];\r\n function appRun(routeHelper) {\r\n routeHelper.configureRoutes(getRoutes());\r\n }\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app`,\r\n abstract: true,\r\n templateUrl: `/App/ui/core/layout/shell.html`,\r\n controller: `app.ui.core.layout.Shell as vm`,\r\n resolve: {\r\n companyFacilities\r\n },\r\n data : {\r\n layoutType: `full`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/layout/i18n/Shell`,\r\n `/App/ui/core/alerts/controls/i18n/esAlerts`,\r\n `/App/ui/core/messages/controls/i18n/esMessages`,\r\n `/App/ui/core/jobs/controls/i18n/esJobs`,\r\n `/App/core/models/jobs/i18n/Job`\r\n ]\r\n }\r\n },\r\n {\r\n state: `not-found`,\r\n url: `*path`,\r\n templateUrl: `/App/ui/core/NotFound.html`,\r\n controller: `NotFound as vm`\r\n },\r\n {\r\n state: `forbidden`,\r\n templateUrl: `/App/ui/core/Forbidden.html`,\r\n controller: `Forbidden as vm`\r\n }\r\n ];\r\n }\r\n\r\n companyFacilities.$inject = [`app.core.services.companyService`];\r\n\r\n function companyFacilities(companyService) {\r\n return companyService.getCompanies();\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esAlertDropdownOpener`, esAlertDropdownOpener);\r\n\r\n esAlertDropdownOpener.$inject = [];\r\n\r\n function esAlertDropdownOpener() {\r\n return {\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n const vm = $scope.vm;\r\n\r\n $scope.$watch(() => vm.openDropdown, () => {\r\n if (vm.openDropdown) {\r\n $element.addClass(`open`);\r\n vm.openDropdown = false;\r\n }\r\n });\r\n\r\n $scope.$watch(() => vm.closeDropdown, () => {\r\n if (vm.closeDropdown) {\r\n $element.removeClass(`open`);\r\n vm.closeDropdown = false;\r\n }\r\n });\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esAlertLevelSpinner`, esAlertLevelSpinner);\r\n\r\n esAlertLevelSpinner.$inject = [`$timeout`];\r\n\r\n function esAlertLevelSpinner($timeout) {\r\n return {\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n const alert = $scope.alert;\r\n\r\n $scope.$watch(() => alert.level, () => {\r\n if ($scope.alert.hasLevelIncreased) {\r\n $element.removeClass(`decreased`).addClass(`increased bounce`);\r\n $timeout(()=> {\r\n $element.removeClass(`bounce`);\r\n }, 1000);\r\n } else {\r\n $element.removeClass(`increased`).addClass(`decreased bounce`);\r\n $timeout(()=> {\r\n $element.removeClass(`bounce`);\r\n }, 1000);\r\n }\r\n\r\n });\r\n }\r\n }\r\n\r\n\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esAlerts`, esAlerts)\n .controller(`esAlertsController`, esAlertsController);\n\n esAlerts.$inject = [];\n\n function esAlerts() {\n return {\n scope: {},\n restrict: `EA`,\n templateUrl: `/App/ui/core/alerts/controls/esAlerts.html`,\n controller: esAlertsController,\n controllerAs: `vm`,\n bindToController: true\n };\n }\n\n esAlertsController.$inject = [\n `$scope`,\n `$state`,\n `$timeout`,\n `lodash`,\n `postal`,\n `app.core.appSettings`,\n `app.core.services.alertService`,\n `app.core.signalR.alerts.state`,\n `app.core.signalR.alerts.events`\n ];\n\n function esAlertsController($scope, $state, $timeout, _, postal, appSettings, alertService, state, alertEvents) {\n let subscriptions;\n const vm = this;\n const dismissedAlerts = {};\n\n vm.state = state;\n vm.alertCount = 0;\n vm.goToAlertHistory = goToAlertHistory;\n vm.dismissAlert = dismissAlert;\n vm.appSettings = appSettings;\n\n activate();\n\n //////////////////////\n\n function activate() {\n\n $scope.$watch(() => appSettings.site.accessControls, refreshAlerts);\n\n $scope.$watch(() => vm.state.alerts.length, () => {\n $timeout(() => {\n vm.alertCount = vm.state.alerts.length;\n }, 600); // allow for the removal/addition animations to complete before updating the badge count\n });\n\n $scope.$on(`$destroy`, unsubscribeFromNotifications);\n }\n\n function refreshAlerts() {\n unsubscribeFromNotifications();\n state.alerts.length = 0;\n alertService.getActiveWebAlerts().then(activeAlerts => {\n state.alerts.push.apply(state.alerts, activeAlerts);\n subscribeToNotifications();\n });\n }\n\n function dismissAlert(alert) {\n dismissedAlerts[alert.alertEventSourceId] = alert.level;\n removeAlertFromState(alert);\n alertService.dismissWebAlert(alert.id);\n }\n\n function goToAlertHistory() {\n vm.closeDropdown = true;\n $state.go(`app.alerts`, {\n companyAlias: vm.appSettings.site.company.alias,\n facilityAlias: vm.appSettings.site.facility.alias\n });\n }\n\n function subscribeToNotifications() {\n const channel = postal.channel(alertEvents.channelName);\n subscriptions = [\n channel.subscribe(alertEvents.topics.notify, onAlertNotification),\n channel.subscribe(alertEvents.topics.dismiss, onAlertDismiss)\n ];\n }\n\n function onAlertNotification(alert) {\n if (isAlertDismissed(alert)) {\n return;\n }\n\n const existingAlert = getAlertForSourceId(alert.alertEventSourceId);\n if (!existingAlert) {\n // cater for duplicate events where an alert has been downgraded to level 0.\n // the first event will remove it from the list. without this check the second event will add it back at the top.\n if (alert.level <= 0) {\n return;\n }\n moveAlertToFrontOfTheList(alert, true);\n\n } else {\n updateExistingAlert(existingAlert, alert);\n\n if (existingAlert.level <= 0) {\n removeAlertFromState(existingAlert);\n\n } else if (existingAlert.hasLevelIncreased) {\n moveAlertToFrontOfTheList(existingAlert);\n }\n }\n\n function isAlertDismissed(alert) {\n if (dismissedAlerts[alert.alertEventSourceId]) {\n if (alert.level <= dismissedAlerts[alert.alertEventSourceId]) {\n dismissedAlerts[alert.alertEventSourceId] = alert.level;\n return true;\n }\n delete dismissedAlerts[alert.alertEventSourceId];\n }\n return false;\n }\n }\n\n function getAlertForSourceId(alertEventSourceId) {\n return _.find(state.alerts, { alertEventSourceId });\n }\n\n function updateExistingAlert(existingAlert, updateAlert) {\n existingAlert.id = updateAlert.id;\n existingAlert.level = updateAlert.level;\n existingAlert.name = updateAlert.name;\n existingAlert.message = updateAlert.message;\n existingAlert.triggerTime = updateAlert.triggerTime;\n existingAlert.sentTime = updateAlert.sentTime;\n }\n\n function removeAlertFromState(alert) {\n _.remove(state.alerts, { alertEventSourceId: alert.alertEventSourceId });\n }\n\n function moveAlertToFrontOfTheList(alert, isNewAlert) {\n vm.openDropdown = true;\n if (isNewAlert) {\n state.alerts.unshift(alert);\n return;\n }\n\n removeAlertFromState(alert);\n delete alert.$$hashKey; // NOTE: we delete the $$hashKey so that the ngRepeater treats this as a new object and applies the ng-leave and ng-enter animation events.\n state.alerts.unshift(alert);\n }\n\n function onAlertDismiss(alertId) {\n _.remove(state.alerts, { id: alertId });\n }\n\n function unsubscribeFromNotifications() {\n _.invokeMap(subscriptions, `unsubscribe`);\n }\n }\n})();\n","`use strict`;\r\n(function() {\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esAccordionPreventCollapse`, esAccordionPreventCollapse);\r\n\r\n /* istanbul ignore next */\r\n esAccordionPreventCollapse.$inject = [`$timeout`];\r\n function esAccordionPreventCollapse($timeout) {\r\n\r\n return {\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n\r\n activate();\r\n\r\n function activate() {\r\n $timeout(preventCollapsingOpenPanelOnClick);\r\n }\r\n\r\n //////////////\r\n\r\n // we want to have one panel open at al times\r\n function preventCollapsingOpenPanelOnClick() {\r\n const accordionLinks = $element.find(`.panel-heading a a`);\r\n accordionLinks.on(`click`, stopPropagation);\r\n $scope.$on(`$destroy`, removeHandler);\r\n\r\n function removeHandler() {\r\n accordionLinks.off(`click`, stopPropagation);\r\n }\r\n\r\n function stopPropagation(e) {\r\n if (angular.element(this).parents(`.panel`).children(`.panel-collapse`).hasClass(`in`)) {\r\n e.stopPropagation();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esAddressLookup`, directive)\r\n .controller(`esAddressLookupController`, controller);\r\n\r\n directive.$inject = [];\r\n\r\n /* istanbul ignore next */\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n templateUrl: `/App/ui/core/controls/esAddressLookup.html`,\r\n require: [`ngModel`],\r\n scope: {\r\n model: `=ngModel`,\r\n boundaries: `=?`\r\n },\r\n link,\r\n controller: `esAddressLookupController`,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n\r\n\r\n function link($scope, $element, attrs, controllers) {\r\n $scope.vm.configureAutoComplete($element.find(`#address`)[0], controllers[0]);\r\n }\r\n }\r\n\r\n controller.$inject = [`$scope`, `$timeout`, `google`, `lodash`];\r\n\r\n function controller($scope, $timeout, google, _) {\r\n const vm = this;\r\n vm.configureAutoComplete = configureAutoComplete;\r\n let locationChangedUnwatch;\r\n activate();\r\n\r\n ////////////////\r\n\r\n function activate() {\r\n watchLocation();\r\n watchBoundaries();\r\n }\r\n\r\n function watchBoundaries() {\r\n $scope.$watchGroup([() => vm.boundaries, () => vm.autocomplete], updateBounds);\r\n\r\n function updateBounds() {\r\n if (vm.autocomplete) {\r\n if (vm.boundaries) {\r\n setAutocompleteBounds();\r\n } else {\r\n vm.autocomplete.setOptions({ strictBounds: false });\r\n }\r\n }\r\n }\r\n\r\n function setAutocompleteBounds() {\r\n const bounds = new google.maps.LatLngBounds();\r\n vm.boundaries.forEach(boundary => {\r\n const [lat, lng ] = boundary;\r\n bounds.extend({ lat, lng });\r\n });\r\n vm.autocomplete.setOptions({ bounds, strictBounds: true });\r\n }\r\n }\r\n\r\n function watchLocation() {\r\n locationChangedUnwatch = $scope.$watch(() => vm.model, locationChanged, true);\r\n\r\n function locationChanged(newValue, oldValue) {\r\n if (newValue && oldValue) {\r\n if (newValue.address === oldValue.address && (newValue.latitude !== oldValue.latitude || newValue.longitude !== oldValue.longitude)) {\r\n //lat & lng changed, but the address didn't. This was prob via the map pin or something.\r\n try {\r\n locationChangedUnwatch();\r\n vm.model.address = `${newValue.latitude}, ${newValue.longitude}`;\r\n } finally {\r\n watchLocation();\r\n }\r\n\r\n } else if (newValue.address !== oldValue.address && (newValue.latitude === oldValue.latitude && newValue.longitude === oldValue.longitude)) {\r\n //address changed, but not lat & lng. This is prob due to user entering text into textbox.\r\n try {\r\n locationChangedUnwatch();\r\n\r\n const latLngMatch = newValue.address.match(/^(-?\\d+(?:\\.\\d+)?),\\s?(-?\\d+(?:\\.\\d+)?)$/);\r\n if (latLngMatch && latLngMatch.length === 3) { //[Entire Match, First Group, Second Group]\r\n const [, latitude, longitude] = latLngMatch;\r\n vm.model.latitude = latitude;\r\n vm.model.longitude = longitude;\r\n }\r\n else {\r\n vm.model.latitude = null;\r\n vm.model.longitude = null;\r\n }\r\n vm.controller.$setDirty();\r\n } finally {\r\n watchLocation();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n function configureAutoComplete(element, controller) {\r\n vm.controller = controller;\r\n vm.autocomplete = new google.maps.places.Autocomplete(element); //todo : should we limit the types? { types: [`address_components`] }\r\n element.onfocus = () => vm.controller.$setTouched();\r\n vm.autocomplete.addListener(`place_changed`, () => {\r\n const place = vm.autocomplete.getPlace();\r\n if (place.geometry) {\r\n $timeout(() => addressPicked(place.geometry.location.lat(), place.geometry.location.lng(), place.formatted_address));\r\n }\r\n });\r\n }\r\n\r\n function addressPicked(lat, lng, address) {\r\n try {\r\n locationChangedUnwatch();\r\n\r\n vm.model.latitude = lat;\r\n vm.model.longitude = lng;\r\n vm.model.address = address;\r\n\r\n vm.controller.$setDirty();\r\n } finally {\r\n watchLocation();\r\n }\r\n }\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esBusyLoading`, esBusyLoading);\r\n\r\n esBusyLoading.$inject = [`$compile`, `i18n`, `esPageBlocker`];\r\n\r\n function esBusyLoading($compile, i18n, esPageBlocker) {\r\n // Usage:\r\n //
      \r\n //\r\n // **** NOTE: ******\r\n //\r\n // Always stick this directive on an element with no other directives (including
      ) as it doesn't play nicely.\r\n //\r\n // *****************\r\n\r\n let blockerCount = 0; // used to generate unique named instances\r\n\r\n return {\r\n restrict: `EA`,\r\n compile: compile,\r\n priority: 1000,\r\n terminal: true\r\n };\r\n\r\n function compile($target) {\r\n // We have to remove the db-busy attribute otherwise we end up in an infinite loop when we compile.\r\n const busy = $target.attr(`es-busy-loading`) || $target.attr(`data-es-busy-loading`);\r\n\r\n $target\r\n .removeAttr(`es-busy-loading`)\r\n .removeAttr(`data-es-busy-loading`);\r\n\r\n return {\r\n post: ($scope, $element) => {\r\n let blockerName = $element.attr(`data-es-busy-loading-id`);\r\n\r\n if (!blockerName) { // the directive wasn't given an existing block-ui identifier\r\n blockerName = `block-ui-loading-` + (++blockerCount); // eslint-disable-line no-extra-parens\r\n $element.attr(`block-ui`, blockerName);\r\n }\r\n\r\n $compile($element)($scope);\r\n\r\n let busyTracker = $scope.$eval(busy);\r\n\r\n // note: this hack makes me cry; the esPageBlock watches the active function which is insane.\r\n if (typeof busyTracker.active !== `function`) {\r\n busyTracker = {\r\n active: () => !!$scope.$eval(busy) // we are using !! to account for incrementing/decrementing loading counters rather than just true/false properties\r\n };\r\n }\r\n\r\n const messageKey = $element.attr(`data-es-busy-loading-message-key`) || `activityIndicator.loading.label`;\r\n const loadingMessage = i18n.i10n(messageKey);\r\n\r\n esPageBlocker.create($scope, blockerName, busyTracker, loadingMessage);\r\n }\r\n };\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esBusySaving`, esBusySaving);\r\n\r\n esBusySaving.$inject = [`i18n`, `esPageBlocker`];\r\n\r\n function esBusySaving(i18n, esPageBlocker) {\r\n // Usage:\r\n //
      \r\n //\r\n // **** NOTE: ******\r\n //\r\n // Always stick this directive on an element with no other directives (including ) as it doesn't play nicely.\r\n //\r\n // *****************\r\n\r\n return {\r\n restrict: `EA`,\r\n link: link,\r\n priority: 1001\r\n };\r\n\r\n function link($scope, $element) {\r\n const blockerName = `full-page`;\r\n\r\n const busy = $element.attr(`es-busy-saving`) || $element.attr(`data-es-busy-saving`);\r\n\r\n let busyTracker = $scope.$eval(busy);\r\n // note: this hack makes me cry; the esPageBlock watches the active function which is insane.\r\n if (typeof busyTracker.active !== `function`) {\r\n busyTracker = {\r\n active: () => !!$scope.$eval(busy) // we are using !! to account for incrementing/decrementing loading counters rather than just true/false properties\r\n };\r\n }\r\n\r\n const messageKey = $element.attr(`data-es-busy-saving-message-key`) || `activityIndicator.saving.label`;\r\n const savingMessage = i18n.i10n(messageKey);\r\n\r\n esPageBlocker.create($scope, blockerName, busyTracker, savingMessage);\r\n }\r\n }\r\n})();\r\n\r\n\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .component(`esButtonCreate`, {\r\n bindings: {\r\n label: `@?`,\r\n disabled: `=ngDisabled`,\r\n type: `@?`\r\n },\r\n require: `ng-click`,\r\n templateUrl: `/App/ui/core/controls/esButtonCreate.html`,\r\n controllerAs: `vm`,\r\n controller\r\n })\r\n .controller(`esButtonCreate`, controller);\r\n\r\n controller.$inject = [`i18n`];\r\n\r\n function controller(i18n) {\r\n const vm = this;\r\n\r\n if (!vm.label) {\r\n vm.label = i18n.i10n(`buttons.create`);\r\n }\r\n }\r\n})();","`use strict`;\r\n(function(){\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esButtonGroup`, esButtonGroup)\r\n .controller(`esButtonGroupController`, esButtonGroupController);\r\n\r\n function esButtonGroup() {\r\n return {\r\n restrict: `A`,\r\n replace: true,\r\n scope: {\r\n items: `=esButtonGroup`,\r\n selected: `=esSelected`,\r\n textField: `=esTextField`,\r\n valueField: `=esValueField`,\r\n translationKey: `@esTranslationKey`\r\n },\r\n templateUrl: `/App/ui/core/controls/esButtonGroup.html`,\r\n controller: esButtonGroupController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esButtonGroupController.$inject = [];\r\n\r\n function esButtonGroupController() {\r\n const vm = this;\r\n\r\n vm.setSelected = setSelected;\r\n\r\n //////////////////\r\n\r\n function setSelected(item) {\r\n vm.selected = item;\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .component(`esButtonPrimary`, {\r\n bindings: {\r\n type: `@?`,\r\n label: `@`,\r\n disabled: `=ngDisabled`\r\n },\r\n require: `ng-click`,\r\n templateUrl: `/App/ui/core/controls/esButtonPrimary.html`,\r\n controllerAs: `vm`\r\n });\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esDateTimeSelector`, directive)\r\n .controller(`esDateTimeSelectorController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n require: [`^form`, `ngModel`],\r\n scope: {\r\n containerName: `@name`,\r\n dateTimeMillis: `=ngModel`\r\n },\r\n templateUrl: `/App/ui/core/controls/esDateTimeSelector.html`,\r\n link: link,\r\n controller: `esDateTimeSelectorController`,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n function link($scope, $element, attrs, controllers) {\r\n const vm = $scope.vm;\r\n vm.$form = controllers[0];\r\n vm.ngModel = controllers[1];\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `kendo`,\r\n `lodash`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function controller($scope, kendo, _, timeZoneDateTime, dateTimeService) {\r\n const vm = this;\r\n\r\n vm.name = `${vm.containerName}-dateTimeSelector`;\r\n vm.options = { format: dateTimeService.formats.kendo.dateTime };\r\n vm.onChange = onKendoDateChanged;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updateKendoDateWhenModelChanges();\r\n updateParentModelValidityWhenValidityChanges();\r\n }\r\n\r\n function updateKendoDateWhenModelChanges() {\r\n $scope.$watch(() => vm.dateTimeMillis, dateTimeMillis => {\r\n vm.date = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(dateTimeMillis));\r\n vm.dateString = kendo.toString(vm.date, vm.options.format);\r\n });\r\n }\r\n\r\n function onKendoDateChanged() {\r\n if (vm.$form[vm.name].$invalid) {\r\n return;\r\n }\r\n\r\n const localTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.date);\r\n vm.dateTimeMillis = localTime && localTime.getTime();\r\n }\r\n\r\n function updateParentModelValidityWhenValidityChanges() {\r\n $scope.$watch(() => vm.$form[vm.name].$error, onErrorsChanged, true);\r\n\r\n function onErrorsChanged(errors, previousErrors) {\r\n if (errors === previousErrors) {\r\n return;\r\n }\r\n\r\n const currentValidatorErrorKeys = Object.keys(errors);\r\n const previousValidatorErrorKeys = previousErrors ? Object.keys(previousErrors) : [];\r\n\r\n const keysRemoved = _.difference(previousValidatorErrorKeys, currentValidatorErrorKeys);\r\n keysRemoved.forEach(key => vm.ngModel.$setValidity(key, true));\r\n\r\n currentValidatorErrorKeys.forEach(key => vm.ngModel.$setValidity(key, !errors[key]));\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n /* eslint-disable no-multi-spaces */\r\n angular\r\n .module(`app.ui.core`)\r\n .component(`esFileUploader`, {\r\n controller: FileUploaderController,\r\n templateUrl: `/App/ui/core/controls/esFileUploader.html`,\r\n controllerAs: `vm`,\r\n bindings: {\r\n heading: `@`, // Heading to be displayed\r\n uploadUrl: `<`, // URL to use for the upload\r\n deleteFile: `&`, // Function for deleting a file\r\n\r\n postData: ` changes.heading)\r\n .hasFirstChanged()\r\n .then(() => {\r\n vm.uploader = getUploader();\r\n });\r\n\r\n changeHandler\r\n .when(changes => changes.postData)\r\n .hasChanged()\r\n .then(postData => {\r\n vm.uploader.formData = [postData];\r\n });\r\n\r\n changeHandler\r\n .when(changes => changes.uploadUrl)\r\n .hasChanged()\r\n .then(uploadUrl => {\r\n vm.uploader.url = uploadUrl;\r\n });\r\n\r\n changeHandler\r\n .when(changes => changes.existingFiles)\r\n .hasChanged()\r\n .then(restorePreviouslyUploadedFiles);\r\n\r\n changeHandler\r\n .when(changes => changes.allowedExtensions)\r\n .hasChanged()\r\n .then(extensions => vm.allowedExtensions = extensions || []);\r\n\r\n ////////////////////\r\n\r\n function getUploader() {\r\n const options = {\r\n autoUpload: false,\r\n alias: `uploadedFile`,\r\n\r\n // POST configuration\r\n url: vm.uploadUrl,\r\n headers: {},\r\n formData: [],\r\n\r\n // Events\r\n onAfterAddingFile: onFileAdded, // File has been added to the queue but not yet uploaded\r\n onSuccessItem: onFileUploaded, // File has been uploaded\r\n withCredentials: true\r\n };\r\n\r\n // The file upload component that we are using uses its own transport layer for uploading the files,\r\n // as opposed to using angular's $http service. Why? Goodness only knows; at a guess, its so it can\r\n // downgrade to using an iFrame + form post as the transport when the user is ignorantly using a\r\n // non HTML5 compatible browser.\r\n //\r\n // As such, we need to add in the request headers (e.g. for the current company/facility alias) that\r\n // would ordinarily be done for us by the $httpInterceptor. Thankfully, the `httpInterceptors.request`\r\n // method already expects to be passed an object with a `headers` property on it (yay for duck typing!),\r\n // and this is conveniently the same property which is expected by the file upload component. Win win!\r\n httpInterceptors.request(options);\r\n\r\n return new FileUploader(options);\r\n }\r\n\r\n function restorePreviouslyUploadedFiles(existingFiles) {\r\n if (!vm.uploader) {\r\n return;\r\n }\r\n\r\n _.invokeMap(vm.uploader.queue, `remove`);\r\n\r\n _.forEach(existingFiles, existingFile => {\r\n const fileItem = new FileUploader.FileItem(vm.uploader, existingFile);\r\n _.extend(fileItem, {\r\n progress: 100,\r\n isUploaded: true,\r\n isSuccess: true\r\n });\r\n\r\n _.extend(fileItem.file, {\r\n size: existingFile.length,\r\n lastModifiedDate: new Date(existingFile.utcLastModifiedTime)\r\n });\r\n\r\n vm.uploader.queue.push(fileItem);\r\n onFileUploaded(fileItem);\r\n });\r\n }\r\n }\r\n\r\n function onFileAdded(fileItem) {\r\n const file = fileItem.file;\r\n const fileName = file.name.toLowerCase();\r\n\r\n if (validateAddedFile()) {\r\n fileItem.upload();\r\n }\r\n\r\n // Automatically overwrite any other files with the same name. We can skip the last item in\r\n // the queue as that's the item that has just been added.\r\n for (let i = 0; i < vm.uploader.queue.length - 1; i++) {\r\n const queuedItem = vm.uploader.queue[i];\r\n\r\n if (queuedItem.file.name.toLowerCase() === fileName) {\r\n vm.uploader.removeFromQueue(i);\r\n break;\r\n }\r\n }\r\n\r\n function validateAddedFile() {\r\n const getValidationError = (errorName, formattingArguments) => {\r\n const errorKey = `esFileUploader.validationErrors.${errorName}`;\r\n return i18n.i10n(errorKey, formattingArguments);\r\n };\r\n\r\n const isValidExtension = validateExtension();\r\n const isValidSize = validateSize();\r\n return isValidExtension && isValidSize;\r\n\r\n ////////////////////\r\n\r\n function validateExtension() {\r\n const fileNameLower = file.name.toLowerCase();\r\n const validExtension =\r\n !(vm.allowedExtensions && vm.allowedExtensions.length) ||\r\n _.find(vm.allowedExtensions, extension => _.endsWith(fileNameLower, extension));\r\n\r\n if (!validExtension) {\r\n fileItem.validationErrors.extension = getValidationError(`extension`, { allowedExtensions: vm.allowedExtensions.join(`, `) });\r\n fileItem.isError = true;\r\n }\r\n\r\n return validExtension;\r\n }\r\n\r\n function validateSize() {\r\n const canUpload = !vm.maxSizeBytes || file.size <= vm.maxSizeBytes;\r\n if (!canUpload) {\r\n fileItem.validationErrors.size = getValidationError(`size`, { maxSizeMb: vm.maxSizeBytes / 1024 / 1024 });\r\n fileItem.isError = true;\r\n }\r\n\r\n return canUpload;\r\n }\r\n }\r\n }\r\n\r\n function onFileUploaded(fileItem, uploadedFile) {\r\n const file = fileItem.file;\r\n\r\n // Cater for the server changing the filename/type (e.g. uploading a KMZ and converting to KML)\r\n if (isResultFileDifferentToUploadedFile()) {\r\n file.name = uploadedFile.name;\r\n file.size = uploadedFile.length;\r\n\r\n dequeueDuplicates();\r\n }\r\n\r\n if (vm.fileUploaded) {\r\n vm.fileUploaded({ fileName: file.name });\r\n }\r\n\r\n ////////////////////\r\n\r\n function isResultFileDifferentToUploadedFile() {\r\n return uploadedFile && file.name !== uploadedFile.name;\r\n }\r\n\r\n function dequeueDuplicates() {\r\n _.remove(vm.uploader.queue, queued => queued.file.name === file.name && queued.file !== file);\r\n }\r\n }\r\n\r\n function removeFile(fileItem) {\r\n fileItem.remove();\r\n\r\n if (fileItem.isUploaded && vm.deleteFile) {\r\n vm.deleteFile({ fileName: fileItem.file.name });\r\n }\r\n }\r\n }\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esLabelledSwitch`, directive)\n .controller(`esLabelledSwitchController`, controller);\n\n function directive() {\n return {\n restrict: `E`,\n required: `ngModel`,\n templateUrl: `/App/ui/core/controls/esLabelledSwitch.html`,\n scope: {\n label: `@`,\n isSelected: `=ngModel`,\n onChange: `=?`\n },\n controller: `esLabelledSwitchController`,\n controllerAs: `vm`,\n bindToController: true\n };\n }\n\n controller.$inject = [`lodash`];\n\n function controller(_) {\n const vm = this;\n vm.onSwitched = onSwitched;\n\n ////////////////\n\n function onSwitched() {\n if (_.isFunction(vm.onChange)) {\n vm.onChange.call(this, vm.isSelected);\n }\n }\n }\n\n})();","`use strict`;\r\n(function() {\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esLegend`, esLegend)\r\n .controller(`esLegendController`, esLegendController);\r\n\r\n function esLegend() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n legend: `=`\r\n },\r\n templateUrl: `/App/ui/core/controls/esLegend.html`,\r\n controller: esLegendController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n function esLegendController() {\r\n }\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esList`, esList)\n .controller(`esListController`, esListController);\n\n const defaultListOptions = {\n isFilterable: true,\n onItemSelected : angular.noop,\n items: [],\n selectedItem : {\n field: `id`,\n value: null\n }\n };\n\n esList.$inject = [];\n function esList() {\n\n return {\n restrict: `E`,\n templateUrl: `/App/ui/core/controls/esList.html`,\n scope: {\n options: `=`\n },\n bindToController: true,\n controller: esListController,\n controllerAs: `vm`\n };\n }\n\n esListController.$inject = [`$scope`, `lodash`];\n function esListController($scope, _) {\n const vm = this;\n let previousSelectedItemId = null;\n\n _.defaults(vm.options, defaultListOptions);\n vm.items = []; // the bound items (not the original data source)\n\n // methods\n vm.filter = filterItems; // verb not noun\n vm.selectItem = selectItem;\n vm.addItem = addItem;\n activate();\n\n //////\n\n function activate() {\n\n rebindListItemsWhenTheDataSourceItemsChange();\n resetSelectedItemWhenIdValueChanges();\n\n ///////\n function rebindListItemsWhenTheDataSourceItemsChange() {\n $scope.$watch(() => vm.options.items, () => {\n setSelectedItemStatus();\n filterItems();\n });\n }\n\n function resetSelectedItemWhenIdValueChanges() {\n $scope.$watch(() => vm.options.selectedItem.value, () => { setSelectedItemStatus(); });\n }\n }\n\n // execute this method when the user selects an item from the list\n function selectItem(item) {\n vm.options.selectedItem.value = item[vm.options.selectedItem.field];\n setSelectedItemStatus(true);\n }\n\n // set the selected item\n function setSelectedItemStatus(invokeItemSelectedFunction) {\n vm.options.items.forEach(item => {\n item.selected = item[vm.options.selectedItem.field] === vm.options.selectedItem.value;\n invokeItemSelectedCallback(item);\n });\n\n previousSelectedItemId = vm.options.selectedItem.value;\n\n function invokeItemSelectedCallback(item) {\n if (invokeItemSelectedFunction && item.selected) {\n vm.options.onItemSelected(item);\n }\n }\n }\n\n function addItem() {\n previousSelectedItemId = null;\n if (vm.options.addItem) {\n vm.options.addItem();\n }\n }\n\n // filters items based on the filter term and whether the item has a corresponding column definition.\n // ie. columns on the data source that don't have a corresponding columnDef are not matched on.\n function filterItems() {\n let term = vm.options.filterTerm;\n const items = vm.options.items;\n const columnDefs = vm.options.columnDefs;\n\n if (term === undefined || term === ``) {\n vm.items = items;\n return;\n }\n term = term.toLowerCase();\n\n const matches = [];\n\n //loop through items and visible fields searching for match\n for (let i = 0; i < items.length; i++) {\n for (let j = 0; j < columnDefs.length; j++) {\n\n const item = items[i];\n const fieldName = columnDefs[j].field;\n const renderedData = item[fieldName];\n\n if (renderedData === null || renderedData === undefined) {\n continue;\n }\n\n //as soon as search term is found, add to match and move to next item\n if (renderedData.toString().toLowerCase().indexOf(term) > -1) {\n matches.push(item);\n break;\n }\n }\n }\n vm.items = matches;\n }\n }\n\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .factory(`esPageBlocker`, esPageBlocker);\r\n\r\n esPageBlocker.$inject = [`blockUI`];\r\n\r\n function esPageBlocker(blockUI) {\r\n return {\r\n create\r\n };\r\n\r\n ////////////////////\r\n\r\n function create($scope, blockerName, busyTracker, busyMessage) {\r\n $scope.blockers = $scope.blockers || {};\r\n $scope.blockers[blockerName] = blockUI.instances.get(blockerName);\r\n $scope.$watch(busyTracker.active, updatePageBlocker);\r\n\r\n // Make sure we turn off any blockers before going out of scope.\r\n $scope.$on(`$destroy`, () => {\r\n const blockers = $scope.blockers;\r\n if (!blockers) {\r\n return;\r\n }\r\n\r\n Object.keys(blockers).forEach(blockerName => {\r\n blockers[blockerName].stop();\r\n });\r\n });\r\n\r\n function updatePageBlocker(isActive) {\r\n if (isActive) {\r\n $scope.blockers[blockerName].start(busyMessage);\r\n } else {\r\n $scope.blockers[blockerName].stop();\r\n }\r\n }\r\n }\r\n }\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esPersistenceStore`, esPersistenceStore)\n .controller(`esPersistenceStoreController`, esPersistenceStoreController);\n\n\n esPersistenceStore.$inject = [];\n /* istanbul ignore next */\n function esPersistenceStore() {\n\n return {\n restrict: `E`,\n scope: {\n model: `=ngModel`,\n item: `@`,\n defaultModel: `=`,\n storageKey: `@`\n },\n controller: `esPersistenceStoreController`,\n controllerAs: `vm`,\n bindToController: true,\n replace: false,\n link: link\n };\n\n function link($scope, $element, attrs, vm) {\n vm.deserializeItem();\n $scope.$watch(() => vm.model[vm.item], vm.serializeItem, true);\n }\n }\n\n esPersistenceStoreController.$inject = [`browserStorage`, `app.core.appSettings`];\n function esPersistenceStoreController(browserStorage, appSettings) {\n const vm = this;\n\n vm.serializeItem = function() {\n const bucket = `${appSettings.site.facility.alias}-${appSettings.userId}`;\n browserStorage.persistBucket(vm.storageKey, bucket, vm.model[vm.item]);\n };\n\n vm.deserializeItem = function() {\n const bucket = `${appSettings.site.facility.alias}-${appSettings.userId}`;\n const storageItem = browserStorage.getBucket(vm.storageKey, bucket) || vm.defaultModel;\n if (storageItem) {\n vm.model[vm.item] = storageItem;\n }\n };\n }\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esSetSideBarDefaultWidth`, esSetSideBarDefaultWidth);\r\n\r\n /* istanbul ignore next */\r\n function esSetSideBarDefaultWidth() {\r\n\r\n return {\r\n scope: {\r\n width: `=esSetSideBarDefaultWidth`\r\n },\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n function link($scope, $elem) {\r\n const sidebarContainer = $elem.closest(`.sidebar-container`);\r\n sidebarContainer.css(`width`, $scope.width);\r\n }\r\n }\r\n})();\r\n\r\n\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esTabSet`, esTabSet)\n .controller(`esTabSetController`, esTabSetController);\n\n esTabSet.$inject = [];\n function esTabSet() {\n return {\n restrict: `E`,\n transclude: true,\n templateUrl: `/App/ui/core/controls/esTabSet.html`,\n scope: {\n tabs: `=`\n },\n bindToController: true,\n controller: esTabSetController,\n controllerAs: `vm`\n };\n }\n\n esTabSetController.$inject = [];\n function esTabSetController() {\n\n activate();\n\n ////////////////\n\n function activate() {}\n }\n\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .controller(`esTimeSliderController`, esTimeSliderController)\r\n .directive(`esTimeSlider`, esTimeSlider);\r\n\r\n esTimeSlider.$inject = [`jQuery`, `lodash`];\r\n\r\n /* istanbul ignore next */\r\n function esTimeSlider($, _) {\r\n\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n isEnabled: `=`,\r\n min: `=`,\r\n max: `=`,\r\n stepSize: `=`,\r\n stepTooltip: `=`,\r\n onStepChanged: `=`,\r\n modelDataAvailability: `=`\r\n },\r\n templateUrl: `/App/ui/core/controls/esTimeSlider.html`,\r\n link: link,\r\n controller: esTimeSliderController,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n transclude: true\r\n };\r\n\r\n function link($scope, $element) {\r\n const vm = $scope.vm;\r\n\r\n let availabilityClasses;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n addTemporalDataClassToMapWhenEnabled();\r\n resizeSliderOnPageResize();\r\n redrawDataAvailabilityWhenUpdated();\r\n redrawDataAvailabilityWhenSliderCreated();\r\n }\r\n\r\n function addTemporalDataClassToMapWhenEnabled() {\r\n const cssClass = `temporal-data-map-container`;\r\n\r\n $scope.$watch(\r\n () => vm.isEnabled,\r\n isEnabled => {\r\n const parent = $element.parent();\r\n\r\n if (isEnabled) {\r\n parent.addClass(cssClass);\r\n\r\n } else {\r\n parent.removeClass(cssClass);\r\n }\r\n });\r\n }\r\n\r\n function resizeSliderOnPageResize() {\r\n $scope.$on(`resizePage`, resize);\r\n\r\n function resize(event, payload) {\r\n if (!vm.timeSlider.kendoSlider || payload && payload.sender === `contentLoaded`) {\r\n return;\r\n }\r\n vm.timeSlider.kendoSlider.resize();\r\n redrawDataAvailabilityLayers();\r\n }\r\n }\r\n\r\n function redrawDataAvailabilityWhenUpdated() {\r\n $scope.$watch(\r\n () => vm.modelDataAvailability,\r\n modelDataAvailability => {\r\n redrawDataAvailabilityLayers(modelDataAvailability);\r\n },\r\n true);\r\n }\r\n\r\n function redrawDataAvailabilityWhenSliderCreated() {\r\n $scope.$watch(() => vm.timeSlider.kendoSlider, kendoSlider => {\r\n if (!!kendoSlider) {\r\n redrawDataAvailabilityLayers();\r\n }\r\n });\r\n }\r\n\r\n function redrawDataAvailabilityLayers(modelDataAvailability) {\r\n if (modelDataAvailability) { buildAvailabilityClasses(modelDataAvailability); }\r\n\r\n // Each `slider-item` represents a single tick mark on the kendo slider. The first and last\r\n // ticks are half the width of the other ticks.\r\n const $sliderItemsContainer = $(`ul.k-slider-items`, $element);\r\n if (!$sliderItemsContainer.length) {\r\n return;\r\n }\r\n\r\n const $esDataAvailability = resetDataAvailabilityContainer($sliderItemsContainer);\r\n if (!(availabilityClasses && availabilityClasses.length)) {\r\n return;\r\n }\r\n\r\n const $sliderItems = $(`li`, $sliderItemsContainer);\r\n const itemCount = $sliderItems.length;\r\n const $items = [];\r\n for (let pointIndex = 0; pointIndex < itemCount; pointIndex++) {\r\n const item = $sliderItems[pointIndex];\r\n const $item = $(item);\r\n const availabilityClass = availabilityClasses[pointIndex];\r\n\r\n $items.push(buildDataAvailabilityIndicator($esDataAvailability, $item.width(), availabilityClass, pointIndex === 0, pointIndex === itemCount - 1));\r\n }\r\n $esDataAvailability.append($items);\r\n\r\n adjustDataAvailabilityContainerPosition($esDataAvailability);\r\n }\r\n\r\n function buildAvailabilityClasses(modelDataAvailability) {\r\n availabilityClasses = [];\r\n\r\n if (!(modelDataAvailability && vm.min && vm.max && vm.stepSize) || _.isEmpty(modelDataAvailability)) {\r\n return availabilityClasses;\r\n }\r\n\r\n const query = _.chain(modelDataAvailability);\r\n const modelCount = _.keys(modelDataAvailability).length;\r\n\r\n for (let tick = vm.sliderMin; tick <= vm.max; tick += vm.stepSize) {\r\n const modelsWithDataAtTick = query\r\n .filter(modelDataAvailability => modelDataAvailability[tick])\r\n .value()\r\n .length;\r\n\r\n const cssClass = modelsWithDataAtTick === modelCount ? `all-data` : modelsWithDataAtTick === 0 ? `no-data` : `some-data`;\r\n availabilityClasses.push(cssClass);\r\n }\r\n\r\n return availabilityClasses;\r\n }\r\n\r\n function resetDataAvailabilityContainer($sliderItemsContainer) {\r\n const $parent = $sliderItemsContainer.parent();\r\n const $container = $(`.es-slider-data-availability`, $parent);\r\n\r\n return $container.length ? $container.empty() : $(`
        `).appendTo($parent);\r\n }\r\n\r\n function buildDataAvailabilityIndicator($container, itemWidth, availabilityClass, isFirstChild, isLastChild) {\r\n let indicatorWidth, marginWidth;\r\n\r\n // Ideally, we want the indicator to be 20px wide. If the kendo item isn`t this wide, then we`ll make\r\n // our indicator take up the entire width of the kendo item.\r\n if (itemWidth < 20) {\r\n indicatorWidth = itemWidth;\r\n\r\n if (isFirstChild || isLastChild) {\r\n indicatorWidth = Math.min(20, indicatorWidth * 2);\r\n marginWidth = Math.max((itemWidth * 2 - indicatorWidth) / 2, 0);\r\n\r\n } else {\r\n marginWidth = 0;\r\n }\r\n\r\n } else {\r\n indicatorWidth = 20;\r\n marginWidth = itemWidth - indicatorWidth;\r\n\r\n // We add in additional margin to cater for the \"overhang\" - see the comment in\r\n // \"adjustDataAvailabilityContainerPosition\" below.\r\n if (isFirstChild || isLastChild) {\r\n marginWidth += indicatorWidth / 2;\r\n }\r\n }\r\n\r\n const $indicator = $(`
      • `);\r\n\r\n if (marginWidth > 0) {\r\n // The first and last indicator get all their margin applied to one side, where-as the other\r\n // items need the margin to be divided equally on both sides.\r\n if (isFirstChild || isLastChild) {\r\n const marginProperty = isFirstChild ? `margin-right` : `margin-left`;\r\n $indicator.css(marginProperty, `${marginWidth}px`);\r\n\r\n } else {\r\n $indicator.css(`margin`, `0 ${marginWidth / 2}px`);\r\n }\r\n }\r\n\r\n return $indicator;\r\n }\r\n\r\n function adjustDataAvailabilityContainerPosition($container) {\r\n // At this point, the data availability container is the same length of the slider bar.\r\n // However, we want the first and the last indicators to overhang the edges of the slider bar.\r\n // In order to do that, we need to move our container to the left by half the width of the first\r\n // indicator (i.e. so that half of the first indicator overhangs the left hand side of the slider bar).\r\n // The right hand indicator will achieve the same effect simply by the extra margin that we added\r\n // when we rendered it.\r\n let originalMarginLeft = $container.data(`original-margin-left`);\r\n if (!originalMarginLeft) {\r\n const marginLeftWithUnits = $container.css(`margin-left`);\r\n originalMarginLeft = parseInt(/\\d+/.exec(marginLeftWithUnits)[0]);\r\n\r\n // Store the original measurement for margin-left so that when we redraw the container, it moves based\r\n // on the original margin, rather than the adjusted margin.\r\n $container.data(`original-margin-left`, originalMarginLeft);\r\n }\r\n\r\n const firstIndicatorWidth = $(`li:first-child`, $container).width();\r\n const marginLeft = originalMarginLeft - firstIndicatorWidth / 2;\r\n\r\n $container.css(`margin-left`, `${marginLeft}px`);\r\n }\r\n }\r\n }\r\n\r\n esTimeSliderController.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `lodash`,\r\n `app.ui.core.controls.StepTicker`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function esTimeSliderController($scope, $timeout, _, StepTicker) {\r\n const vm = this;\r\n vm.sliderMin = 0;\r\n vm.hasTimeSliderParameters = false;\r\n\r\n let tickerSpeeds, tickerSpeedIndex, tickerSpeedLabels;\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n vm.sliderMin = calculateSliderMin();\r\n vm.timeSlider = createTimeSlider();\r\n vm.ticker = createStepTicker();\r\n vm.changeTickerSpeed = changeTickerSpeed;\r\n vm.tickerSpeedLabel = ``;\r\n\r\n updateTickerWhenBoundsChange();\r\n raiseStepChangedEvent();\r\n cleanupWhenScopeDestroyed();\r\n calculateTickerSpeeds();\r\n\r\n $scope.$watch(() => vm.min, () => {\r\n vm.sliderMin = calculateSliderMin();\r\n });\r\n\r\n const watches = [\r\n () => vm.stepSize,\r\n () => vm.min,\r\n () => vm.max\r\n ];\r\n $scope.$watchGroup(watches, rebuildTimeSlider);\r\n\r\n $scope.$watch(() => vm.isEnabled, isEnabled => {\r\n vm.ticker.isRunning = vm.timeSlider.options.enabled = !!isEnabled;\r\n\r\n const slider = vm.timeSlider.kendoSlider;\r\n if (slider) {\r\n slider.enable(vm.ticker.isRunning);\r\n }\r\n });\r\n }\r\n\r\n function createTimeSlider() {\r\n const timeSlider = {\r\n options: {\r\n smallStep: vm.stepSize, // arrow keys\r\n largeStep: vm.stepSize, // page up/down\r\n tickPlacement: `topLeft`,\r\n enabled: vm.isEnabled\r\n },\r\n step: vm.sliderMin, // the currently active step\r\n onChange: () => {\r\n vm.ticker.isRunning = false;\r\n $timeout(() => {\r\n raiseStepChangedEvent();\r\n\r\n // Reset the ticker to this date so when the user presses \"Play\" again, the ticker starts from here.\r\n vm.ticker.activeStep = calculateStepIndex(vm.timeSlider.step);\r\n });\r\n }\r\n };\r\n\r\n if (vm.stepTooltip) {\r\n timeSlider.options.tooltip = vm.stepTooltip;\r\n }\r\n\r\n return timeSlider;\r\n }\r\n\r\n function rebuildTimeSlider() {\r\n vm.timeSlider.options.min = vm.sliderMin || 0;\r\n vm.timeSlider.options.max = vm.max || 0;\r\n vm.timeSlider.options.smallStep = vm.stepSize || 0;\r\n vm.timeSlider.options.largeStep = vm.timeSlider.options.smallStep * 5;\r\n\r\n // We need to reset the `enabled` property because when the time slider's bounds change, it\r\n // re-reads the options object to recreate itself.\r\n vm.timeSlider.options.enabled = vm.isEnabled;\r\n\r\n // Don't bother showing the time slider unless it has enough parameters to display properly.\r\n // If you give the slider all \"0\" parameters it basically gets into an infinite loop and dies.\r\n vm.hasTimeSliderParameters = vm.sliderMin < vm.max && vm.stepSize;\r\n }\r\n\r\n function calculateSliderMin() {\r\n // The time slider's minimum value needs to be one interval bigger than the time range.\r\n // This is because each step on the slider effectively represents the end time of the \"interval\"\r\n // of data. e.g. a dataset from 8 AM - 10 AM will be represented by two steps on the slider:\r\n // - 9 AM (for the 8 AM - 9 AM step);\r\n // - 10 AM (for the 9 AM - 10 AM step).\r\n return vm.min && vm.stepSize ? vm.min + vm.stepSize : 0;\r\n }\r\n\r\n function updateTickerWhenBoundsChange() {\r\n $scope.$watch(\r\n () => vm.sliderMin + `-` + vm.max, () => {\r\n // Cater for the scenario where vm.min and vm.max have been updated in the same digest cycle,\r\n // but we`ve received this event (because vm.max has changed) before we`ve received the vm.min\r\n // changed event (which would consequently update vm.sliderMin).\r\n const sliderMin = calculateSliderMin();\r\n const stepCount = calculateStepIndex(vm.max);\r\n\r\n if (vm.sliderMin === sliderMin && vm.ticker.stepCount === stepCount) {\r\n return;\r\n }\r\n\r\n vm.sliderMin = sliderMin;\r\n vm.ticker.stepCount = stepCount;\r\n calculateTickerSpeeds();\r\n });\r\n }\r\n\r\n function raiseStepChangedEvent() {\r\n vm.onStepChanged(vm.timeSlider.step);\r\n }\r\n\r\n function cleanupWhenScopeDestroyed() {\r\n $scope.$on(`$destroy`, () => {\r\n if (vm.timeSlider.kendoSlider) {\r\n vm.timeSlider.kendoSlider.destroy();\r\n }\r\n\r\n vm.ticker.destroy();\r\n });\r\n }\r\n\r\n function createStepTicker() {\r\n const ticker = new StepTicker();\r\n ticker.stepCount = calculateStepIndex(vm.max);\r\n ticker.loop = true;\r\n\r\n ticker.onTick = stepIndex => {\r\n vm.timeSlider.step = vm.sliderMin + stepIndex * vm.stepSize;\r\n raiseStepChangedEvent();\r\n };\r\n\r\n return ticker;\r\n }\r\n\r\n function calculateStepIndex(stepValue) {\r\n return (stepValue - vm.sliderMin) / vm.stepSize;\r\n }\r\n\r\n function calculateTickerSpeeds() {\r\n const stepCount = calculateStepIndex(vm.max);\r\n if (_.isNaN(stepCount)) {\r\n if (vm.ticker && vm.ticker.isRunning) {\r\n vm.ticker.isRunning = false;\r\n }\r\n\r\n return;\r\n }\r\n\r\n const defaultSpeed = getDefaultTickerSpeedForIntervalCount(stepCount);\r\n\r\n tickerSpeeds = [defaultSpeed * 2, defaultSpeed, defaultSpeed * 0.5];\r\n tickerSpeedLabels = [`0.5`, `1`, `2`];\r\n\r\n if (!tickerSpeedIndex) {\r\n tickerSpeedIndex = Math.floor(tickerSpeeds.length / 2);\r\n }\r\n\r\n changeTickerSpeed(0);\r\n }\r\n\r\n function getDefaultTickerSpeedForIntervalCount(intervalCount) {\r\n if (!intervalCount || intervalCount <= 15) {\r\n return 1000;\r\n }\r\n\r\n if (intervalCount <= 60) {\r\n return 500;\r\n }\r\n\r\n return 250;\r\n }\r\n\r\n function changeTickerSpeed(delta) {\r\n tickerSpeedIndex += delta;\r\n\r\n if (tickerSpeedIndex >= tickerSpeeds.length) {\r\n tickerSpeedIndex = 0;\r\n }\r\n\r\n vm.ticker.tickMillis = tickerSpeeds[tickerSpeedIndex];\r\n vm.tickerSpeedLabel = tickerSpeedLabels[tickerSpeedIndex];\r\n }\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .factory(`app.ui.core.controls.StepTicker`, StepTickerFactory);\r\n\r\n StepTickerFactory.$inject = [`lodash`, `$timeout`];\r\n\r\n function StepTickerFactory(_, $timeout) {\r\n function StepTicker() {\r\n const self = this;\r\n self.onTick = null;\r\n self.destroy = destroy;\r\n\r\n let stepCount = 0;\r\n let activeStep = 0;\r\n let tickMillis = 500;\r\n let loop = false;\r\n let timer = null;\r\n\r\n Object.defineProperty(self, `stepCount`, {\r\n get: () => stepCount,\r\n set: value => updatePropertyThenRestart(() => {\r\n stepCount = value;\r\n activeStep = Math.max(0, Math.min(activeStep, value));\r\n })\r\n });\r\n\r\n Object.defineProperty(self, `activeStep`, {\r\n get: () => activeStep,\r\n set: value => updatePropertyThenRestart(() => activeStep = Math.max(0, value))\r\n });\r\n\r\n Object.defineProperty(self, `tickMillis`, {\r\n get: () => tickMillis,\r\n set: value => updatePropertyThenRestart(() => tickMillis = value)\r\n });\r\n\r\n Object.defineProperty(self, `loop`, {\r\n get: () => loop,\r\n set: value => {\r\n loop = value;\r\n\r\n if (value && !self.isRunning) {\r\n self.isRunning = true;\r\n }\r\n }\r\n });\r\n\r\n Object.defineProperty(self, `isRunning`, {\r\n get: () => !!timer,\r\n set: value => {\r\n if (value) {\r\n start();\r\n } else {\r\n pause();\r\n }\r\n }\r\n });\r\n\r\n ////////////////////\r\n\r\n function updatePropertyThenRestart(update) {\r\n const shouldRestart = self.isRunning;\r\n pause();\r\n update();\r\n\r\n if (shouldRestart) {\r\n start();\r\n }\r\n }\r\n\r\n function start() {\r\n if (self.isRunning || !canStart()) {\r\n return;\r\n }\r\n\r\n ensureActiveStepIsValid();\r\n\r\n const tick = () => {\r\n const step = hasReachedFinalStep() ? 0 : activeStep + 1;\r\n updateActiveStep(step);\r\n\r\n timer = hasReachedFinalStep() && !loop ? null : $timeout(tick, tickMillis);\r\n };\r\n\r\n timer = $timeout(tick, tickMillis);\r\n }\r\n\r\n function canStart() {\r\n return stepCount > 0;\r\n }\r\n\r\n function ensureActiveStepIsValid() {\r\n if (!activeStep || hasReachedFinalStep()) {\r\n updateActiveStep(0);\r\n }\r\n }\r\n\r\n function hasReachedFinalStep() {\r\n return activeStep >= stepCount;\r\n }\r\n\r\n function updateActiveStep(step) {\r\n activeStep = step;\r\n\r\n if (_.isFunction(self.onTick)) {\r\n self.onTick.call(this, step);\r\n }\r\n }\r\n\r\n function pause() {\r\n $timeout.cancel(timer);\r\n timer = null;\r\n }\r\n\r\n function destroy() {\r\n pause();\r\n delete self.onTick;\r\n }\r\n }\r\n\r\n return StepTicker;\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .value(`app.ui.core.controls.Tab`, Tab);\r\n\r\n function Tab(name, getUrl, isActive = () => false, isVisible = () => true) {\r\n this.name = name;\r\n this.getUrl = getUrl;\r\n this.isActive = isActive;\r\n this.isVisible = isVisible;\r\n this.isDirty = false;\r\n this.isBusyLoading = false;\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .factory(`esComponentChangeHandlerFactory`, esComponentChangeHandlerFactory);\r\n\r\n esComponentChangeHandlerFactory.$inject = [];\r\n\r\n /*\r\n * Usage:\r\n *\r\n * function $onChanges(changes) {\r\n * const changeHandler = changeHandlerFactory(changes);\r\n *\r\n * // Check for initial change\r\n * changeHandler\r\n * .when(changes => changes.name)\r\n * .hasFirstChanged()\r\n * .then(name => vm.name = name);\r\n *\r\n * // Check if a primitive has changed\r\n * changeHandler\r\n * .when(changes => changes.name)\r\n * .hasChanged()\r\n * .then(name => vm.name = name);\r\n *\r\n * // Use a filter to check if a specific property has changed\r\n * changeHandler\r\n * .when(changes => changes.state)\r\n * .hasChanged(state => state.name)\r\n * .then(name => vm.name = name);\r\n *\r\n * // Use a custom comparer\r\n * changeHandler\r\n * .when(changes => changes.state)\r\n * .hasChanged(state => state.name)\r\n * .because((currentName, previousName) => currentName.toUpperCase() !== previousName.toUpperCase())\r\n * .then(name => vm.name = name);\r\n *\r\n * // Use a custom comparer to check for a single property change\r\n * changeHandler\r\n * .when(changes => changes.state)\r\n * .hasChanged()\r\n * .because((currentState, previousState) => currentState.id !== previousState.id)\r\n * .then(state => vm.name = state.name);\r\n *\r\n * // Check for multiple changes on the same property\r\n * const whenState = changeHandler.when(changes => changes.state);\r\n * whenState\r\n * .hasChanged(state => state.name)\r\n * .then(name => vm.name = name);\r\n * whenState\r\n * .hasChanged(state => state.age)\r\n * .then(age => vm.age = age);\r\n * }\r\n */\r\n function esComponentChangeHandlerFactory() {\r\n const defaultHasChangedEvaluator = (currentValue, previousValue) => currentValue !== previousValue;\r\n\r\n return function esComponentChangeHandlerFactory(changes) {\r\n return {\r\n when\r\n };\r\n\r\n ////////////////////\r\n\r\n function when(propertySelector) {\r\n const propertyChanges = propertySelector(changes);\r\n const isPropertyInChangeMap = propertyChanges !== undefined;\r\n\r\n const isFirstChange = isPropertyInChangeMap && propertyChanges.isFirstChange();\r\n const currentBoundValue = isPropertyInChangeMap ? propertyChanges.currentValue : undefined;\r\n const previousBoundValue = isPropertyInChangeMap ? propertyChanges.previousValue : undefined;\r\n\r\n return {\r\n hasFirstChanged,\r\n hasChanged\r\n };\r\n\r\n function hasFirstChanged(filter) {\r\n const fluentResult = {\r\n then: () => {}\r\n };\r\n\r\n if (isFirstChange) {\r\n const currentValue = applyFilter(filter, currentBoundValue);\r\n fluentResult.then = createThenFunction(currentValue);\r\n }\r\n\r\n return fluentResult;\r\n }\r\n\r\n function hasChanged(filter) {\r\n return {\r\n because: function(hasChangedEvaluator) {\r\n return hasPropertyChanged(filter, hasChangedEvaluator);\r\n },\r\n then: function(processChange) {\r\n return hasPropertyChanged(filter, defaultHasChangedEvaluator).then(processChange);\r\n }\r\n };\r\n }\r\n\r\n function hasPropertyChanged(filter, hasChangedEvaluator) {\r\n const fluentResult = {\r\n then: () => {}\r\n };\r\n\r\n if (isPropertyInChangeMap) {\r\n let hasChanged = isFirstChange;\r\n\r\n const currentValue = applyFilter(filter, currentBoundValue);\r\n let previousValue = undefined;\r\n\r\n if (!isFirstChange) {\r\n previousValue = applyFilter(filter, previousBoundValue);\r\n hasChanged = hasChangedEvaluator(currentValue, previousValue);\r\n }\r\n\r\n if (hasChanged) {\r\n fluentResult.then = createThenFunction(currentValue, previousValue);\r\n }\r\n }\r\n\r\n return fluentResult;\r\n }\r\n }\r\n\r\n function applyFilter(filter, value) {\r\n return filter ? filter(value) : value;\r\n }\r\n\r\n function createThenFunction(currentValue, previousValue) {\r\n return function then(processChange) {\r\n processChange(currentValue, previousValue);\r\n };\r\n }\r\n };\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .factory(`esStateStore`, esStateStore);\r\n\r\n esStateStore.$inject = [\r\n `$rootScope`,\r\n `lodash`,\r\n `utils`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function esStateStore($rootScope, _, utils) {\r\n return function(initialStateResolver, dispatchers) {\r\n let _state = utils.freeze(getBaseState());\r\n\r\n let unsubscribeFromRouteChanges;\r\n let loading = 0;\r\n let saving = 0;\r\n\r\n const store = {\r\n get state() {\r\n return _state;\r\n },\r\n set state(newState) {\r\n _state = utils.freeze(newState);\r\n }\r\n };\r\n\r\n store.dispatch = _.mapValues(dispatchers, createDispatcher => createDispatcher(store));\r\n\r\n // this function is utilized by ui-router as a 'resolve' before transitioning to the route.\r\n // the store.state is then one-way bound down to the component.\r\n store.resolve = () => {\r\n const initialStateLoader = initialStateResolver().then(state => {\r\n return store.state = {\r\n ...getBaseState(),\r\n ...state\r\n };\r\n });\r\n\r\n return store.load(initialStateLoader).then(() => store);\r\n };\r\n\r\n // Use the load function in a dispatcher when an asynchronous 'loading/fetching' operation is taking place.\r\n store.load = promise => {\r\n store.state = { ...store.state, loading: ++loading };\r\n return promise.then(delta => {\r\n store.state = { ...store.state, loading: --loading, ...delta };\r\n });\r\n };\r\n\r\n // Use the save function in a dispatcher when an asynchronous 'save' operation is taking place.\r\n store.save = promise => {\r\n store.state = { ...store.state, saving: ++saving };\r\n return promise.then(delta => {\r\n store.state = { ...store.state, saving: --saving, ...delta };\r\n });\r\n };\r\n\r\n store.init = () => {\r\n unsubscribeFromRouteChanges = subscribeToRouteChanges(store);\r\n };\r\n\r\n store.destroy = () => {\r\n unsubscribeFromRouteChanges && unsubscribeFromRouteChanges();\r\n };\r\n\r\n return store;\r\n };\r\n\r\n function getBaseState() {\r\n return {\r\n loading: 0,\r\n saving: 0\r\n };\r\n }\r\n\r\n function subscribeToRouteChanges(store) {\r\n return $rootScope.$on(`$stateChangeSuccess`, ($scope, toRoute, toRouteParams) => {\r\n store.state = {\r\n ...store.state,\r\n $routeParams: toRouteParams\r\n };\r\n });\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .controller(`Forbidden`, Forbidden);\r\n\r\n Forbidden.$inject = [`app.core.services.locationService`];\r\n function Forbidden(locationService) {\r\n const vm = this;\r\n vm.goHome = locationService.goHome;\r\n vm.logout = locationService.logout;\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esJobs`, esJobs)\r\n .controller(`esJobsController`, esJobsController);\r\n\r\n esJobs.$inject = [];\r\n\r\n function esJobs() {\r\n return {\r\n scope: {},\r\n restrict: `EA`,\r\n templateUrl: `/App/ui/core/jobs/controls/esJobs.html`,\r\n controller: esJobsController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esJobsController.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `lodash`,\r\n `postal`,\r\n `app.core.appSettings`,\r\n `app.core.services.gisModelService`,\r\n `app.core.signalR.jobs.state`,\r\n `app.core.signalR.jobs.events`\r\n ];\r\n function esJobsController($scope, $timeout, _, postal, appSettings, gisModelService, state, jobEvents) {\r\n const vm = this;\r\n\r\n const channel = postal.channel(jobEvents.channelName);\r\n\r\n let subscriptions = [];\r\n const subscribedFacility = null;\r\n\r\n vm.activeJobCount = 0;\r\n\r\n vm.jobs = [];\r\n vm.clearJob = clearJob;\r\n vm.clearCompleted = clearCompleted;\r\n\r\n activate();\r\n\r\n //////////////////////\r\n\r\n function activate() {\r\n updateJobsWhenJobsChange();\r\n updateActiveJobCountOnJobCreated();\r\n updateActiveJobCountOnJobComplete();\r\n reloadJobsWhenFacilityChanges();\r\n }\r\n\r\n function updateJobsWhenJobsChange() {\r\n $scope.$watchCollection(() => state.jobs, (newJobs, oldJobs) => {\r\n const jobsAdded = _.difference(newJobs, oldJobs);\r\n const jobsRemoved = _.difference(oldJobs, newJobs);\r\n\r\n _.forEach(jobsAdded, job => {\r\n if (!job.hasCompleted) {\r\n vm.jobs.splice(0, 0, job);\r\n } else {\r\n vm.jobs.push(job);\r\n }\r\n });\r\n\r\n _.forEach(jobsRemoved, job => _.remove(vm.jobs, job));\r\n });\r\n }\r\n\r\n function updateActiveJobCountOnJobCreated() {\r\n $scope.$watch(() => vm.jobs.length, recalculateActiveJobCount);\r\n }\r\n\r\n function updateActiveJobCountOnJobComplete() {\r\n subscriptions = [\r\n channel.subscribe(jobEvents.topics.jobCompleted, recalculateActiveJobCount)\r\n ];\r\n\r\n $scope.$on(`$destroy`, () => {\r\n _.invokeMap(subscriptions, `unsubscribe`);\r\n });\r\n }\r\n\r\n function recalculateActiveJobCount() {\r\n let activeJobCount = 0;\r\n\r\n _.forEach(vm.jobs, job => {\r\n if (!job.hasCompleted) {\r\n activeJobCount++;\r\n }\r\n });\r\n\r\n vm.activeJobCount = activeJobCount;\r\n }\r\n\r\n function reloadJobsWhenFacilityChanges() {\r\n $scope.$watch(() => appSettings.site.accessControls, () => {\r\n if (!appSettings.site.accessControls || !appSettings.site.facility.alias || appSettings.site.facility.alias === subscribedFacility) {\r\n return;\r\n }\r\n\r\n state.jobs.length = 0;\r\n\r\n gisModelService.getModellingJobs().then(jobs => {\r\n _.forEach(jobs, job => state.jobs.push(job));\r\n });\r\n });\r\n }\r\n\r\n function clearJob(job) {\r\n // Eagerly remove the job so the UI is more responsive.\r\n // If this fails, the job will come back after a refresh, but... meh.\r\n _.remove(state.jobs, job);\r\n\r\n // The jobStatusHub will only publish the jobDismissed event if it is responsible for removing the\r\n // job from the state; since we've already done that, we have to also publish the event.\r\n $timeout(() => channel.publish(jobEvents.topics.jobDismissed, job));\r\n\r\n gisModelService.dismissJob(job.jobId);\r\n }\r\n\r\n function clearCompleted() {\r\n const jobsToDismiss = [];\r\n\r\n for (let i = state.jobs.length - 1; i >= 0; i--) {\r\n const job = state.jobs[i];\r\n if (!job.hasCompleted) {\r\n continue;\r\n }\r\n\r\n state.jobs.splice(i, 1);\r\n jobsToDismiss.push(job.jobId);\r\n }\r\n\r\n if (jobsToDismiss.length) {\r\n gisModelService.dismissJobs(jobsToDismiss);\r\n }\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .factory(`app.ui.core.keyboardShortcuts`, keyboardShortcuts);\r\n\r\n keyboardShortcuts.$inject = [`lodash`, `Mousetrap`];\r\n function keyboardShortcuts(_, Mousetrap) {\r\n let keyboardShortcutCollections = [];\r\n\r\n const originalCallback = Mousetrap.prototype.stopCallback;\r\n Mousetrap.prototype.stopCallback = (event, element) => {\r\n return element.className.indexOf(`ignore-mousetrap`) > -1 || originalCallback(event, element);\r\n };\r\n\r\n return {\r\n add,\r\n remove: () => _.forEach(keyboardShortcutCollections, unbind),\r\n list: () => keyboardShortcutCollections\r\n };\r\n\r\n function add(description, shortcutCollection) {\r\n if (!shortcutCollection) {\r\n throw new Error(`The shortcut collection must be defined.`);\r\n }\r\n\r\n _.forEach(_.values(shortcutCollection), shortcut => {\r\n if (!shortcut.hasOwnProperty(`visible`)) {\r\n shortcut.visible = true;\r\n }\r\n });\r\n\r\n keyboardShortcutCollections.push({ description: description, shortcuts: shortcutCollection });\r\n bind(shortcutCollection);\r\n\r\n return {\r\n remove : () => unbind(shortcutCollection)\r\n };\r\n }\r\n\r\n function bind(shortcutCollection) {\r\n const shortcuts = Object.keys(shortcutCollection);\r\n _.forEach(shortcuts, shortcut => {\r\n Mousetrap.bind(shortcut, shortcutCollection[shortcut].action);\r\n });\r\n }\r\n\r\n function unbind(shortcutCollection) {\r\n const shortcuts = Object.keys(shortcutCollection);\r\n _.forEach(shortcuts, shortcut => {\r\n Mousetrap.unbind(shortcut);\r\n delete shortcuts[shortcut];\r\n });\r\n keyboardShortcutCollections = _.reject(keyboardShortcutCollections, { shortcuts: shortcutCollection });\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esFullScreen`, esFullScreen);\r\n\r\n esFullScreen.$inject = [`$rootScope`, `$timeout`];\r\n function esFullScreen($rootScope, $timeout) {\r\n\r\n const directive = {\r\n restrict: `A`,\r\n scope: {\r\n isFullScreen: `=esFullScreen`\r\n },\r\n bindToController: true,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n $element.bind(`click`, () => {\r\n $timeout(() => {\r\n $scope.vm.isFullScreen = !$scope.vm.isFullScreen;\r\n });\r\n });\r\n }\r\n\r\n controller.$inject = [`$scope`, `$state`, `$timeout`];\r\n function controller($scope, $state, $timeout) {\r\n const vm = this;\r\n const $shellView = angular.element(`#shell-view`);\r\n\r\n activate();\r\n\r\n //////////////\r\n\r\n function activate() {\r\n $scope.$watch(\r\n () => vm.isFullScreen,\r\n () => {\r\n if (vm.isFullScreen) {\r\n $shellView.addClass(`full-screen`);\r\n } else {\r\n $shellView.removeClass(`full-screen`);\r\n }\r\n\r\n $timeout(() => $rootScope.$broadcast(`resizePage`));\r\n }\r\n );\r\n\r\n // only overwrite $scope value if the query param is present\r\n if ($state.params.fullScreen) {\r\n vm.isFullScreen = true;\r\n }\r\n }\r\n }\r\n\r\n return directive;\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esSideBar`, esSideBar);\r\n\r\n esSideBar.$inject = [`$rootScope`, `$window`, `lodash`];\r\n\r\n function esSideBar($rootScope, $window, _) {\r\n\r\n const directive = {\r\n link: link,\r\n scope: true,\r\n restrict: `A`\r\n };\r\n return directive;\r\n\r\n function link($scope, $element) {\r\n $element.find(`.sidebar-container`).resizable({\r\n handles: { e: `.ui-resizable-handle` },\r\n maxWidth: $window.innerWidth / 3,\r\n minWidth: 300,\r\n resize: _.debounce(triggerResizePage, 50)\r\n });\r\n\r\n $element.find(`.sidebar-handle`).click(() => {\r\n $element.toggleClass(`collapsed`);\r\n triggerResizePage();\r\n });\r\n\r\n function triggerResizePage() {\r\n $rootScope.$broadcast(`resizePage`, { sender: `esSideBar` });\r\n }\r\n\r\n $element.find(`.sidebar-hide-overlay`).click(() => {\r\n $element.addClass(`collapsed`);\r\n triggerResizePage();\r\n });\r\n\r\n $element.find(`.ui-resizable-handle`).click(() => {\r\n $element.toggleClass(`collapsed`);\r\n triggerResizePage();\r\n });\r\n\r\n $scope.$on(`resizePage`, (evt, args) => {\r\n if (args && args.sender === `esSideBar`) { return; }\r\n window.innerWidth <= 996 ? $element.addClass(`collapsed`) : $element.removeClass(`collapsed`);\r\n });\r\n\r\n if (window.innerWidth <= 996) {\r\n $element.toggleClass(`collapsed`);\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esWindowResize`, esWindowResize);\n\n esWindowResize.$inject = [`$rootScope`, `$window`, `$timeout`, `lodash`];\n function esWindowResize($rootScope, $window, $timeout, _) {\n\n return {\n link: link,\n scope: true,\n restrict: `A`\n };\n\n function link($scope) {\n\n let unsubscribeMe;\n\n registerWindowResizeHandler();\n registerPageLoadedHandler();\n\n function triggerResizePage(sender) {\n $timeout($rootScope.$broadcast(`resizePage`, { sender: sender }));\n }\n\n function registerWindowResizeHandler() {\n const debouncedResize = _.debounce(() => { triggerResizePage(`windowResize`); }, 50);\n const window = angular.element($window);\n window.on(`resize`, debouncedResize);\n }\n\n function registerPageLoadedHandler() {\n const debounceContentLoaded = _.debounce(() => { triggerResizePage(`contentLoaded`); }, 50);\n unsubscribeMe = $rootScope.$on(`$includeContentLoaded`, debounceContentLoaded);\n }\n\n $scope.$on(`$destroy`, () => {\n unsubscribeMe();\n });\n }\n }\n\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .controller(`app.ui.core.layout.Shell`, Shell);\r\n\r\n Shell.$inject = [\r\n `$scope`,\r\n `jQuery`,\r\n `$filter`,\r\n `$timeout`,\r\n `$state`,\r\n `$window`,\r\n `$modal`,\r\n `i18n`,\r\n `httpBatcher`,\r\n `app.ui.core.keyboardShortcuts`,\r\n `app.core.appSettings`,\r\n `app.core.models.messages.messageList`,\r\n `app.core.services.securityService`,\r\n `app.core.services.companyService`,\r\n `app.core.services.locationService`,\r\n `app.core.providers.errorThrowingDataProvider`,\r\n `app.core.signalR.jobs.state`,\r\n `app.core.signalR.alerts.state`,\r\n `companyFacilities`];\r\n\r\n function Shell(\r\n $scope,\r\n $,\r\n $filter,\r\n $timeout,\r\n $state,\r\n $window,\r\n $modal,\r\n i18n,\r\n httpBatcher,\r\n keyboardShortcuts,\r\n appSettings,\r\n messageList,\r\n securityService,\r\n companyService,\r\n locationService,\r\n errorThrower,\r\n jobState,\r\n alertState,\r\n companyFacilities) {\r\n\r\n const vm = this;\r\n\r\n vm.appSettings = appSettings;\r\n vm.messageList = messageList;\r\n vm.companies = companyFacilities;\r\n vm.changeRoute = changeRoute;\r\n vm.jobCount = 0;\r\n vm.alertCount = 0;\r\n vm.classes = [];\r\n vm.showLeftPanel = $state.$current.data.layoutType === `split`;\r\n\r\n vm.filterText = ``;\r\n vm.setFilterText = setFilterText;\r\n vm.resetFilterText = resetFilterText;\r\n vm.menu = null;\r\n vm.menuClick = calculateOperationsMenuHeight;\r\n vm.logout = logout;\r\n\r\n vm.filterCompanies = filterCompanies;\r\n\r\n let $dropdown;\r\n\r\n let menuShortcuts = {};\r\n let menuShortcutBindings;\r\n\r\n const globalShortcuts = {};\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n const showOperationsMenu = shouldShowOperationsMenu();\r\n\r\n $timeout(() => $dropdown = $(`.menu.dropdown-toggle`));\r\n\r\n updateFacilityDetails(vm.appSettings.site.company.alias, vm.appSettings.site.facility.alias);\r\n\r\n vm.showFacilityMenu = !vm.appSettings.isGuestUser;\r\n\r\n setupGlobalShortcuts();\r\n\r\n $scope.$watch(() => jobState.jobs.length, jobCount => {\r\n vm.jobCount = jobCount;\r\n });\r\n\r\n $scope.$watch(() => alertState.alerts.length, alertCount => {\r\n vm.alertCount = alertCount;\r\n });\r\n\r\n $scope.$watch(() => locationService.pageHeading, pageHeading => {\r\n vm.pageHeading = pageHeading;\r\n });\r\n\r\n $scope.$watch(() => locationService.exitPoint, exitPoint => {\r\n vm.exitPoint = exitPoint;\r\n });\r\n\r\n $scope.$watch(() => $state.$current, route => {\r\n vm.showLeftPanel = route.data.layoutType === `split`;\r\n vm.classes = getClasses();\r\n });\r\n\r\n $scope.$watch(() => vm.appSettings.site.accessControls, accessControls => {\r\n const companyAlias = vm.appSettings.site.company.alias;\r\n const facilityAlias = vm.appSettings.site.facility.alias;\r\n\r\n if (menuShortcutBindings) {\r\n menuShortcutBindings.remove();\r\n menuShortcuts = {};\r\n }\r\n\r\n if (showOperationsMenu) {\r\n vm.menu = {\r\n operations: getActionMenuItems(accessControls, companyAlias, facilityAlias),\r\n incidentIntelligence: getIncidentIntelligenceMenuItems(accessControls, companyAlias, facilityAlias),\r\n configuration: getConfigurationMenuItems(accessControls, companyAlias, facilityAlias)\r\n };\r\n }\r\n\r\n menuShortcutBindings = keyboardShortcuts.add(i18n.i10n(`app.ui.core.layout.shell.navigation.menu.shortcut.description`), menuShortcuts);\r\n\r\n if (showOperationsMenu) {\r\n vm.menu.columnClass = getColumnClass();\r\n }\r\n\r\n function getColumnClass() {\r\n let columnCount = 1; // profile\r\n\r\n if (showOperationsMenu) {\r\n if (vm.menu.operations.length) {\r\n columnCount++;\r\n }\r\n if (vm.menu.incidentIntelligence.length) {\r\n columnCount++;\r\n }\r\n }\r\n\r\n return `col-sm-${12 / columnCount}`;\r\n }\r\n });\r\n\r\n $scope.$on(`resizePage`, calculateOperationsMenuHeight);\r\n\r\n $scope.$on(`$destroy`, () => {\r\n keyboardShortcuts.remove(); // remove all keyboard shortcut bindings\r\n });\r\n }\r\n\r\n function getClasses() {\r\n const classes = [];\r\n let routeState = $state.$current;\r\n if (vm.showLeftPanel) {\r\n classes.push(`es-layout-split`);\r\n }\r\n if (vm.appSettings.icpCertificate && vm.appSettings.internetSecurityNumberText\r\n && vm.appSettings.internetSecurityRegistrationLink) {\r\n classes.push(`display-icp-registrations-view`);\r\n }\r\n do {\r\n if (routeState.self.state) {\r\n classes.push(`es-route-` + routeState.self.state.replace(/\\./g, `-`));\r\n }\r\n } while (routeState = routeState.parent); // eslint-disable-line no-cond-assign\r\n\r\n return classes;\r\n }\r\n\r\n function changeRoute(selectedCompanyAlias, selectedFacilityAlias) {\r\n updateFacilityDetails(selectedCompanyAlias, selectedFacilityAlias);\r\n const currentState = $state.current.name;\r\n $state.go(currentState, { companyAlias: selectedCompanyAlias, facilityAlias: selectedFacilityAlias });\r\n }\r\n\r\n function updateFacilityDetails(companyAlias, facilityAlias) {\r\n // note: we flush the batch requests so that the web api doesn't get confused processing multiple company/facility database connections.\r\n httpBatcher.flush();\r\n\r\n companyService.getFacilityDetails(companyAlias, facilityAlias).then(facility => {\r\n vm.facilityName = facility.name;\r\n });\r\n }\r\n\r\n function setupGlobalShortcuts() {\r\n globalShortcuts[`capslock capslock 5 0 0`] = {\r\n visible: false,\r\n description : `Receive a server-side error exception`,\r\n action : () => {\r\n $timeout(errorThrower.getException());\r\n }\r\n };\r\n\r\n globalShortcuts[`capslock capslock 4 0 0`] = {\r\n visible: false,\r\n description : `Receive a server-side failed result (non 200)`,\r\n action: () => {\r\n $timeout(errorThrower.getFailedResult());\r\n }\r\n };\r\n\r\n globalShortcuts[`capslock capslock f a t a l`] = {\r\n visible: false,\r\n description : `Throw an unrecoverable Javascript exception`,\r\n action : () => {\r\n const monkey = {};\r\n console.log(monkey.balls.friday);\r\n $scope.$apply(() => {\r\n throw new Error(`This is an unrecoverable JavaScript exception.`);\r\n });\r\n }\r\n };\r\n\r\n globalShortcuts[`capslock capslock i n f o`] = {\r\n visible: false,\r\n description : `Test information messages`,\r\n action : () => {\r\n $timeout(messageList.addInfo(`Test Information Message`, `This is an information message.`));\r\n }\r\n };\r\n\r\n globalShortcuts[`capslock capslock w a r n`] = {\r\n visible: false,\r\n description : `Test warning messages`,\r\n action : () => {\r\n $timeout(messageList.addWarning(`Test Warning Message`, `This is a warning message.`));\r\n }\r\n };\r\n\r\n globalShortcuts[`g c`] = {\r\n description: i18n.i10n(`app.ui.core.layout.shell.globalShortcuts.company.openMenu`),\r\n action: () => {\r\n $dropdown.dropdown(`toggle`);\r\n $dropdown.parent().focus();\r\n }\r\n };\r\n\r\n globalShortcuts[`?`] = {\r\n description: i18n.i10n(`app.ui.core.layout.shell.globalShortcuts.help`),\r\n action: () => {\r\n const scope = $scope.$new();\r\n scope.keyboardShortcuts = keyboardShortcuts;\r\n $modal.open({\r\n templateUrl: `/App/ui/core/keyboardShortcuts.html`,\r\n animation: false, // a bug means the backdrop stays when animations are on :(.\r\n size: `modal-lg`,\r\n scope: scope\r\n });\r\n }\r\n };\r\n\r\n keyboardShortcuts.add(i18n.i10n(`app.ui.core.layout.shell.globalShortcuts.description`), globalShortcuts);\r\n }\r\n\r\n function setFilterText($event) {\r\n if ($event.keyCode === 27) {\r\n vm.filterText = ``;\r\n } else if ($event.keyCode === 13) {\r\n vm.changeRoute(vm.filteredCompanies[0].alias, vm.filteredCompanies[0].filteredFacilities[0].alias);\r\n $dropdown.dropdown(`toggle`);\r\n vm.filterText = ``;\r\n $dropdown.parent().blur();\r\n } else if ($event.keyCode === 8) {\r\n vm.filterText = vm.filterText.length > 1\r\n ? vm.filterText.substr(0, vm.filterText.length - 1)\r\n : ``;\r\n } else {\r\n vm.filterText += String.fromCharCode($event.keyCode);\r\n }\r\n }\r\n\r\n function resetFilterText($event) {\r\n vm.filterText = ``;\r\n $event.stopPropagation();\r\n }\r\n\r\n function filterCompanies() {\r\n return company => {\r\n const facilities = $filter(`filter`)(company.facilities, { searchTerms: vm.filterText });\r\n return facilities.length;\r\n };\r\n }\r\n\r\n function getActionMenuItems(accessControls, companyAlias, facilityAlias) {\r\n const menuItems = [];\r\n if (!accessControls) {\r\n return menuItems;\r\n }\r\n\r\n if (!appSettings.isGuestUser) {\r\n menuItems.push({\r\n href: $state.href(`app.dashboard`, { companyAlias, facilityAlias }),\r\n label: getMenuItemLabel(`actions.dashboard`),\r\n key: `operations-menu-dashboard`\r\n });\r\n menuShortcuts[`/ d a s h`] = {\r\n description: getMenuItemShortcutDescription(`actions.dashboard`),\r\n action: () => {\r\n $state.go(`app.dashboard`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`app.monitoring`] && !accessControls[`zeus.monitoring`]) {\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.monitoring`, { companyAlias, facilityAlias }),\r\n label: getMenuItemLabel(`actions.monitoring`),\r\n key: `operations-menu-monitoring`\r\n });\r\n\r\n menuShortcuts[`/ m o n`] = {\r\n description: getMenuItemShortcutDescription(`actions.monitoring`),\r\n action: () => {\r\n $state.go(`app.monitoring`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`zeus.monitoring`]) {\r\n const url = `${vm.appSettings.zeusHostUri}map/real-time?companyAlias=${companyAlias}&facilityAlias=${facilityAlias}`;\r\n menuItems.push(\r\n {\r\n href: url,\r\n target: `_blank`,\r\n label: getMenuItemLabel(`actions.zeus.monitoring`),\r\n key: `operations-menu-monitoring`\r\n });\r\n\r\n menuShortcuts[`/ m o n`] = {\r\n description: getMenuItemShortcutDescription(`actions.zeus.monitoring`),\r\n action: () => {\r\n window.open(url, `_blank`);\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`app.modelling`]) {\r\n menuItems.push({\r\n href: $state.href(`app.modelling.gisModelling`, { companyAlias, facilityAlias }),\r\n label: getMenuItemLabel(`actions.modelling`),\r\n key: `operations-menu-modelling`\r\n });\r\n menuShortcuts[`/ m o d`] = {\r\n description: getMenuItemShortcutDescription(`actions.modelling`),\r\n action: () => {\r\n $state.go(`app.modelling.gisModelling`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`app-legacy.modelling.first-response`]) {\r\n menuItems.push({\r\n href: `${vm.appSettings.mvcHostUri}${vm.appSettings.site.facility.es1RouteName}/FirstResponse/EventDetails`,\r\n target: `_blank`,\r\n label: getMenuItemLabel(`actions.firstResponseModelling`),\r\n key: `operations-menu-first-response-modelling`\r\n });\r\n }\r\n\r\n if (accessControls[`app.blasting`]) {\r\n menuItems.push({\r\n href: $state.href(`app.blasting.scenarios`, { companyAlias, facilityAlias }),\r\n label: getMenuItemLabel(`actions.blasting`),\r\n key: `operations-menu-blasting`\r\n });\r\n menuShortcuts[`/ b l a s t`] = {\r\n description: getMenuItemShortcutDescription(`actions.blasting`),\r\n action: () => {\r\n $state.go(`app.blasting.scenarios`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`app.modelling.trajectory`]) {\r\n menuItems.push({\r\n href: $state.href(`app.modelling.trajectory.runs`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`actions.trajectories`),\r\n key: `operations-menu-trajectories`\r\n });\r\n }\r\n\r\n if (accessControls[`app.reports`]) {\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.reporting`, { companyAlias, facilityAlias }),\r\n label: getMenuItemLabel(`actions.reports`),\r\n key: `operations-menu-reports`\r\n });\r\n }\r\n\r\n return menuItems;\r\n }\r\n\r\n function getIncidentIntelligenceMenuItems(accessControls, companyAlias, facilityAlias) {\r\n let menuItems = [];\r\n\r\n if (!accessControls || appSettings.isGuestUser) {\r\n return menuItems;\r\n }\r\n\r\n if (accessControls[`app.incident-intelligence`]) {\r\n\r\n if (appSettings.site.facility.ticketingSystem) {\r\n menuItems.push({\r\n href: appSettings.site.facility.ticketingSystem.ticketsUrl,\r\n target: `_blank`,\r\n label: getMenuItemLabel(`incidentIntelligence.ticketingSystem`),\r\n key: `operations-menu-ticketing-system`\r\n });\r\n }\r\n\r\n menuItems = menuItems.concat([\r\n {\r\n href: $state.href(`app.incidentIntelligence.tickets.summary.cluster`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`incidentIntelligence.summaryCluster`),\r\n key: `operations-menu-cluster-map`\r\n },\r\n {\r\n href: $state.href(`app.incidentIntelligence.tickets.summary.heat`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`incidentIntelligence.summaryHeat`),\r\n key: `operations-menu-heat-map`\r\n }]\r\n );\r\n\r\n menuShortcuts[`/ i n c`] = {\r\n description: getMenuItemShortcutDescription(`incidentIntelligence`),\r\n action: () => {\r\n $state.go(`app.incidentIntelligence.tickets.summary.cluster`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n return menuItems;\r\n }\r\n\r\n function getConfigurationMenuItems(accessControls, companyAlias, facilityAlias) {\r\n const menuItems = [];\r\n if (!accessControls || !accessControls[`app.config`]) {\r\n return menuItems;\r\n }\r\n\r\n if (accessControls[`app.modelling.run-aermod-modelling`]) {\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.configuration.company.modelling.aermet`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`configuration.modelling.aermet`),\r\n key: `operations-menu-modelling-aermet`\r\n }\r\n );\r\n }\r\n\r\n if (accessControls[`app.config.modelling`]) {\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.configuration.company.modelling.models`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`configuration.modelling.models`),\r\n key: `operations-menu-modelling-models`\r\n }\r\n );\r\n\r\n menuShortcuts[`/ c m o d`] = {\r\n description: getMenuItemShortcutDescription(`configuration.modelling`),\r\n action: () => {\r\n $state.go(`app.configuration.company.modelling.models`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n\r\n menuShortcuts[`/ r m o d`] = {\r\n visible: false,\r\n description: getMenuItemShortcutDescription(`configuration.modelling.modelRuns`),\r\n action: () => {\r\n $state.go(`app.configuration.system.modelling.modelRuns`);\r\n }\r\n };\r\n\r\n if (accessControls[`app.config.modelling.run-models`]) {\r\n\r\n menuItems.push(\r\n {\r\n href: `${vm.appSettings.mvcHostUri}${vm.appSettings.site.facility.es1RouteName}/plume/getmodelstatus`,\r\n target: `_blank`,\r\n label: getMenuItemLabel(`configuration.modelling.model-status`),\r\n key: `operations-menu-modelling-model-status`\r\n }\r\n );\r\n\r\n menuShortcuts[`/ x m a s`] = {\r\n description: getMenuItemShortcutDescription(`configuration.modelling.model-status`),\r\n action: () => {\r\n $window.location.href = `${vm.appSettings.mvcHostUri}${vm.appSettings.site.facility.es1RouteName}/plume/getmodelstatus`;\r\n }\r\n };\r\n }\r\n }\r\n\r\n if (accessControls[`app.config.modelling.emission-data`]) {\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.configuration.company.modelling.emissionsData`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`configuration.modelling.emissionsData`),\r\n key: `operations-menu-modelling-emissions-data`\r\n }\r\n );\r\n }\r\n\r\n if (accessControls[`app.config.monitoring`]) {\r\n menuItems.push({});\r\n\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.configuration.company.monitoring.monitors`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`configuration.monitoring.monitors`),\r\n key: `operations-menu-monitoring-monitors`\r\n }\r\n );\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.configuration.company.monitoring.measurementGroups`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`configuration.monitoring.measurementGroups`),\r\n key: `operations-menu-monitoring-measurement-groups`\r\n }\r\n );\r\n\r\n menuShortcuts[`/ c m o n`] = {\r\n description: getMenuItemShortcutDescription(`configuration.monitoring`),\r\n action: () => {\r\n $state.go(`app.configuration.company.monitoring.monitors`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`app.config.annotations.monitor-pollutants`]) {\r\n menuItems.push({});\r\n\r\n menuItems.push(\r\n {\r\n href: $state.href(`app.configuration.company.annotations.monitorPollutants`, {\r\n companyAlias,\r\n facilityAlias\r\n }),\r\n label: getMenuItemLabel(`configuration.annotations.monitor-pollutants`),\r\n key: `operations-menu-annotations-monitor-pollutants`\r\n }\r\n );\r\n\r\n menuShortcuts[`/ c a m p`] = {\r\n description: getMenuItemShortcutDescription(`configuration.annotations.monitor-pollutants`),\r\n action: () => {\r\n $state.go(`app.configuration.company.annotations.monitorPollutants`, { companyAlias, facilityAlias });\r\n }\r\n };\r\n }\r\n\r\n if (accessControls[`app-legacy.mailer`]) {\r\n menuItems.push({});\r\n menuItems.push(\r\n {\r\n href: `${vm.appSettings.mvcHostUri}${vm.appSettings.site.facility.es1RouteName}/Admin/Mailer`,\r\n label: getMenuItemLabel(`configuration.reporting.mailers`),\r\n key: `operations-menu-reporting-mailers`\r\n }\r\n );\r\n }\r\n\r\n return menuItems;\r\n }\r\n\r\n function getMenuItemLabel(menuItem) {\r\n return i18n.i10n(`app.ui.core.layout.shell.navigation.menu.submenu.${menuItem}.label`);\r\n }\r\n\r\n function getMenuItemShortcutDescription(menuItem) {\r\n return i18n.i10n(`app.ui.core.layout.shell.navigation.menu.submenu.${menuItem}.shortcut`);\r\n }\r\n\r\n function logout() {\r\n return securityService.logout();\r\n }\r\n\r\n let isAttached;\r\n\r\n /* istanbul ignore next */\r\n function calculateOperationsMenuHeight() {\r\n $timeout(() => {\r\n const dropdownMenu = $(`.open .dropdown-menu-large`);\r\n if (!dropdownMenu.length) {\r\n return;\r\n }\r\n\r\n if (!isAttached) {\r\n dropdownMenu.on(`click`, () => $(`.navbar-toggle`).click());\r\n isAttached = true;\r\n }\r\n\r\n const scrollHeight = window.innerWidth < 768\r\n ? window.innerHeight - dropdownMenu.offset().top - $(`#shell-view-header`).height()\r\n : `inherit`;\r\n\r\n dropdownMenu.height(scrollHeight);\r\n });\r\n }\r\n\r\n function shouldShowOperationsMenu() {\r\n try {\r\n const params = new URLSearchParams(window.location.search);\r\n const from = params.get(`from`);\r\n if (from !== `omnis`) { return true; }\r\n return false;\r\n } catch(error) {\r\n console.error(error);\r\n return true;\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapCenter`, esMapCentre)\r\n .controller(`esMapCentreController`, esMapCentreController);\r\n\r\n function esMapCentre() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n defaultCentre: `=`,\r\n centre: `=`,\r\n bounds: `=?`\r\n },\r\n replace: true,\r\n bindToController: true,\r\n controller: esMapCentreController,\r\n controllerAs: `vm`\r\n };\r\n }\r\n\r\n esMapCentreController.$inject = [`$scope`, `esLeafletData`, `leafletLib`, `i18n`, `$timeout`, `google`, `lodash`];\r\n function esMapCentreController($scope, esLeafletData, L, i18n, $timeout, google, _) {\r\n const vm = this;\r\n const originalCentre = angular.merge({}, vm.defaultCentre);\r\n\r\n activate();\r\n\r\n ////////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId)\r\n .then(addControl)\r\n .then(fitMapToBounds);\r\n }\r\n\r\n function addControl(map) {\r\n\r\n const control = new L.Control.EasyButtons({\r\n icon: `fa-crosshairs`,\r\n title: i18n.i10n(`esMapCentre.button.tooltip`),\r\n click: onClick\r\n });\r\n\r\n map.addControl(control);\r\n control.enable();\r\n\r\n map.on(`dragend`, areCentresInSync);\r\n map.on(`zoomend`, areCentresInSync);\r\n $scope.$watch(() => vm.centre, areCentresInSync);\r\n\r\n return map;\r\n\r\n //////////////\r\n\r\n function onClick() {\r\n control.setActive();\r\n fitBounds(map);\r\n }\r\n\r\n function areCentresInSync() {\r\n if (latLngMatch(vm.centre, originalCentre)) {\r\n control.setActive();\r\n } else {\r\n control.setInactive();\r\n }\r\n }\r\n }\r\n\r\n function fitMapToBounds(map) {\r\n const googleLayer = _.find(map._layers, layer => layer._google);\r\n if (googleLayer) {\r\n google.maps.event.addListenerOnce(googleLayer._google, `idle`, zoomToExtents);\r\n } else {\r\n // Get the first tile layer and setup trigger event on loaded.\r\n let firstTileLayer;\r\n map.eachLayer(function(layer) {\r\n if (!firstTileLayer && layer instanceof L.TileLayer) {\r\n firstTileLayer = layer;\r\n }\r\n });\r\n\r\n if (firstTileLayer) {\r\n firstTileLayer.on(`load`, zoomToExtents);\r\n }\r\n }\r\n\r\n //////////////\r\n\r\n function zoomToExtents() {\r\n const unwatch = $scope.$watch(() => vm.bounds, () => {\r\n if (!vm.bounds || !vm.bounds.length) {\r\n return;\r\n }\r\n unwatch();\r\n if (!vm.centre || latLngMatch(vm.centre, vm.defaultCentre)) {\r\n fitBounds(map);\r\n }\r\n });\r\n }\r\n };\r\n\r\n function latLngMatch(current, original) {\r\n if (!(current && current.lat && current.lng && original && original.lat && original.lng)) {\r\n return false;\r\n }\r\n\r\n if (current.lat.toFixed(6) !== original.lat.toFixed(6)) {\r\n return false;\r\n }\r\n if (current.lng.toFixed(6) !== original.lng.toFixed(6)) {\r\n return false;\r\n }\r\n return current.zoom === original.zoom;\r\n\r\n }\r\n\r\n function fitBounds(map) {\r\n if (vm.bounds && vm.bounds.length) {\r\n map.fitBounds(vm.bounds);\r\n } else {\r\n map.setView(vm.defaultCentre, vm.defaultCentre.zoom);\r\n }\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .component(`esMapCluster`, {\r\n controller: esMapCluster,\r\n bindings: {\r\n mapId: `@`,\r\n models: `<`,\r\n onclick: `=`\r\n }\r\n });\r\n\r\n esMapCluster.$inject = [`lodash`, `leafletLib`, `esLeafletData`];\r\n\r\n function esMapCluster(_, L, esLeafletData) {\r\n const vm = this;\r\n let clusterGroup;\r\n let mapReady;\r\n\r\n vm.$onInit = () => {\r\n mapReady = esLeafletData.getMap(vm.mapId);\r\n mapReady.then(renderClusters);\r\n };\r\n\r\n vm.$onChanges = changes => {\r\n if (changes.models && mapReady) {\r\n mapReady.then(map => {\r\n clearLayers();\r\n renderClusters(map);\r\n });\r\n }\r\n };\r\n\r\n vm.$onDestroy = () => {\r\n clearLayers();\r\n };\r\n\r\n /////////////////////\r\n\r\n function renderClusters(map) {\r\n clusterGroup = L.markerClusterGroup(\r\n {\r\n iconCreateFunction: cluster => getClusterIcon(cluster.getChildCount()),\r\n chunkedLoading: true,\r\n polygonOptions: { className: `cluster-area` }\r\n });\r\n\r\n const markers = _.map(vm.models, model => {\r\n const marker = L.marker(L.latLng(model.lat, model.long), { icon: getMarkerIcon(), riseOnHover: true });\r\n marker.bindTooltip(model.tooltip);\r\n if (vm.onclick) {\r\n marker.on(`click`, e => {\r\n if (model.isToggleMarker) {\r\n let icon = {};\r\n if (model.isSelected) {\r\n icon = getMarkerIcon();\r\n } else {\r\n icon = getSelectedMarkerIcon();\r\n }\r\n model.isSelected = !model.isSelected;\r\n e.target.setIcon(icon);\r\n }\r\n vm.onclick && vm.onclick(model);\r\n });\r\n }\r\n return marker;\r\n });\r\n\r\n clusterGroup.addLayers(markers);\r\n map.addLayer(clusterGroup);\r\n }\r\n\r\n function clearLayers() {\r\n if (clusterGroup) {\r\n clusterGroup.clearLayers();\r\n }\r\n }\r\n\r\n function getMarkerIcon() {\r\n return L.AwesomeMarkers.icon({\r\n prefix: `fa`,\r\n icon: `bell-o`,\r\n markerColor: `orange`\r\n });\r\n }\r\n\r\n function getSelectedMarkerIcon() {\r\n return L.AwesomeMarkers.icon({\r\n prefix: `fa`,\r\n icon: `bell`,\r\n markerColor: `orange`\r\n });\r\n }\r\n\r\n function getClusterIcon(childCount) {\r\n const clusterSize = `marker-cluster-${childCount < 10 ? `small` : childCount < 100 ? `medium` : `large`}`;\r\n return new L.DivIcon({\r\n html: `
        ${childCount}
        `,\r\n className: `marker-cluster ${clusterSize}`,\r\n iconSize: new L.Point(40, 40)\r\n });\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapCredits`, esMapCredits)\r\n .controller(`esMapCreditsController`, esMapCreditsController);\r\n\r\n function esMapCredits() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`\r\n },\r\n bindToController: true,\r\n controller: esMapCreditsController,\r\n controllerAs: `vm`\r\n };\r\n }\r\n\r\n esMapCreditsController.$inject = [\r\n `$scope`,\r\n `$modal`,\r\n `leafletLib`,\r\n `esLeafletData`,\r\n `browserStorage`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.services.mappingService`,\r\n `app.core.appSettings`\r\n ];\r\n\r\n function esMapCreditsController($scope, $modal, L, esLeafletData, browserStorage, _, i18n, mappingService, appSettings) {\r\n const vm = this;\r\n const storageKey = `map-credits`;\r\n const storageBucketKey = `${appSettings.site.facility.alias}-${appSettings.userId}`;\r\n\r\n activate();\r\n\r\n ///////\r\n\r\n function activate() {\r\n mappingService.getMapCredits().then(mapCredits => {\r\n if (!_.size(mapCredits)) {\r\n return;\r\n }\r\n\r\n const control = new L.es.MapCredits();\r\n\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n control.addTo(map);\r\n\r\n processCredits(control, mapCredits);\r\n });\r\n });\r\n }\r\n\r\n function processCredits(control, mapCredits) {\r\n mapCredits.forEach(mapCredit => {\r\n const text = mapCredit.text;\r\n let popupFunction = null;\r\n if (text) {\r\n const textVersion = mapCredit.textVersion;\r\n popupFunction = () => showCreditText(text, textVersion);\r\n\r\n if (!hasDismissedText(textVersion)) {\r\n showCreditText(text, textVersion);\r\n }\r\n }\r\n const imageUrl = `data:${mapCredit.logoMimeType};base64,${mapCredit.logoData}`;\r\n control.addCredit(imageUrl, popupFunction);\r\n });\r\n }\r\n\r\n function hasDismissedText(textVersion) {\r\n const storedTextVersion = browserStorage.getBucket(storageKey, storageBucketKey);\r\n return storedTextVersion === textVersion;\r\n }\r\n\r\n function dismissVersion(textVersion) {\r\n browserStorage.persistBucket(storageKey, storageBucketKey, textVersion);\r\n }\r\n\r\n function showCreditText(text, textVersion) {\r\n const newScope = $scope.$new(true);\r\n newScope.text = text;\r\n newScope.title = i18n.i10n(`esMapCredits.dialog.title`);\r\n const modalInstance = $modal.open({\r\n templateUrl: `/App/ui/core/mapping/controls/esMapCreditsDialog.html`,\r\n animation: false, // a bug means the backdrop stays when animations are on :(.\r\n size: `modal-lg`,\r\n scope: newScope\r\n });\r\n\r\n modalInstance.result.catch(() => dismissVersion(textVersion));\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapDomainBoundaries`, directive)\r\n .controller(`esMapDomainBoundariesController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n boundaries: `=?`,\r\n showModelling: `=`,\r\n showBlasting: `=`,\r\n showIncidentIntelligence: `=`\r\n },\r\n bindToController: true,\r\n controller: controller,\r\n controllerAs: `vm`\r\n };\r\n }\r\n\r\n controller.$inject = [`$q`, `esLeafletData`, `leafletLib`, `i18n`, `app.core.services.companyService`];\r\n\r\n function controller($q, esLeafletData, L, i18n, companyService) {\r\n const vm = this;\r\n let layerGroup = null;\r\n let isActive = false;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n const mapPromise = esLeafletData.getMap(vm.mapId);\r\n const boundariesPromise = companyService.getDomainBoundaries(!!vm.showModelling, !!vm.showBlasting, !!vm.showIncidentIntelligence);\r\n\r\n $q.all([mapPromise, boundariesPromise]).then(results => addControl(...results));\r\n }\r\n\r\n function addControl(map, boundaries) {\r\n vm.boundaries = boundaries;\r\n\r\n const control = createToggleButtonAndAddToMap();\r\n buildLayerGroup();\r\n toggleDomainBoundaries();\r\n\r\n ////////////////////\r\n\r\n function createToggleButtonAndAddToMap() {\r\n const easyButton = new L.Control.EasyButtons({\r\n icon: `fa-clone`,\r\n title: i18n.i10n(`esMapDomainBoundaries.button.tooltip`),\r\n click: toggleDomainBoundaries\r\n });\r\n\r\n map.addControl(easyButton);\r\n easyButton.enable();\r\n\r\n return easyButton;\r\n }\r\n\r\n function buildLayerGroup() {\r\n layerGroup = new L.LayerGroup();\r\n\r\n if (!(vm.boundaries && vm.boundaries.length)) {\r\n return;\r\n }\r\n\r\n const lineOptions = {\r\n color: `#1ba6d5`, // = @es-highlight\r\n opacity: 1,\r\n weight: 2,\r\n dashArray: `2,3`\r\n };\r\n\r\n vm.boundaries.forEach(boundary => {\r\n const bottomRight = new L.LatLng(boundary.bottomRight.latitude, boundary.bottomRight.longitude);\r\n const bottomLeft = new L.LatLng(boundary.bottomLeft.latitude, boundary.bottomLeft.longitude);\r\n const topRight = new L.LatLng(boundary.topRight.latitude, boundary.topRight.longitude);\r\n const topLeft = new L.LatLng(boundary.topLeft.latitude, boundary.topLeft.longitude);\r\n\r\n const firstPolyline = new L.Polyline([bottomLeft, bottomRight], lineOptions);\r\n const secondPolyline = new L.Polyline([bottomLeft, topLeft], lineOptions);\r\n const thirdPolyline = new L.Polyline([topLeft, topRight], lineOptions);\r\n const fourthPolyline = new L.Polyline([topRight, bottomRight], lineOptions);\r\n\r\n layerGroup.addLayer(firstPolyline);\r\n layerGroup.addLayer(secondPolyline);\r\n layerGroup.addLayer(thirdPolyline);\r\n layerGroup.addLayer(fourthPolyline);\r\n });\r\n }\r\n\r\n function toggleDomainBoundaries() {\r\n if (isActive) {\r\n control.setInactive();\r\n map.removeLayer(layerGroup);\r\n\r\n } else {\r\n control.setActive();\r\n layerGroup.addTo(map);\r\n }\r\n\r\n isActive = !isActive;\r\n }\r\n }\r\n }\r\n})();\r\n","(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapEmissionSources`, esMapEmissionSources)\r\n .controller(`esMapEmissionSourcesController`, esMapEmissionSourcesController);\r\n\r\n function esMapEmissionSources() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`\r\n },\r\n templateUrl: `/App/ui/core/mapping/controls/esMapEmissionSources.html`,\r\n controller: esMapEmissionSourcesController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esMapEmissionSourcesController.$inject = [\r\n `leafletLib`,\r\n `esLeafletData`,\r\n `app.core.services.mappingService`\r\n ];\r\n\r\n function esMapEmissionSourcesController(L, esLeafletData, mappingService) {\r\n const vm = this;\r\n const layerGroup = new L.LayerGroup();\r\n let map;\r\n\r\n vm.isVisible = true;\r\n vm.hasSources = true;\r\n vm.toggleSources = toggleSources;\r\n\r\n esLeafletData.getMap(vm.mapId).then(leafletMap => {\r\n map = leafletMap;\r\n activate();\r\n });\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n loadSourcesOverlay();\r\n }\r\n\r\n function toggleSources() {\r\n if (vm.isVisible) {\r\n layerGroup.addTo(map);\r\n }\r\n else {\r\n map.removeLayer(layerGroup);\r\n }\r\n }\r\n\r\n function loadSourcesOverlay() {\r\n mappingService.getEmissionSourceKml()\r\n .then(kml => {\r\n if (kml === null) {\r\n vm.hasSources = false;\r\n return;\r\n }\r\n\r\n const kmlLayer = new L.KML(null, {\r\n async: true,\r\n autoPan: false\r\n });\r\n\r\n const parser = new DOMParser();\r\n const xmlDoc = parser.parseFromString(kml.data, `text/xml`);\r\n kmlLayer._addKML(xmlDoc);\r\n layerGroup.addLayer(kmlLayer);\r\n layerGroup.addTo(map);\r\n });\r\n }\r\n }\r\n})();\r\n","`use strict`;\n\n(function () {\n angular\n .module(`app.ui.core`)\n .component(`esMapHeatMap`, {\n controller: esMapHeatMapController,\n bindings: {\n mapId: `@`,\n models: `<`\n }\n });\n\n esMapHeatMapController.$inject = [`$timeout`, `lodash`, `leafletLib`, `esLeafletData`];\n function esMapHeatMapController($timeout, _, L, esLeafletData) {\n const vm = this;\n vm.points = [];\n let heatLayer;\n let mapReady;\n let retryCount = 0;\n\n vm.$onInit = () => {\n mapReady = esLeafletData.getMap(vm.mapId);\n mapReady.then(renderClusters);\n };\n\n vm.$onChanges = changes => {\n if (changes.models && mapReady) {\n mapReady.then(map => {\n clearLayers(map);\n renderClusters(map);\n });\n }\n };\n\n vm.$onDestroy = () => {\n if (mapReady) {\n mapReady.then(clearLayers);\n }\n };\n\n ////////////////\n\n function clearLayers() {\n if (heatLayer) {\n heatLayer.setLatLngs([]);\n }\n }\n\n function renderClusters(map) {\n if (map.getSize().y === 0 && retryCount < 10) { // workaround for a bug where the map is not yet ready.\n $timeout(() => {\n retryCount++;\n renderClusters(map);\n }, 100);\n }\n else {\n retryCount = 0;\n const points = _.map(vm.models, point => [point.lat, point.long, 1]);\n if (!heatLayer) {\n heatLayer = L.heatLayer(points);\n heatLayer.setOptions({ radius: 25, max: 1, minOpacity: 0.1, maxZoom: 15 });\n map.addLayer(heatLayer);\n }\n else {\n heatLayer.setLatLngs(points);\n }\n }\n }\n }\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapInfluenceArcs`, esMapInfluenceArcDirective)\r\n .controller(`esMapInfluenceArcsController`, esMapInfluenceArcsController);\r\n\r\n function esMapInfluenceArcDirective() {\r\n return {\r\n restrict: `E`,\r\n require: `esLeaflet`,\r\n scope: {\r\n mapId: `@`,\r\n influenceArcs: `=`\r\n },\r\n controller: esMapInfluenceArcsController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esMapInfluenceArcsController.$inject = [`$scope`, `leafletLib`, `esLeafletData`];\r\n function esMapInfluenceArcsController($scope, L, esLeafletData) {\r\n\r\n const vm = this;\r\n const leafletArcs = {};\r\n\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n\r\n $scope.$watch(() => vm.influenceArcs, arcs => {\r\n\r\n if (!arcs) {\r\n return;\r\n }\r\n\r\n esLeafletData.getLayers().then(layers => {\r\n\r\n for (let i = 0; i < arcs.length; i++) {\r\n const influenceArc = arcs[i];\r\n if (!influenceArc) {\r\n continue;\r\n }\r\n\r\n let influenceArcPolygon = leafletArcs[influenceArc.monitorId];\r\n const layerGroup = layers.overlays[`influenceArcs-` + influenceArc.monitorType];\r\n\r\n if (influenceArc.unrender) {\r\n if (influenceArcPolygon) {\r\n layerGroup.removeLayer(influenceArcPolygon);\r\n delete leafletArcs[influenceArc.monitorId];\r\n }\r\n continue;\r\n }\r\n\r\n if (influenceArcPolygon) {\r\n influenceArcPolygon.update(influenceArc);\r\n } else {\r\n influenceArcPolygon = L.es.influenceArcs(map, influenceArc);\r\n leafletArcs[influenceArc.monitorId] = influenceArcPolygon;\r\n layerGroup.addLayer(influenceArcPolygon);\r\n }\r\n influenceArcPolygon.bringToBack();\r\n }\r\n });\r\n });\r\n });\r\n }\r\n\r\n})();","/* istanbul ignore next */\n(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esMapKml`, directive)\n .controller(`esMapKmlController`, controller);\n\n function directive() {\n return {\n restrict: `E`,\n scope: {\n mapId: `@`,\n overlayProvider: `=`,\n showControls: `=`,\n interactive: `=?`\n },\n replace: true,\n bindToController: true,\n controller: controller,\n controllerAs: `vm`\n };\n }\n\n controller.$inject = [`$scope`, `leafletLib`, `esLeafletData`, `i18n`, `lodash`];\n\n function controller($scope, L, esLeafletData, i18n, _) {\n const vm = this;\n const layerGroup = new L.FeatureGroup();\n\n let map;\n let isShowing = false;\n\n const layerToggleControl = new L.Control.EasyButtons({\n icon: `fa-pencil-square-o`,\n title: i18n.i10n(`esMapKml.button.tooltip`),\n click: toggleLayerGroup\n });\n\n esLeafletData.getMap(vm.mapId).then(leafletMap => {\n map = leafletMap;\n activate();\n });\n\n ////////////////////\n\n function activate() {\n if (_.isUndefined(vm.interactive) || _.isNull(vm.interactive)) {\n vm.interactive = true;\n }\n\n showLayerToggleControlWhenShowControlsRequested();\n renderOverlaysWhenOverlaySourceChanges();\n }\n\n function showLayerToggleControlWhenShowControlsRequested() {\n $scope.$watch(() => vm.showControls, showControls => {\n const isAddedToMap = layerToggleControl._map;\n\n if (showControls && !isAddedToMap) {\n map.addControl(layerToggleControl);\n\n } else if (!showControls && isAddedToMap) {\n map.removeControl(layerToggleControl);\n }\n });\n }\n\n function renderOverlaysWhenOverlaySourceChanges() {\n $scope.$watchCollection(() => vm.overlayProvider, renderOverlays);\n\n function renderOverlays(overlayProvider) {\n layerGroup.clearLayers();\n layerToggleControl.setInactive();\n layerToggleControl.disable();\n\n if (!overlayProvider || _.isEmpty(overlayProvider)) {\n return;\n }\n\n layerToggleControl.enable();\n layerToggleControl.setActive();\n\n _.forEach(overlayProvider, kml => {\n const kmlLayer = new L.KML(null, {\n async: true,\n autoPan: false\n });\n\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(kml.data, `text/xml`);\n kmlLayer._addKML(xmlDoc);\n layerGroup.addLayer(kmlLayer);\n\n kmlLayer.on(`click`, onKmlLayerClicked);\n });\n\n if (!isShowing) {\n toggleLayerGroup();\n }\n }\n }\n\n function onKmlLayerClicked(evnt) {\n if (vm.interactive) {\n return;\n }\n\n evnt.layer.closePopup();\n\n // Since the user has clicked on a KML image (i.e. a marker), leaflet always sets the lat/lng of the event\n // to the lat/long of the marker. However, when we are in `non-interactive` mode, we want to pass-through\n // the event at the ACTUAL lat/lng of the mouse click. As such, we need to calculate where this is based\n // on the point that the user has clicked.\n //\n // To do this, we emulate (read: `copy`) the way that the leaflet Map fires mouse events (see\n // `_fireMouseEvent` in the L.map class for details).\n //\n // Note: Once we upgrade to Leaflet 1.0.0 (when it gets released), we should be able to achieve this\n // by simply making the marker non-interactive - see: http://mourner.github.io/Leaflet/reference.html#marker\n const originalEvent = evnt.originalEvent;\n\n const containerPoint = map.mouseEventToContainerPoint(originalEvent);\n const layerPoint = map.containerPointToLayerPoint(containerPoint);\n const latlng = map.layerPointToLatLng(layerPoint);\n\n map.fire(`click`, {\n latlng,\n layerPoint,\n containerPoint,\n originalEvent\n });\n\n }\n\n function toggleLayerGroup() {\n if (isShowing) {\n map.removeLayer(layerGroup);\n layerToggleControl.setInactive();\n\n } else {\n layerGroup.addTo(map);\n layerToggleControl.setActive();\n }\n\n isShowing = !isShowing;\n }\n }\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapLocationSelector`, directive)\r\n .controller(`esMapLocationSelectorController`, controller);\r\n\r\n directive.$inject = [\r\n `lodash`,\r\n `esLeafletData`\r\n ];\r\n\r\n function directive(_, esLeafletData) {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n latitude: `=`,\r\n longitude: `=`,\r\n isActive: `=`,\r\n boundaries: `=?`,\r\n icon: `@`,\r\n markerColor: `@`\r\n },\r\n link: link,\r\n bindToController: true,\r\n controller: controller,\r\n controllerAs: `vm`\r\n };\r\n\r\n function link($scope, $element) {\r\n const vm = $scope.vm;\r\n const targetingClassName = `map-location-selector-active`;\r\n const outOfBoundsClassName = `map-location-selector-out-of-bounds`;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n let unregisterOutOfBoundsWatcher = null;\r\n let wasInBounds;\r\n\r\n $scope.$watch(() => vm.isActive, addTargetingCssClassWhenTargeting);\r\n\r\n ////////////////////\r\n\r\n function addTargetingCssClassWhenTargeting(isTargeting) {\r\n const $map = $element.closest(`.angular-leaflet-map`);\r\n\r\n if (isTargeting) {\r\n $map.addClass(targetingClassName);\r\n\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n unregisterOutOfBoundsWatcher = addOutOfBoundsCssClassWhenOutOfBounds($map, map);\r\n });\r\n\r\n } else {\r\n $map.removeClass(targetingClassName);\r\n $map.removeClass(outOfBoundsClassName);\r\n\r\n if (unregisterOutOfBoundsWatcher) {\r\n unregisterOutOfBoundsWatcher();\r\n unregisterOutOfBoundsWatcher = null;\r\n }\r\n }\r\n }\r\n\r\n function addOutOfBoundsCssClassWhenOutOfBounds($map, map) {\r\n const boundaries = vm.boundaries;\r\n if (!(boundaries && boundaries.length)) {\r\n return null;\r\n }\r\n\r\n map.on(`mousemove`, onMouseMoved);\r\n\r\n return () => {\r\n wasInBounds = null;\r\n map.off(`mousemove`, onMouseMoved);\r\n };\r\n\r\n ////////////////////\r\n\r\n function onMouseMoved(evnt) {\r\n const location = evnt.latlng;\r\n const isInBounds = !!_.find(boundaries, boundary => boundary.contains(location.lat, location.lng));\r\n\r\n // coerce isInBounds to a boolean, otherwise we could be comparing two undefined values.\r\n if (wasInBounds === isInBounds) {\r\n return;\r\n }\r\n\r\n if (isInBounds) {\r\n $map.removeClass(outOfBoundsClassName);\r\n\r\n } else {\r\n $map.addClass(outOfBoundsClassName);\r\n }\r\n\r\n wasInBounds = isInBounds;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n controller.$inject = [`$scope`, `esLeafletData`, `leafletLib`, `i18n`];\r\n\r\n function controller($scope, esLeafletData, L, i18n) {\r\n const vm = this;\r\n\r\n let marker = null;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n addControl(map);\r\n moveMarkerWhenLocationChanges(map);\r\n });\r\n }\r\n\r\n function addControl(map) {\r\n const control = new L.Control.EasyButtons({\r\n icon: `fa-map-marker`,\r\n title: i18n.i10n(`esMapLocationSelector.button.tooltip`),\r\n click: toggleTargetting\r\n });\r\n\r\n map.addControl(control);\r\n control.enable();\r\n\r\n //////////////\r\n\r\n function toggleTargetting() {\r\n const shouldEnableTargetting = !vm.isActive;\r\n\r\n if (shouldEnableTargetting) {\r\n enableTargetting();\r\n\r\n } else {\r\n disableTargetting();\r\n }\r\n }\r\n\r\n function enableTargetting() {\r\n control.setActive();\r\n map.on(`click`, onLocationSelected);\r\n\r\n vm.isActive = true;\r\n }\r\n\r\n function disableTargetting() {\r\n control.setInactive();\r\n map.off(`click`, onLocationSelected);\r\n\r\n vm.isActive = false;\r\n }\r\n\r\n function onLocationSelected(e) {\r\n const latLng = e.latlng;\r\n vm.latitude = latLng.lat;\r\n vm.longitude = latLng.lng;\r\n\r\n disableTargetting();\r\n }\r\n }\r\n\r\n function moveMarkerWhenLocationChanges(map) {\r\n const watches = [\r\n () => vm.latitude,\r\n () => vm.longitude\r\n ];\r\n\r\n $scope.$watchGroup(watches, onLocationChanged);\r\n\r\n ////////////////////\r\n\r\n function onLocationChanged(location) {\r\n const [latitude, longitude] = location;\r\n\r\n if (!(latitude && longitude)) {\r\n if (marker !== null) {\r\n map.removeLayer(marker);\r\n marker = null;\r\n }\r\n\r\n return;\r\n }\r\n\r\n if (!marker) {\r\n const icon = new L.AwesomeMarkers.Icon({\r\n prefix: `fa`,\r\n icon: vm.icon,\r\n markerColor: vm.markerColor\r\n });\r\n\r\n marker = new L.Marker([latitude, longitude], {\r\n icon,\r\n clickable: false,\r\n keyboard: false\r\n });\r\n\r\n marker.addTo(map);\r\n\r\n } else {\r\n marker.setLatLng(new L.LatLng(latitude, longitude));\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapReady`, esMapReady)\r\n .controller(`esMapReadyController`, esMapReadyController);\r\n\r\n function esMapReady() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n isReady: `=?`\r\n },\r\n bindToController:true,\r\n controller: esMapReadyController,\r\n controllerAs: `vm`,\r\n template : `
        `\r\n };\r\n }\r\n\r\n esMapReadyController.$inject = [`$scope`, `$timeout`, `$log`, `google`, `lodash`, `esLeafletData`, `leafletLib`];\r\n function esMapReadyController($scope, $timeout, $log, google, _, esLeafletData, L) {\r\n const vm = this;\r\n vm.isMapIdle = false;\r\n vm.isMapReady = false;\r\n vm.isReady = vm.isReady !== undefined ? vm.isReady : true;\r\n\r\n activate();\r\n\r\n ////////////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n const googleLayer = _.find(map._layers, layer => layer._google);\r\n\r\n // $timeouts() are to update the values within the angular digest cycle\r\n if (googleLayer) {\r\n google.maps.event.addListenerOnce(googleLayer._google, `tilesloaded`, () => {\r\n $timeout(() => vm.mapTilesLoaded = true);\r\n });\r\n\r\n google.maps.event.addListenerOnce(googleLayer._google, `idle`, () => {\r\n $timeout(() => vm.isMapIdle = true);\r\n });\r\n } else {\r\n // Using the load event would be nicer but the esLeafletData.getMap() promise resolves *after* the\r\n // map is loaded. Fortunately the moveend event seems to work as well.\r\n map.once(`moveend`, e => {\r\n $timeout(() => vm.isMapIdle = true);\r\n });\r\n\r\n let firstTileLayer;\r\n map.eachLayer(function(layer) {\r\n if (!firstTileLayer && layer instanceof L.TileLayer) {\r\n firstTileLayer = layer;\r\n }\r\n });\r\n \r\n if (firstTileLayer) {\r\n firstTileLayer.on(`load`, () => {\r\n $timeout(() => vm.mapTilesLoaded = true);\r\n });\r\n }\r\n }\r\n\r\n $scope.$watchGroup([`vm.mapTilesLoaded`, `vm.isReady`], () => {\r\n vm.isMapReady = vm.mapTilesLoaded && vm.isReady && vm.isMapIdle;\r\n });\r\n });\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapResizer`, esMapResizer)\r\n .controller(`esMapResizerController`, esMapResizerController);\r\n\r\n function esMapResizer() {\r\n\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`\r\n },\r\n bindToController:true,\r\n controller: esMapResizerController,\r\n controllerAs: `vm`\r\n };\r\n }\r\n\r\n esMapResizerController.$inject = [`$scope`, `$log`, `lodash`, `esLeafletData`];\r\n function esMapResizerController($scope, $log, _, esLeafletData) {\r\n const vm = this;\r\n\r\n activate();\r\n\r\n ////////////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n\r\n const debounceInvalidateMap = _.debounce(invalidateMap, 50);\r\n $scope.$on(`resizePage`, debounceInvalidateMap);\r\n\r\n debounceInvalidateMap();\r\n\r\n function invalidateMap() {\r\n $log.debug(`esMapResizer: invalidating map to force redraw`);\r\n try {\r\n map.invalidateSize();\r\n } catch(ex) {\r\n // swallow\r\n }\r\n }\r\n });\r\n }\r\n }\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esMapScale`, directive)\n .controller(`esMapScaleController`, controller);\n\n function directive() {\n return {\n restrict: `E`,\n scope: {\n mapId: `@`\n },\n bindToController: true,\n controller: controller,\n controllerAs: `vm`\n };\n }\n\n controller.$inject = [\n `leafletLib`,\n `esLeafletData`\n ];\n\n function controller(L, esLeafletData) {\n const vm = this;\n\n activate();\n\n ////////////////////\n\n function activate() {\n esLeafletData.getMap(vm.mapId).then(addControl);\n }\n\n function addControl(map) {\n const control = new L.Control.Scale({\n imperial: false,\n position: `bottomright`\n });\n\n control.addTo(map);\n }\n }\n})();\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .directive(`esMapTemporalEvents`, directive);\n\n function directive() {\n return {\n restrict: `E`,\n scope: {\n mapId: `@`,\n temporalEventGroups: `=`,\n showControls: `=` // future enhancement to show a control that allows user to turn on/off geoJson at the map layer group level.\n },\n bindToController: true,\n controller: controller,\n controllerAs: `vm`\n };\n }\n\n controller.$inject = [`$scope`, `leafletLib`, `esLeafletData`, `lodash`];\n\n function controller($scope, L, esLeafletData, _) {\n const vm = this;\n const geoJsonOptions = getGeoJsonOptions();\n let map;\n let leafletLayerGroups = [];\n\n esLeafletData.getMap(vm.mapId).then(leafletMap => {\n map = leafletMap;\n activate();\n });\n\n ////////////////////\n\n function activate() {\n $scope.$watchCollection(() => vm.temporalEventGroups, () => {\n _.forEach(leafletLayerGroups, removeLeafletGeoJsonLayerGroup);\n _.forEach(vm.temporalEventGroups, createLeafletLayerGroups);\n });\n }\n\n function removeLeafletGeoJsonLayerGroup() {\n if (!(map && _.isArray(leafletLayerGroups))) {\n return;\n }\n _.forEach(leafletLayerGroups, llg => {\n map.removeLayer(llg);\n });\n leafletLayerGroups = [];\n }\n\n function createLeafletLayerGroups(eventGroup) {\n const geoJsonContentType = `geojson`;\n const kmlContentType = `kml`;\n const geoJsons = [];\n const kmls = [];\n const parser = new DOMParser();\n\n if (!(eventGroup.events && Object.keys(eventGroup.events).length) && eventGroup.fallbackContentType) {\n switch (eventGroup.fallbackContentType.toLowerCase()) {\n case kmlContentType:\n kmls.push(parser.parseFromString(eventGroup.fallbackContent, `text/xml`));\n break;\n case geoJsonContentType:\n geoJsons.push(JSON.parse(eventGroup.fallbackContent));\n break;\n }\n } else {\n _.forEach(eventGroup.events, function(temporalEvent) {\n switch (temporalEvent.contentType.toLowerCase()) {\n case kmlContentType:\n kmls.push(parser.parseFromString(temporalEvent.content, `text/xml`));\n break;\n case geoJsonContentType:\n geoJsons.push(JSON.parse(temporalEvent.content));\n break;\n }\n });\n }\n\n if (kmls.length > 0) {\n _.forEach(kmls, function(kml) {\n const kmlLayer = new L.KML(null, {\n async: true,\n autoPan: false\n });\n kmlLayer._addKML(kml);\n leafletLayerGroups.push(kmlLayer);\n kmlLayer.addTo(map);\n });\n }\n\n if (geoJsons.length > 0) {\n const leafletLayerGroup = L.geoJson(geoJsons, geoJsonOptions);\n leafletLayerGroups.push(leafletLayerGroup);\n leafletLayerGroup.addTo(map);\n }\n }\n\n function getGeoJsonOptions() {\n return {\n style: feature => feature.properties && feature.properties.style,\n onEachFeature: bindPopup,\n pointToLayer: createHtmlMarker\n };\n\n function bindPopup(feature, layer) {\n const popupContent = feature.properties && feature.properties.popupContent;\n if (popupContent) {\n layer.bindPopup(popupContent);\n }\n }\n\n function createHtmlMarker(feature, latlng) {\n const content = feature.properties && feature.properties.content;\n if (!content) {\n throw new Error(`HTML content was not provided.`);\n }\n const options = { content };\n return L.marker(latlng, { icon: L.htmlIcon(options) });\n }\n }\n }\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapTiles`, esMapTiles)\r\n .controller(`esMapTilesController`, esMapTilesController);\r\n\r\n /*\r\n * This directive adds a layer to show custom tiles that a customer provides for the maps.\r\n */\r\n esMapTiles.$inject = [];\r\n function esMapTiles() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`\r\n },\r\n replace: true,\r\n bindToController:true,\r\n controller: esMapTilesController,\r\n controllerAs: `vm`\r\n\r\n };\r\n }\r\n\r\n esMapTilesController.$inject = [`$scope`,`leafletLib`, `lodash`, `i18n`, `app.core.services.mappingService`, `app.core.appSettings`, `esLeafletData`];\r\n function esMapTilesController($scope, L, _, i18n, mappingService, appSettings, esLeafletData) {\r\n\r\n const vm = this;\r\n\r\n const tileServerUrl = `${appSettings.webApiHostUri}map/tile/{facilityCode}/{name}/{z}/{x}/{y}`;\r\n const layerGroup = L.layerGroup();\r\n const layers = [];\r\n const layerToggleControl = new L.Control.EasyButtons({\r\n icon: `fa-picture-o`,\r\n title: i18n.i10n(`esMapTiles.button.tooltip`),\r\n click: onClick\r\n });\r\n\r\n activate();\r\n\r\n ///////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n mappingService.getTileLayers().then(tileConfigs => {\r\n\r\n if (!_.size(tileConfigs)) {\r\n return;\r\n }\r\n\r\n layerGroup.addTo(map);\r\n map.addControl(layerToggleControl);\r\n layerToggleControl.enable();\r\n layerToggleControl.setActive();\r\n\r\n _.forEach(tileConfigs, config => {\r\n const layer = L.tileLayer(tileServerUrl, config);\r\n layers.push(layer);\r\n layerGroup.addLayer(layer);\r\n });\r\n });\r\n });\r\n }\r\n\r\n function onClick() {\r\n if (!!layerGroup.getLayers().length) {\r\n _.forEach(layerGroup.getLayers(), layer => layerGroup.removeLayer(layer));\r\n layerToggleControl.setInactive();\r\n } else {\r\n _.forEach(layers, layer => layerGroup.addLayer(layer));\r\n layerToggleControl.setActive();\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .directive(`esMapType`, esMapType)\r\n .controller(`esMapTypeController`, esMapTypeController);\r\n\r\n /*\r\n * This directive enables the user to toggle between terrain and street view maps.\r\n */\r\n esMapType.$inject = [];\r\n function esMapType() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n isColor: `=?`\r\n },\r\n replace: true,\r\n bindToController:true,\r\n controller: esMapTypeController,\r\n controllerAs: `vm`\r\n };\r\n }\r\n\r\n esMapTypeController.$inject = [`$scope`, `$state`, `leafletLib`, `esLeafletData`, `i18n`, `lodash`, `app.core.appSettings`];\r\n function esMapTypeController($scope, $state, L, esLeafletData, i18n, _, appSettings) {\r\n\r\n const vm = this;\r\n\r\n let mapLayer;\r\n\r\n const control = new L.Control.EasyButtons({\r\n icon: `fa-compass`,\r\n title: i18n.i10n(`esMapType.button.tooltip`),\r\n click: onClick\r\n });\r\n\r\n activate();\r\n\r\n ///////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n map.addControl(control);\r\n control.enable();\r\n control.setActive();\r\n\r\n esLeafletData.getLayers().then(layers => {\r\n mapLayer = layers.baselayers[appSettings.mapProvider] || layers.baselayers.google;\r\n toggleMapColours();\r\n });\r\n\r\n });\r\n }\r\n\r\n function onClick() {\r\n vm.isColor = !vm.isColor;\r\n toggleMapColours();\r\n }\r\n\r\n function toggleMapColours() {\r\n if (!vm.isColor) {\r\n angular.element(`body`).addClass(`grayscale-map`);\r\n } else {\r\n angular.element(`body`).removeClass(`grayscale-map`);\r\n }\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .factory(`app.ui.core.mapping.mapLayerRenderer`, mapLayerRenderer);\r\n\r\n mapLayerRenderer.$inject = [\r\n `lodash`,\r\n `i18n`,\r\n `esLeafletHelpers`,\r\n `leafletLib`,\r\n `app.core.models.mapping.dataPointType`\r\n ];\r\n\r\n function mapLayerRenderer(_, i18n, esLeafletHelpers, L, dataPointType) {\r\n const millisPerMinute = 60 * 1000;\r\n\r\n return {\r\n renderLayer,\r\n removeLayer,\r\n renderPathLayer: buildPathLayer,\r\n getColour\r\n };\r\n\r\n //////////////////\r\n\r\n function renderLayer(dataPoint) {\r\n if (dataPoint.layerGroup) {\r\n return;\r\n }\r\n\r\n dataPoint.layerGroup = new L.LayerGroup();\r\n\r\n switch (dataPoint.type) {\r\n case dataPointType.wind:\r\n buildArrowLayer(dataPoint);\r\n break;\r\n\r\n case dataPointType.plume:\r\n buildPolygonLayer(dataPoint);\r\n break;\r\n\r\n case dataPointType.path:\r\n buildPathLayer(dataPoint);\r\n break;\r\n\r\n default:\r\n throw new Error(`Rendering of ${dataPoint.type} layers has not been implemented.`);\r\n }\r\n }\r\n\r\n function removeLayer(dataPoint) {\r\n delete dataPoint.layerGroup;\r\n }\r\n\r\n function buildPolygonLayer(dataPoint) {\r\n dataPoint.data.forEach(concentration => {\r\n const color = concentration.color;\r\n\r\n concentration.polygons.forEach(polygon => {\r\n const points = polygon.map(point => new L.LatLng(point.lat, point.lng));\r\n\r\n dataPoint.layerGroup.addLayer(new L.Polygon(points, {\r\n color: color,\r\n weight: 3,\r\n opacity: 1,\r\n smoothFactor: 1\r\n }));\r\n });\r\n });\r\n }\r\n\r\n function buildArrowLayer(dataPoint) {\r\n dataPoint.data.forEach(speedRange => {\r\n const windVectors = speedRange.windVectors.filter(esLeafletHelpers.isValidPoint);\r\n const options = {\r\n color: speedRange.color,\r\n weight: 3,\r\n opacity: 0.75,\r\n smoothFactor: 1\r\n };\r\n\r\n const windArrows = windVectors.map(windVector => {\r\n return {\r\n point: new L.LatLng(windVector.lat, windVector.lng),\r\n bearing: windVector.bearing,\r\n magnitude: windVector.magnitude\r\n };\r\n });\r\n\r\n dataPoint.layerGroup.addLayer(new L.es.ArrowMultiPolyLine(windArrows, options));\r\n });\r\n }\r\n\r\n function buildPathLayer(dataPoint, isForward = true, showLabels = true) {\r\n dataPoint.layerGroup = dataPoint.layerGroup || new L.LayerGroup();\r\n\r\n dataPoint.labels = [];\r\n\r\n const sortedData = _.chain(dataPoint.data).sortBy(`timeMillis`);\r\n\r\n const latLngs = sortedData\r\n .map(pathData => {\r\n const latLng = new L.LatLng(pathData.latitude, pathData.longitude);\r\n latLng.timeMillis = pathData.timeMillis;\r\n let testLatitude = pathData.latitude + (pathData.latitudeStdDev ? pathData.latitudeStdDev : 0);\r\n let testLongitude = pathData.longitude + (pathData.longitudeStdDev ? pathData.longitudeStdDev : 0);\r\n //make sure its a valid latitude.\r\n while (testLongitude > 180) {\r\n testLongitude = testLongitude - 360;\r\n }\r\n while (testLongitude < -180) {\r\n testLongitude = testLongitude + 360;\r\n }\r\n if (testLatitude > 90) {\r\n testLatitude = 180 - testLatitude;\r\n testLongitude = testLongitude * -1;\r\n }\r\n else if (testLatitude < -90) {\r\n testLatitude = (180 + testLatitude) * -1;\r\n testLongitude = testLongitude * -1;\r\n }\r\n const latitudeDistance = latLng.distanceTo(L.latLng(testLatitude, pathData.longitude));\r\n const longitudeDistance = latLng.distanceTo(L.latLng(pathData.latitude, testLongitude));\r\n latLng.stdDevRadius = (latitudeDistance + longitudeDistance) / 2;\r\n\r\n return latLng;\r\n })\r\n .value();\r\n\r\n const polylineOptions = createPolylineOptions(dataPoint);\r\n dataPoint.layerGroup.addLayer(new L.Polyline(latLngs, polylineOptions));\r\n\r\n const startTimeMillis = (isForward ? sortedData.first() : sortedData.last()).value().timeMillis;\r\n const green = `#00ff00`;\r\n const red = `#ff0000`;\r\n const stdDevPaneName = `path-std-deviation`;\r\n const stdDevGroup = L.layerGroup([], { pane: stdDevPaneName });\r\n\r\n const stepIncrement = 100.0 / latLngs.length;\r\n\r\n latLngs.forEach((latLng, index) => {\r\n\r\n const timeOffsetMinutes = Math.abs((latLng.timeMillis - startTimeMillis) / millisPerMinute);\r\n\r\n const markerOptions = {\r\n color: getColour(green, red, index * stepIncrement / 100.0),\r\n opacity: 0.8,\r\n fillOpacity: 0.8,\r\n radius : 5\r\n };\r\n\r\n const marker = new L.Circle(latLng, markerOptions);\r\n marker.bindTooltip(i18n.i10n(`mapLayerRenderer.path.labels.timeOffset`, {\r\n sign: isForward ? `+` : `-`,\r\n offsetMinutes: timeOffsetMinutes\r\n }));\r\n dataPoint.layerGroup.addLayer(marker);\r\n\r\n if (showLabels && (index === 0 || index === latLngs.length - 1)) {\r\n dataPoint.labels.push(marker);\r\n }\r\n\r\n const next = latLngs[index + 1];\r\n if (next) {\r\n const options = {\r\n corridor: Math.max(next.stdDevRadius, 50), // min 50 meters\r\n className: stdDevPaneName,\r\n pane: stdDevPaneName\r\n };\r\n stdDevGroup.addLayer(L.corridor([latLng, next], options));\r\n }\r\n });\r\n dataPoint.layerGroup.addLayer(stdDevGroup);\r\n\r\n ////////////////////\r\n\r\n function createPolylineOptions() {\r\n const options = {\r\n color: `#111`,\r\n weight: 5,\r\n opacity: 0.7,\r\n smoothFactor: 0\r\n };\r\n\r\n return options;\r\n }\r\n }\r\n\r\n function getColour(startColour, endColour, ratio) {\r\n startColour = sanitizeColour(startColour);\r\n endColour = sanitizeColour(endColour);\r\n const r = Math.ceil(parseInt(startColour.substring(0, 2), 16) * ratio + parseInt(endColour.substring(0, 2), 16) * (1 - ratio));\r\n const g = Math.ceil(parseInt(startColour.substring(2, 4), 16) * ratio + parseInt(endColour.substring(2, 4), 16) * (1 - ratio));\r\n const b = Math.ceil(parseInt(startColour.substring(4, 6), 16) * ratio + parseInt(endColour.substring(4, 6), 16) * (1 - ratio));\r\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\r\n\r\n function sanitizeColour(colour) {\r\n if (colour.indexOf(`#`) === 0) {\r\n return colour.substring(1, 7);\r\n } else {\r\n return colour;\r\n }\r\n }\r\n\r\n function toHex(val) {\r\n val = val.toString(16);\r\n return val.length === 1 ? `0` + val : val;\r\n }\r\n }\r\n }\r\n})();\r\n\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.core`)\n .component(`esMessages`, {\n templateUrl: `/App/ui/core/messages/controls/esMessages.html`,\n controller: esMessagesController,\n controllerAs: `vm`\n });\n\n esMessagesController.$inject = [\n `$scope`,\n `lodash`,\n `app.core.models.messages.messageList`\n ];\n\n function esMessagesController($scope, _, messageList) {\n const vm = this;\n vm.messageList = messageList;\n }\n\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.core`)\r\n .controller(`NotFound`, NotFound);\r\n\r\n NotFound.$inject = [`app.core.services.locationService`];\r\n function NotFound(locationService) {\r\n const vm = this;\r\n vm.goHome = locationService.goHome;\r\n vm.logout = locationService.logout;\r\n }\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.features.alerts`)\n .controller(`app.ui.features.alerts.ContentPanel`, ContentPanel);\n\n ContentPanel.$inject = [\n `i18n`,\n `app.core.services.dateTimeService`,\n `app.core.services.alertService`,\n `$state`,\n `app.core.appSettings`\n ];\n\n function ContentPanel(i18n, dateTimeService, alertService, $state, appSettings) {\n const formatMessage = row => {\n const message = row.message || ``;\n return message.replace(/\\<(?!p|br).*?\\>/g, ` `);\n };\n const defaultSentTime = new Date();\n defaultSentTime.setDate(defaultSentTime.getDate() - 30);\n defaultSentTime.setMinutes(Math.floor(defaultSentTime.getMinutes() / 30) * 30);\n\n const vm = this;\n vm.options = {\n dataProvider: alertService.getAlertsHistory,\n dataSource: {\n pageSize: 25,\n filter: {\n filters:[{\n field:`sentTime`,\n operator:`gte`,\n value:defaultSentTime\n }],\n logic:`and`\n }\n },\n columns: [{\n field: `sentTime`,\n title: i18n.i10n(`app.ui.features.alerts.contentPanel.dataGrid.headings.sentTime`),\n width: 200,\n dataType: `datetime`,\n sort: {\n order: 2,\n dir: `desc`\n },\n click: dataItem => {\n const dateTime = dataItem && dataItem.sentTime && dateTimeService.formatAs.iso(dataItem.sentTime);\n $state.go(`app.monitoring`, {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias,\n dateTime: dateTime\n });\n }\n }, {\n field: `type`,\n title: i18n.i10n(`app.ui.features.alerts.contentPanel.dataGrid.headings.type`),\n width: 120\n }, {\n field: `description`,\n title: i18n.i10n(`app.ui.features.alerts.contentPanel.dataGrid.headings.description`),\n width: 200\n }, {\n field: `message`,\n title: i18n.i10n(`app.ui.features.alerts.contentPanel.dataGrid.headings.message`),\n width: 800,\n sort: {\n order: 1,\n dir: `asc`\n },\n template: formatMessage,\n encoded: false\n }, {\n field: `dismissed`,\n title: i18n.i10n(`app.ui.features.alerts.contentPanel.dataGrid.headings.dismissed`),\n dataType: `datetime`,\n width: 200\n }]\n };\n }\n\n})();\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.features.alerts`)\n .run(appRun);\n\n appRun.$inject = [`routeHelper`];\n\n function appRun(routeHelper) {\n\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: `app.alerts`,\n url: `/alerts/{companyAlias}/{facilityAlias}`,\n views: {\n contentPanel: {\n templateUrl: `/App/ui/features/alerts/ContentPanel.html`,\n controller: `app.ui.features.alerts.ContentPanel as vm`\n }\n },\n settings: {\n requiredAccessControl: `app.alerts`,\n i18n: [\n `/App/ui/features/alerts/i18n/alerts`\n ]\n }\n }];\n }\n }\n\n})();\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .controller(`app.ui.features.blasting.AddScenarioContentPanel`, AddScenarioContentPanel);\r\n\r\n AddScenarioContentPanel.$inject = [\r\n `app.core.appSettings`,\r\n `app.core.services.locationService`,\r\n `scenarioConfigurationState`\r\n ];\r\n\r\n function AddScenarioContentPanel(appSettings, locationService, scenarioConfigurationState) {\r\n const vm = this;\r\n vm.scenario = scenarioConfigurationState;\r\n\r\n activate();\r\n\r\n //////////////////////\r\n\r\n function activate() {\r\n locationService.updatePageHeading({ name: vm.scenarioAlias });\r\n locationService.updateExitPoint(`app.blasting.scenarios`, {\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias\r\n });\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .controller(`app.ui.features.blasting.AddScenarioLeftPanel`, AddScenarioLeftPanel);\r\n\r\n AddScenarioLeftPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `$window`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.appSettings`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.services.configuration.blastingService`,\r\n `app.core.services.blastingService`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastSetup`,\r\n `scenarioConfigurationState`\r\n ];\r\n\r\n function AddScenarioLeftPanel($scope, $state, $window, _, promiseTracker, appSettings, dateTimeService, blastingConfigService, blastingService, blastModelType, blastSetup, scenarioConfigurationState) {\r\n const vm = this;\r\n\r\n vm.cancel = cancel;\r\n vm.save = save;\r\n vm.busy = promiseTracker();\r\n vm.allowedOverlayFileExtensions = [`.kml`, `.dxf`];\r\n\r\n activate();\r\n\r\n //////////////////////\r\n\r\n function activate() {\r\n const alias = $state.params.scenarioAlias;\r\n\r\n vm.scenario = scenarioConfigurationState;\r\n\r\n if (alias) {\r\n const scenarioPromise = blastingService.getScenario(alias);\r\n vm.busy.addPromise(scenarioPromise);\r\n\r\n scenarioPromise.then(existing => {\r\n _.merge(vm.scenario, existing.blastParameters, { blastTimesMillis: existing.blastTimesMillis });\r\n\r\n const hasModel = modelType => !!_.find(existing.models, { modelType });\r\n Object.keys(vm.scenario.models).forEach(key => vm.scenario.models[key] = hasModel(blastModelType[key]));\r\n });\r\n }\r\n }\r\n\r\n function save() {\r\n vm.scenario.isSubmitted = true;\r\n if (vm.$form.$invalid) {\r\n return;\r\n }\r\n\r\n const savingPromise = blastingConfigService.createScenario(scenarioConfigurationState);\r\n vm.busy.addPromise(savingPromise);\r\n\r\n savingPromise.then(result => {\r\n $state.go(`app.blasting.scenarios.scenario`, {\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias,\r\n scenarioAlias: result.scenarioAlias\r\n });\r\n });\r\n }\r\n\r\n function cancel() {\r\n $window.history.back();\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .factory(`app.ui.features.blasting.BlastDataMediator`, blastDataMediatorFactory);\r\n\r\n blastDataMediatorFactory.$inject = [\r\n `lodash`,\r\n `postal`,\r\n `app.core.models.modelLoadingStatus`,\r\n `app.core.services.blastingService`,\r\n `app.core.signalR.jobs.state`,\r\n `app.core.signalR.jobs.events`,\r\n `app.core.models.jobs.jobCompletionStatus`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function blastDataMediatorFactory(_, postal, modelLoadingStatus, blastingService, jobState, jobEvents, jobCompletionStatus) {\r\n\r\n return function BlastDataMediator(state, mapPromise, onRefreshed) {\r\n const self = this;\r\n\r\n let subscriptions;\r\n\r\n this.refresh = function() {\r\n mapPromise.then(map => {\r\n self.map = map;\r\n refresh();\r\n });\r\n };\r\n this.dispose = dispose;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n const dataStore = state.blastDataStore;\r\n\r\n function activate() {\r\n if (!state) {\r\n throw new Error(`You must provide the state object`);\r\n }\r\n\r\n if (!_.isFunction(onRefreshed)) {\r\n throw new Error(`You must provide a callback for 'onRefreshed'`);\r\n }\r\n\r\n const channel = postal.channel(jobEvents.channelName);\r\n\r\n subscriptions = [\r\n channel.subscribe(jobEvents.topics.jobStale, onJobStale),\r\n channel.subscribe(jobEvents.topics.jobCompleted, onJobCompleted),\r\n channel.subscribe(jobEvents.topics.jobDismissed, onJobDismissed)\r\n ];\r\n }\r\n\r\n function refresh() {\r\n const wasModelDataImported = importDataForSelectedModels();\r\n const wasModelDataRemoved = removeUnselectedModelData();\r\n\r\n if (wasModelDataImported || wasModelDataRemoved) {\r\n onRefreshed();\r\n }\r\n }\r\n\r\n function importDataForSelectedModels() {\r\n const selectedModels = state.selectedModels;\r\n\r\n let wereModelsImported = false;\r\n\r\n _.forEach(selectedModels, (blastTimesMillis, modelId) => {\r\n const model = state.scenario.models[modelId];\r\n\r\n _.forEach(blastTimesMillis, blastTimeMillis => {\r\n // Don't do anything if the data is already imported\r\n if (dataStore.hasImportedData(modelId, blastTimeMillis)) {\r\n return;\r\n }\r\n\r\n // Check if we have any data for this model at the nominated blast time. Note that if the model\r\n // loaded with a failure, then blastData will be null. In this case, we'll try to load the\r\n // blast data again.\r\n const hasModelLoadedData = _.has(model.data, blastTimeMillis);\r\n const modelData = model.data[blastTimeMillis];\r\n\r\n if (hasModelLoadedData && modelData) {\r\n wereModelsImported |= importDataIntoDataStore(model, blastTimeMillis); // eslint-disable-line no-bitwise\r\n } else {\r\n // Request the data, even if the last time we tried it returned an error.\r\n loadData(model, blastTimeMillis);\r\n }\r\n });\r\n });\r\n\r\n return wereModelsImported;\r\n }\r\n\r\n function loadData(model, blastTimeMillis) {\r\n const currentStatus = state.getModelLoadingStatus(model.id, blastTimeMillis);\r\n if (currentStatus === modelLoadingStatus.loading) {\r\n return;\r\n }\r\n\r\n //TODO: 16/07/2015 - gthomas - Check if there is already a job running for this model / time range\r\n blastingService.getBlastData(state.scenario.alias, model.modelType, blastTimeMillis).then(loadBlastDataSuccess, loadBlastDataFailed);\r\n state.setModelLoadingStatus(model.id, blastTimeMillis, modelLoadingStatus.loading);\r\n\r\n function loadBlastDataSuccess(getBlastDataResult) {\r\n addBlastDataToModel(getBlastDataResult.availableBlastModelData);\r\n addActiveJobToJobState(getBlastDataResult.activeJobForBlastModel);\r\n\r\n function addBlastDataToModel(blastData) {\r\n model.data[blastTimeMillis] = blastData;\r\n\r\n // If this model/blast time has data, and it's still selected, then add the data to the map and refresh.\r\n if (!(blastData && state.isModelSelected(model.id, blastTimeMillis))) {\r\n return;\r\n }\r\n\r\n const wasDataImported = importDataIntoDataStore(model, blastTimeMillis);\r\n if (wasDataImported) {\r\n onRefreshed();\r\n }\r\n\r\n const status = blastData !== null ? modelLoadingStatus.loaded : modelLoadingStatus.failed;\r\n state.setModelLoadingStatus(model.id, blastTimeMillis, status);\r\n }\r\n\r\n function addActiveJobToJobState(job) {\r\n if (!job || job.requesterId !== model.id) {\r\n return;\r\n }\r\n\r\n // We also need to check if we are already tracking this job - depends on if the SignalR JobCreated\r\n // event was received before the call returned.\r\n const existingJob = _.find(jobState.jobs, { jobId: job.jobId });\r\n if (!existingJob) {\r\n jobState.jobs.push(job);\r\n }\r\n }\r\n }\r\n\r\n function loadBlastDataFailed() {\r\n model.data[blastTimeMillis] = null;\r\n state.setModelLoadingStatus(model.id, blastTimeMillis, modelLoadingStatus.failed);\r\n }\r\n }\r\n\r\n function importDataIntoDataStore(model, blastTimeMillis) {\r\n const dataPoints = model.getDataPoints(blastTimeMillis, self.map);\r\n return dataStore.importData(model.id, blastTimeMillis, dataPoints);\r\n }\r\n\r\n function removeUnselectedModelData() {\r\n let wereModelsRemoved = false;\r\n\r\n _.forEach(dataStore.importedModelsAndTimes, (blastTimesMillis, modelId) => {\r\n _.forEach(_.keys(blastTimesMillis), blastTimeMillis => {\r\n blastTimeMillis = parseInt(blastTimeMillis);\r\n\r\n if (state.isModelSelected(modelId, blastTimeMillis)) {\r\n return;\r\n }\r\n\r\n dataStore.removeData(modelId, blastTimeMillis);\r\n wereModelsRemoved = true;\r\n });\r\n });\r\n\r\n return wereModelsRemoved;\r\n }\r\n\r\n function onJobCompleted(job) {\r\n if (!(job && job.requesterId)) {\r\n return;\r\n }\r\n\r\n const modelId = job.requesterId;\r\n const model = state.scenario.models[modelId];\r\n\r\n if (!model) {\r\n return;\r\n }\r\n\r\n processJobCompleted(job, modelId, model);\r\n }\r\n\r\n function processJobCompleted(job, modelId, model) {\r\n if (job.hasFailed) {\r\n state.setModelLoadingStatus(modelId, job.fromMillis, modelLoadingStatus.failed);\r\n\r\n } else {\r\n // Note that we use `Pending` if the job didn't fail, to signal that the model should\r\n // now try to load its data if it is selected again.\r\n state.setModelLoadingStatus(modelId, job.fromMillis, modelLoadingStatus.pending);\r\n\r\n // If the job is currently selected, we force the update of the data\r\n if (state.selectedModels[modelId]) {\r\n loadData(model, job.fromMillis);\r\n }\r\n }\r\n }\r\n\r\n //todo refactor into jobservice\r\n function onJobDismissed(job) {\r\n if (!job.isStale) {\r\n return;\r\n }\r\n\r\n const modelId = job.requesterId;\r\n if (!modelId) {\r\n return;\r\n }\r\n\r\n const currentLoadingStatus = state.getModelLoadingStatus(modelId, job.fromMillis);\r\n if (currentLoadingStatus !== modelLoadingStatus.loading) {\r\n return;\r\n }\r\n\r\n const hasActiveJob = doesActiveJobExist(modelId, job.fromMillis);\r\n if (!hasActiveJob) {\r\n state.setModelLoadingStatus(modelId, job.fromMillis, modelLoadingStatus.failed);\r\n }\r\n }\r\n\r\n //todo refactor into jobservice\r\n function doesActiveJobExist(modelId, fromMillis, clearStaleJobs = false) {\r\n const existingJobs = _.filter(jobState.jobs, job =>\r\n job.requesterId === modelId &&\r\n job.fromMillis === fromMillis &&\r\n !job.hasCompleted);\r\n\r\n if (!existingJobs.length) {\r\n return false;\r\n }\r\n\r\n let hasActiveJob = false;\r\n\r\n _.forEach(existingJobs, job => {\r\n if (!job.isStale) {\r\n hasActiveJob = true;\r\n\r\n } else if (clearStaleJobs) {\r\n blastingService.dismissJob(job.jobId);\r\n }\r\n });\r\n\r\n return hasActiveJob;\r\n }\r\n\r\n function onJobStale(job) {\r\n if (!(job && job.requesterId)) {\r\n return;\r\n }\r\n\r\n const modelId = job.requesterId;\r\n const model = state.scenario.models[modelId]; // get model data from the available models\r\n\r\n if (!model) {\r\n return;\r\n }\r\n\r\n // Cater for SignalR crapping itself by manually checking the job status\r\n blastingService.getStatus(job.jobId).then(status => {\r\n job.progress = status.progress;\r\n if (!status.hasCompleted) {\r\n job.completionStatus = jobCompletionStatus.incomplete;\r\n } else {\r\n job.completionStatus = jobCompletionStatus.calculate(status.jobSucceededCount, status.jobFailedCount);\r\n processJobCompleted(job, modelId, model);\r\n }\r\n });\r\n }\r\n\r\n function dispose() {\r\n _.invokeMap(subscriptions, `unsubscribe`);\r\n }\r\n };\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .factory(`app.ui.features.blasting.BlastDataStore`, blastDataStoreFactory);\r\n\r\n blastDataStoreFactory.$inject = [\r\n `lodash`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function blastDataStoreFactory(_) {\r\n return function BlastDataStore() {\r\n this.hasImportedData = hasImportedData;\r\n this.importData = importData;\r\n this.removeData = removeData;\r\n this.getDataAtOffset = getDataAtOffset;\r\n\r\n ////////////////////\r\n\r\n /**\r\n * Quick lookup to find which models and times are currently imported. This is only used internally to\r\n * work out if blast data for a given model has already been imported into the data store. Stored as:\r\n *
        \r\n             *     ModelId => Blast Time => Visibility\r\n             * 
        \r\n * For example:\r\n *
        \r\n             *     {\r\n             *         \"model-1234\": {\r\n             *             \"1437010250000\": true,\r\n             *             \"1437010250000\": true,\r\n             *         },\r\n             *         \"model-5678\": {\r\n             *             \"1437010500000\": true,\r\n             *         }\r\n             *     }\r\n             * 
        \r\n *\r\n * @type {object}\r\n */\r\n const importedModelsAndTimes = {};\r\n\r\n /**\r\n * Time step data for all currently loaded models. This is used to quickly retrieve data for all models at\r\n * the given time offset. Since the user may look at multiple blast times at the same time, the thing in\r\n * common is the offset from the original blast time. Stored as:\r\n *
        \r\n             *     Offset from blast time => Model Id => Blast Time => Data\r\n             * 
        \r\n * For example, the data stored for each blast model at the actual time of the blast (T+0) may be:\r\n *
        \r\n             *     {\r\n             *         \"0\": {                       // offset from blast time\r\n             *             \"model-1234\": {              // model id (guid)\r\n             *                 \"1437010250000\": [],         // blast time => data points for this model / blast time / offset\r\n             *                 \"1437010500000\": [],         // blast time => data points for this model / blast time / offset\r\n             *             },\r\n             *             \"model-5678\": {              // model id (guid)\r\n             *                 \"1437010500000\": [],         // blast time => data points for this model / blast time / offset\r\n             *             },\r\n             *         }\r\n             *     }\r\n             * 
        \r\n *\r\n * @type {object}\r\n */\r\n const importedData = {};\r\n\r\n ////////////////////\r\n\r\n Object.defineProperty(this, `importedModelsAndTimes`, { get: () => importedModelsAndTimes });\r\n\r\n /**\r\n * Determines if any data has been imported. If the modelId and blastTimeMillis\r\n * parameters are not passed, this method will report if data for any model/blast time\r\n * has been imported.\r\n *\r\n * @returns {bool}\r\n */\r\n function hasImportedData(modelId = null, blastTimeMillis = null) {\r\n if (modelId && blastTimeMillis) {\r\n return (importedModelsAndTimes[modelId] || {})[blastTimeMillis];\r\n }\r\n\r\n return !_.isEmpty(importedModelsAndTimes);\r\n }\r\n\r\n function setHasImportedData(modelId, blastTimeMillis, hasData) {\r\n if (hasData) {\r\n const importedTimesForModel = importedModelsAndTimes[modelId] || (importedModelsAndTimes[modelId] = {});\r\n importedTimesForModel[blastTimeMillis] = true;\r\n\r\n } else {\r\n const importedTimesForModel = importedModelsAndTimes[modelId];\r\n if (!importedTimesForModel) {\r\n return;\r\n }\r\n\r\n delete importedTimesForModel[blastTimeMillis];\r\n\r\n if (_.isEmpty(importedTimesForModel)) {\r\n delete importedModelsAndTimes[modelId];\r\n }\r\n }\r\n }\r\n\r\n function importData(modelId, blastTimeMillis, blastData) {\r\n const hasBlastData = blastData && blastData.length;\r\n setHasImportedData(modelId, blastTimeMillis, hasBlastData);\r\n\r\n if (!hasBlastData) {\r\n return false;\r\n }\r\n\r\n _.forEach(blastData, dataPoint => {\r\n const offset = dataPoint.offsetMinutes;\r\n const allDataForOffset = importedData[offset] || (importedData[offset] = {});\r\n const modelDataForOffset = allDataForOffset[modelId] || (allDataForOffset[modelId] = {});\r\n\r\n modelDataForOffset[blastTimeMillis] = dataPoint;\r\n });\r\n\r\n return true;\r\n }\r\n\r\n function removeData(modelId, blastTimeMillis) {\r\n blastTimeMillis = parseInt(blastTimeMillis);\r\n\r\n if (!hasImportedData(modelId, blastTimeMillis)) {\r\n return false;\r\n }\r\n\r\n _.forEach(importedData, (allDataForTimeStep, offset) => {\r\n const modelDataAtTimeStep = allDataForTimeStep[modelId];\r\n delete modelDataAtTimeStep[blastTimeMillis];\r\n\r\n if (_.isEmpty(modelDataAtTimeStep)) {\r\n delete allDataForTimeStep[modelId];\r\n\r\n if (_.isEmpty(allDataForTimeStep)) {\r\n delete importedData[offset];\r\n }\r\n }\r\n });\r\n\r\n setHasImportedData(modelId, blastTimeMillis, false);\r\n return true;\r\n }\r\n\r\n function getDataAtOffset(offsetMinutes) {\r\n if (!_.has(importedData, offsetMinutes)) {\r\n return null;\r\n }\r\n\r\n return _.chain(importedData[offsetMinutes])\r\n // Key is modelId, value is a map of blast time => data point. All we want are the data points.\r\n .map(modelDataAtTimeStep => _.map(modelDataAtTimeStep, dataPoint => dataPoint))\r\n .flatten()\r\n .value();\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbscFileUploader`, directive)\r\n .controller(`esbscFileUploaderController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n scenario: `=`,\r\n extensions: `=`,\r\n maxSize: `@`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscFileUploader.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n `i18n`,\r\n `lodash`,\r\n `leafletLib`,\r\n `FileUploader`,\r\n `promiseTracker`,\r\n `app.core.httpInterceptors`,\r\n `app.core.services.configuration.blastingService`\r\n ];\r\n\r\n function controller(i18n, _, L, FileUploader, promiseTracker, httpInterceptors, blastingService) {\r\n const vm = this;\r\n\r\n // Used for validating uploaded overlays\r\n const xmlParser = new DOMParser();\r\n const kmlValidator = new L.KML(null);\r\n\r\n vm.uploader = null;\r\n vm.busyLoading = promiseTracker();\r\n vm.removeFile = removeFile;\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n vm.uploader = getUploader();\r\n restorePreviouslyUploadedFiles();\r\n }\r\n\r\n function getUploader() {\r\n const options = {\r\n autoUpload: false,\r\n alias: `overlayFile`,\r\n\r\n // POST configuration\r\n headers: {},\r\n url: blastingService.getAddOverlayUrl(),\r\n\r\n // Events\r\n onAfterAddingFile: onFileAdded,\r\n onSuccessItem: validateUploadedFile,\r\n withCredentials: true\r\n };\r\n\r\n if (vm.scenario.id) {\r\n options.formData = [{ scenarioId: vm.scenario.id }];\r\n }\r\n\r\n // The file upload component that we are using uses its own transport layer for uploading the files,\r\n // as opposed to using angular's $http service. Why? Goodness only knows; at a guess, its so it can\r\n // downgrade to using an iFrame + form post as the transport when the user is ignorantly using a\r\n // non HTML5 compatible browser.\r\n //\r\n // As such, we need to add in the request headers (e.g. for the current company/facility alias) that\r\n // would ordinarily be done for us by the $httpInterceptor. Thankfully, the `httpInterceptors.request`\r\n // method already expects to be passed an object with a `headers` property on it (yay for duck typing!),\r\n // and this is conveniently the same property which is expected by the file upload component. Win win!\r\n httpInterceptors.request(options);\r\n\r\n return new FileUploader(options);\r\n }\r\n\r\n function onFileAdded(fileItem) {\r\n const file = fileItem.file;\r\n const fileName = file.name.toLowerCase();\r\n\r\n if (validatePotentialUpload()) {\r\n fileItem.upload();\r\n }\r\n\r\n // Automatically overwrite any other files with the same name. We can skip the last item in\r\n // the queue as that's the item that has just been added.\r\n for (let i = 0; i < vm.uploader.queue.length - 1; i++) {\r\n const queuedItem = vm.uploader.queue[i];\r\n\r\n if (queuedItem.file.name.toLowerCase() === fileName) {\r\n vm.uploader.removeFromQueue(i);\r\n break;\r\n }\r\n }\r\n\r\n\r\n function validatePotentialUpload() {\r\n const isValidExtension = validateExtension();\r\n const isValidSize = validateSize();\r\n return isValidExtension && isValidSize;\r\n\r\n function validateExtension() {\r\n const fileNameLower = file.name.toLowerCase();\r\n const validExtension = _.find(vm.extensions, extension => _.endsWith(fileNameLower, extension));\r\n\r\n if (!validExtension) {\r\n setValidationError(fileItem, `extension`);\r\n fileItem.isError = true;\r\n }\r\n\r\n return validExtension;\r\n }\r\n\r\n function validateSize() {\r\n const canUpload = file.size <= vm.maxSize;\r\n if (!canUpload) {\r\n setValidationError(fileItem, `size`);\r\n fileItem.isError = true;\r\n }\r\n\r\n return canUpload;\r\n }\r\n }\r\n }\r\n\r\n function restorePreviouslyUploadedFiles() {\r\n const loaderPromise = blastingService.getOverlayFiles(vm.scenario.id).then(files => {\r\n _.forEach(files, overlayFile => {\r\n const fileItem = new FileUploader.FileItem(vm.uploader, overlayFile);\r\n fileItem.progress = 100;\r\n fileItem.isUploaded = fileItem.isSuccess = true;\r\n\r\n vm.uploader.queue.push(fileItem);\r\n validateUploadedFile(fileItem);\r\n });\r\n });\r\n\r\n vm.busyLoading.addPromise(loaderPromise);\r\n }\r\n\r\n function validateUploadedFile(fileItem, overlayFile) {\r\n const file = fileItem.file;\r\n\r\n if (isResultFileDifferentToUploadedFile()) {\r\n file.name = overlayFile.name;\r\n file.size = overlayFile.length;\r\n\r\n dequeueDuplicates();\r\n }\r\n\r\n return blastingService.getOverlayFile(file.name)\r\n .then(validateOverlay)\r\n .then(overlay => {\r\n vm.scenario.overlayFiles[file.name] = overlay;\r\n return overlay;\r\n }).catch(angular.noop); //TODO: 28/02/2019 - ben.priebe - Test what happens in front-end\r\n\r\n ////////////////////\r\n function validateOverlay(overlay) {\r\n if (_.endsWith(overlay.name, `.kml`)) {\r\n return validateKmlOverlay(overlay);\r\n }\r\n return overlay;\r\n }\r\n\r\n function validateKmlOverlay(overlay) {\r\n const xmlDoc = xmlParser.parseFromString(overlay.data, `text/xml`);\r\n kmlValidator._addKML(xmlDoc);\r\n const hasNoLayers = !_.size(kmlValidator._layers);\r\n kmlValidator.clearLayers();\r\n\r\n if (hasNoLayers) {\r\n setValidationError(fileItem, `overlay`);\r\n throw {\r\n handled: true\r\n };\r\n }\r\n\r\n return overlay;\r\n }\r\n\r\n function isResultFileDifferentToUploadedFile() {\r\n return overlayFile && file.name !== overlayFile.name;\r\n }\r\n\r\n function dequeueDuplicates() {\r\n _.remove(vm.uploader.queue, queued => queued.file.name === file.name && queued.file !== file);\r\n }\r\n }\r\n\r\n function setValidationError(fileItem, field) {\r\n fileItem.validationErrors = fileItem.validationErrors || {};\r\n fileItem.validationErrors[field] = i18n.i10n(`esbscFileUploader.validationErrors.` + field);\r\n }\r\n\r\n function removeFile(fileItem) {\r\n const file = fileItem.file;\r\n fileItem.remove();\r\n blastingService.deleteOverlayFile(vm.scenario.id, fileItem.file.name);\r\n delete vm.scenario.overlayFiles[file.name];\r\n }\r\n }\r\n})();\r\n","`use strict`;\r\n/* istanbul ignore next */\r\n(function(){\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbscLocation`, directive)\r\n .controller(`esbscLocationController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n scenario: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscLocation.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `lodash`\r\n ];\r\n function controller($scope, _) {\r\n const outOfBoundsValidationErrorKey = `outOfBounds`;\r\n\r\n const vm = this;\r\n vm.isLocationOutOfBounds = false;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n invalidateLocationWhenOutsideDomainBoundaries();\r\n\r\n ////////////////////\r\n\r\n function invalidateLocationWhenOutsideDomainBoundaries() {\r\n const watches = [\r\n () => vm.scenario.latitude,\r\n () => vm.scenario.longitude\r\n ];\r\n\r\n $scope.$watchGroup(watches, validateSelectedLocationIsWithinBounds);\r\n\r\n function validateSelectedLocationIsWithinBounds(location) {\r\n const isLocationOutOfBounds = isOutOfBounds(location);\r\n if (vm.isLocationOutOfBounds === isLocationOutOfBounds) {\r\n return;\r\n }\r\n\r\n angular.forEach(vm.$form, ctrl => {\r\n if (angular.isObject(ctrl) && angular.isDefined(ctrl.$setValidity)) {\r\n ctrl.$setValidity(outOfBoundsValidationErrorKey, !isLocationOutOfBounds);\r\n }\r\n });\r\n\r\n vm.isLocationOutOfBounds = isLocationOutOfBounds;\r\n }\r\n\r\n function isOutOfBounds(location) {\r\n const boundaries = vm.scenario.map && vm.scenario.map.boundaries;\r\n if (!(boundaries && boundaries.length)) {\r\n return false;\r\n }\r\n\r\n const [latitude, longitude] = location;\r\n if (!(latitude && longitude)) {\r\n return false;\r\n }\r\n\r\n return !_.find(boundaries, boundary => boundary.contains(latitude, longitude));\r\n }\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\n\n `use strict`;\n\n angular\n .module(`app.ui.features.blasting`)\n .directive(`esbscMap`, directive)\n .controller(`esbscMapController`, controller);\n\n function directive() {\n return {\n restrict: `E`,\n scope: {\n scenario: `=`\n },\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscMap.html`,\n controller: controller,\n controllerAs: `vm`,\n bindToController: true\n };\n }\n\n controller.$inject = [\n `lodash`,\n `app.core.mapDefaults`,\n `app.core.services.mappingService`\n ];\n\n function controller(_, mapDefaults, mappingService) {\n const vm = this;\n vm.isSelectingBlastLocation = false;\n\n activate();\n\n ///////////////////\n\n function activate() {\n initilizeMap();\n loadFacilityOverlays();\n }\n\n function initilizeMap() {\n vm.scenario.map = {\n defaultCentre: vm.scenario.lookups.facilityLocation,\n centre: vm.scenario.lookups.facilityLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n isColor: false,\n layers: {\n baselayers: mapDefaults.baselayers,\n overlays: buildLayers()\n }\n };\n }\n\n\n function buildLayers(){\n const layers = {};\n const vibrationLayer = createVibrationMarkerLayer();\n layers[vibrationLayer.name] = vibrationLayer;\n return layers;\n }\n\n function createVibrationMarkerLayer() {\n return {\n type: `group`,\n visible: true,\n name: `VibrationPOILayer`\n };\n }\n\n function loadFacilityOverlays() {\n mappingService.getKmls().then(overlays => {\n _.forEach(overlays, overlay => {\n vm.scenario.overlayFiles[overlay.name] = overlay;\n });\n });\n }\n }\n})();\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbscModelParameters`, directive)\r\n .controller(`esbscModelParametersController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n scenario: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscModelParameters.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `app.core.services.mappingService`,\r\n `app.core.models.blasting.blastSetup`\r\n ];\r\n\r\n function controller($scope, _, mappingService, blastSetup) {\r\n const vm = this;\r\n vm.isModelSelected = isModelSelected;\r\n vm.isStemming = () => vm.scenario.blastSetup === blastSetup.stemming;\r\n vm.isBurden = () => vm.scenario.blastSetup === blastSetup.burden;\r\n vm.selectedPollutant = vm.scenario.modelPollutantId && _.find(vm.scenario.lookups.pollutantOptions, { modelPollutantId: vm.scenario.modelPollutantId });\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updatePollutantOptionsWhenPollutantChanges();\r\n updateAzimuthWhenValueFallsOutsideValidRange();\r\n updateElevationWhenBlastLocationChanges();\r\n\r\n ////////////////////\r\n\r\n function updatePollutantOptionsWhenPollutantChanges() {\r\n $scope.$watch(() => vm.scenario.modelPollutantId, modelPollutantId => {\r\n vm.selectedPollutant = modelPollutantId && _.find(vm.scenario.lookups.pollutantOptions, { modelPollutantId });\r\n vm.scenario.displayUnitId = modelPollutantId && _.first(vm.selectedPollutant.displayUnitOptions).id;\r\n vm.scenario.pollutantScientificModelId = modelPollutantId && vm.selectedPollutant.associatedPlumeScientificModels.length\r\n ? _.first(vm.selectedPollutant.associatedPlumeScientificModels).id\r\n : null;\r\n });\r\n }\r\n\r\n function updateAzimuthWhenValueFallsOutsideValidRange() {\r\n $scope.$watch(() => vm.scenario.azimuth, azimuth => {\r\n if (!_.isNumber(azimuth) || azimuth >= 0 && azimuth < 360) {\r\n return;\r\n }\r\n\r\n if (azimuth < 0) {\r\n vm.scenario.azimuth = 360 - Math.abs(azimuth) % 360;\r\n } else {\r\n vm.scenario.azimuth = azimuth - (Math.abs(azimuth) % 360 + 360);\r\n }\r\n });\r\n }\r\n\r\n function updateElevationWhenBlastLocationChanges() {\r\n const watches = [\r\n () => vm.scenario.latitude,\r\n () => vm.scenario.longitude,\r\n () => vm.scenario.isPollutantModelSelected,\r\n () => vm.scenario.isOverpressureModelSelected\r\n ];\r\n\r\n $scope.$watchGroup(watches, onLocationChanged);\r\n\r\n function onLocationChanged(locationData, oldLocationData) {\r\n if (locationData === oldLocationData) {\r\n return;\r\n }\r\n\r\n const [latitude, longitude] = locationData;\r\n\r\n if (isElevationRequired()) {\r\n getElevationForSelectedLocation();\r\n }\r\n\r\n ////////////////////\r\n\r\n function isElevationRequired() {\r\n const hasLocation = latitude && longitude;\r\n return hasLocation && isModelSelected();\r\n }\r\n\r\n function getElevationForSelectedLocation() {\r\n mappingService.getElevation(latitude, longitude).then(elevationData => {\r\n if (!elevationData) {\r\n return;\r\n }\r\n\r\n vm.scenario.elevation = parseFloat(elevationData.elevation.toFixed(2));\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n function isModelSelected() {\r\n return vm.scenario.isPollutantModelSelected ||\r\n vm.scenario.isOverpressureModelSelected ||\r\n vm.scenario.isPathModelSelected ||\r\n vm.scenario.isFlyrockSelected ||\r\n vm.scenario.isGroundVibrationSelected;\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbscModelSelector`, directive)\r\n .controller(`esbscModelSelectorController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n scenario: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscModelSelector.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n ];\r\n function controller() {\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n }\r\n\r\n\r\n }\r\n})();\r\n","(function(){\r\n `use strict`;\r\n\r\n const directiveName = `esbscModelTypeRequired`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(directiveName, validator);\r\n\r\n validator.$inject = [`lodash`];\r\n\r\n /* istanbul ignore next */\r\n function validator(_) {\r\n return {\r\n restrict: `A`,\r\n require: `ngModel`,\r\n scope: {\r\n isValidationRequired: `=${directiveName}`\r\n },\r\n link: link\r\n };\r\n\r\n function link($scope, $element, $attrs, ngModel) {\r\n $scope.$watch(() => $scope.isValidationRequired, validateHasSelectedModel);\r\n $scope.$watch(() => ngModel.$modelValue, validateHasSelectedModel, true);\r\n\r\n function validateHasSelectedModel() {\r\n let isValid = !$scope.isValidationRequired;\r\n\r\n if ($scope.isValidationRequired) {\r\n isValid = _.some(ngModel.$modelValue, value => value);\r\n }\r\n\r\n ngModel.$setValidity(`modelTypeRequired`, isValid);\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\n\n `use strict`;\n\n angular\n .module(`app.ui.features.blasting`)\n .directive(`esbscName`, directive)\n .controller(`esbscName`, controller);\n\n function directive() {\n return {\n restrict: `E`,\n scope: {\n scenario: `=`\n },\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscName.html`,\n controller: controller,\n controllerAs: `vm`,\n bindToController: true\n };\n }\n\n controller.$inject = [\n `$scope`,\n `app.core.services.configuration.blastingService`\n ];\n\n function controller($scope, blastingService) {\n const vm = this;\n vm.isEditingAlias = false;\n vm.hasAlias = hasAlias;\n\n vm.setDefaultAlias = setDefaultAlias;\n vm.editAlias = editAlias;\n vm.refreshAlias = refreshAlias;\n\n activate();\n\n ////////////////////\n\n function activate() {}\n\n function editAlias() {\n vm.isEditingAlias = true;\n }\n\n function setDefaultAlias() {\n if (hasAlias()) {\n return;\n }\n updateAlias(vm.scenario.name);\n }\n\n function hasAlias() {\n return vm.scenario.alias;\n }\n\n function refreshAlias() {\n updateAlias(vm.scenario.alias || vm.scenario.name);\n vm.isEditingAlias = false;\n }\n\n // calls the server to get a unique alias value\n function updateAlias(alias) {\n if (alias === null || alias === undefined) {\n return;\n }\n vm.isBusy = true;\n blastingService.getValidScenarioAlias(alias)\n .then(validAlias => {\n vm.scenario.alias = validAlias;\n })\n .finally(() => {\n vm.isBusy = false;\n });\n }\n\n }\n})();\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbscPollutantConcentrationSelector`, directive)\r\n .controller(`esbscPollutantConcentrationSelectorController`, controller);\r\n\r\n\r\n directive.$inject = [`jQuery`];\r\n function directive($) {\r\n return {\r\n restrict: `E`,\r\n require: [`^form`],\r\n scope: {\r\n scenario: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscPollutantConcentrationSelector.html`,\r\n link: link,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n\r\n function link($scope, $element, attrs, controllers) {\r\n const vm = $scope.vm;\r\n vm.$form = controllers[0];\r\n\r\n vm.itemTemplate = $(`#nox-item-template`).html();\r\n $scope.$watch(() => vm.noxComboBox, () => {\r\n if (vm.noxComboBox) {\r\n vm.noxComboBox.input.attr(`type`, `number`);\r\n vm.noxComboBox.input.attr(`min`, `0`);\r\n vm.noxComboBox.input.attr(`step`, `any`);\r\n }\r\n });\r\n }\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `lodash`\r\n ];\r\n\r\n function controller($scope, _) {\r\n const vm = this;\r\n\r\n vm.isEditingInitialConcentration = false;\r\n\r\n vm.editInitialConcentration = editInitialConcentration;\r\n vm.hasInitialConcentration = hasInitialConcentration;\r\n vm.refreshInitialConcentration = refreshInitialConcentration;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function editInitialConcentration() {\r\n vm.isEditingInitialConcentration = true;\r\n }\r\n\r\n function hasInitialConcentration() {\r\n return vm.scenario.initialConcentration !== undefined && vm.scenario.initialConcentration !== null;\r\n }\r\n\r\n function refreshInitialConcentration() {\r\n vm.isEditingInitialConcentration = false;\r\n }\r\n\r\n function updateInitialConcentration() {\r\n const modelPollutant = _.find(vm.scenario.lookups.pollutantOptions, { modelPollutantId: vm.scenario.modelPollutantId });\r\n vm.scenario.initialConcentration = modelPollutant ? vm.scenario.defaultConcentrations.get(modelPollutant.libraryPollutantId.toUpperCase()) : null;\r\n }\r\n\r\n function activate() {\r\n $scope.$watch(() => vm.scenario.modelPollutantId, updateInitialConcentration);\r\n }\r\n }\r\n})();\r\n","(function() {\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbscTimeSelector`, directive);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n scenario: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/configuration/esbscTimeSelector.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [];\r\n function controller() {\r\n const millisPerMinute = 60 * 1000;\r\n const millisPerHalfHour = 30 * millisPerMinute;\r\n const millisPerHour = 2 * millisPerHalfHour;\r\n\r\n const vm = this;\r\n vm.addAnotherBlastTimeSelector = addAnotherBlastTimeSelector;\r\n vm.removeBlastTimeSelector = removeBlastTimeSelector;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n initialiseBlastTimeSelectors();\r\n }\r\n\r\n function initialiseBlastTimeSelectors() {\r\n if (vm.scenario.blastTimesMillis.length === 0) {\r\n const nextBlastTime = estimateNextBlastTime(new Date().getTime());\r\n vm.scenario.blastTimesMillis.push(nextBlastTime);\r\n }\r\n }\r\n\r\n function addAnotherBlastTimeSelector() {\r\n const latestBlastTime = Math.max(...vm.scenario.blastTimesMillis);\r\n const nextBlastTime = estimateNextBlastTime(latestBlastTime);\r\n\r\n vm.scenario.blastTimesMillis.push(nextBlastTime);\r\n }\r\n\r\n function removeBlastTimeSelector(index) {\r\n if (vm.scenario.blastTimesMillis.length <= 1) {\r\n return;\r\n }\r\n\r\n vm.scenario.blastTimesMillis.splice(index, 1);\r\n }\r\n\r\n function estimateNextBlastTime(lastBlastTime) {\r\n const nextBlastTime = roundUpToHalfHour(lastBlastTime + 2 * millisPerHour);\r\n\r\n return ensureBlastIsDuringDaylightHours(nextBlastTime);\r\n\r\n ////////////////////\r\n\r\n function roundUpToHalfHour(timeMillis) {\r\n const millisOverHalfHour = timeMillis % millisPerHalfHour;\r\n\r\n return millisOverHalfHour === 0 ? timeMillis : timeMillis + millisPerHalfHour - millisOverHalfHour;\r\n }\r\n\r\n function ensureBlastIsDuringDaylightHours(timeMillis) {\r\n const blastDate = new Date(timeMillis);\r\n const hours = blastDate.getHours();\r\n\r\n if (hours >= 7 && (hours < 19 || hours === 19 && blastDate.getMinutes() === 0)) {\r\n return timeMillis;\r\n }\r\n\r\n if (hours >= 19) {\r\n blastDate.setDate(blastDate.getDate() + 1);\r\n }\r\n\r\n blastDate.setHours(7);\r\n blastDate.setMinutes(0);\r\n\r\n return blastDate.getTime();\r\n }\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsActualBlastTime`, esbsActualBlastTime)\r\n .controller(`esbsActualBlastTimeController`, esbsActualBlastTimeController);\r\n\r\n function esbsActualBlastTime() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n state: `=state`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/esbsActualBlastTime.html`,\r\n controller: esbsActualBlastTimeController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esbsActualBlastTimeController.$inject = [\r\n `$scope`,\r\n `i18n`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.appSettings`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.services.configuration.blastingService`\r\n ];\r\n\r\n function esbsActualBlastTimeController($scope, i18n, _, promiseTracker, appSettings, timeZoneDateTime, dateTimeService, blastingService) {\r\n const vm = this;\r\n\r\n const canModifyBlasting = appSettings.site.accessControls[`app.blasting.modify`];\r\n vm.canUpdateBlastTime = true;\r\n\r\n vm.originalBlastTime = null;\r\n vm.actualBlastTimeModel = buildActualBlastTimeModel(null);\r\n vm.datePicker = getDatePicker();\r\n\r\n vm.isEditingBlastTime = false;\r\n vm.isSubmitted = false;\r\n vm.busySaving = promiseTracker();\r\n\r\n vm.changeBlastTime = changeBlastTime;\r\n vm.save = save;\r\n vm.cancel = cancel;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updateVisibilityWhenScenarioChanges();\r\n updateDisplayedBlastTimeWhenActualBlastTimeChanges();\r\n }\r\n\r\n function updateVisibilityWhenScenarioChanges() {\r\n $scope.$watch(() => vm.state.scenario, scenario => {\r\n if (!scenario) {\r\n return;\r\n }\r\n\r\n const { actualBlastTime } = scenario;\r\n vm.isEditingBlastTime = !actualBlastTime;\r\n vm.canUpdateBlastTime = vm.isEditingBlastTime || canModifyBlasting;\r\n\r\n if (vm.isEditingBlastTime) {\r\n changeBlastTime();\r\n }\r\n });\r\n }\r\n\r\n function updateDisplayedBlastTimeWhenActualBlastTimeChanges() {\r\n $scope.$watch(() => vm.state.scenario.actualBlastTime, actualBlastTime => {\r\n vm.actualBlastTimeModel = buildActualBlastTimeModel(actualBlastTime);\r\n });\r\n }\r\n\r\n function buildActualBlastTimeModel(actualBlastTime) {\r\n return {\r\n date: actualBlastTime,\r\n formattedString: actualBlastTime && dateTimeService.formatAs.dateTime(actualBlastTime) || `-`\r\n };\r\n }\r\n\r\n function getDatePicker() {\r\n return {\r\n hasFocus: false,\r\n options: {\r\n format: dateTimeService.formats.kendo.dateTime,\r\n timeFormat: dateTimeService.formats.kendo.time,\r\n interval: 1,\r\n max: new Date()\r\n }\r\n };\r\n }\r\n\r\n function changeBlastTime() {\r\n vm.isEditingBlastTime = true;\r\n vm.originalBlastTime = vm.state.scenario.actualBlastTime;\r\n\r\n vm.actualBlastTimeModel = buildActualBlastTimeModel(vm.state.scenario.actualBlastTime);\r\n }\r\n\r\n function save() {\r\n vm.isSubmitted = true;\r\n if (vm.$form.$invalid || !vm.$form.$dirty) {\r\n return;\r\n }\r\n\r\n const { scenario } = vm.state;\r\n const selectedBlastTime = vm.actualBlastTimeModel.date;\r\n const actualBlastTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(selectedBlastTime);\r\n\r\n const savingPromise = blastingService.updateActualBlastTime(scenario.alias, actualBlastTime);\r\n vm.busySaving.addPromise(savingPromise);\r\n\r\n savingPromise.then(() => {\r\n scenario.actualBlastTime = selectedBlastTime;\r\n vm.isEditingBlastTime = false;\r\n });\r\n }\r\n\r\n function cancel() {\r\n vm.isEditingBlastTime = false;\r\n vm.actualBlastTimeModel = buildActualBlastTimeModel(vm.originalBlastTime);\r\n }\r\n }\r\n})();\r\n","`use strict`;\r\n(function() {\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsFlyrockLegend`, esbsFlyrockLegend)\r\n .controller(`esbsFlyrockLegendController`, esbsFlyrockLegendController);\r\n\r\n function esbsFlyrockLegend() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n legend: `=`,\r\n time: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/esbsFlyrockLegend.html`,\r\n controller: esbsFlyrockLegendController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n function esbsFlyrockLegendController() {\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsModelCategorySelector`, esbsModelCategorySelector)\r\n .controller(`esbsModelCategorySelectorController`, esbsModelCategorySelectorController);\r\n\r\n function esbsModelCategorySelector() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n state: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/esbsModelCategorySelector.html`,\r\n controller: esbsModelCategorySelectorController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esbsModelCategorySelectorController.$inject = [`$scope`, `lodash`];\r\n function esbsModelCategorySelectorController($scope, _) {\r\n const vm = this;\r\n\r\n vm.modelCategories = _.toArray(vm.state.modelCategories);\r\n vm.selectedModelCategory = null;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updateModelTypeWhenStateChanges();\r\n updateStateWhenModelTypeChanges();\r\n }\r\n\r\n function updateModelTypeWhenStateChanges() {\r\n $scope.$watch(\r\n () => vm.state.selectedModelCategory,\r\n type => vm.selectedModelCategory = _.find(vm.state.modelCategories, { type }));\r\n }\r\n\r\n function updateStateWhenModelTypeChanges() {\r\n $scope.$watch(\r\n () => vm.selectedModelCategory,\r\n category => vm.state.selectedModelCategory = category.type);\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsModelGroupingSelector`, esbsModelGroupingSelector)\r\n .controller(`esbsModelGroupingSelectorController`, esbsModelGroupingSelectorController);\r\n\r\n function esbsModelGroupingSelector() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n state: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/esbsModelGroupingSelector.html`,\r\n controller: esbsModelGroupingSelectorController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esbsModelGroupingSelectorController.$inject = [\r\n `$scope`,\r\n `lodash`\r\n ];\r\n\r\n function esbsModelGroupingSelectorController($scope, _) {\r\n const vm = this;\r\n\r\n vm.groupingTypes = _.toArray(vm.state.modelGroupingTypes);\r\n vm.hasModelsForCategory = true;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updateHasModelsForCategoryWhenCategoryChanges();\r\n }\r\n\r\n function updateHasModelsForCategoryWhenCategoryChanges() {\r\n $scope.$watch(() => vm.state.selectedModelCategory, modelCategory => {\r\n if (!modelCategory) {\r\n return;\r\n }\r\n\r\n const { scenario } = vm.state;\r\n vm.hasModelsForCategory = scenario && scenario.models && _.find(scenario.models, { modelCategory });\r\n });\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsModelLegendToggle`, esbsModelLegendToggle)\r\n .controller(`esbsModelLegendToggleController`, esbsModelLegendToggleController);\r\n\r\n function esbsModelLegendToggle() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n isShowing: `=`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/esbsModelLegendToggle.html`,\r\n controller: esbsModelLegendToggleController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esbsModelLegendToggleController.$inject = [];\r\n function esbsModelLegendToggleController() {\r\n const vm = this;\r\n\r\n vm.toggleLegendVisible = toggleLegendVisible;\r\n\r\n ////////////////////\r\n\r\n function toggleLegendVisible() {\r\n vm.isShowing = !vm.isShowing;\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsModelParameters`, esbsModelParameters)\r\n .controller(`esbsModelParametersController`, esbsModelParametersController);\r\n\r\n esbsModelParameters.$inject = [];\r\n\r\n function esbsModelParameters() {\r\n return {\r\n scope: {\r\n state: `=`\r\n },\r\n restrict: `EA`,\r\n templateUrl: `/App/ui/features/blasting/controls/esbsModelParameters.html`,\r\n controller: esbsModelParametersController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esbsModelParametersController.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `app.core.models.blasting.blastSetup`\r\n ];\r\n function esbsModelParametersController($scope, $state, _, blastSetup) {\r\n const vm = this;\r\n vm.duplicate = duplicate;\r\n\r\n activate();\r\n\r\n //////////////////////\r\n\r\n function activate() {\r\n $scope.$watch(() => vm.state.scenario, () => {\r\n vm.scenario = vm.state.scenario;\r\n\r\n if (!vm.scenario || !vm.scenario.blastParameters) {\r\n return;\r\n }\r\n\r\n vm.showPathParameters = hasBlastModelParameters(\r\n `blastHeight`,\r\n `windScientificModel`,\r\n `forwardTrajectoryScientificModel`\r\n );\r\n\r\n vm.showPollutantParameters = hasBlastModelParameters(\r\n `blastHeight`,\r\n `blastLength`,\r\n `blastWidth`,\r\n `azimuth`,\r\n `elevation`,\r\n `windScientificModel`,\r\n `pollutant`,\r\n `pollutantScientificModel`,\r\n `displayUnit`,\r\n `initialConcentration`\r\n );\r\n\r\n vm.showOverpressureParameters = !!vm.scenario.blastParameters.blastSetup;\r\n vm.showOverpressureBurdenParameters = vm.scenario.blastParameters.blastSetup === blastSetup.burden;\r\n vm.showOverpressureStemmingParameters = vm.scenario.blastParameters.blastSetup === blastSetup.stemming;\r\n\r\n vm.showFlyrockParameters = hasBlastModelParameters(\r\n `azimuth`,\r\n `chargeMass`,\r\n `burden`,\r\n `stemmingHeight`,\r\n `flyrockSiteConstantKv`,\r\n `dispersalAngle`,\r\n `holeAngle`\r\n );\r\n\r\n vm.showGroundVibrationParameters = hasBlastModelParameters(\r\n `chargeMassPerHole`,\r\n `groundVibrationSiteConstantKv`,\r\n `groundVibrationSiteExponentKb`\r\n );\r\n });\r\n }\r\n\r\n function duplicate() {\r\n $state.go(`app.blasting.scenarios.add`, { scenarioAlias: vm.scenario.alias });\r\n }\r\n\r\n function hasBlastModelParameters(...blastParameters) {\r\n return !_.find(blastParameters, isNullOrUndefined);\r\n }\r\n\r\n function isNullOrUndefined(blastParameter) {\r\n const parameter = vm.scenario.blastParameters[blastParameter];\r\n return parameter === null || parameter === undefined;\r\n }\r\n\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsPollutantOutline`, directive)\r\n .controller(`esbsPollutantOutlineController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n scenario: `=`\r\n },\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `esLeafletData`,\r\n `leafletLib`\r\n ];\r\n\r\n function controller($scope, _, esLeafletData, L) {\r\n const vm = this;\r\n\r\n let outline = null;\r\n let arrows = null;\r\n\r\n activate();\r\n\r\n ///////////////////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(map => {\r\n showPollutantBlastOutlineWhenBlastParametersAreValid(map);\r\n });\r\n }\r\n\r\n function getBlastParametersForDisplay() {\r\n if (!vm.scenario) {\r\n return null;\r\n }\r\n\r\n return {\r\n latitude: vm.scenario.latitude,\r\n longitude: vm.scenario.longitude,\r\n azimuth: vm.scenario.azimuth,\r\n blastLength: vm.scenario.blastLength,\r\n blastWidth: vm.scenario.blastWidth\r\n };\r\n }\r\n\r\n function showPollutantBlastOutlineWhenBlastParametersAreValid(map) {\r\n $scope.$watch(getBlastParametersForDisplay, updatePollutantBlastOutline, true);\r\n\r\n ///////////////////\r\n\r\n function updatePollutantBlastOutline(params) {\r\n const areParametersValid = params && _.every(params, value => _.isNumber(value));\r\n if (!areParametersValid) {\r\n hidePollutantBlastOutline(map);\r\n\r\n } else {\r\n showPollutantBlastOutline(map, params);\r\n }\r\n }\r\n }\r\n\r\n function hidePollutantBlastOutline(map) {\r\n if (outline) {\r\n map.removeLayer(outline);\r\n outline = null;\r\n }\r\n\r\n if (arrows) {\r\n map.removeLayer(arrows);\r\n arrows = null;\r\n }\r\n\r\n }\r\n\r\n function showPollutantBlastOutline(map, params) {\r\n const polygonBounds = calculatePolygonBounds(map, params);\r\n\r\n if (polygonBounds.outline) {\r\n if (!outline) {\r\n outline = new L.Polygon(polygonBounds.outline, {\r\n color: `#333`,\r\n weight: 3,\r\n opacity: 1\r\n });\r\n\r\n outline.addTo(map);\r\n\r\n } else {\r\n outline.setLatLngs(polygonBounds.outline);\r\n }\r\n }\r\n\r\n if (polygonBounds.arrows) {\r\n if (!arrows) {\r\n arrows = new L.Polyline(polygonBounds.arrows, {\r\n color: `#ffd`,\r\n weight: 2,\r\n opacity: 1\r\n });\r\n\r\n arrows.addTo(map);\r\n\r\n } else {\r\n arrows.setLatLngs(polygonBounds.arrows);\r\n }\r\n }\r\n }\r\n\r\n function calculatePolygonBounds(map, params) {\r\n // Get a point (X,Y) for the centre of the blast\r\n const centreLatLng = L.latLng([params.latitude, params.longitude]);\r\n const centrePoint = convertToCartesian(centreLatLng);\r\n const scale = calculateScale();\r\n\r\n // Map back to lat longs.\r\n return {\r\n outline: calculateOutlinePoints(),\r\n arrows: calculateArrowPoints()\r\n };\r\n\r\n function calculateScale() {\r\n const referencePoint = convertToLatLng([centrePoint.x + 1000, centrePoint.y]);\r\n const metresToReferencePoint = centreLatLng.distanceTo(referencePoint);\r\n\r\n return Math.abs(metresToReferencePoint) / 1000;\r\n }\r\n\r\n function calculateTranslationDelta(width, length, azimuth) {\r\n if (!(width && length)) {\r\n return null;\r\n }\r\n\r\n width /= scale;\r\n length /= scale;\r\n\r\n // Radius of the circle made up from this width/length\r\n const radius = Math.sqrt(Math.pow(width, 2) + Math.pow(length, 2));\r\n\r\n // The angle between the diagonal (radius) and the long-edge of the bounding rectangle\r\n const theta = Math.atan(length / width);\r\n\r\n // Beta is the difference between the azimuth and +/- theta (depending on which point we are swinging to).\r\n const azimuthRad = azimuth.toRad();\r\n const beta = Math.PI / 2 - azimuthRad;\r\n\r\n return {\r\n x1: radius * Math.cos(beta + theta),\r\n y1: radius * Math.sin(beta + theta),\r\n x2: radius * Math.cos(beta - theta),\r\n y2: radius * Math.sin(beta - theta)\r\n };\r\n }\r\n\r\n function calculateOutlinePoints() {\r\n // Use half width/height since the centre point is half way along each edge\r\n const width = params.blastWidth / 2;\r\n const length = params.blastLength / 2;\r\n const delta = calculateTranslationDelta(width, length, params.azimuth);\r\n if (!delta) {\r\n return;\r\n }\r\n\r\n const points = [\r\n [centrePoint.x + delta.x1, centrePoint.y - delta.y1],\r\n [centrePoint.x + delta.x2, centrePoint.y - delta.y2],\r\n [centrePoint.x - delta.x1, centrePoint.y + delta.y1],\r\n [centrePoint.x - delta.x2, centrePoint.y + delta.y2]\r\n ];\r\n\r\n return _.map(points, point => convertToLatLng(point));\r\n }\r\n\r\n function calculateArrowPoints() {\r\n const arrowLength = params.blastWidth / 2 * 0.75;\r\n const offsetFromCentre = params.blastLength / 4;\r\n const arrowLineDelta = calculateTranslationDelta(arrowLength, offsetFromCentre, params.azimuth);\r\n if (!arrowLineDelta) {\r\n return;\r\n }\r\n\r\n const topArrow = createArrowPoints(\r\n L.point([centrePoint.x + arrowLineDelta.x1, centrePoint.y - arrowLineDelta.y1]),\r\n L.point([centrePoint.x - arrowLineDelta.x2, centrePoint.y + arrowLineDelta.y2])\r\n );\r\n\r\n const bottomArrow = createArrowPoints(\r\n L.point([centrePoint.x + arrowLineDelta.x2, centrePoint.y - arrowLineDelta.y2]),\r\n L.point([centrePoint.x - arrowLineDelta.x1, centrePoint.y + arrowLineDelta.y1])\r\n );\r\n\r\n return topArrow.concat(bottomArrow);\r\n\r\n function createArrowPoints(tip, tail) {\r\n const headLength = arrowLength * 0.4;\r\n const headSpread = arrowLength * 0.15;\r\n\r\n const arrowHeadDelta = calculateTranslationDelta(headLength, headSpread, params.azimuth);\r\n const tipPoint1 = [tip.x - arrowHeadDelta.x1, tip.y + arrowHeadDelta.y1];\r\n const tipPoint2 = [tip.x - arrowHeadDelta.x2, tip.y + arrowHeadDelta.y2];\r\n\r\n const arrowLines = [\r\n [tip, tail],\r\n [tip, tipPoint1],\r\n [tip, tipPoint2]\r\n ];\r\n\r\n return _.map(arrowLines, linePoints => _.map(linePoints, point => convertToLatLng(point)));\r\n }\r\n }\r\n\r\n function convertToCartesian(point) {\r\n return map.latLngToContainerPoint(point);\r\n }\r\n\r\n function convertToLatLng(point) {\r\n return map.containerPointToLatLng(point);\r\n }\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsTimeSelector`, esbsTimeSelector)\r\n .controller(`esbsTimeSelectorController`, esbsTimeSelectorController);\r\n\r\n function esbsTimeSelector() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n state: `=state`\r\n },\r\n templateUrl: `/App/ui/features/blasting/controls/esbsTimeSelector.html`,\r\n controller: esbsTimeSelectorController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esbsTimeSelectorController.$inject = [\r\n `$scope`,\r\n `i18n`,\r\n `lodash`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function esbsTimeSelectorController($scope, i18n, _, timeZoneDateTime, dateTimeService) {\r\n const vm = this;\r\n\r\n vm.modelGroups = null;\r\n vm.timeGroups = null;\r\n\r\n vm.toggleLegend = toggleLegend;\r\n vm.toggleTimeSelectedForModel = toggleTimeSelectedForModel;\r\n vm.toggleModelSelectedForTime = toggleModelSelectedForTime;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n createGroupsWhenScenarioChanges();\r\n updateGroupsWhenGroupingChanges();\r\n }\r\n\r\n function createGroupsWhenScenarioChanges() {\r\n $scope.$watch(() => vm.state.scenario, createScenarioGroups);\r\n $scope.$watch(() => vm.state.selectedModelCategory, createScenarioGroups);\r\n\r\n function createScenarioGroups() {\r\n const scenario = vm.state.scenario;\r\n const models = _.chain(_.values(scenario.models))\r\n .filter(model => model.modelCategory === vm.state.selectedModelCategory)\r\n .sortBy(model => {\r\n model.label = i18n.i10n(`esbsTimeSelectorHeading.blastModelTypes.${model.modelType}.label`);\r\n return model.label;\r\n })\r\n .value();\r\n\r\n vm.modelGroups = createModelGroups(models, scenario.blastTimesMillis);\r\n vm.timeGroups = createTimeGroups(models, scenario.blastTimesMillis);\r\n\r\n updateGroupsFromState();\r\n }\r\n\r\n function createModelGroups(models, blastTimesMillis) {\r\n return _.map(models, model => ({\r\n model: model,\r\n times: _.map(blastTimesMillis, timeMillis => {\r\n const facilityDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(timeMillis));\r\n\r\n return {\r\n timeMillis,\r\n label: dateTimeService.formatAs.dateTime(facilityDate),\r\n isSelected: false,\r\n isLegendVisible: false\r\n };\r\n })\r\n }));\r\n }\r\n\r\n function createTimeGroups(models, blastTimesMillis) {\r\n if (!(models && models.length)) {\r\n return;\r\n }\r\n return _.map(blastTimesMillis, timeMillis => {\r\n const facilityDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date(timeMillis));\r\n\r\n return {\r\n timeMillis,\r\n label: dateTimeService.formatAs.dateTime(facilityDate),\r\n models: _.map(models, model => ({\r\n model,\r\n isSelected: false,\r\n isLegendVisible: false\r\n }))\r\n };\r\n });\r\n }\r\n }\r\n\r\n function updateGroupsWhenGroupingChanges() {\r\n $scope.$watch(() => vm.state.selectedModelGroupingType, updateGroupsFromState);\r\n }\r\n\r\n function updateGroupsFromState() {\r\n if (!vm.state.selectedModelGroupingType){\r\n return;\r\n }\r\n const selectedType = vm.state.selectedModelGroupingType;\r\n const selectedModels = vm.state.selectedModels;\r\n\r\n if (selectedType === vm.state.modelGroupingTypes.model.type) {\r\n updateModelGroupsFromState(selectedModels);\r\n\r\n } else if (selectedType === vm.state.modelGroupingTypes.time.type) {\r\n updateTimeGroupsFromState(selectedModels);\r\n\r\n } else {\r\n throw new Error(`Unknown model grouping type: ${selectedType}`);\r\n }\r\n }\r\n\r\n function updateModelGroupsFromState(selectedModels) {\r\n _.forEach(vm.modelGroups, grouping => {\r\n const selectedTimesForModel = selectedModels[grouping.model.id] || [];\r\n\r\n _.forEach(grouping.times, time => {\r\n time.isSelected = !!_.find(selectedTimesForModel, selectedTimeMillis => selectedTimeMillis === time.timeMillis);\r\n });\r\n });\r\n }\r\n\r\n function updateTimeGroupsFromState(selectedModels) {\r\n // Remap the active models to be indexed by time\r\n const selectedTimes = {};\r\n _.forEach(selectedModels, (timesMillis, modelId) => {\r\n _.forEach(timesMillis, timeMillis => {\r\n const models = selectedTimes[timeMillis] || (selectedTimes[timeMillis] = []);\r\n models.push(modelId);\r\n });\r\n });\r\n\r\n _.forEach(vm.timeGroups, grouping => {\r\n const selectedModelsForTime = selectedTimes[grouping.timeMillis] || [];\r\n\r\n _.forEach(grouping.models, model => {\r\n model.isSelected = !!_.find(selectedModelsForTime, modelId => modelId === model.model.id);\r\n });\r\n });\r\n }\r\n\r\n function toggleLegend(model) {\r\n model.isLegendVisible = !model.isLegendVisible;\r\n }\r\n\r\n function toggleTimeSelectedForModel(grouping, time) {\r\n vm.state.setModelSelected(grouping.model.id, time.timeMillis, time.isSelected);\r\n }\r\n\r\n function toggleModelSelectedForTime(grouping, model) {\r\n vm.state.setModelSelected(model.model.id, grouping.timeMillis, model.isSelected);\r\n }\r\n }\r\n\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .directive(`esbsVibrationPointsOfInterest`, directive)\r\n .controller(`esbsVibrationPointsOfInterestController`, controller);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`,\r\n scenario: `=`\r\n },\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `$q`,\r\n `lodash`,\r\n `esLeafletData`,\r\n `leafletLib`,\r\n `app.core.services.monitoringService`,\r\n `app.core.services.configuration.monitoringService`,\r\n `app.core.models.blasting.VibrationPointOfInterestMapMarker`\r\n ];\r\n\r\n function controller($scope, $q, _, esLeafletData, L, monitoringService, configMonitoringService, VibrationPointOfInterestMapMarker) {\r\n const vm = this;\r\n activate();\r\n\r\n ///////////////////\r\n\r\n function activate() {\r\n esLeafletData.getMap(vm.mapId).then(getVibrationMonitors);\r\n }\r\n\r\n function getVibrationMonitors() {\r\n $scope.$watch(() => vm.scenario.isGroundVibrationSelected, loadAndDisplayVibrationMonitors);\r\n\r\n function loadAndDisplayVibrationMonitors(isSelected) {\r\n if (!vm.scenario.groundVibrationPois && isSelected) {\r\n loadVibrationMonitors().then(monitors => {\r\n vm.scenario.groundVibrationPois = monitors;\r\n vm.scenario.map.markers = bindMarkers();\r\n });\r\n }\r\n else {\r\n vm.scenario.map.markers = isSelected ? bindMarkers() : [];\r\n }\r\n }\r\n\r\n function bindMarkers(){\r\n return vm.scenario.groundVibrationPois && vm.scenario.groundVibrationPois.map(monitor => new VibrationPointOfInterestMapMarker(monitor));\r\n }\r\n\r\n function loadVibrationMonitors(){\r\n return monitoringService.getMonitorsByType().then(monitorsByType => {\r\n if (monitorsByType.vibrationMonitor) {\r\n const monitorLoaders = _.map(monitorsByType.vibrationMonitor.monitorIds, id =>\r\n configMonitoringService.getMonitor(monitorsByType.vibrationMonitor.monitorType, id));\r\n return $q.all(monitorLoaders);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .factory(`app.ui.features.blasting.hashParser`, hashParser);\r\n\r\n hashParser.$inject = [];\r\n\r\n /* istanbul ignore next */\r\n function hashParser() {\r\n return {\r\n buildScenarioOptionsHash,\r\n configureScenarioOptionsFromHash\r\n };\r\n\r\n ////////////////////\r\n\r\n function buildScenarioOptionsHash(modelCategory) {\r\n return `${modelCategory}`;\r\n }\r\n\r\n function configureScenarioOptionsFromHash(hash, scenarioModelsState) {\r\n const options = parseHashString(hash);\r\n\r\n scenarioModelsState.selectedModelCategory = options.modelCategory;\r\n }\r\n\r\n function parseHashString(hash = ``) {\r\n const parts = hash.split(`|`);\r\n\r\n return {\r\n modelCategory: parts[0]\r\n };\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .config(configureRouteAliases)\r\n .run(appRun);\r\n\r\n configureRouteAliases.$inject = [`$urlRouterProvider`];\r\n function configureRouteAliases($urlRouterProvider) {\r\n $urlRouterProvider.when(`/blasting/:companyAlias/:facilityAlias`, redirectTo);\r\n $urlRouterProvider.when(`/blasting/:companyAlias/:facilityAlias/`, redirectTo);\r\n\r\n redirectTo.$inject = [`$state`, `$match`];\r\n\r\n function redirectTo($state, $match) {\r\n $state.go(`app.blasting.scenarios`, {\r\n companyAlias: $match.companyAlias,\r\n facilityAlias: $match.facilityAlias\r\n });\r\n }\r\n }\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.blasting.scenarioModelsState`,\r\n `app.ui.features.blasting.scenarioConfigurationState`\r\n ];\r\n /* istanbul ignore next */\r\n function appRun(routeHelper, scenarioModelsState, scenarioConfigurationState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n abstract: true,\r\n state: `app.blasting`,\r\n url: `/blasting/:companyAlias/:facilityAlias`,\r\n data: {\r\n requiredAccessControl: `app.blasting`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/blasting/i18n/blasting`,\r\n `/App/ui/features/blasting/controls/i18n/esBlastingScenario`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.blasting.scenarios`,\r\n url: `/scenarios`,\r\n views: {\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/blasting/ScenarioSelectionContentPanel.html`,\r\n controller: `app.ui.features.blasting.ScenarioSelectionContentPanel as vm`\r\n }\r\n },\r\n data: {\r\n requiredAccessControl: `app.blasting`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/controls/i18n/esList`\r\n ]\r\n },\r\n resolve: {\r\n scenarioModelsState: scenarioModelsState\r\n }\r\n },\r\n {\r\n state: `app.blasting.scenarios.scenario`,\r\n url: `/scenario/:scenarioAlias`, // view scenario models\r\n views: {\r\n 'actionsPanel@app': {\r\n templateUrl: `/App/ui/features/blasting/ScenarioModelsActionsPanel.html`,\r\n controller: `app.ui.features.blasting.ScenarioModelsActionsPanel as vm`\r\n },\r\n 'leftPanel@app': {\r\n templateUrl: `/App/ui/features/blasting/ScenarioModelsLeftPanel.html`,\r\n controller: `app.ui.features.blasting.ScenarioModelsLeftPanel as vm`\r\n },\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/blasting/ScenarioModelsContentPanel.html`,\r\n controller: `app.ui.features.blasting.ScenarioModelsContentPanel as vm`\r\n }\r\n },\r\n data: {\r\n // We need to explicitly set the layout type since this route's layout is different from the\r\n // layout of its parent route (app.blasting).\r\n layoutType: `split`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/mapping/i18n/mapLayerRenderer`,\r\n `/App/ui/core/mapping/controls/i18n/esMapKml`,\r\n `/App/ui/core/mapping/controls/i18n/esMapTiles`,\r\n `/App/ui/core/mapping/controls/i18n/esMapType`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCredits`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCentre`,\r\n `/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries`,\r\n `/App/ui/core/controls/i18n/esTimeSlider`,\r\n `/App/ui/features/blasting/controls/i18n/esbsFlyrockLegend`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.blasting.scenarios.add`,\r\n url: `/scenario/add/:scenarioAlias`, // create a new scenario or duplicate an existing scenario\r\n views: {\r\n 'leftPanel@app': {\r\n templateUrl: `/App/ui/features/blasting/AddScenarioLeftPanel.html`,\r\n controller: `app.ui.features.blasting.AddScenarioLeftPanel as vm`\r\n },\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/blasting/AddScenarioContentPanel.html`,\r\n controller: `app.ui.features.blasting.AddScenarioContentPanel as vm`\r\n }\r\n },\r\n data: {\r\n layoutType: `split`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/mapping/controls/i18n/esMapKml`,\r\n `/App/ui/core/mapping/controls/i18n/esMapTiles`,\r\n `/App/ui/core/mapping/controls/i18n/esMapType`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCredits`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCentre`,\r\n `/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries`,\r\n `/App/ui/core/mapping/controls/i18n/esMapLocationSelector`,\r\n `/App/ui/features/blasting/controls/configuration/i18n/esBlastingScenarioConfig`\r\n ]\r\n },\r\n resolve: {\r\n scenarioConfigurationState: scenarioConfigurationState\r\n }\r\n\r\n }\r\n ];\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .factory(`app.ui.features.blasting.scenarioConfigurationState`, stateFactory);\r\n\r\n stateFactory.$inject = [\r\n `$q`,\r\n `i18n`,\r\n `lodash`,\r\n `app.core.appSettings`,\r\n `app.core.services.companyService`,\r\n `app.core.services.configuration.blastingService`,\r\n `app.core.models.blasting.blastModelType`,\r\n `app.core.models.blasting.blastSetup`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function stateFactory($q, i18n, _, appSettings, companyService, blastingService, blastModelType, blastSetup) {\r\n return function stateFactoryResolver() {\r\n const loaders = [\r\n companyService.getFacilityLocation(),\r\n blastingService.getModelOptions(),\r\n blastingService.getModelTypes()\r\n ];\r\n\r\n return $q.all(loaders).then(results => {\r\n const [facilityLocation, modelOptions, modelTypes] = results;\r\n\r\n return new ScenarioConfigurationState(facilityLocation, modelOptions, modelTypes);\r\n });\r\n };\r\n\r\n function ScenarioConfigurationState(facilityLocation, modelOptions, modelTypes) {\r\n const self = this;\r\n\r\n self.lookups = {\r\n facilityLocation,\r\n windScientificModelOptions: modelOptions.windGisModelOptions.windScientificModels,\r\n pollutantOptions: modelOptions.pollutantGisModelOptions.pollutantOptions,\r\n pollutantScientificModelOptions: modelOptions.pollutantGisModelOptions.pollutantScientificModelOptions,\r\n pollutantDisplayUnitOptions: modelOptions.pollutantGisModelOptions.pollutantDisplayUnitOptions,\r\n noxScale: modelOptions.pollutantGisModelOptions.noxScale,\r\n forwardTrajectoryScientificModelOptions: modelOptions.forwardTrajectoryModelOptions.forwardTrajectoryScientificModels\r\n };\r\n\r\n // Default the wind to a two-minute interval if we have one\r\n const defaultWindScientificModel = _.find(self.lookups.windScientificModelOptions, { intervalDurationInMinutes: 2 });\r\n const defaultWindScientificModelId = defaultWindScientificModel && defaultWindScientificModel.id || undefined;\r\n\r\n // Typically there should only be one forward track - \"Blast Traj\".\r\n const defaultForwardTrajectoryScientificModelId = self.lookups.forwardTrajectoryScientificModelOptions.length === 1 ? self.lookups.forwardTrajectoryScientificModelOptions[0].id : undefined;\r\n\r\n // Default the pollutant to oxide of nitrogen if present\r\n const nox = _.find(self.lookups.pollutantOptions, pollutant => pollutant.libraryPollutantId.toLowerCase() === `b183985a-f356-4204-87e7-246a95ec3315`);\r\n const defaultModelPollutantId = nox && nox.modelPollutantId || undefined;\r\n\r\n let defaultPollutantDisplayUnitId, defaultPollutantScientificModelId;\r\n\r\n if (nox) {\r\n // Default the display unit to micro-grams per cubic metre\r\n const defaultUnit = _.find(nox.displayUnitOptions, displayUnit => displayUnit.id.toLowerCase() === `bd7b6b9c-d634-4a96-ba6b-35ef9dae82a3`);\r\n defaultPollutantDisplayUnitId = defaultUnit && defaultUnit.id || undefined;\r\n\r\n // For scientific model, auto-select the first items in the cascaded drop-downs (like kendo does).\r\n defaultPollutantScientificModelId = nox.associatedPlumeScientificModels.length\r\n ? nox.associatedPlumeScientificModels[0].id\r\n : null;\r\n }\r\n\r\n self.canUpdateOverpressureModels = appSettings.site.accessControls[`app.blasting.overpressure`];\r\n self.canUpdateFlyrockModels = appSettings.site.accessControls[`app.blasting.flyrock`];\r\n self.canUpdateGroundvibrationModels = appSettings.site.accessControls[`app.blasting.ground-vibration`];\r\n\r\n // the form data\r\n self.name = ``;\r\n self.alias = ``;\r\n self.blastTimesMillis = [];\r\n self.latitude = null;\r\n self.longitude = null;\r\n\r\n const overlayFiles = {};\r\n Object.defineProperty(self, `overlayFiles`, { get: () => overlayFiles });\r\n\r\n self.models = {\r\n path: false,\r\n dispersion: false,\r\n fmz: false,\r\n gain: false,\r\n contour: false,\r\n flyrock: false,\r\n groundVibration: false\r\n };\r\n\r\n self.windScientificModelId = defaultWindScientificModelId;\r\n self.forwardTrajectoryScientificModelId = defaultForwardTrajectoryScientificModelId;\r\n self.blastHeight = null;\r\n self.blastLength = null;\r\n self.blastWidth = null;\r\n self.azimuth = null;\r\n self.elevation = null;\r\n self.modelPollutantId = defaultModelPollutantId;\r\n self.pollutantScientificModelId = defaultPollutantScientificModelId;\r\n self.displayUnitId = defaultPollutantDisplayUnitId;\r\n self.defaultConcentrations = modelOptions.pollutantGisModelOptions.defaultConcentrations;\r\n self.initialConcentration = self.defaultConcentrations.get(defaultPollutantScientificModelId);\r\n self.chargeMass = null;\r\n self.chargeMassPerHole = null;\r\n self.holeDiameter = null;\r\n self.blastSetup = blastSetup.burden;\r\n self.burden = null;\r\n self.stemmingHeight = null;\r\n self.frontFaceKFactor = null;\r\n self.backFaceKFactor = null;\r\n\r\n self.flyrockSiteConstantKv = getDefaultConfigurationValue(blastModelType.flyrock, `Kv`);\r\n self.dispersalAngle = getDefaultConfigurationValue(blastModelType.flyrock, `DispersalAngle`);\r\n\r\n self.groundVibrationSiteExponentKb = getDefaultConfigurationValue(blastModelType.groundVibration, `Kb`);\r\n self.groundVibrationSiteConstantKv = getDefaultConfigurationValue(blastModelType.groundVibration, `Kv`);\r\n\r\n Object.defineProperty(self, `isPathModelSelected`, { get: () => self.models.path });\r\n Object.defineProperty(self, `isPollutantModelSelected`, { get: () => self.models.dispersion || self.models.fmz });\r\n Object.defineProperty(self, `isOverpressureModelSelected`, { get: () => self.models.contour || self.models.gain });\r\n Object.defineProperty(self, `isFlyrockSelected`, { get: () => self.models.flyrock });\r\n Object.defineProperty(self, `isGroundVibrationSelected`, { get: () => self.models.groundVibration });\r\n\r\n Object.defineProperty(self, `isNOxPollutant`, {\r\n get: () => {\r\n const modelPollutant = _.find(self.lookups.pollutantOptions, { modelPollutantId: self.modelPollutantId });\r\n return modelPollutant && blastingService.isNOxPollutant(modelPollutant.libraryPollutantId);\r\n }\r\n });\r\n\r\n ////////////////////\r\n\r\n function getDefaultConfigurationValue(blastModelType, key){\r\n const config = modelTypes[blastModelType];\r\n return config && config[key];\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .controller(`app.ui.features.blasting.ScenarioModelsActionsPanel`, ActionsPanel);\r\n\r\n ActionsPanel.$inject = [\r\n `scenarioModelsState`\r\n ];\r\n\r\n function ActionsPanel(state) {\r\n const vm = this;\r\n vm.state = state;\r\n\r\n activate();\r\n\r\n /////////////////////\r\n \r\n function activate() {\r\n }\r\n\r\n }\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.features.blasting`)\n .controller(`app.ui.features.blasting.ScenarioModelsContentPanel`, ScenarioModelsContentPanel);\n\n ScenarioModelsContentPanel.$inject = [\n `$scope`,\n `$state`,\n `esLeafletData`,\n `leafletLib`,\n `i18n`,\n `lodash`,\n `app.core.appSettings`,\n `app.core.services.locationService`,\n `app.ui.features.blasting.BlastDataMediator`,\n `scenarioModelsState`,\n `app.core.services.blastingService`,\n `app.core.services.mappingService`\n ];\n\n /* istanbul ignore next */\n function ScenarioModelsContentPanel($scope, $state, esLeafletData, L, i18n, _, appSettings, locationService, BlastDataMediator, state, blastingService, mappingService) {\n const vm = this;\n\n let blastCentreMarker = null;\n let resolveMap = null;\n\n vm.state = state;\n vm.scenarioAlias = $state.params.scenarioAlias;\n\n vm.map = state.map;\n vm.map.id = `map-canvas`;\n vm.map.overlayProvider = {};\n vm.mapLayerDatasets = [];\n\n vm.activeOffsetMinutes = 0;\n vm.onActiveOffsetChanged = onActiveOffsetChanged;\n vm.activeOffsetTooltip = {\n template: stepValue => i18n.i10n(`app.ui.features.blasting.scenarioModelsContentPanel.timeOffset`, {\n offsetMinutes: stepValue.value\n })\n };\n\n vm.isAnimatedModel = false;\n vm.hasSelectedModels = false;\n vm.hasModelData = false;\n\n const mediator = new BlastDataMediator(state, esLeafletData.getMap(vm.map.id), onMediatorRefreshed);\n\n activate();\n\n //////////////////////\n\n function activate() {\n locationService.updatePageHeading({ name: vm.scenarioAlias });\n locationService.updateExitPoint(`app.blasting.scenarios`, {\n companyAlias: appSettings.site.company.alias,\n facilityAlias: appSettings.site.facility.alias\n });\n\n resolveMap = esLeafletData.getMap(vm.map.id);\n\n showBlastOriginWhenScenarioIsLoaded();\n updateIsAnimatedWhenModelCategoryChanges();\n updateVisibleModelsWhenSelectedModelsChange();\n destroyMediatorOnDeactivate();\n\n loadOverlays();\n }\n\n function loadOverlays() {\n $scope.$watch(() => vm.state.scenario, onScenarioUpdated);\n\n mappingService.getKmls().then(addOverlays);\n\n function onScenarioUpdated(scenario, existingScenario) {\n if (scenario === existingScenario) {\n return;\n }\n\n blastingService.getOverlays(scenario.id).then(addOverlays);\n }\n\n function addOverlays(overlays) {\n _.forEach(overlays, overlay => {\n vm.map.overlayProvider[overlay.name] = overlay;\n });\n }\n }\n\n function destroyMediatorOnDeactivate() {\n $scope.$on(`$destroy`, mediator.dispose);\n }\n\n function showBlastOriginWhenScenarioIsLoaded() {\n $scope.$watch(() => vm.state.scenario.blastParameters, showBlastOrigin);\n\n ////////////////////\n\n function showBlastOrigin(blastParameters) {\n if (!blastParameters) {\n return;\n }\n\n if (blastCentreMarker) {\n blastCentreMarker.setLatLng(new L.LatLng(blastParameters.latitude, blastParameters.longitude));\n\n } else {\n const icon = new L.AwesomeMarkers.Icon({\n prefix: `fa`,\n icon: `bomb`,\n markerColor: `orange`\n });\n\n blastCentreMarker = new L.Marker([blastParameters.latitude, blastParameters.longitude], {\n icon,\n clickable: false,\n keyboard: false\n });\n\n resolveMap.then(map => blastCentreMarker.addTo(map));\n }\n }\n }\n\n function updateIsAnimatedWhenModelCategoryChanges() {\n $scope.$watch(() => vm.state.selectedModelCategory, category => {\n const isAnimatedModel = category === vm.state.modelCategories.animated.type;\n if (isAnimatedModel === vm.isAnimatedModel) {\n return;\n }\n\n vm.isAnimatedModel = isAnimatedModel;\n triggerMapResize();\n\n vm.activeOffsetMinutes = 0;\n mediator.refresh();\n });\n }\n\n function updateVisibleModelsWhenSelectedModelsChange() {\n const selectedModels = state.selectedModels;\n\n $scope.$watch(() => selectedModels, updateVisibleModels, true);\n\n ////////////////////\n\n function updateVisibleModels(selectedModels) {\n const hadSelectedModels = vm.hasSelectedModels;\n vm.hasSelectedModels = !_.isEmpty(selectedModels);\n\n if (vm.hasSelectedModels !== hadSelectedModels) {\n triggerMapResize();\n }\n\n mediator.refresh();\n }\n }\n\n function onActiveOffsetChanged(offsetMinutes) {\n vm.activeOffsetMinutes = offsetMinutes;\n bindVisibleTimeStepDataToMap(offsetMinutes);\n }\n\n function onMediatorRefreshed() {\n vm.hasModelData = state.blastDataStore.hasImportedData();\n\n bindVisibleTimeStepDataToMap();\n }\n\n function bindVisibleTimeStepDataToMap(offsetMinutes) {\n vm.mapLayerDatasets = state.blastDataStore.getDataAtOffset(offsetMinutes || vm.activeOffsetMinutes);\n }\n\n function triggerMapResize() {\n $scope.$broadcast(`resizePage`);\n }\n }\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .controller(`app.ui.features.blasting.ScenarioModelsLeftPanel`, ScenarioModelsLeftPanel);\r\n\r\n ScenarioModelsLeftPanel.$inject = [\r\n `$state`,\r\n `$location`,\r\n `i18n`,\r\n `promiseTracker`,\r\n `lodash`,\r\n `app.ui.features.blasting.hashParser`,\r\n `app.core.models.blasting.blastModelCategory`,\r\n `app.core.services.blastingService`,\r\n `scenarioModelsState`,\r\n `app.core.services.configuration.blastingService`,\r\n `confirmationDialog`,\r\n `app.core.appSettings`\r\n ];\r\n /* istanbul ignore next */\r\n function ScenarioModelsLeftPanel($state, $location, i18n, promiseTracker, _, hashParser, blastModelCategory, blastingService, scenarioModelsState, blastingConfigurationService, confirmationDialog, appSettings) {\r\n const vm = this;\r\n vm.scenarioAlias = $state.params.scenarioAlias;\r\n vm.state = scenarioModelsState;\r\n vm.deleteScenario = deleteScenario;\r\n vm.busyLoading = promiseTracker();\r\n vm.showBottomControls = appSettings.site.accessControls[`app.blasting.modify`];\r\n\r\n activate();\r\n\r\n //////////////////////\r\n\r\n function activate() {\r\n configureScenarioOptions();\r\n loadScenarioModels();\r\n\r\n function configureScenarioOptions() {\r\n hashParser.configureScenarioOptionsFromHash($location.search().scenarioHash, scenarioModelsState);\r\n\r\n if (!scenarioModelsState.selectedModelCategory) {\r\n scenarioModelsState.selectedModelCategory = scenarioModelsState.getDefaultModelCategory().type;\r\n }\r\n\r\n if (!scenarioModelsState.selectedModelGroupingType) {\r\n scenarioModelsState.selectedModelGroupingType = scenarioModelsState.getDefaultModelGroupingType().type;\r\n }\r\n }\r\n }\r\n\r\n function deleteScenario() {\r\n const headingKey = `app.ui.features.blasting.scenarioModelsLeftPanel.remove.heading`;\r\n const descKey = `app.ui.features.blasting.scenarioModelsLeftPanel.remove.instructions`;\r\n\r\n const modalOptions = {\r\n css: `modal-center`,\r\n buttons: {\r\n 'continue': {\r\n text: i18n.i10n(`buttons.delete`)\r\n }\r\n }\r\n };\r\n\r\n confirmationDialog.ask(headingKey, descKey, modalOptions).then(onConfirm);\r\n\r\n function onConfirm() {\r\n const removalPromise = blastingConfigurationService.deleteScenario(vm.scenarioAlias);\r\n removalPromise.then(removeSuccess);\r\n }\r\n\r\n function removeSuccess() {\r\n $state.go(`app.blasting.scenarios`);\r\n }\r\n }\r\n\r\n function loadScenarioModels() {\r\n const scenarioPromise = blastingService.getScenario(vm.scenarioAlias);\r\n vm.busyLoading.addPromise(scenarioPromise);\r\n\r\n scenarioPromise.then(scenario => {\r\n vm.state.scenario = scenario;\r\n\r\n const hasAnimatedModels = _.find(scenario.models, { modelCategory: blastModelCategory.animated });\r\n vm.state.selectedModelCategory = hasAnimatedModels ? blastModelCategory.animated : blastModelCategory.snapshot;\r\n });\r\n }\r\n }\r\n})();\r\n","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .factory(`app.ui.features.blasting.scenarioModelsState`, stateFactory);\r\n\r\n stateFactory.$inject = [\r\n `$q`,\r\n `i18n`,\r\n `lodash`,\r\n `app.core.mapDefaults`,\r\n `app.core.models.modelLoadingStatus`,\r\n `app.core.models.blasting.blastModelCategory`,\r\n `app.core.models.blasting.blastSetup`,\r\n `app.core.services.companyService`,\r\n `app.ui.features.blasting.BlastDataStore`\r\n ];\r\n\r\n function stateFactory($q, i18n, _, mapDefaults, modelLoadingStatus, blastModelCategory, blastSetup, companyService, BlastDataStore) {\r\n return function stateFactoryResolver() {\r\n const loaders = [\r\n companyService.getFacilityLocation(),\r\n companyService.getDomainBoundaries(false, true, false)\r\n ];\r\n\r\n return $q.all(loaders).then(results => {\r\n const [facilityLocation, domainBoundaries] = results;\r\n return new ScenarioModelsState(facilityLocation, domainBoundaries);\r\n });\r\n };\r\n\r\n function ScenarioModelsState(facilityLocation, domainBoundaries) {\r\n const self = this;\r\n\r\n this.modelCategories = _.chain(blastModelCategory)\r\n .map(buildModelCategory)\r\n .keyBy(`type`)\r\n .value();\r\n\r\n this.modelGroupingTypes = {\r\n model: buildModelGroupingType(`model`),\r\n time: buildModelGroupingType(`time`)\r\n };\r\n\r\n this.simulationParameters = {\r\n // How long each blast simulation runs for\r\n durationMinutes: 60,\r\n\r\n // Interval between each data point in the simulation data\r\n intervalMinutes: 2\r\n };\r\n\r\n this.scenario = { blastSetup: blastSetup.burden };\r\n this.selectedModelGroupingType = null;\r\n\r\n const selectedModels = {};\r\n let selectedModelCategory = null;\r\n\r\n Object.defineProperty(this, `selectedModels`, { get: () => selectedModels });\r\n Object.defineProperty(this, `selectedModelCategory`, {\r\n get: () => selectedModelCategory,\r\n set: value => {\r\n if (selectedModelCategory === value) {\r\n return;\r\n }\r\n\r\n selectedModelCategory = value;\r\n _.forEach(_.keys(selectedModels), key => delete selectedModels[key]);\r\n }\r\n });\r\n\r\n this.map = {\r\n defaultCentre: facilityLocation,\r\n centre: facilityLocation,\r\n defaults: {\r\n settings: mapDefaults.settings\r\n },\r\n bounds: getMapBounds(),\r\n isColor: false,\r\n layers: {\r\n baselayers: mapDefaults.baselayers\r\n },\r\n overlayProvider: {}\r\n };\r\n\r\n this.getDefaultModelCategory = getDefaultModelCategory;\r\n this.getDefaultModelGroupingType = getDefaultModelGroupingType;\r\n\r\n this.setModelSelected = setModelSelected;\r\n this.isModelSelected = isModelSelected;\r\n\r\n this.getModelLoadingStatus = getModelLoadingStatus;\r\n this.setModelLoadingStatus = setModelLoadingStatus;\r\n\r\n const blastDataStore = new BlastDataStore();\r\n Object.defineProperty(this, `blastDataStore`, { get: () => blastDataStore });\r\n\r\n const modelLoadingStatuses = {};\r\n Object.defineProperty(this, `modelLoadingStatuses`, { get: () => modelLoadingStatuses });\r\n\r\n ////////////////////\r\n\r\n function getDefaultModelCategory() {\r\n return self.modelCategories.animated;\r\n }\r\n\r\n function getDefaultModelGroupingType() {\r\n return self.modelGroupingTypes.model;\r\n }\r\n\r\n function setModelSelected(modelId, timeMillis, isSelected) {\r\n const isInSelectedModels = _.has(selectedModels, modelId);\r\n\r\n if (isSelected) {\r\n if (!isInSelectedModels) {\r\n selectedModels[modelId] = [];\r\n }\r\n\r\n selectedModels[modelId].push(timeMillis);\r\n\r\n } else {\r\n if (!isInSelectedModels) {\r\n return;\r\n }\r\n\r\n const selectedTimesForModel = selectedModels[modelId];\r\n _.remove(selectedTimesForModel, selectedTimeMillis => selectedTimeMillis === timeMillis);\r\n\r\n if (!selectedTimesForModel.length) {\r\n delete selectedModels[modelId];\r\n }\r\n }\r\n }\r\n\r\n function isModelSelected(modelId, blastTimeMillis) {\r\n if (!_.has(selectedModels, modelId)) {\r\n return false;\r\n }\r\n\r\n const selectedBlastTimesForModel = selectedModels[modelId];\r\n return _.includes(selectedBlastTimesForModel, blastTimeMillis);\r\n }\r\n\r\n function getModelLoadingStatus(modelId, blastTimeMillis) {\r\n const key = buildModelLoadingStatusKey(modelId, blastTimeMillis);\r\n\r\n return modelLoadingStatuses[key] || modelLoadingStatus.pending;\r\n }\r\n\r\n function setModelLoadingStatus(modelId, blastTimeMillis, status) {\r\n const key = buildModelLoadingStatusKey(modelId, blastTimeMillis);\r\n\r\n modelLoadingStatuses[key] = status;\r\n }\r\n\r\n function buildModelLoadingStatusKey(modelId, blastTimeMillis) {\r\n if (!_.isString(modelId)) {\r\n throw new Error(`The modelId must be passed as a string; modelId provided was ${modelId}`);\r\n }\r\n\r\n if (!blastTimeMillis) {\r\n throw new Error(`You must provide the blast time in order to retrieve the loading status.`);\r\n }\r\n\r\n return `${modelId}-${blastTimeMillis}`;\r\n }\r\n\r\n function getMapBounds() {\r\n return domainBoundaries &&\r\n _.reduce(domainBoundaries, (memo, boundary) => {\r\n const coordinates = [boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight];\r\n return memo.concat(_.map(coordinates, coordinate => [coordinate.latitude, coordinate.longitude]));\r\n }, []);\r\n }\r\n }\r\n\r\n function buildModelCategory(type) {\r\n return {\r\n type,\r\n label: i18n.i10n(`esbsModelCategorySelector.modelCategories.${type}`)\r\n };\r\n }\r\n\r\n function buildModelGroupingType(groupingType) {\r\n return {\r\n type: groupingType,\r\n label: i18n.i10n(`esbsModelGroupingSelector.modelGroupingTypes.${groupingType}`)\r\n };\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.blasting`)\r\n .controller(`app.ui.features.blasting.ScenarioSelectionContentPanel`, ScenarioSelectionContentPanel);\r\n\r\n ScenarioSelectionContentPanel.$inject = [\r\n `$state`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.locationService`,\r\n `app.core.services.blastingService`,\r\n `app.core.appSettings`,\r\n `i18n`\r\n ];\r\n /* istanbul ignore next */\r\n function ScenarioSelectionContentPanel($state, _, promiseTracker, locationService, blastingService, appSettings, i18n) {\r\n const vm = this;\r\n vm.options = {\r\n dataProvider: blastingService.getScenarios,\r\n dataSource: {\r\n pageSize: 25\r\n },\r\n sortable: true,\r\n filterable: false,\r\n columns: [{\r\n title: i18n.i10n(`app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.name.heading`),\r\n field: `name`,\r\n click: onScenarioSelected\r\n },\r\n {\r\n title: i18n.i10n(`app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.firstScenarioTime.heading`),\r\n field: `firstScenarioTime`,\r\n dataType: `datetime`\r\n },\r\n {\r\n title: i18n.i10n(`app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.actualBlastTime.heading`),\r\n field: `actualBlastTime`,\r\n dataType: `datetime`\r\n },\r\n {\r\n title: i18n.i10n(`app.ui.features.blasting.scenarioSelectionContentPanel.list.columns.lastUpdated.heading`),\r\n field: `lastUpdated`,\r\n dataType: `datetime`,\r\n sort: {\r\n order: 1,\r\n dir: `desc`\r\n }\r\n }],\r\n selectedItem: {\r\n field: `alias`,\r\n value: null\r\n },\r\n busyLoading: promiseTracker(),\r\n onItemSelected: onScenarioSelected,\r\n addItem: appSettings.site.accessControls[`app.blasting.modify`] && addScenario,\r\n dataSource: {\r\n serverPaging: false,\r\n serverSorting: false,\r\n serverGrouping: false,\r\n serverFiltering: false,\r\n schema: {\r\n id: `id`\r\n }\r\n }\r\n };\r\n\r\n //////////////////////\r\n\r\n function onScenarioSelected(scenario) {\r\n locationService.updatePageHeading(scenario);\r\n $state.go(`app.blasting.scenarios.scenario`, { scenarioAlias: scenario.alias });\r\n }\r\n\r\n function addScenario(){\r\n $state.go(`app.blasting.scenarios.add`);\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.blasting`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.configuration.company.blasting.scenarios.state`\r\n ];\r\n function appRun(routeHelper, scenariosState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.blasting`,\r\n url: `/blasting`,\r\n data : {\r\n requiredAccessControl: `app.blasting.modify`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/blasting/i18n/blasting`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.blasting.scenarios`,\r\n url: `/scenarios`,\r\n views: {\r\n 'contentPanel@app': { // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\r\n templateUrl: `/App/ui/features/configuration/company/blasting/scenarios/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.company.blasting.scenarios.ContentPanel as vm`\r\n }\r\n },\r\n resolve : {\r\n scenariosState : scenariosState\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.blasting.scenarios.edit`,\r\n url: `/edit/:scenarioId`,\r\n views: {\r\n detailPanel: {\r\n templateUrl: `/App/ui/features/configuration/company/blasting/scenarios/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.blasting.scenarios.DetailPanel as vm`\r\n }\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.blasting.scenarios.add`,\r\n url: `/add`,\r\n views: {\r\n detailPanel: {\r\n templateUrl: `/App/ui/features/configuration/company/blasting/scenarios/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.blasting.scenarios.DetailPanel as vm`\r\n }\r\n }\r\n }\r\n ];\r\n }\r\n }\r\n\r\n})();","//TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\r\n/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.blasting`)\r\n .controller(`app.ui.features.configuration.company.blasting.scenarios.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.locationService`,\r\n `app.core.services.configuration.blastingService`,\r\n `scenariosState`\r\n ];\r\n\r\n function ContentPanel($scope, $state, _, promiseTracker, locationService, blastingService, scenariosState) {\r\n const vm = this;\r\n\r\n vm.listOptions = getListOptions();\r\n scenariosState.loadScenarios = loadScenarios;\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n loadScenarios().then(updateUIWithSelectedScenario);\r\n\r\n /////////////\r\n\r\n function updateUIWithSelectedScenario(scenarios) {\r\n $scope.$watch(() => $state.params.scenarioId, scenarioId => {\r\n vm.listOptions.selectedItem.value = scenarioId;\r\n locationService.updatePageHeading(_.find(scenarios, { scenarioId }));\r\n });\r\n }\r\n }\r\n\r\n function getListOptions() {\r\n return {\r\n columnDefs: [\r\n {\r\n heading: {\r\n i18n: {\r\n key: `app.ui.features.configuration.company.blasting.scenarios.contentPanel.list.columns.name.heading`\r\n }\r\n },\r\n field: `name`\r\n }\r\n ],\r\n items: [],\r\n selectedItem: {\r\n field: `scenarioId`,\r\n value: null\r\n },\r\n busyLoading: promiseTracker(),\r\n onItemSelected: onScenarioSelected,\r\n addItem: addScenario\r\n };\r\n }\r\n\r\n function addScenario() {\r\n $state.go(`app.configuration.company.blasting.scenarios.add`);\r\n }\r\n\r\n function onScenarioSelected(scenario) {\r\n $state.go(`app.configuration.company.blasting.scenarios.edit`, { scenarioId: scenario.scenarioId });\r\n }\r\n\r\n function loadScenarios() {\r\n const scenarios = blastingService.getAllScenarios().then(scenarios => vm.listOptions.items = scenarios);\r\n vm.listOptions.busyLoading.addPromise(scenarios);\r\n return scenarios;\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.blasting`)\r\n .directive(`esBlastScenarioForm`, esBlastScenarioForm)\r\n .controller(`esBlastScenarioFormController`, esBlastScenarioFormController);\r\n\r\n esBlastScenarioForm.$inject = [];\r\n\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function esBlastScenarioForm() {\r\n const directive = {\r\n restrict: `E`,\r\n scope: {\r\n state: `=`\r\n },\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: esBlastScenarioFormController,\r\n templateUrl: `/App/ui/features/configuration/company/blasting/scenarios/controls/esBlastScenarioForm.html`\r\n };\r\n return directive;\r\n }\r\n\r\n esBlastScenarioFormController.$inject = [\r\n `promiseTracker`\r\n ];\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function esBlastScenarioFormController(promiseTracker) {\r\n const vm = this;\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.blasting`)\r\n .directive(`esBlastScenarioFormMap`, esBlastScenarioFormMap)\r\n .controller(`esBlastScenarioFormMapController`, esBlastScenarioFormMapController);\r\n\r\n esBlastScenarioFormMap.$inject = [];\r\n\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function esBlastScenarioFormMap() {\r\n const directive = {\r\n restrict: `E`,\r\n scope: {\r\n state: `=`\r\n },\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: esBlastScenarioFormMapController,\r\n templateUrl: `/App/ui/features/configuration/company/blasting/scenarios/controls/esBlastScenarioFormMap.html`\r\n };\r\n return directive;\r\n }\r\n\r\n esBlastScenarioFormMapController.$inject = [\r\n `promiseTracker`,\r\n `app.core.services.configuration.blastingService`\r\n ];\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function esBlastScenarioFormMapController(promiseTracker) {\r\n const vm = this;\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n }\r\n }\r\n\r\n})();","//TODO: 22/06/2015 - bpriebe - remove the instanbul flag once tests are in place.\r\n/* istanbul ignore next */\r\n(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.blasting`)\r\n .controller(`app.ui.features.configuration.company.blasting.scenarios.DetailPanel`, DetailPanel);\r\n\r\n DetailPanel.$inject = [\r\n `$q`,\r\n `$state`,\r\n `promiseTracker`,\r\n `app.core.services.configuration.blastingService`,\r\n `scenariosState`\r\n ];\r\n\r\n function DetailPanel($q, $state, promiseTracker, blastingService, scenariosState) {\r\n const vm = this;\r\n vm.state = scenariosState;\r\n\r\n const scenarioId = $state.params.scenarioId;\r\n vm.isNew = !scenarioId;\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n const loadingPromise = !vm.isNew ? loadScenario() : $q.when();\r\n vm.busyLoading.addPromise(loadingPromise);\r\n }\r\n\r\n function loadScenario() {\r\n return blastingService.getScenario(scenarioId).then(scenario => vm.state.selectedScenario = scenario);\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.blasting`)\r\n .factory(`app.ui.features.configuration.company.blasting.scenarios.state`, stateFactory);\r\n\r\n stateFactory.$inject = [];\r\n function stateFactory() {\r\n\r\n function stateFactoryResolver() {\r\n return {\r\n loadScenarios : angular.noop\r\n };\r\n }\r\n\r\n return stateFactoryResolver;\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .component(`modelling.aermet.contentPanel`, {\r\n controller: ContentPanelController,\r\n templateUrl: `/App/ui/features/configuration/company/modelling/aermet/ContentPanel.html`,\r\n controllerAs: `vm`,\r\n bindings: {\r\n state: `<`\r\n }\r\n });\r\n\r\n ContentPanelController.$inject = [\r\n `lodash`,\r\n `i18n`,\r\n `notifier`,\r\n `app.core.services.dateTimeService`,\r\n `esComponentChangeHandlerFactory`,\r\n `app.ui.features.configuration.company.modelling.aermet.store`\r\n ];\r\n\r\n function ContentPanelController(_, i18n, notifier, dateTimeService, changeHandlerFactory, store) {\r\n const vm = this;\r\n\r\n vm.upperAirWeatherStationsDefaultValue = i18n.i10n(`app.ui.features.configuration.company.modelling.aermet.contentPanel.upperAirWeatherStations.defaultValue`);\r\n vm.surfaceWeatherStationsDefaultValue = i18n.i10n(`app.ui.features.configuration.company.modelling.aermet.contentPanel.surfaceWeatherStations.defaultValue`);\r\n\r\n vm.onUpperAirWeatherStationChanged = store.dispatch.selectedUpperAirWeatherStationChanged;\r\n vm.onSurfaceWeatherStationChanged = store.dispatch.selectedSurfaceWeatherStationChanged;\r\n vm.cancel = cancel;\r\n vm.runAermet = runAermet;\r\n\r\n vm.$onChanges = changes => {\r\n const changeHandler = changeHandlerFactory(changes);\r\n\r\n mapStateToVm();\r\n\r\n ////////////////////\r\n\r\n function mapStateToVm() {\r\n const whenState = changeHandler.when(changes => changes.state);\r\n\r\n whenState\r\n .hasChanged(state => state.selectedUpperAirWeatherStationId)\r\n .then(value => vm.upperAirWeatherStationId = value);\r\n\r\n whenState\r\n .hasChanged(state => state.selectedSurfaceWeatherStationId)\r\n .then(value => vm.surfaceWeatherStationId = value);\r\n\r\n whenState\r\n .hasFirstChanged()\r\n .then(state => {\r\n vm.fromDate = buildDatePicker(state.fromDate, store.dispatch.fromDateChanged);\r\n vm.toDate = buildDatePicker(state.toDate, store.dispatch.toDateChanged);\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.fromDate)\r\n .then(fromDate => {\r\n vm.fromDate.value = fromDate.value;\r\n vm.fromDate.formattedString = fromDate.value ? dateTimeService.formatAs.date(fromDate.value) : null;\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.toDate)\r\n .then(toDate => {\r\n vm.toDate.value = toDate.value;\r\n vm.toDate.formattedString = toDate.value ? dateTimeService.formatAs.date(toDate.value) : null;\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.lastRunDetails)\r\n .then(runDetails => {\r\n if (!runDetails) {\r\n return;\r\n }\r\n\r\n vm.$form.$setPristine();\r\n\r\n const runDates = {\r\n fromDate: dateTimeService.formatAs.date(runDetails.fromDate),\r\n toDate: dateTimeService.formatAs.date(runDetails.toDate)\r\n };\r\n\r\n notifier.success(\r\n i18n.i10n(`app.ui.features.configuration.company.modelling.aermet.contentPanel.aermetRunScheduled.instructions`, runDates),\r\n i18n.i10n(`app.ui.features.configuration.company.modelling.aermet.contentPanel.aermetRunScheduled.heading`));\r\n });\r\n\r\n function buildDatePicker(dateObj, onChanged) {\r\n return {\r\n options: {\r\n format: dateTimeService.formats.kendo.date,\r\n min: dateObj.min,\r\n max: dateObj.max\r\n },\r\n onChanged: onChanged\r\n };\r\n }\r\n }\r\n };\r\n\r\n function runAermet() {\r\n if (vm.$form.$valid) {\r\n store.dispatch.runAermet();\r\n }\r\n }\r\n\r\n function cancel() {\r\n vm.$form.$setPristine();\r\n store.dispatch.resetState();\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .factory(`app.ui.features.configuration.company.modelling.aermet.store`, aermetStore);\r\n\r\n aermetStore.$inject = [\r\n `$q`,\r\n `moment`,\r\n `esStateStore`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.configuration.monitoringService`,\r\n `app.core.services.configuration.modellingService`\r\n ];\r\n function aermetStore($q, moment, esStateStore, timeZoneDateTime, monitoringService, modellingService) {\r\n\r\n const initialStateResolver = () => {\r\n const min = moment().add(-5, `year`).startOf(`year`).toDate();\r\n\r\n const state = {\r\n fromDate: {\r\n min,\r\n max: moment().startOf(`day`).toDate()\r\n },\r\n toDate: {\r\n min,\r\n max: moment().startOf(`day`).add(4, `day`).toDate()\r\n },\r\n selectedUpperAirWeatherStationId: null,\r\n selectedSurfaceWeatherStationId: null\r\n };\r\n\r\n return $q.all([\r\n monitoringService.getSurfaceWeatherStations(),\r\n monitoringService.getUpperAirWeatherStations()\r\n ]).then(monitors => {\r\n const [surfaceWeatherStations, upperAirWeatherStations] = monitors;\r\n return {\r\n ...state,\r\n surfaceWeatherStations,\r\n upperAirWeatherStations\r\n };\r\n });\r\n };\r\n\r\n const dispatchers = {\r\n fromDateChanged,\r\n toDateChanged,\r\n selectedUpperAirWeatherStationChanged,\r\n selectedSurfaceWeatherStationChanged,\r\n runAermet,\r\n resetState\r\n };\r\n\r\n return esStateStore(initialStateResolver, dispatchers);\r\n\r\n ////////////////////\r\n\r\n // DISPATCHERS\r\n\r\n function fromDateChanged(store) {\r\n return value => {\r\n store.state = { ...store.state, fromDate: { ...store.state.fromDate, value } };\r\n };\r\n }\r\n\r\n function toDateChanged(store) {\r\n return value => {\r\n store.state = { ...store.state, toDate: { ...store.state.toDate, value } };\r\n };\r\n }\r\n\r\n function selectedUpperAirWeatherStationChanged(store) {\r\n return selectedUpperAirWeatherStationId => {\r\n store.state = { ...store.state, selectedUpperAirWeatherStationId };\r\n };\r\n }\r\n\r\n function selectedSurfaceWeatherStationChanged(store) {\r\n return selectedSurfaceWeatherStationId => {\r\n store.state = { ...store.state, selectedSurfaceWeatherStationId };\r\n };\r\n }\r\n\r\n function resetState(store) {\r\n return () => store.resolve();\r\n }\r\n\r\n function runAermet(store) {\r\n return () => {\r\n const fromDate = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(store.state.fromDate.value);\r\n const toDate = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(moment(store.state.toDate.value).endOf(`day`).toDate());\r\n\r\n const runDetails = {\r\n ...store.state,\r\n fromDate,\r\n toDate\r\n };\r\n\r\n modellingService\r\n .runAerModelling(store.state.selectedUpperAirWeatherStationId, store.state.selectedSurfaceWeatherStationId, fromDate, toDate)\r\n .then(() => {\r\n store.dispatch.resetState().then(() => {\r\n store.state = {\r\n ...store.state,\r\n lastRunDetails: runDetails\r\n };\r\n });\r\n });\r\n };\r\n }\r\n }\r\n})();\r\n\r\n\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .component(`modelling.emissionsData.contentPanel`, {\r\n controller: ContentPanelController,\r\n templateUrl: `/App/ui/features/configuration/company/modelling/emissionsData/ContentPanel.html`,\r\n controllerAs: `vm`,\r\n bindings: {\r\n state: `<`\r\n }\r\n });\r\n\r\n ContentPanelController.$inject = [\r\n `lodash`,\r\n `i18n`,\r\n `notifier`,\r\n `confirmationDialog`,\r\n `esComponentChangeHandlerFactory`,\r\n `app.ui.features.configuration.company.modelling.emissionsData.store`\r\n ];\r\n\r\n function ContentPanelController(_, i18n, notifier, confirmationDialog, changeHandlerFactory, store) {\r\n const vm = this;\r\n\r\n vm.$onChanges = onChanges;\r\n\r\n vm.hasUploadedEmissionsData = false;\r\n vm.onSelectedCalpuffConfigChanged = store.dispatch.selectedCalpuffConfigChanged;\r\n\r\n vm.saving = 0;\r\n vm.save = store.dispatch.importEmissionsData;\r\n vm.cancel = cancel;\r\n\r\n ////////////////////\r\n\r\n function onChanges(changes) {\r\n const whenState = changeHandlerFactory(changes).when(changes => changes.state);\r\n\r\n mapStateToVm();\r\n\r\n ////////////////////\r\n\r\n function mapStateToVm() {\r\n whenState\r\n .hasFirstChanged()\r\n .then(state => {\r\n vm.emissionsDataUpload = {\r\n maxSizeBytes: 5 * 1024 * 1024,\r\n allowedExtensions: [`xlsx`],\r\n url: state.emissionsDataFileUploadUrl,\r\n fileUploaded: store.dispatch.emissionsDataFileAdded,\r\n deleteFile: store.dispatch.emissionsDataFileDeleted,\r\n existingFiles: state.existingEmissionsDataFiles,\r\n postData: {\r\n calpuffConfigId: vm.selectedCalpuffConfigId\r\n }\r\n };\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.calpuffConfigs)\r\n .then(calpuffConfigs => {\r\n vm.selectedCalpuffConfigId = null;\r\n vm.calpuffConfigs = _.sortBy(calpuffConfigs, `name`);\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.selectedCalpuffConfigId)\r\n .then(selectedCalpuffConfigId => {\r\n vm.selectedCalpuffConfigId = selectedCalpuffConfigId;\r\n vm.emissionsDataUpload.postData = { calpuffConfigId: selectedCalpuffConfigId };\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.existingEmissionsDataFiles)\r\n .then(existingEmissionsDataFiles => vm.emissionsDataUpload.existingFiles = existingEmissionsDataFiles);\r\n\r\n whenState\r\n .hasChanged(state => state.saving)\r\n .then(saving => vm.saving = saving);\r\n\r\n whenState\r\n .hasChanged(state => state.hasImportComplete)\r\n .then(hasImportComplete => {\r\n if (!hasImportComplete) {\r\n return;\r\n }\r\n\r\n notifier.success(\r\n i18n.i10n(`app.ui.features.configuration.company.modelling.emissionsData.contentPanel.importComplete.instructions`),\r\n i18n.i10n(`app.ui.features.configuration.company.modelling.emissionsData.contentPanel.importComplete.heading`));\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.uploadedFiles)\r\n .then(uploadedFiles => {\r\n vm.hasUploadedEmissionsData = uploadedFiles && uploadedFiles.length;\r\n });\r\n\r\n whenState\r\n .hasChanged(state => state.canRunImport)\r\n .then(canRunImport => vm.canRunImport = canRunImport);\r\n }\r\n }\r\n\r\n function cancel() {\r\n if (!vm.state.uploadedFiles.length) {\r\n return;\r\n }\r\n\r\n const headingKey = `app.ui.features.configuration.company.modelling.emissionsData.contentPanel.cancel.heading`;\r\n const descKey = `app.ui.features.configuration.company.modelling.emissionsData.contentPanel.cancel.instructions`;\r\n\r\n confirmationDialog.ask(headingKey, descKey).then(store.dispatch.emissionsDataImportCancelled);\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .factory(`app.ui.features.configuration.company.modelling.emissionsData.store`, store);\r\n\r\n store.$inject = [\r\n `$q`,\r\n `lodash`,\r\n `esStateStore`,\r\n `app.core.services.configuration.gisModelService`\r\n ];\r\n\r\n function store($q, _, esStateStore, gisModelService) {\r\n const initialStateResolver = () => {\r\n const resolvers = [\r\n gisModelService.getCalpuffConfigs(),\r\n gisModelService.getEmissionsDataFileUploadUrl()\r\n ];\r\n\r\n return $q.all(resolvers).then(results => {\r\n const [calpuffConfigs, emissionsDataFileUploadUrl] = results;\r\n\r\n return {\r\n calpuffConfigs,\r\n emissionsDataFileUploadUrl,\r\n selectedCalpuffConfigId: null,\r\n existingEmissionsDataFiles: [],\r\n uploadedFiles: [],\r\n hasImportComplete: false,\r\n canRunImport: false\r\n };\r\n });\r\n };\r\n\r\n const dispatchers = {\r\n selectedCalpuffConfigChanged,\r\n emissionsDataFileAdded,\r\n emissionsDataFileDeleted,\r\n emissionsDataImportCancelled,\r\n importEmissionsData\r\n };\r\n\r\n return esStateStore(initialStateResolver, dispatchers);\r\n\r\n ////////////////////\r\n\r\n // DISPATCHERS\r\n\r\n function selectedCalpuffConfigChanged(store) {\r\n return calpuffConfigId => {\r\n store.state = {\r\n ...store.state,\r\n selectedCalpuffConfigId: calpuffConfigId,\r\n existingEmissionsDataFiles: [],\r\n uploadedFiles: [],\r\n hasImportComplete: false,\r\n canRunImport: false\r\n };\r\n\r\n if (calpuffConfigId) {\r\n gisModelService.getExistingEmissionsDataFiles(calpuffConfigId).then(existingFiles => {\r\n store.state = {\r\n ...store.state,\r\n existingEmissionsDataFiles: existingFiles,\r\n canRunImport: existingFiles.length > 0\r\n };\r\n });\r\n }\r\n };\r\n }\r\n\r\n function emissionsDataFileAdded(store) {\r\n return fileName => {\r\n const uploadedFiles = [...store.state.uploadedFiles, fileName];\r\n\r\n store.state = {\r\n ...store.state,\r\n uploadedFiles: uploadedFiles,\r\n hasImportComplete: false,\r\n canRunImport: true\r\n };\r\n };\r\n }\r\n\r\n function emissionsDataFileDeleted(store) {\r\n return fileName => {\r\n const calpuffConfigId = store.state.selectedCalpuffConfigId;\r\n const $delete$ = gisModelService.deleteEmissionsDataFiles(calpuffConfigId, [fileName]).then(() => {\r\n const uploadedFiles = _.filter(store.state.uploadedFiles, uploadedFileName => uploadedFileName !== fileName);\r\n\r\n return {\r\n uploadedFiles,\r\n canRunImport: uploadedFiles.length > 0\r\n };\r\n });\r\n\r\n store.save($delete$);\r\n };\r\n }\r\n\r\n function importEmissionsData(store) {\r\n return () => {\r\n if (!store.state.canRunImport) {\r\n return;\r\n }\r\n\r\n const calpuffConfigId = store.state.selectedCalpuffConfigId;\r\n const $save$ = gisModelService.importEmissionsData(calpuffConfigId).then(() => {\r\n return {\r\n uploadedFiles: [],\r\n existingEmissionsDataFiles: [],\r\n hasImportComplete: true,\r\n canRunImport: false\r\n };\r\n });\r\n\r\n store.save($save$);\r\n };\r\n }\r\n\r\n function emissionsDataImportCancelled(store) {\r\n return () => {\r\n const calpuffConfigId = store.state.selectedCalpuffConfigId;\r\n const $delete$ = gisModelService.deleteEmissionsDataFiles(calpuffConfigId).then(() => {\r\n return {\r\n uploadedFiles: [],\r\n existingEmissionsDataFiles: [],\r\n hasImportComplete: false,\r\n canRunImport: false\r\n };\r\n });\r\n\r\n store.save($delete$);\r\n };\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .controller(`app.ui.features.configuration.company.modelling.models.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.locationService`,\r\n `app.core.services.configuration.gisModelService`,\r\n `modelsState`\r\n ];\r\n function ContentPanel($scope, $state, _, promiseTracker, locationService, gisModelService, modelsState) {\r\n const vm = this;\r\n vm.listOptions = getListOptions();\r\n modelsState.loadModels = loadModels;\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n loadModels().then(updateUIWithSelectedModel);\r\n\r\n ///////////////\r\n\r\n function updateUIWithSelectedModel(models) {\r\n $scope.$watch(() => $state.params.modelId, modelId => {\r\n vm.listOptions.selectedItem.value = modelId;\r\n locationService.updatePageHeading(_.find(models, { modelId }));\r\n });\r\n }\r\n }\r\n\r\n function getListOptions() {\r\n return {\r\n columnDefs: [\r\n {\r\n heading: {\r\n i18n: {\r\n key: `app.ui.features.configuration.company.modelling.models.contentPanel.list.columns.name.heading`\r\n }\r\n },\r\n field: `name`\r\n }\r\n ],\r\n items: [],\r\n selectedItem: {\r\n field: `modelId`,\r\n value: null\r\n },\r\n busyLoading: promiseTracker(),\r\n onItemSelected: onModelSelected,\r\n addItem: onAddModel\r\n };\r\n }\r\n\r\n function onAddModel() {\r\n $state.go(`app.configuration.company.modelling.models.add`);\r\n }\r\n\r\n function onModelSelected(model) {\r\n $state.go(`app.configuration.company.modelling.models.model.edit`, { modelId: model.modelId });\r\n }\r\n\r\n function loadModels() {\r\n const models = gisModelService.getAll().then(models => vm.listOptions.items = models);\r\n vm.listOptions.busyLoading.addPromise(models);\r\n return models;\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .service(`app.ui.features.configuration.company.modelling.models.DeleteModal`, DeleteModal);\r\n\r\n DeleteModal.$inject = [\r\n `$state`,\r\n `confirmationDialog`,\r\n `app.core.services.configuration.gisModelService`\r\n ];\r\n\r\n function DeleteModal($state, confirmationDialog, gisModelService) {\r\n\r\n const headingKey = `app.ui.features.configuration.company.modelling.models.detailPanel.remove.heading`;\r\n const descKey = `app.ui.features.configuration.company.modelling.models.detailPanel.remove.instructions`;\r\n\r\n return { open: [`$stateParams`, openModal] };\r\n\r\n ////////////////\r\n\r\n function openModal($stateParams) {\r\n\r\n const modelId = $stateParams.modelId;\r\n\r\n if (!modelId) {\r\n navigateToModelsList();\r\n return;\r\n }\r\n\r\n confirmationDialog\r\n .ask(headingKey, descKey, { css: `modal-center` })\r\n .then(onConfirm)\r\n .catch(returnToEdit);\r\n\r\n function onConfirm() {\r\n const removalPromise = gisModelService.remove(modelId);\r\n removalPromise.finally(navigateToModelsList);\r\n }\r\n\r\n function navigateToModelsList() {\r\n $state.go(`app.configuration.company.modelling.models`, null, { reload: true });\r\n }\r\n\r\n function returnToEdit() {\r\n $state.go(`app.configuration.company.modelling.models.model.edit`, { modelId });\r\n }\r\n }\r\n\r\n\r\n }\r\n})();","`use strict`;\r\n\r\n(function() {\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .controller(`app.ui.features.configuration.company.modelling.models.DetailPanel`, DetailPanel);\r\n\r\n DetailPanel.$inject = [\r\n `$state`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.configuration.gisModelService`,\r\n `modelsState`\r\n ];\r\n function DetailPanel($state, _, promiseTracker, gisModelService, modelsState) {\r\n const vm = this;\r\n const modelId = $state.params.modelId;\r\n\r\n vm.pollutants = [];\r\n vm.displayUnits = [];\r\n vm.isNew = !modelId;\r\n\r\n vm.updateDefaultName = updateDefaultName;\r\n vm.resetPollutantDependentFields = resetPollutantDependentFields;\r\n vm.resetField = resetField;\r\n vm.setModelType = setModelType;\r\n vm.cancel = cancel;\r\n vm.save = save;\r\n vm.remove = remove;\r\n\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n\r\n activate();\r\n\r\n ///////////////////////////////\r\n\r\n function activate() {\r\n vm.model = {};\r\n\r\n let loadingPromise = loadDropDownData();\r\n if (!vm.isNew) {\r\n loadingPromise = loadingPromise.then(loadExistingModel);\r\n }\r\n\r\n vm.busyLoading.addPromise(loadingPromise);\r\n\r\n function loadDropDownData() {\r\n return gisModelService.getOptions().then(setDropDownDataToVm);\r\n }\r\n\r\n function loadExistingModel() {\r\n return gisModelService.get(modelId).then(setExistingModelToVm);\r\n }\r\n\r\n function setDropDownDataToVm(options) {\r\n vm.plumeOptions = {\r\n pollutants: options.plumeOptions.pollutants,\r\n windScientificModels: options.plumeOptions.windScientificModels\r\n };\r\n\r\n vm.windOptions = options.windOptions;\r\n }\r\n\r\n function setExistingModelToVm(model) {\r\n vm.model.type = model.type;\r\n vm.model.isPlume = model.type.toLowerCase() === `plume`;\r\n vm.model.isWind = model.type.toLowerCase() === `wind`;\r\n vm.model.name = model.name;\r\n vm.model.autoGenerate = model.autoGenerateGisModel;\r\n\r\n if (vm.model.isPlume) {\r\n vm.model.selectedPollutant = _.find(vm.plumeOptions.pollutants, { modelPollutantId: model.calpuffConfigPollutantId });\r\n vm.model.selectedDisplayUnit = _.find(vm.model.selectedPollutant.displayUnits, { id: model.displayUnitId });\r\n vm.model.selectedAssociatedWindScientificModel = _.find(vm.plumeOptions.windScientificModels, { id: model.associatedWindScientificModelId });\r\n vm.model.selectedPlumeScientificModel = _.find(vm.model.selectedPollutant.scientificModels, { id: model.scientificModelId });\r\n }\r\n \r\n if (vm.model.isWind) {\r\n vm.model.selectedDisplayUnit = _.find(vm.windOptions.displayUnits, { id: model.displayUnitId });\r\n vm.model.selectedWindScientificModel = _.find(vm.windOptions.scientificModels, { id: model.scientificModelId });\r\n }\r\n\r\n updateDefaultName();\r\n\r\n return model;\r\n }\r\n }\r\n\r\n function remove() {\r\n $state.go(`app.configuration.company.modelling.models.model.delete`, { modelId });\r\n }\r\n\r\n function cancel() {\r\n vm.$form.$setPristine(true);\r\n activate();\r\n }\r\n\r\n function save() {\r\n const savingPromise = vm.model.isPlume ? getSavePlumePromise() : getSaveWindPromise();\r\n\r\n savingPromise\r\n .then(saveSuccess)\r\n .then(modelsState.loadModels);\r\n\r\n vm.busySaving.addPromise(savingPromise);\r\n\r\n function saveSuccess(modelId) {\r\n vm.$form.$setPristine(true);\r\n $state.go(`app.configuration.company.modelling.models.model.edit`, { modelId: modelId }, { reload: true });\r\n }\r\n\r\n function getSavePlumePromise() {\r\n\r\n const plumeModel = {\r\n id: modelId,\r\n name: vm.model.name || vm.model.defaultName,\r\n calpuffConfigPollutantId: vm.model.selectedPollutant.modelPollutantId,\r\n displayUnitId: vm.model.selectedDisplayUnit.id,\r\n associatedWindScientificModelId: vm.model.selectedAssociatedWindScientificModel.id,\r\n intervalDurationInMinutes: vm.model.selectedAssociatedWindScientificModel.intervalDurationInMinutes,\r\n scientificModelId: vm.model.selectedPlumeScientificModel.id,\r\n autoGenerateGisModel : vm.model.autoGenerate\r\n };\r\n\r\n return vm.isNew ? gisModelService.addPlume(plumeModel) : gisModelService.updatePlume(plumeModel);\r\n }\r\n\r\n function getSaveWindPromise() {\r\n const windModel = {\r\n id: modelId,\r\n name: vm.model.name || vm.model.defaultName,\r\n displayUnitId: vm.model.selectedDisplayUnit.id,\r\n type: vm.model.type,\r\n scientificModelId: vm.model.selectedWindScientificModel.id,\r\n intervalDurationInMinutes: vm.model.selectedWindScientificModel.intervalDurationInMinutes,\r\n autoGenerateGisModel : vm.model.autoGenerate\r\n };\r\n\r\n return vm.isNew ? gisModelService.addWind(windModel) : gisModelService.updateWind(windModel);\r\n }\r\n }\r\n\r\n function setModelType(modelType) {\r\n vm.model.type = modelType;\r\n vm.model.isPlume = modelType.toLowerCase() === `plume`;\r\n vm.model.isWind = modelType.toLowerCase() === `wind`;\r\n vm.$form.$setPristine(true);\r\n updateDefaultName();\r\n }\r\n\r\n function resetPollutantDependentFields(displayUnitField, plumeScientificModelField) {\r\n resetField(vm.model.selectedPollutant.displayUnits, newValue => vm.model.selectedDisplayUnit = newValue, displayUnitField);\r\n resetField(vm.model.selectedPollutant.scientificModels, newValue => vm.model.selectedPlumeScientificModel = newValue, plumeScientificModelField);\r\n\r\n updateDefaultName();\r\n }\r\n\r\n function resetField(allowedOptions, funcToSetNewValue, fieldToSetToPristine) {\r\n if (allowedOptions.length === 1) {\r\n funcToSetNewValue(allowedOptions[0]);\r\n } else {\r\n funcToSetNewValue(null);\r\n }\r\n fieldToSetToPristine.$setPristine(true);\r\n }\r\n\r\n function updateDefaultName() {\r\n if (vm.model.isPlume) {\r\n const pollutant = vm.model.selectedPollutant ? vm.model.selectedPollutant.modelPollutantShortName : `plume`;\r\n const displayUnit = vm.model.selectedDisplayUnit ? ` (${vm.model.selectedDisplayUnit.name})` : ``;\r\n const associatedWindScientificModel = vm.model.selectedAssociatedWindScientificModel ? `, ${vm.model.selectedAssociatedWindScientificModel.name}` : ``;\r\n vm.model.defaultName = pollutant + displayUnit + associatedWindScientificModel;\r\n } else {\r\n vm.model.defaultName = vm.model.type;\r\n }\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .factory(`app.ui.features.configuration.company.modelling.models.state`, stateFactory);\r\n\r\n stateFactory.$inject = [];\r\n function stateFactory() {\r\n\r\n function stateFactoryResolver() {\r\n return {\r\n loadModels : angular.noop\r\n };\r\n }\r\n\r\n return stateFactoryResolver;\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.modelling`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.configuration.company.modelling.models.state`,\r\n `app.ui.features.configuration.company.modelling.models.DeleteModal`,\r\n `app.ui.features.configuration.company.modelling.aermet.store`,\r\n `app.ui.features.configuration.company.modelling.emissionsData.store`\r\n ];\r\n function appRun(routeHelper, modelsState, deleteModal, aermetStore, emissionsDataStore) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app.configuration.company.modelling`,\r\n abstract: true,\r\n url: `/modelling`,\r\n data: {\r\n requiredAccessControl: `app.config.modelling`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/modelling/i18n/modelling`,\r\n `/App/core/services/configuration/i18n/gisModelService`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.modelling.aermet`,\r\n url: `/aermet`,\r\n data: {\r\n requiredAccessControl: `app.modelling.run-aermod-modelling`\r\n },\r\n views: {\r\n 'contentPanel@app': {\r\n // if we update to ui-router 1.x we can use route to component syntax.\r\n // https://ui-router.github.io/guide/ng1/route-to-component\r\n // e.g. component: `modelling.aermet.content-panel`\r\n template: ``\r\n }\r\n },\r\n resolve: {\r\n store: aermetStore.resolve\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/modelling/aermet/i18n/ContentPanel`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.modelling.emissionsData`,\r\n url: `/emissions-data`,\r\n views: {\r\n 'contentPanel@app': {\r\n template: ``\r\n }\r\n },\r\n onEnter: () => emissionsDataStore.init(),\r\n onExit: () => emissionsDataStore.destroy(),\r\n resolve: {\r\n store: emissionsDataStore.resolve\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/controls/i18n/esFileUploader`,\r\n `/App/ui/features/configuration/company/modelling/emissionsData/i18n/ContentPanel`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.modelling.models`,\r\n url: `/models`,\r\n views: {\r\n 'contentPanel@app': { // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\r\n templateUrl: `/App/ui/features/configuration/company/modelling/models/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.company.modelling.models.ContentPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n modelsState\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.modelling.models.add`,\r\n url: `/add`,\r\n views: {\r\n 'detailPanel': {\r\n templateUrl: `/App/ui/features/configuration/company/modelling/models/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.modelling.models.DetailPanel as vm`\r\n }\r\n }\r\n },\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.modelling.models.model`,\r\n url: `/:modelId`,\r\n views: {\r\n 'detailPanel': {\r\n templateUrl: `/App/ui/features/configuration/company/modelling/models/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.modelling.models.DetailPanel as vm`\r\n }\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.modelling.models.model.edit`,\r\n url: `/edit`\r\n },\r\n {\r\n state: `app.configuration.company.modelling.models.model.delete`,\r\n url: `/delete`,\r\n onEnter: deleteModal.open\r\n }\r\n ];\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.measurementGroups.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.services.locationService`,\r\n `app.core.services.configuration.measurementGroupService`\r\n ];\r\n function ContentPanel($scope, $state, _, i18n, locationService, measurementGroupService) {\r\n const vm = this;\r\n\r\n vm.gridOptions = getGridOptions();\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n $scope.$watch(() => $state.params.measurementGroupId, measurementGroupId => vm.gridOptions.selectedId = measurementGroupId);\r\n }\r\n\r\n function getGridOptions() {\r\n return {\r\n dataProvider: getMeasurementGroups,\r\n rowCallback: onSelectMeasurementGroup,\r\n addItem: addMeasurementGroup,\r\n sortable: false,\r\n columns: [\r\n {\r\n field: `description`,\r\n title: i18n.i10n(`app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.heading`),\r\n dataType: `string`\r\n },\r\n {\r\n field: `defaultOrder`,\r\n title: `Default Order`,\r\n hidden: true,\r\n sort: {\r\n order: 1,\r\n dir: `asc`\r\n }\r\n },\r\n {\r\n format: i18n.i10n(`app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.list.columns.command`),\r\n click: measurementGroup => $state.go(`app.configuration.company.monitoring.measurementGroups.measurementGroup.delete`, { measurementGroupId: measurementGroup.id }),\r\n title: ` `,\r\n width: 100\r\n }\r\n ],\r\n onDataBound: handleDataBound\r\n };\r\n }\r\n\r\n function getMeasurementGroups(searchCriteria) {\r\n return measurementGroupService.queryMeasurementGroups(searchCriteria).then(result => {\r\n if (vm.gridOptions.selectedId) {\r\n const selectedItem = _.find(result.data, measurementGroup => measurementGroup.id === vm.gridOptions.selectedId);\r\n locationService.updatePageHeading(selectedItem);\r\n }\r\n\r\n const byId = _.reduce(result.data, (map, mg) => map.set(mg.id, mg), new Map());\r\n\r\n result.data = _.chain(result.data)\r\n .map(mg => {\r\n // If this is a child measurement group, change the order so that it will appear underneath\r\n // its parent measurement group.\r\n const parent = byId.get(mg.parentId);\r\n if (parent) {\r\n mg.defaultOrder = parseFloat(`${parent.defaultOrder}.${byId.size - mg.defaultOrder}`);\r\n }\r\n\r\n return mg;\r\n })\r\n .sortBy(mg => mg.defaultOrder)\r\n .value();\r\n\r\n return result;\r\n });\r\n }\r\n\r\n function onSelectMeasurementGroup(measurementGroup) {\r\n locationService.updatePageHeading(measurementGroup);\r\n $state.go(`app.configuration.company.monitoring.measurementGroups.measurementGroup.edit`, { measurementGroupId: measurementGroup.id });\r\n }\r\n\r\n function addMeasurementGroup() {\r\n $state.go(`app.configuration.company.monitoring.measurementGroups.add`);\r\n }\r\n\r\n function handleDataBound(event) {\r\n // This is pretty much the only way that we can style individual cells in a kendo grid.\r\n // See: https://docs.telerik.com/kendo-ui/knowledge-base/style-rows-cells-based-on-data-item-values\r\n const { dataSource, tbody } = event.sender;\r\n\r\n const dataItems = dataSource.view();\r\n for (const dataItem of dataItems) {\r\n const isChild = !!dataItem.parentId;\r\n\r\n if (isChild) {\r\n const row = tbody.find(`[data-uid='${dataItem.uid}']`);\r\n row.addClass(`child-measurement-group`);\r\n }\r\n }\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .service(`app.ui.features.configuration.company.monitoring.measurementGroups.DeleteModal`, DeleteModal);\r\n\r\n DeleteModal.$inject = [\r\n `$state`,\r\n `$q`,\r\n `confirmationDialog`,\r\n `app.core.services.configuration.measurementGroupService`\r\n ];\r\n\r\n function DeleteModal($state, $q, confirmationDialog, measurementGroupService) {\r\n\r\n return { open: [`$stateParams`, openModal] };\r\n\r\n ////////////////\r\n\r\n function openModal($stateParams) {\r\n\r\n const measurementGroupId = $stateParams.measurementGroupId;\r\n\r\n if (!measurementGroupId) {\r\n navigateToMeasurementGroupsList();\r\n return;\r\n }\r\n\r\n $q.all([isInUse(), hasChildren()])\r\n .then(() => {\r\n const confirmRemove = `app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.remove`;\r\n confirmationDialog\r\n .ask(`${confirmRemove}.heading`, `${confirmRemove}.body`)\r\n .then(() => measurementGroupService.deleteMeasurementGroup(measurementGroupId))\r\n .then(navigateToMeasurementGroupsList)\r\n .catch(returnToEdit);\r\n })\r\n .catch(returnToEdit)\r\n .finally(returnToEdit);\r\n\r\n function isInUse() {\r\n return measurementGroupService\r\n .isMeasurementGroupBeingUsed(measurementGroupId)\r\n .then(response => {\r\n if (!response) {\r\n return;\r\n }\r\n\r\n const removeExisting = `app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.remove.existing`;\r\n return confirmationDialog\r\n .notify(`${removeExisting}.heading`, `${removeExisting}.body`)\r\n .finally(() => $q.reject(`Measurement group in use`));\r\n });\r\n }\r\n\r\n function hasChildren() {\r\n return measurementGroupService\r\n .getMeasurementGroupChildCount(measurementGroupId)\r\n .then(response => {\r\n if (response === 0) {\r\n return;\r\n }\r\n\r\n const removeParent = `app.ui.features.configuration.company.monitoring.measurementGroups.contentPanel.remove.parent`;\r\n return confirmationDialog\r\n .notify(`${removeParent}.heading`, `${removeParent}.body`)\r\n .finally(() => $q.reject(`Measurement group is a parent`));\r\n });\r\n }\r\n\r\n function returnToEdit() {\r\n $state.go(`app.configuration.company.monitoring.measurementGroups.measurementGroup.edit`, { measurementGroupId });\r\n }\r\n\r\n function navigateToMeasurementGroupsList() {\r\n $state.go(`app.configuration.company.monitoring.measurementGroups`, null, { reload: true });\r\n }\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.measurementGroups.DetailPanel`, DetailPanel);\r\n\r\n DetailPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.configuration.measurementGroupService`\r\n ];\r\n\r\n function DetailPanel($scope, $state, _, promiseTracker, measurementGroupService) {\r\n const vm = this;\r\n const { measurementGroupId } = $state.params;\r\n\r\n vm.isNew = !measurementGroupId;\r\n vm.$form = undefined;\r\n vm.measurementGroupDescription = ``;\r\n vm.measurementGroupDefaultOrder = 0;\r\n vm.measurementGroupParentId = null;\r\n vm.measurementGroupCanHaveParent = true;\r\n\r\n let measurementGroupsNested = [];\r\n vm.parents = [];\r\n\r\n vm.busySaving = promiseTracker();\r\n vm.busyLoading = promiseTracker();\r\n vm.save = save;\r\n vm.cancel = cancel;\r\n\r\n activate();\r\n\r\n ///////////////////\r\n\r\n function activate() {\r\n loadMeasurementGroups();\r\n updateOrderWhenParentChanges();\r\n }\r\n\r\n function loadMeasurementGroups() {\r\n const loadingPromise = measurementGroupService.getMeasurementGroupsNested()\r\n .then(measurementGroups => {\r\n measurementGroupsNested = measurementGroups;\r\n\r\n getPotentialParentMeasurementGroups();\r\n\r\n if (vm.isNew) {\r\n vm.measurementGroupDefaultOrder = getNextDefaultOrder(measurementGroups);\r\n\r\n } else {\r\n getMeasurementGroupToEdit();\r\n }\r\n\r\n ////////////////////\r\n\r\n function getPotentialParentMeasurementGroups() {\r\n vm.parents = _.chain(measurementGroups)\r\n .filter(mg => !mg.parentId && mg.id !== $state.params.measurementGroupId)\r\n .sortBy(mg => mg.description)\r\n .value();\r\n }\r\n\r\n function getMeasurementGroupToEdit() {\r\n let editGroup = null;\r\n\r\n // Find the measurement group to edit - it may be a child of another measurement group.\r\n for (const mg of measurementGroups) {\r\n editGroup = mg.id === $state.params.measurementGroupId\r\n ? mg\r\n : _.find(mg.children, child => child.id === $state.params.measurementGroupId);\r\n\r\n if (editGroup) { break; }\r\n }\r\n\r\n if (editGroup) {\r\n vm.measurementGroupDescription = editGroup.description;\r\n vm.measurementGroupDefaultOrder = editGroup.defaultOrder;\r\n vm.measurementGroupParentId = editGroup.parentId;\r\n\r\n vm.measurementGroupCanHaveParent = !(editGroup.children && editGroup.children.length);\r\n }\r\n }\r\n });\r\n\r\n vm.busyLoading.addPromise(loadingPromise);\r\n }\r\n\r\n function updateOrderWhenParentChanges() {\r\n $scope.$watch(() => vm.measurementGroupParentId, (parentId, oldParentId) => {\r\n if (parentId === oldParentId) {\r\n return;\r\n }\r\n\r\n if (!parentId) {\r\n vm.measurementGroupDefaultOrder = getNextDefaultOrder(measurementGroupsNested);\r\n\r\n } else {\r\n const parent = _.find(measurementGroupsNested, measurementGroup => measurementGroup.id === parentId);\r\n vm.measurementGroupDefaultOrder = getNextDefaultOrder(parent.children);\r\n }\r\n });\r\n }\r\n\r\n function getNextDefaultOrder(measurementGroups) {\r\n // The default order for a new measurement group has to be one higher than the previously\r\n // existing highest order.\r\n const measurementGroupWithHighestDefaultOrder = findHighestDefaultOrderRecursive(measurementGroups);\r\n if (measurementGroupWithHighestDefaultOrder === null) {\r\n return 1;\r\n }\r\n\r\n return measurementGroupWithHighestDefaultOrder.id !== measurementGroupId\r\n ? measurementGroupWithHighestDefaultOrder.defaultOrder + 1\r\n : measurementGroupWithHighestDefaultOrder.defaultOrder;\r\n\r\n ////////////////////\r\n\r\n function findHighestDefaultOrderRecursive(measurementGroups) {\r\n if (!(measurementGroups && measurementGroups.length)) {\r\n return null;\r\n }\r\n\r\n return measurementGroups.reduce((max, measurementGroup) => {\r\n return findHighestDefaultOrder(max, measurementGroup, findHighestDefaultOrderRecursive(measurementGroup.children));\r\n });\r\n }\r\n\r\n function findHighestDefaultOrder(...measurementGroups) {\r\n return measurementGroups.reduce((max, measurementGroup) => {\r\n if (max && measurementGroup) {\r\n return max.defaultOrder > measurementGroup.defaultOrder ? max : measurementGroup;\r\n }\r\n\r\n return max ? max : measurementGroup;\r\n });\r\n }\r\n }\r\n\r\n function save() {\r\n const measurementGroup = {\r\n id: measurementGroupId,\r\n description: vm.measurementGroupDescription,\r\n defaultOrder: vm.measurementGroupDefaultOrder,\r\n parentId: vm.measurementGroupParentId || null\r\n };\r\n\r\n const savingPromise = vm.isNew\r\n ? measurementGroupService.createMeasurementGroup(measurementGroup)\r\n : measurementGroupService.updateMeasurementGroup(measurementGroup);\r\n\r\n savingPromise\r\n .then(measurementGroupId => {\r\n vm.$form.$setPristine(true);\r\n $state.go(`app.configuration.company.monitoring.measurementGroups.measurementGroup.edit`, { measurementGroupId }, { reload: true });\r\n });\r\n\r\n vm.busySaving.addPromise(savingPromise);\r\n }\r\n\r\n function cancel() {\r\n activate();\r\n vm.$form.$setPristine(true);\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .factory(`app.ui.features.configuration.company.monitoring.measurementGroups.state`, stateFactory);\r\n\r\n stateFactory.$inject = [];\r\n\r\n function stateFactory() {\r\n return () => {\r\n return { };\r\n };\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.services.locationService`,\r\n `app.core.services.configuration.monitoringService`\r\n ];\r\n function ContentPanel($scope, $state, _, i18n, locationService, monitoringService) {\r\n const vm = this;\r\n vm.gridOptions = getGridOptions();\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n $scope.$watch(() => $state.params.monitorId, monitorId => vm.gridOptions.selectedId = monitorId);\r\n }\r\n\r\n function getGridOptions() {\r\n return {\r\n dataProvider: getMonitors,\r\n rowCallback: onSelectMonitor,\r\n addItem: onAddMonitor,\r\n columns: [\r\n {\r\n field: `name`,\r\n title: i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.contentPanel.list.columns.name.heading`),\r\n dataType: `string`,\r\n sort: {\r\n order: 1,\r\n dir: `asc`\r\n },\r\n template: `
        #: name#
        `\r\n }\r\n ]\r\n };\r\n }\r\n\r\n function getMonitors(searchCriteria) {\r\n return monitoringService.queryMonitors(searchCriteria).then(result => {\r\n if (vm.gridOptions.selectedId) {\r\n const selectedItem = _.find(result.data, monitor => monitor.id === vm.gridOptions.selectedId);\r\n locationService.updatePageHeading(selectedItem);\r\n }\r\n return result;\r\n });\r\n }\r\n\r\n function onSelectMonitor(monitor) {\r\n locationService.updatePageHeading(monitor);\r\n\r\n const aSelectedMonitorRoute = `app.configuration.company.monitoring.monitors.tabs.monitor`;\r\n const aMeasurementTypeRoute = `${aSelectedMonitorRoute}.measurementTypes`;\r\n const aDataImportRoute = `${aSelectedMonitorRoute}.dataImport`;\r\n const detailsRoute = `${aSelectedMonitorRoute}.details`;\r\n\r\n let route = $state.$current.name; // we'll try and keep the user on the monitor route they are already on.\r\n\r\n if ($state.$current.name.indexOf(aMeasurementTypeRoute) >= 0) { // take off edit/delete route portion if it exists\r\n route = aMeasurementTypeRoute;\r\n } else if ($state.$current.name.indexOf(aDataImportRoute) >= 0) {\r\n route = aDataImportRoute;\r\n } else if ($state.$current.name.indexOf(aSelectedMonitorRoute) === -1) { // e.g. add monitor, list monitors routes\r\n route = detailsRoute;\r\n }\r\n\r\n $state.go(route, { monitorId: monitor.id });\r\n }\r\n\r\n function onAddMonitor() {\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.add`);\r\n }\r\n\r\n }\r\n})();","(function() {\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .directive(`esMeasurementTypeThresholds`, directive);\r\n\r\n function directive() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n measurementType: `=`,\r\n unitTypes: `=`,\r\n isSubmitted: `=`\r\n },\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/controls/esMeasurementTypeThresholds.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.mathService`];\r\n function controller($scope, $timeout, _, promiseTracker, math) {\r\n const vm = this;\r\n const baseValue = math.floatMinValue;\r\n\r\n const thresholdColours = {\r\n green: `#679B38`,\r\n yellow: `#C58B32`,\r\n brown: `#C05022`,\r\n red: `#EF190F`,\r\n purple: `#FF00F9`\r\n };\r\n\r\n vm.colourPalette = _.values(thresholdColours);\r\n\r\n vm.addThreshold = addThreshold;\r\n vm.removeThreshold = removeThreshold;\r\n\r\n vm.validateThresholdColour = validateThresholdColour;\r\n vm.validateThresholdValue = validateThresholdValue;\r\n\r\n vm.influenceArcDisplayThresholdBaseValue = baseValue;\r\n vm.influenceArcDisplayThresholdMaxValue = -1 * baseValue;\r\n\r\n vm.setInfluenceArcThreshold = setInfluenceArcThreshold;\r\n vm.defaultDisplayUnitName = ``;\r\n\r\n vm.busyLoading = promiseTracker();\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n $scope.$watch(()=> vm.measurementType.defaultDisplayUnitId, displayUnitId => {\r\n if (!displayUnitId) {\r\n return;\r\n }\r\n\r\n updateBaseThreshold();\r\n setInfluenceArcThreshold();\r\n updateDisplayUnitText(displayUnitId);\r\n });\r\n\r\n function updateDisplayUnitText(displayUnitId) {\r\n const displayUnit = _.find(vm.unitTypes, { id: displayUnitId });\r\n\r\n // Cater for PVs that have been set up incorrectly, where their display unit is not\r\n // available for the selected process variable type.\r\n vm.defaultDisplayUnitName = displayUnit && displayUnit.name || null;\r\n }\r\n\r\n function updateBaseThreshold() {\r\n let baseThreshold = _.find(vm.measurementType.exceedanceThresholds, { valueInBaseUnit: baseValue });\r\n if (!baseThreshold) {\r\n baseThreshold = {\r\n valueInBaseUnit: baseValue,\r\n valueInDisplayUnit: baseValue,\r\n hexColor: thresholdColours.green,\r\n description: `Base Value`\r\n };\r\n vm.measurementType.exceedanceThresholds.unshift(baseThreshold);\r\n }\r\n }\r\n }\r\n\r\n function validateThresholdValue(threshold, $index = 0, thirdPartyCheck = false) {\r\n const previousThresholdValue = $index === 0 ? undefined : vm.measurementType.exceedanceThresholds[$index - 1].valueInDisplayUnit;\r\n\r\n const isThresholdValid =\r\n _.isNumber(threshold.valueInDisplayUnit) &&\r\n (previousThresholdValue === undefined || threshold.valueInDisplayUnit > previousThresholdValue);\r\n\r\n vm.$form[`threshold-value-${$index}`].$setValidity(`threshold-value-validator`, isThresholdValid);\r\n\r\n _.forEach(vm.measurementType.exceedanceThresholds, (value, index) => {\r\n if (index === $index || thirdPartyCheck) {\r\n return;\r\n }\r\n validateThresholdValue(vm.measurementType.exceedanceThresholds[index], index, true);\r\n });\r\n }\r\n\r\n function validateThresholdColour() {\r\n const uniqueColours = _.chain(vm.measurementType.exceedanceThresholds)\r\n .map(`hexColor`)\r\n .map(hexColor => hexColor.toUpperCase())\r\n .uniq()\r\n .value();\r\n vm.hasDuplicateThresholdColour = uniqueColours.length !== vm.measurementType.exceedanceThresholds.length;\r\n }\r\n\r\n function setInfluenceArcThreshold(thresholdType = getThresholdType()) {\r\n vm.arcThresholdType = thresholdType;\r\n\r\n switch (thresholdType) {\r\n case `always` :\r\n vm.measurementType.influenceArcDisplayThreshold = vm.influenceArcDisplayThresholdBaseValue;\r\n break;\r\n case `never` :\r\n vm.measurementType.influenceArcDisplayThreshold = vm.influenceArcDisplayThresholdMaxValue;\r\n break;\r\n case `custom` :\r\n if (hasExistingCustomThresholdValue()) {\r\n break;\r\n }\r\n\r\n vm.measurementType.influenceArcDisplayThreshold =\r\n vm.measurementType.exceedanceThresholds.length > 1\r\n ? vm.measurementType.exceedanceThresholds[1].valueInDisplayUnit\r\n : null;\r\n }\r\n\r\n function hasExistingCustomThresholdValue() {\r\n return vm.measurementType.influenceArcDisplayThreshold !== vm.influenceArcDisplayThresholdBaseValue &&\r\n vm.measurementType.influenceArcDisplayThreshold !== vm.influenceArcDisplayThresholdMaxValue &&\r\n vm.measurementType.influenceArcDisplayThreshold !== undefined &&\r\n vm.measurementType.influenceArcDisplayThreshold !== null;\r\n }\r\n }\r\n\r\n function getThresholdType() {\r\n if (vm.measurementType.influenceArcDisplayThreshold === null ||\r\n vm.measurementType.influenceArcDisplayThreshold === undefined ||\r\n vm.measurementType.influenceArcDisplayThreshold === vm.influenceArcDisplayThresholdBaseValue) {\r\n return `always`;\r\n } else if (vm.measurementType.influenceArcDisplayThreshold === vm.influenceArcDisplayThresholdMaxValue) {\r\n return `never`;\r\n } else {\r\n return `custom`;\r\n }\r\n }\r\n\r\n function addThreshold() {\r\n if (vm.measurementType.exceedanceThresholds.length >= 5) {\r\n return;\r\n }\r\n const newThreshold = {\r\n valueInBaseUnit: undefined,\r\n valueInDisplayUnit: undefined,\r\n hexColor: vm.colourPalette[vm.measurementType.exceedanceThresholds.length]\r\n };\r\n vm.measurementType.exceedanceThresholds.push(newThreshold);\r\n $timeout(() => validateThresholdColour());\r\n vm.$form.$setDirty();\r\n }\r\n\r\n function removeThreshold(index) {\r\n if (vm.measurementType.exceedanceThresholds.length <= 1) {\r\n return;\r\n }\r\n vm.measurementType.exceedanceThresholds.splice(index, 1);\r\n $timeout(() => validateThresholdColour());\r\n vm.$form.$setDirty();\r\n }\r\n }\r\n})();\r\n","( function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .directive(`esMonitorVariableDisplay`, directive);\r\n\r\n directive.$inject = [];\r\n function directive() {\r\n return {\r\n restrict: `A`,\r\n scope: {},\r\n bindToController: {\r\n processVariable: `=esMonitorVariableDisplay`,\r\n sortable: `=`,\r\n state: `=`\r\n },\r\n controllerAs: `vm`,\r\n controller: controller,\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/controls/esMonitorVariableDisplay.html`\r\n };\r\n }\r\n\r\n controller.$inject = [`$scope`, `lodash`];\r\n function controller($scope, _) {\r\n const vm = this;\r\n\r\n activate();\r\n\r\n function activate() {\r\n vm.selectedMeasurementGroup = _.find(vm.state.measurementGroups, { id: vm.processVariable.measurementGroupId });\r\n\r\n $scope.$watch(() => vm.selectedMeasurementGroup, () => {\r\n vm.processVariable.measurementGroupId = vm.selectedMeasurementGroup && vm.selectedMeasurementGroup.id || null;\r\n });\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .directive(`esMonitorVariablePreferences`, directive);\r\n\r\n directive.$inject = [`lodash`];\r\n\r\n function directive(_) {\r\n return {\r\n restrict: `A`,\r\n scope: {\r\n sortables: `=esMonitorVariablePreferences`,\r\n state: `=`\r\n },\r\n link: link,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: controller,\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/controls/esMonitorVariablePreferences.html`\r\n };\r\n\r\n function link($scope, $element, attrs, vm) {\r\n\r\n $scope.$watch(\r\n () => vm.sortables,\r\n sortables => {\r\n vm.sortableOptions = _.map(sortables, (sortable, index) => {\r\n\r\n switch (index) {\r\n case 0:\r\n sortable.listId = `list-available`;\r\n break;\r\n case 1:\r\n sortable.listId = `list-display`;\r\n break;\r\n case 2:\r\n sortable.listId = `list-graph`;\r\n break;\r\n }\r\n\r\n return getSortableOptions(sortable);\r\n });\r\n });\r\n\r\n function getSortableOptions(sortable) {\r\n\r\n return {\r\n connectWith: `.connected-apps-container`,\r\n\r\n over: function(event, ui) {\r\n const sourceList = ui.item.sortable.sourceModel;\r\n const item = ui.item.sortable.model;\r\n\r\n if (!draggingFromAvailableList() && !reorderingInSameList()) {\r\n addDangerZone();\r\n return;\r\n }\r\n\r\n if (!reorderingInSameList() && notInTheAvailableListEventHandler()) {\r\n const processVariableExistsInTargetList = _.find(sortable.items, { id: item.id });\r\n if (processVariableExistsInTargetList) {\r\n addDangerZone();\r\n return;\r\n }\r\n }\r\n\r\n addDropZone();\r\n\r\n function notInTheAvailableListEventHandler() {\r\n return sortable.listId !== `list-available`;\r\n }\r\n\r\n function reorderingInSameList() {\r\n return sourceList === sortable.items;\r\n }\r\n\r\n function draggingFromAvailableList() {\r\n return sourceList === vm.sortables[0].items;\r\n }\r\n\r\n },\r\n out: function() {\r\n removeDangerZone();\r\n removeDropZone();\r\n },\r\n update: function(event, ui) {\r\n const sourceList = ui.item.sortable.sourceModel;\r\n const item = sourceList[ui.item.sortable.index];\r\n\r\n removeDangerZone();\r\n removeDropZone();\r\n\r\n if (!ui.item.sortable.received) {\r\n\r\n if (reorderingInTheSameList()) {\r\n return; // allow drag n drop\r\n }\r\n\r\n if (draggingFromAvailableList()) {\r\n const processVariableExistsInTargetList = _.find(ui.item.sortable.droptargetModel, { id: item.id });\r\n if (!processVariableExistsInTargetList) {\r\n return; // allow drag n drop.\r\n }\r\n }\r\n\r\n ui.item.sortable.cancel();\r\n }\r\n\r\n function reorderingInTheSameList() {\r\n return ui.item.sortable.sourceModel === ui.item.sortable.droptargetModel;\r\n }\r\n\r\n function draggingFromAvailableList() {\r\n return sourceList === vm.sortables[0].items;\r\n }\r\n },\r\n stop: function(event, ui) {\r\n\r\n if (droppingAvailableVariableIntoAnotherList()) {\r\n refreshAvailableListWithAllAvailableProcessVariables();\r\n }\r\n\r\n function droppingAvailableVariableIntoAnotherList() {\r\n return event.target.id === `list-available` && ui.item.sortable.droptarget && event.target !== ui.item.sortable.droptarget[0];\r\n }\r\n\r\n function refreshAvailableListWithAllAvailableProcessVariables() {\r\n vm.sortables[0].items = vm.refreshAvailableProcessVariables();\r\n }\r\n\r\n }\r\n };\r\n\r\n function removeDangerZone() {\r\n removeClass(`danger-zone`);\r\n }\r\n\r\n function addDangerZone() {\r\n addClass(`danger-zone`);\r\n }\r\n\r\n function removeDropZone() {\r\n removeClass(`drop-zone`);\r\n }\r\n\r\n function addDropZone() {\r\n addClass(`drop-zone`);\r\n }\r\n\r\n function addClass(className) {\r\n const $list = $element.find(`#${sortable.listId}`);\r\n $list.addClass(className);\r\n }\r\n\r\n function removeClass(className) {\r\n const $list = $element.find(`#${sortable.listId}`);\r\n $list.removeClass(className);\r\n }\r\n }\r\n }\r\n }\r\n\r\n controller.$inject = [`$scope`, `lodash`];\r\n\r\n function controller($scope, _) {\r\n const vm = this;\r\n let availableProcessVariables;\r\n\r\n vm.refreshAvailableProcessVariables = refreshAvailableProcessVariables;\r\n vm.remove = remove;\r\n\r\n activate();\r\n\r\n function activate() {\r\n $scope.$watchCollection(() => vm.sortables, cloneTheAvailableProcessVariables);\r\n\r\n function cloneTheAvailableProcessVariables() {\r\n if (vm.sortables[0] && vm.sortables[0].items && !availableProcessVariables) {\r\n availableProcessVariables = [...vm.sortables[0].items]; // clone the array\r\n }\r\n }\r\n }\r\n\r\n function remove(index, itemIndex) {\r\n vm.sortables[index].items.splice(itemIndex, 1);\r\n }\r\n\r\n function refreshAvailableProcessVariables() {\r\n return availableProcessVariables.map(pv => _.assign({}, pv));\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n const directiveName = `esRequireUniqueMeasurementGroupSelection`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .directive(directiveName, validator);\r\n\r\n validator.$inject = [`lodash`];\r\n\r\n function validator(_) {\r\n return {\r\n restrict: `A`,\r\n require: `ngModel`,\r\n scope: {\r\n isValidationRequired: `=${directiveName}`,\r\n sortable: `=`\r\n },\r\n link: link\r\n };\r\n\r\n function link($scope, $element, $attrs, ngModel) {\r\n $scope.$watch(() => $scope.isValidationRequired, validateUniqueMeasurementGroup);\r\n $scope.$watch(() => ngModel.$modelValue, validateUniqueMeasurementGroup, true);\r\n\r\n function validateUniqueMeasurementGroup() {\r\n let isValid = !$scope.isValidationRequired;\r\n\r\n if ($scope.isValidationRequired) {\r\n const selectedMeasurementGroup = ngModel.$modelValue;\r\n isValid = !selectedMeasurementGroup || _.filter($scope.sortable.items, { measurementGroupId: selectedMeasurementGroup.id }).length <= 1;\r\n }\r\n ngModel.$setValidity(`uniqueMeasurementGroup`, isValid);\r\n }\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.DataImportTab`, DataImportTab);\r\n\r\n DataImportTab.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `promiseTracker`,\r\n `i18n`,\r\n `app.core.services.securityService`,\r\n `dataImportState`\r\n ];\r\n \r\n function DataImportTab($scope, $state, promiseTracker, i18n, securityService, dataImportState) {\r\n const vm = this;\r\n const searchCriteria = { take: 0, pageSize: 0, sort: [{ field: `description`, dir: `asc`, order: 1 }] };\r\n\r\n vm.monitorId = $state.params.monitorId;\r\n vm.apiCredentialId = $state.params.apiCredentialId;\r\n\r\n vm.$form = null;\r\n vm.busySaving = promiseTracker();\r\n vm.busyLoading = promiseTracker();\r\n\r\n vm.apiCredentials = undefined;\r\n vm.apiCredentialsDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.monitor.dataImport.fields.credential.defaultValue`);\r\n vm.onSelectApiCredential = onSelectApiCredential;\r\n vm.onCreateApiCredential = onCreateApiCredential;\r\n\r\n activate();\r\n\r\n /////////////////\r\n\r\n function activate() {\r\n registerForStateEvents();\r\n\r\n const loadingPromise = securityService\r\n .queryApiCredentials(vm.monitorId, searchCriteria)\r\n .then(apiCredentials => vm.apiCredentials = apiCredentials);\r\n\r\n vm.busyLoading.addPromise(loadingPromise);\r\n\r\n /////////////////////\r\n\r\n function registerForStateEvents() {\r\n $scope.$on(dataImportState.events.loading, (event, loadingPromise) => vm.busyLoading.addPromise(loadingPromise));\r\n $scope.$on(dataImportState.events.saving, (event, savingPromise) => vm.busySaving.addPromise(savingPromise));\r\n }\r\n }\r\n\r\n function onSelectApiCredential(apiCredentialId) {\r\n if (apiCredentialId) {\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential.edit`, { apiCredentialId });\r\n } else {\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.dataImport`);\r\n }\r\n }\r\n\r\n function onCreateApiCredential() {\r\n vm.apiCredentialId = null;\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.add`);\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.dataImport.DataImportTabEditPanel`, DataImportTabEditPanel);\r\n\r\n DataImportTabEditPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `$q`,\r\n `lodash`,\r\n `app.core.errorService`,\r\n `app.core.services.securityService`,\r\n `monitorTabs`,\r\n `dataImportState`,\r\n `app.core.appSettings`\r\n ];\r\n\r\n function DataImportTabEditPanel($scope, $state, $q, _, errorService, securityService, monitorTabs, dataImportState, appSettings) {\r\n const vm = this;\r\n const emptyGuid = `00000000-0000-0000-0000-000000000000`;\r\n vm.accessControls = {\r\n [`api.monitoring.data.read`]: false,\r\n [`api.monitoring.data.write`]: false\r\n }; // the access controls that a monitor can be assigned to\r\n\r\n vm.isNew = undefined;\r\n vm.isEdit = undefined;\r\n\r\n vm.apiCredential = undefined;\r\n vm.isActive = true;\r\n\r\n vm.cancel = cancel;\r\n vm.save = save;\r\n vm.toggleIsEnabled = toggleIsEnabled;\r\n\r\n activate();\r\n\r\n /////////////////\r\n\r\n function activate() {\r\n\r\n vm.isNew = !$state.params.apiCredentialId;\r\n vm.isEdit = !vm.isNew;\r\n $scope.$watch(() => vm.$form.$dirty, () => monitorTabs.dataImport.isDirty = vm.$form.$dirty);\r\n const loadingPromises = [];\r\n\r\n if (vm.isEdit) {\r\n\r\n const loadingCredentialPromise = securityService.getApiCredential($state.params.apiCredentialId)\r\n .then(apiCredential => {\r\n vm.apiCredential = apiCredential;\r\n vm.isEnabled = apiCredential.deactivatedTime === null;\r\n _.forOwn(vm.accessControls, (value, key) => {\r\n vm.accessControls[key] = _.has(apiCredential.overrideAccessControls, key) ? apiCredential.overrideAccessControls[key] : vm.accessControls[key];\r\n });\r\n })\r\n .catch(response => {\r\n errorService.processError(response);\r\n $state.go(`app.configuration.company.monitoring.monitors`);\r\n });\r\n loadingPromises.push(loadingCredentialPromise);\r\n } else {\r\n initialiseForm();\r\n }\r\n $scope.$emit(dataImportState.events.loading, $q.all(loadingPromises));\r\n }\r\n\r\n function initialiseForm() {\r\n vm.apiCredential = {\r\n id: $state.params.apiCredentialId,\r\n processId: $state.params.monitorId,\r\n apiKey: emptyGuid,\r\n requiresSecureConnection: true,\r\n deactivatedTime: null,\r\n overrideAccessControls: { ...vm.accessControls }\r\n };\r\n vm.isEnabled = vm.apiCredential.deactivatedTime === null;\r\n }\r\n\r\n function cancel() {\r\n activate();\r\n vm.$form.$setPristine();\r\n }\r\n\r\n function save() {\r\n\r\n if (vm.$form.$invalid || !vm.$form.$dirty) {\r\n return;\r\n }\r\n\r\n vm.apiCredential.overrideAccessControls = { ...vm.accessControls };\r\n\r\n const savingPromise = persistApiCredential();\r\n savingPromise.then(saveSuccess);\r\n $scope.$emit(dataImportState.events.saving, savingPromise);\r\n\r\n function persistApiCredential() {\r\n return vm.isNew\r\n ? securityService.createApiCredential(vm.apiCredential)\r\n : securityService.updateApiCredential(vm.apiCredential);\r\n }\r\n\r\n function saveSuccess(apiCredentialId) {\r\n vm.$form.$setPristine();\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential.edit`,\r\n { apiCredentialId },\r\n { reload: true }\r\n );\r\n }\r\n }\r\n function toggleIsEnabled() {\r\n vm.apiCredential.deactivatedTime = vm.isEnabled ? null : new Date() ;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.DetailPanel`, DetailPanel);\r\n\r\n DetailPanel.$inject = [`monitorTabs`];\r\n\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function DetailPanel(monitorTabs) {\r\n const vm = this;\r\n\r\n vm.tabs = monitorTabs;\r\n\r\n activate();\r\n\r\n ///////////////////\r\n\r\n function activate() {\r\n \r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.DetailsTab`, DetailsTab);\r\n\r\n DetailsTab.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `i18n`,\r\n `$q`,\r\n `$timeout`,\r\n `promiseTracker`,\r\n `Utm`,\r\n `LatLon`,\r\n `app.core.mapDefaults`,\r\n `app.core.appSettings`,\r\n `app.core.errorService`,\r\n `app.core.services.configuration.monitoringService`,\r\n `app.core.services.mappingService`,\r\n `monitorTabs`,\r\n `detailsState`\r\n ];\r\n function DetailsTab(\r\n $scope,\r\n $state,\r\n _,\r\n i18n,\r\n $q,\r\n $timeout,\r\n promiseTracker,\r\n Utm,\r\n LatLon,\r\n mapDefaults,\r\n appSettings,\r\n errorService,\r\n monitoringService,\r\n mappingService,\r\n monitorTabs,\r\n detailsState) {\r\n\r\n const vm = this;\r\n let formIsReady = false;\r\n\r\n vm.isNew = !$state.params.monitorId;\r\n vm.isEdit = !vm.isNew;\r\n\r\n vm.configurationOptions = detailsState.configurationOptions;\r\n\r\n vm.configurationOptions.typeDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.detailsTab.fields.type.defaultValue`);\r\n vm.configurationOptions.timeZoneDefaultValue = {\r\n id: null,\r\n description: i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.detailsTab.fields.timeZone.defaultValue`)\r\n };\r\n\r\n const monitorTemplate = `
        {{ dataItem.name }}
        `;\r\n vm.configurationOptions.monitorTypeGridOptions = {\r\n valueTemplate: monitorTemplate,\r\n template: monitorTemplate,\r\n change: onMonitorTypeChanged\r\n };\r\n\r\n vm.configurationOptions.preferredWeatherMonitoringStationDefaultValue = {\r\n monitorId: null,\r\n name: i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.detailsTab.fields.preferredWeatherMonitoringStation.defaultValue`)\r\n };\r\n\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n\r\n vm.cancel = cancel;\r\n vm.save = save;\r\n\r\n let unwatchUtm = angular.noop;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n\r\n initialiseForm();\r\n\r\n $scope.$watch(() => vm.$form.$dirty, () => monitorTabs.details.isDirty = vm.$form.$dirty);\r\n $scope.$watch(() => vm.busyLoading.active(), isBusyLoading => monitorTabs.details.isBusyLoading = isBusyLoading);\r\n\r\n const latlongWatches = [\r\n () => vm.monitor.latitude,\r\n () => vm.monitor.longitude\r\n ];\r\n\r\n $scope.$watchGroup(latlongWatches, () => {\r\n if (!vm.monitor.latitude || !vm.monitor.longitude) {\r\n return;\r\n }\r\n updateMap();\r\n updateElevation();\r\n if (formIsReady) {\r\n vm.$form.latitude.$setDirty();\r\n vm.$form.longitude.$setDirty();\r\n }\r\n });\r\n\r\n $scope.$watch(() => vm.gcs, () => {\r\n if (vm.gcs === `latlong`) {\r\n unwatchUtm();\r\n $scope.$watchGroup(latlongWatches, updateUtm);\r\n } else {\r\n unwatchUtm = $scope.$watch(() => vm.utm, updateLatLong, true);\r\n }\r\n });\r\n\r\n if (vm.isNew) {\r\n $timeout(() => formIsReady = true);\r\n }\r\n\r\n if (vm.isEdit) {\r\n const getMonitorType = monitoringService.getMonitorType(vm.monitor.id).then(type => {\r\n vm.monitor.type = type;\r\n const getMonitor = monitoringService.getMonitor(type, vm.monitor.id);\r\n const getMonitorLocation = monitoringService.getMonitorLocation(vm.monitor.id);\r\n\r\n const loadingPromise = $q.all([getMonitor, getMonitorLocation])\r\n .then(results => {\r\n _.assign(vm.monitor, results[0], results[1]);\r\n $timeout(() => formIsReady = true);\r\n })\r\n .catch(response => {\r\n errorService.processError(response);\r\n $state.go(`app.configuration.company.monitoring.monitors`);\r\n });\r\n\r\n vm.busyLoading.addPromise(loadingPromise);\r\n });\r\n\r\n vm.busyLoading.addPromise(getMonitorType);\r\n }\r\n }\r\n\r\n function initialiseForm() {\r\n formIsReady = false;\r\n\r\n if (vm.timeZoneDDL) {\r\n vm.timeZoneDDL.value(``);\r\n vm.timeZoneDDL.trigger(`change`);\r\n }\r\n\r\n if (vm.monitorTypeDDL) {\r\n vm.monitorTypeDDL.value(``);\r\n vm.monitorTypeDDL.trigger(`change`);\r\n }\r\n\r\n vm.gcs = `latlong`;\r\n vm.utm = {\r\n hemisphere: `N`\r\n };\r\n\r\n vm.map = {\r\n centre: detailsState.configurationOptions.facilityLocation,\r\n defaults: {\r\n settings: mapDefaults.settings\r\n },\r\n layers: {\r\n baselayers: mapDefaults.baselayers\r\n }\r\n };\r\n\r\n vm.monitor = {\r\n id: $state.params.monitorId,\r\n type: undefined,\r\n isVisible: true,\r\n windowsTimeZoneId: appSettings.site.facility.windowsTimeZoneId\r\n };\r\n }\r\n\r\n function cancel() {\r\n activate();\r\n vm.$form.$setPristine();\r\n }\r\n\r\n function save() {\r\n const savingPromise = persistMonitor();\r\n savingPromise.then(saveSuccess);\r\n vm.busySaving.addPromise(savingPromise);\r\n\r\n function persistMonitor() {\r\n return vm.isNew\r\n ? monitoringService.createMonitor(vm.monitor.type, vm.monitor)\r\n : monitoringService.updateMonitor(vm.monitor.type, vm.monitor);\r\n }\r\n\r\n function saveSuccess(monitorId) {\r\n vm.$form.$setPristine();\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.details`, { monitorId }, { reload: true });\r\n }\r\n }\r\n\r\n function updateLatLong() {\r\n if (!vm.utm.northing || !vm.utm.easting || !vm.utm.zone) {\r\n return;\r\n }\r\n const utm = new Utm(vm.utm.zone, vm.utm.hemisphere, vm.utm.easting, vm.utm.northing);\r\n const latlong = utm.toLatLonE();\r\n vm.monitor.latitude = latlong.lat;\r\n vm.monitor.longitude = latlong.lon;\r\n }\r\n\r\n function updateUtm() {\r\n if (!vm.monitor.latitude || !vm.monitor.longitude) {\r\n return;\r\n }\r\n const latlong = new LatLon(vm.monitor.latitude, vm.monitor.longitude);\r\n vm.utm = latlong.toUtm();\r\n }\r\n\r\n function updateElevation() {\r\n if (formIsReady) {\r\n mappingService\r\n .getElevation(vm.monitor.latitude, vm.monitor.longitude)\r\n .then(result => {\r\n vm.monitor.elevation = parseFloat(result.elevation.toFixed(2));\r\n });\r\n }\r\n }\r\n\r\n function updateMap() {\r\n vm.map.centre = {\r\n lat: vm.monitor.latitude,\r\n lng: vm.monitor.longitude,\r\n zoom: vm.configurationOptions.facilityLocation.zoom\r\n };\r\n }\r\n\r\n function onMonitorTypeChanged() {\r\n // we need to jump back into a digest cycle from within the kendo event\r\n $timeout(()=> vm.monitor.isVisible = vm.monitor.type !== `upperAirWeatherStation`);\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.MapConfigurationTab`, MapConfigurationTab);\r\n\r\n MapConfigurationTab.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `i18n`,\r\n `app.core.errorService`,\r\n `app.core.services.configuration.monitoringService`,\r\n `monitorTabs`,\r\n `mapConfigurationState`\r\n ];\r\n function MapConfigurationTab($scope, $state, _, promiseTracker, i18n, errorService, monitoringService, monitorTabs, mapConfigurationState) {\r\n const vm = this;\r\n\r\n let availableVariables,\r\n displayVariables,\r\n graphVariables;\r\n\r\n vm.monitorId = $state.params.monitorId;\r\n vm.$form = null;\r\n vm.sortables = [];\r\n vm.state = mapConfigurationState;\r\n\r\n vm.save = saveDisplay;\r\n vm.cancel = loadDisplay;\r\n\r\n vm.busySaving = promiseTracker();\r\n vm.busyLoading = promiseTracker();\r\n\r\n activate();\r\n\r\n /////////////////\r\n\r\n function activate() {\r\n loadDisplay();\r\n syncDirtyStatus();\r\n\r\n $scope.$watch(() => vm.$form && vm.$form.$dirty, isFormDirty => monitorTabs.mapConfiguration.isDirty = isFormDirty);\r\n $scope.$watch(()=> vm.busyLoading.active(), isBusyLoading => monitorTabs.mapConfiguration.isBusyLoading = isBusyLoading);\r\n }\r\n\r\n function loadDisplay() {\r\n\r\n const loadingPromise = monitoringService.getMonitorDisplay(vm.monitorId).then(setSortables, processError);\r\n\r\n vm.busyLoading.addPromise(loadingPromise);\r\n\r\n function setSortables(display) {\r\n\r\n availableVariables = {\r\n name: i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.content.sortables.availableVariables`),\r\n items: display.availableVariables\r\n };\r\n\r\n displayVariables = {\r\n name: i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.content.sortables.displayVariables`),\r\n items: display.displayVariables,\r\n original: _.map(display.displayVariables, dv => _.assign({}, dv))\r\n };\r\n\r\n graphVariables = {\r\n name: i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.content.sortables.graphVariables`),\r\n items: display.graphVariables,\r\n original: _.map(display.graphVariables, dv => _.assign({}, dv))\r\n };\r\n\r\n vm.sortables = [\r\n availableVariables,\r\n displayVariables,\r\n graphVariables\r\n ];\r\n }\r\n\r\n function processError(response) {\r\n errorService.processError(response);\r\n $state.go(`app.configuration.company.monitoring.monitors`);\r\n }\r\n }\r\n\r\n function syncDirtyStatus() {\r\n $scope.$watch(() => vm.sortables, () => {\r\n\r\n if (!vm.$form) {\r\n return;\r\n }\r\n\r\n if (!displayVariables || !graphVariables || !displayVariables.original || !graphVariables.original) {\r\n vm.$form.$setPristine(true);\r\n return;\r\n }\r\n\r\n if (haveVariablesChanged(graphVariables)) {\r\n vm.$form.$setDirty(true);\r\n return;\r\n }\r\n\r\n if (haveVariablesChanged(displayVariables)) {\r\n vm.$form.$setDirty(true);\r\n return;\r\n }\r\n\r\n vm.$form.$setPristine(true);\r\n }, true);\r\n\r\n function haveVariablesChanged(variableType) {\r\n if (!variableType.items) {\r\n return false;\r\n }\r\n\r\n return variableType.items.length !== variableType.original.length ||\r\n _.zip(variableType.items, variableType.original).some(comparer => {\r\n const current = comparer[0];\r\n const original = comparer[1];\r\n return current.id !== original.id || current.measurementGroupId !== original.measurementGroupId;\r\n });\r\n }\r\n }\r\n\r\n function saveDisplay() {\r\n if (vm.$form.$invalid) {\r\n return;\r\n }\r\n\r\n const params = {\r\n displayVariables: _.map(displayVariables.items, getDisplayVariable),\r\n graphVariables: _.map(graphVariables.items, getId)\r\n };\r\n\r\n const savingPromise = monitoringService\r\n .updateMonitorDisplay(vm.monitorId, params)\r\n .then(loadDisplay);\r\n\r\n vm.busySaving.addPromise(savingPromise);\r\n\r\n function getId(item) {\r\n return item.id;\r\n }\r\n\r\n function getDisplayVariable(item) {\r\n return {\r\n id: item.id,\r\n measurementGroupId: item.measurementGroupId\r\n };\r\n }\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTab`, MeasurementTypesTab);\r\n\r\n MeasurementTypesTab.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `promiseTracker`,\r\n `i18n`,\r\n `app.core.services.configuration.monitoringService`,\r\n `measurementTypesState`\r\n ];\r\n function MeasurementTypesTab($scope, $state, promiseTracker, i18n, monitoringService, measurementTypesState) {\r\n const vm = this;\r\n const searchCriteria = { take: 0, pageSize: 0, sort: [{ field: `name`, dir: `asc`, order: 1 }] };\r\n\r\n vm.monitorId = $state.params.monitorId;\r\n vm.measurementTypeId = $state.params.measurementTypeId;\r\n\r\n vm.$form = null;\r\n vm.busySaving = promiseTracker();\r\n vm.busyLoading = promiseTracker();\r\n\r\n vm.measurementTypesDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.measurementType.defaultValue`);\r\n vm.onSelectMeasurementType = onSelectMeasurementType;\r\n vm.onCreateMeasurementType = onCreateMeasurementType;\r\n\r\n activate();\r\n\r\n /////////////////\r\n\r\n function activate() {\r\n\r\n registerForMeasurementTypeStateEvents();\r\n\r\n const loadingPromise = monitoringService\r\n .queryMonitorMeasurementTypes(vm.monitorId, searchCriteria)\r\n .then(measurementTypes => vm.measurementTypes = measurementTypes);\r\n\r\n vm.busyLoading.addPromise(loadingPromise);\r\n\r\n ////////////////////\r\n\r\n function registerForMeasurementTypeStateEvents() {\r\n $scope.$on(measurementTypesState.events.loading, (event, loadingPromise) => vm.busyLoading.addPromise(loadingPromise));\r\n $scope.$on(measurementTypesState.events.saving, (event, savingPromise) => vm.busySaving.addPromise(savingPromise));\r\n }\r\n }\r\n\r\n function onSelectMeasurementType(measurementTypeId) {\r\n if (measurementTypeId) {\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType.edit`, { measurementTypeId });\r\n } else {\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes`);\r\n }\r\n }\r\n\r\n function onCreateMeasurementType() {\r\n vm.measurementTypeId = null;\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.add`);\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .controller(`app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTabEditPanel`, MeasurementTypesTabEditPanel);\r\n\r\n MeasurementTypesTabEditPanel.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `$timeout`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.errorService`,\r\n `app.core.services.configuration.monitoringService`,\r\n `measurementTypesState`,\r\n `monitorTabs`\r\n ];\r\n function MeasurementTypesTabEditPanel($scope, $state, $timeout, _, i18n, errorService, monitoringService, measurementTypesState, monitorTabs) {\r\n const vm = this;\r\n\r\n vm.maxStaleDataTimeoutSeconds = 60 * 60 * 24 * 7; // 7 days\r\n\r\n vm.isNew = !$state.params.measurementTypeId;\r\n vm.isEdit = !vm.isNew;\r\n\r\n vm.configurationOptions = measurementTypesState.configurationOptions;\r\n vm.configurationOptions.pollutantDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.pollutant.defaultValue`);\r\n vm.configurationOptions.categoryDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.category.defaultValue`);\r\n vm.configurationOptions.defaultDisplayUnitDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.defaultDisplayUnit.defaultValue`);\r\n vm.configurationOptions.defaultImportUnitDefaultValue = i18n.i10n(`app.ui.features.configuration.company.monitoring.monitors.measurementTypesTab.fields.defaultImportUnit.defaultValue`);\r\n\r\n vm.onCategoryChanged = categoryId => {\r\n onCategoryChanged(parseInt(categoryId));\r\n };\r\n\r\n vm.onDefaultImportUnitChanged = onDefaultImportUnitChanged;\r\n vm.onDefaultDisplayUnitChanged = onDefaultDisplayUnitChanged;\r\n\r\n vm.cancel = cancel;\r\n vm.save = save;\r\n\r\n activate();\r\n\r\n /////////////////\r\n\r\n function activate() {\r\n\r\n initialiseForm();\r\n\r\n $scope.$watch(() => vm.$form.$dirty, () => monitorTabs.measurementTypes.isDirty = vm.$form.$dirty);\r\n\r\n if (vm.isNew) {\r\n vm.measurementType.staleDataTimeoutSeconds = 3600;\r\n }\r\n else if (vm.isEdit) {\r\n const loadingPromise = monitoringService.getMeasurementType(vm.measurementType.id)\r\n .then(importMeasurementType)\r\n .catch(response => {\r\n errorService.processError(response);\r\n $state.go(`app.configuration.company.monitoring.monitors`);\r\n });\r\n\r\n $scope.$emit(measurementTypesState.events.loading, loadingPromise);\r\n }\r\n\r\n /////////////////\r\n\r\n function importMeasurementType(measurementType) {\r\n onCategoryChanged(measurementType.categoryId);\r\n // make sure the units collection has been $digested.\r\n $timeout(() => {\r\n _.assign(vm.measurementType, measurementType);\r\n vm.showErrors = true;\r\n });\r\n\r\n }\r\n }\r\n\r\n function initialiseForm() {\r\n if (vm.$form) {\r\n vm.$form.$setPristine();\r\n }\r\n vm.unitCollection = [];\r\n\r\n vm.pollutantCollection = vm.configurationOptions.pollutants;\r\n\r\n vm.measurementType = {\r\n id: $state.params.measurementTypeId,\r\n monitorId: $state.params.monitorId,\r\n categoryId: null,\r\n defaultAggregateTypeId: vm.configurationOptions.aggregateTypes[0].type,\r\n exceedanceThresholds: [],\r\n dataAvailabilityThresholds: []\r\n };\r\n }\r\n\r\n function onCategoryChanged(categoryId) {\r\n vm.measurementType.defaultDisplayUnitId = null;\r\n vm.measurementType.defaultImportUnitId = null;\r\n\r\n if (!_.isNumber(categoryId)) { // i.e. chose `Select Category...` option.\r\n return;\r\n }\r\n\r\n const category = _.find(vm.configurationOptions.measurementTypeCategories, { id: categoryId });\r\n if (!category) {\r\n return;\r\n }\r\n\r\n if (category.id === monitoringService.genericMeasurementTypeCategoryId) {\r\n // user can choose any unit.\r\n vm.unitCollection =\r\n _.chain(vm.configurationOptions.units)\r\n .map(unit => unit)\r\n .flatten()\r\n .value();\r\n } else {\r\n // user can only chose units for the selected category\r\n vm.unitCollection = vm.configurationOptions.units[category.unitTypeId];\r\n }\r\n }\r\n\r\n function onDefaultDisplayUnitChanged(unitId) {\r\n vm.measurementType.defaultImportUnitId = vm.measurementType.defaultImportUnitId || unitId;\r\n }\r\n\r\n function onDefaultImportUnitChanged(unitId) {\r\n vm.measurementType.defaultDisplayUnitId = vm.measurementType.defaultDisplayUnitId || unitId;\r\n }\r\n\r\n function cancel() {\r\n activate();\r\n vm.$form.$setPristine();\r\n }\r\n\r\n function save() {\r\n const savingPromise = persistMeasurementType();\r\n savingPromise.then(saveSuccess);\r\n $scope.$emit(measurementTypesState.events.saving, savingPromise);\r\n\r\n function persistMeasurementType() {\r\n return vm.isNew\r\n ? monitoringService.createMeasurementType(vm.measurementType)\r\n : monitoringService.updateMeasurementType(vm.measurementType);\r\n }\r\n\r\n function saveSuccess(measurementTypeId) {\r\n vm.$form.$setPristine();\r\n $state.go(`app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType.edit`,\r\n { measurementTypeId },\r\n { reload: true }\r\n );\r\n }\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .factory(`app.ui.features.configuration.company.monitoring.monitors.state`, stateFactory);\r\n\r\n stateFactory.$inject = [\r\n `$state`,\r\n `$q`,\r\n `app.core.services.companyService`,\r\n `app.core.services.configuration.legacyLookupService`,\r\n `app.core.services.configuration.measurementGroupService`,\r\n `app.core.services.configuration.monitoringService`,\r\n `app.core.appSettings`,\r\n `app.ui.core.controls.Tab`\r\n ];\r\n /* istanbul ignore next */\r\n function stateFactory($state, $q, companyService, lookupService, measurementGroupService, monitoringService, appSettings, Tab) {\r\n\r\n return {\r\n monitorTabs,\r\n detailsState,\r\n measurementTypesState,\r\n mapConfigurationState,\r\n dataImportState\r\n };\r\n\r\n //////////////////\r\n\r\n function monitorTabs() {\r\n return {\r\n details: new Tab(\r\n `app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.details.heading`,\r\n () => getUrl(`app.configuration.company.monitoring.monitors.tabs.monitor.details`),\r\n () =>\r\n $state.$current.name === `app.configuration.company.monitoring.monitors.tabs.add` ||\r\n $state.$current.name === `app.configuration.company.monitoring.monitors.tabs.monitor.details`\r\n ),\r\n measurementTypes: new Tab(\r\n `app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.measurementTypes.heading`,\r\n () => getUrl(`app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes`),\r\n () => $state.$current.name.indexOf(`app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes`) !== -1,\r\n hasMonitorId\r\n ),\r\n mapConfiguration: new Tab(\r\n `app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.mapConfiguration.heading`,\r\n () => getUrl(`app.configuration.company.monitoring.monitors.tabs.monitor.mapConfiguration`),\r\n () => $state.$current.name === `app.configuration.company.monitoring.monitors.tabs.monitor.mapConfiguration`,\r\n hasMonitorId\r\n ),\r\n dataImport: new Tab(\r\n `app.ui.features.configuration.company.monitoring.monitors.detailPanel.tabs.dataImport.heading`,\r\n () => getUrl(`app.configuration.company.monitoring.monitors.tabs.monitor.dataImport`),\r\n () => $state.$current.name.indexOf(`app.configuration.company.monitoring.monitors.tabs.monitor.dataImport`) !== -1,\r\n hasMonitorId\r\n )\r\n };\r\n\r\n function hasMonitorId() {\r\n return !!$state.params.monitorId;\r\n }\r\n\r\n function getUrl(stateName) {\r\n const stateParams = {\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias,\r\n monitorId: $state.params.monitorId\r\n };\r\n\r\n return $state.href(stateName, stateParams);\r\n }\r\n }\r\n\r\n function detailsState() {\r\n const monitorsPromise = monitoringService.getMonitors();\r\n const monitorTypesPromise = monitoringService.getMonitorTypes();\r\n const windowsTimeZonesPromise = lookupService.getWindowsTimeZones();\r\n const facilityLocationPromise = companyService.getFacilityLocation();\r\n return $q.all([monitorTypesPromise, windowsTimeZonesPromise, facilityLocationPromise, monitorsPromise]).then(results => {\r\n return {\r\n configurationOptions: {\r\n monitorTypes: results[0],\r\n timeZones: results[1],\r\n facilityLocation: results[2],\r\n monitors: results[3]\r\n }\r\n };\r\n });\r\n }\r\n\r\n function measurementTypesState() {\r\n const events = {\r\n loading: `app.ui.features.configuration.company.monitoring.monitors.measurementTypes.loading`,\r\n saving: `app.ui.features.configuration.company.monitoring.monitors.measurementTypes.saving`\r\n };\r\n\r\n return monitoringService.getMeasurementTypeConfigurationOptions().then(configurationOptions => {\r\n return {\r\n events,\r\n configurationOptions\r\n };\r\n });\r\n }\r\n\r\n function mapConfigurationState() {\r\n return measurementGroupService.getMeasurementGroupsFlattened(mg => mg.description)\r\n .then(measurementGroups => ({ measurementGroups }));\r\n }\r\n\r\n function dataImportState() {\r\n const events = {\r\n loading: `app.ui.features.configuration.company.monitoring.monitors.dataImport.loading`,\r\n saving: `app.ui.features.configuration.company.monitoring.monitors.dataImport.saving`\r\n };\r\n\r\n return {\r\n events\r\n };\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.core.controls.Tab`,\r\n `app.ui.features.configuration.company.monitoring.monitors.state`,\r\n `app.ui.features.configuration.company.monitoring.measurementGroups.state`,\r\n `app.ui.features.configuration.company.monitoring.measurementGroups.DeleteModal`\r\n ];\r\n function appRun(routeHelper, Tab, monitorsState, measurementGroupsState, deleteModal) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.monitoring`,\r\n url: `/monitoring`,\r\n data: {\r\n requiredAccessControl: `app.config.monitoring`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/i18n/monitoring`\r\n ]\r\n }\r\n },\r\n\r\n ///////////////////\r\n // Monitor Creation\r\n ///////////////////\r\n\r\n {\r\n // display monitors data grid and provides action to add a new monitor.\r\n state: `app.configuration.company.monitoring.monitors`,\r\n url: `/monitors`,\r\n views: {\r\n 'contentPanel@app': {\r\n // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.ContentPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n monitorTabs: monitorsState.monitorTabs\r\n }\r\n },\r\n {\r\n // provides details panel responsible for managing the tabs.\r\n abstract: true,\r\n state: `app.configuration.company.monitoring.monitors.tabs`,\r\n views: {\r\n detailPanel: {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.DetailPanel as vm`\r\n }\r\n }\r\n },\r\n {\r\n // create a new monitor\r\n state: `app.configuration.company.monitoring.monitors.tabs.add`,\r\n url: `/add`,\r\n views: {\r\n tab: {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/DetailsTab.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.DetailsTab as vm`\r\n }\r\n },\r\n resolve: {\r\n detailsState: monitorsState.detailsState\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/monitors/i18n/DetailsTab`\r\n ]\r\n }\r\n },\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor`,\r\n url: `/:monitorId`\r\n },\r\n {\r\n // edit the details of an existing monitor\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.details`,\r\n url: `/details`,\r\n views: {\r\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/DetailsTab.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.DetailsTab as vm`\r\n }\r\n },\r\n resolve: {\r\n detailsState: monitorsState.detailsState\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/monitors/i18n/DetailsTab`\r\n ]\r\n }\r\n },\r\n\r\n\r\n ////////////////////\r\n // Measurement Types\r\n ////////////////////\r\n\r\n {\r\n // measurement types tab\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes`,\r\n url: `/measurement-types`,\r\n views: {\r\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTab.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTab as vm`\r\n }\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/monitors/i18n/MeasurementTypesTab`,\r\n `/App/ui/features/configuration/company/monitoring/monitors/controls/i18n/esMeasurementTypeThresholds`\r\n ]\r\n },\r\n resolve: {\r\n measurementTypesState: monitorsState.measurementTypesState\r\n }\r\n },\r\n {\r\n // add new measurement type\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.add`,\r\n url: `/add`,\r\n views: {\r\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTabEditPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTabEditPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n measurementTypesState: monitorsState.measurementTypesState\r\n },\r\n onExit: [`monitorTabs`, monitorTabs => monitorTabs.measurementTypes.isDirty = false]\r\n },\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType`,\r\n url: `/:measurementTypeId`\r\n },\r\n {\r\n // edit a measurement type\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes.measurementType.edit`,\r\n url: `/edit`,\r\n views: {\r\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.measurementTypes': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/MeasurementTypesTabEditPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.MeasurementTypesTabEditPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n measurementTypesState: monitorsState.measurementTypesState\r\n },\r\n onExit: [`monitorTabs`, monitorTabs => monitorTabs.measurementTypes.isDirty = false]\r\n },\r\n\r\n //////////////\r\n // Map Configuration\r\n //////////////\r\n\r\n {\r\n // edit the visibility and grouping of measurement types on the maps and graphs\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.mapConfiguration`,\r\n url: `/map-configuration`,\r\n views: {\r\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/MapConfigurationTab.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.MapConfigurationTab as vm`\r\n }\r\n },\r\n resolve: {\r\n mapConfigurationState: monitorsState.mapConfigurationState\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/monitors/controls/i18n/esMonitorVariableDisplay`\r\n ]\r\n }\r\n },\r\n\r\n //////////////\r\n // Data Import\r\n //////////////\r\n\r\n {\r\n // index\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.dataImport`,\r\n url: `/data-import`,\r\n views: {\r\n 'tab@app.configuration.company.monitoring.monitors.tabs': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/DataImportTab.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.DataImportTab as vm`\r\n }\r\n },\r\n resolve: {\r\n dataImportState: monitorsState.dataImportState\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/monitors/i18n/DataImportTab`\r\n ]\r\n }\r\n },\r\n {\r\n // create\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.add`,\r\n url: `/add`,\r\n views: {\r\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.dataImport': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/DataImportTabEditPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.dataImport.DataImportTabEditPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n dataImportState: monitorsState.dataImportState\r\n },\r\n onExit: [`monitorTabs`, monitorTabs => monitorTabs.dataImport.isDirty = false]\r\n },\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential`,\r\n url: `/:apiCredentialId`\r\n },\r\n {\r\n // update\r\n state: `app.configuration.company.monitoring.monitors.tabs.monitor.dataImport.apiCredential.edit`,\r\n url: `/edit`,\r\n views: {\r\n 'form@app.configuration.company.monitoring.monitors.tabs.monitor.dataImport': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/monitors/DataImportTabEditPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.monitors.dataImport.DataImportTabEditPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n dataImportState: monitorsState.dataImportState\r\n },\r\n onExit: [`monitorTabs`, monitorTabs => monitorTabs.dataImport.isDirty = false]\r\n },\r\n\r\n\r\n /////////////////////\r\n // Measurement Groups\r\n /////////////////////\r\n\r\n {\r\n state: `app.configuration.company.monitoring.measurementGroups`,\r\n url: `/measurement-groups`,\r\n views: {\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/measurementGroups/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.measurementGroups.ContentPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n measurementGroupsState: measurementGroupsState\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.monitoring.measurementGroups.add`,\r\n url: `/add`,\r\n views: {\r\n detailPanel: {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/measurementGroups/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.measurementGroups.DetailPanel as vm`\r\n }\r\n }\r\n },\r\n {\r\n abstract: true,\r\n state: `app.configuration.company.monitoring.measurementGroups.measurementGroup`,\r\n url: `/:measurementGroupId`,\r\n views: {\r\n detailPanel: {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/measurementGroups/DetailPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.measurementGroups.DetailPanel as vm`\r\n }\r\n }\r\n },\r\n {\r\n state: `app.configuration.company.monitoring.measurementGroups.measurementGroup.edit`,\r\n url: `/edit`\r\n },\r\n {\r\n state: `app.configuration.company.monitoring.measurementGroups.measurementGroup.delete`,\r\n url: `/delete`,\r\n onEnter: deleteModal.open\r\n },\r\n\r\n ///////\r\n // Base\r\n ///////\r\n\r\n {\r\n state: `app.configuration.company.monitoring.settings`,\r\n url: `/settings`,\r\n views: {\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/settings/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.company.monitoring.settings.ContentPanel as vm`\r\n }\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/company/monitoring/settings/controls/i18n/esWeatherStationConfiguration`\r\n ]\r\n }\r\n }\r\n\r\n ];\r\n }\r\n }\r\n\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.features.configuration.company.monitoring`)\n .controller(`app.ui.features.configuration.company.monitoring.settings.ContentPanel`, ContentPanel);\n\n ContentPanel.$inject = [`$scope`];\n function ContentPanel($scope) {\n const vm = this;\n }\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.company.monitoring`)\r\n .directive(`esWeatherStationConfiguration`, esWeatherStationConfiguration)\r\n .controller(`esWeatherStationConfigurationController`, esWeatherStationConfigurationController);\r\n\r\n esWeatherStationConfiguration.$inject = [];\r\n\r\n function esWeatherStationConfiguration() {\r\n return {\r\n scope: {},\r\n restrict: `E`,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: esWeatherStationConfigurationController,\r\n templateUrl: `/App/ui/features/configuration/company/monitoring/settings/controls/esWeatherStationConfiguration.html`\r\n };\r\n }\r\n\r\n esWeatherStationConfigurationController.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `app.core.services.configuration.monitoringService`,\r\n `promiseTracker`\r\n ];\r\n function esWeatherStationConfigurationController($scope, _, configurationMonitoringService, promiseTracker) {\r\n const vm = this;\r\n\r\n vm.stations = [];\r\n vm.selectedStation = null;\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n vm.cancel = cancel;\r\n vm.save = save;\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n const promise = configurationMonitoringService.getAllMetStations().then(result => {\r\n vm.stations = result;\r\n vm.selectedStation = _.find(result, { isDefault: true });\r\n });\r\n vm.busyLoading.addPromise(promise);\r\n return promise;\r\n }\r\n\r\n function cancel() {\r\n vm.$form.$setPristine(true);\r\n return activate();\r\n }\r\n\r\n function save() {\r\n const promise = configurationMonitoringService.setDefaultMetStation(vm.selectedStation.id)\r\n .then(() => vm.$form.$setPristine(true));\r\n vm.busySaving.addPromise(promise);\r\n return promise;\r\n }\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration`)\r\n .controller(`app.ui.features.configuration.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [];\r\n\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function ContentPanel() {\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n\r\n }\r\n }\r\n})();","`use strict`;\r\n(function() {\r\n\r\n angular\r\n .module(`app.ui.features.configuration`)\r\n .directive(`esAccordionConfigurationSetContainerHeight`, esAccordionConfigurationSetContainerHeight);\r\n\r\n /* istanbul ignore next */\r\n esAccordionConfigurationSetContainerHeight.$inject = [`lodash`];\r\n function esAccordionConfigurationSetContainerHeight(_) {\r\n\r\n return {\r\n restrict: `A`,\r\n link: link\r\n };\r\n\r\n function link($scope, $element) {\r\n\r\n activate();\r\n\r\n function activate() {\r\n $scope.$on(`resizePage`, setAccordionBodyMaxSize);\r\n setAccordionBodyMaxSize();\r\n }\r\n\r\n //////////////\r\n\r\n function setAccordionBodyMaxSize() {\r\n const $container = angular.element(`#module-view-sidebar .sidebar-container`);\r\n const $panels = $element.find(`.panel`);\r\n const $panelBody = $element.find(`.panel-body`);\r\n const $bottomToggle = $container.find(`.advanced-toggle`);\r\n\r\n if (!$panels.length) {\r\n return;\r\n }\r\n\r\n const availableHeight = $container.height();\r\n const bottomToggleHeight = $bottomToggle.height();\r\n const accordionScaffoldingHeight = _.reduce($panels, (height, panel) => {\r\n const $panel = angular.element(panel);\r\n return height +\r\n $panel.find(`.panel-heading`).innerHeight() +\r\n pxToInt($panel, `border-top-width`) +\r\n pxToInt($panel, `border-bottom-width`) +\r\n pxToInt($panel, `margin-top`) +\r\n pxToInt($panel, `margin-bottom`);\r\n }, 0);\r\n const maxPanelHeight = availableHeight - accordionScaffoldingHeight - bottomToggleHeight;\r\n\r\n $panelBody.css(`max-height`, maxPanelHeight + `px`);\r\n }\r\n\r\n function pxToInt(element, css) {\r\n return parseInt(element.css(css).replace(`px`, ``));\r\n }\r\n }\r\n }\r\n\r\n})();\r\n","`use strict`;\r\n(function() {\r\n\r\n angular\r\n .module(`app.ui.features.configuration`)\r\n .directive(`esFormStateTracker`, esFormStateTracker);\r\n\r\n esFormStateTracker.$inject = [];\r\n function esFormStateTracker() {\r\n return {\r\n restrict: `E`,\r\n scope: {},\r\n bindToController: {\r\n isDirty: `=`,\r\n discardChanges: `&`,\r\n loading: `=`\r\n },\r\n controllerAs: `vm`,\r\n controller: controller,\r\n templateUrl: `/App/ui/features/configuration/controls/esFormStateTracker.html`\r\n };\r\n }\r\n\r\n controller.$inject = [`$scope`, `$q`, `$timeout`, `$window`, `i18n`, `routeHelper`, `confirmationDialog`];\r\n function controller($scope, $q, $timeout, $window, i18n, routeHelper, confirmationDialog) {\r\n const vm = this;\r\n\r\n const unsavedChangesHeading = i18n.i10n(`forms.unsaved.changes.heading`);\r\n const unsavedChangesText = i18n.i10n(`forms.unsaved.changes.message.text`);\r\n const unsavedChangesHtml = i18n.i10n(`forms.unsaved.changes.message.html`);\r\n const modalOptions = {\r\n css: `modal-center`,\r\n buttons: {\r\n 'continue': {\r\n text: i18n.i10n(`forms.unsaved.changes.buttons.continue`)\r\n },\r\n cancel : {\r\n text: i18n.i10n(`forms.unsaved.changes.buttons.cancel`)\r\n }\r\n }\r\n };\r\n\r\n vm.discardChanges = vm.discardChanges || angular.noop;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n const removeStateChangeStartEventHandler = routeHelper.addStateChangeStartEventHandler(routeChangingListener, -1); // run this before routeHandler pipeline.\r\n $window.addEventListener(`beforeunload`, windowUnloadListener);\r\n\r\n $scope.$on(`$destroy`, unbindListeners);\r\n\r\n function unbindListeners() {\r\n $window.removeEventListener(`beforeunload`, windowUnloadListener);\r\n removeStateChangeStartEventHandler();\r\n }\r\n }\r\n\r\n function routeChangingListener() {\r\n return $q((resolve, reject) => {\r\n // guard against the $state transition event occurring before the vm.dirty property is processed by a $digest cycle.\r\n $timeout(() => {\r\n if (!vm.isDirty) {\r\n resolve();\r\n return;\r\n }\r\n confirmationDialog\r\n .ask(unsavedChangesHeading, unsavedChangesHtml, modalOptions)\r\n .then(() => {\r\n vm.discardChanges();\r\n resolve();\r\n })\r\n .catch(reject);\r\n });\r\n });\r\n }\r\n\r\n function windowUnloadListener(event) {\r\n if (vm.isDirty) {\r\n (event || $window.event).returnValue = unsavedChangesText; // GECKO and IE\r\n return unsavedChangesText; //Webkit, Safari, Chrome, etc.\r\n }\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration`)\r\n .controller(`app.ui.features.configuration.LeftPanel`, LeftPanel);\r\n\r\n LeftPanel.$inject = [\r\n `$state`,\r\n `lodash`,\r\n `app.core.appSettings`,\r\n `configurationState`\r\n ];\r\n function LeftPanel($state, _, appSettings, configurationState) {\r\n const vm = this;\r\n\r\n vm.appSettings = appSettings;\r\n vm.companyNavigationGroups = [];\r\n vm.configurationState = configurationState;\r\n vm.isRouteSelected = isRouteSelected;\r\n vm.getCompanyRoute = getCompanyRoute;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n vm.companyNavigationGroups = getCompanyNavigationGroups();\r\n }\r\n\r\n function getCompanyNavigationGroups() {\r\n const accessControls = vm.appSettings.site.accessControls;\r\n let groups = [];\r\n\r\n if (accessControls[`app.config.monitoring`]) {\r\n const monitoringGroup = {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.heading`,\r\n ref: `monitoring`,\r\n items: [\r\n {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.monitors.label`,\r\n ref: `monitors`\r\n },\r\n {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.measurementGroups.label`,\r\n ref: `measurementGroups`\r\n },\r\n {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.monitoring.settings.label`,\r\n ref: `settings`\r\n }\r\n ]\r\n };\r\n\r\n groups = [...groups, monitoringGroup];\r\n }\r\n\r\n if (accessControls[`app.config.annotations.monitor-pollutants`]) {\r\n const annotationsGroup = {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.annotations.heading`,\r\n ref: `annotations`,\r\n items: [\r\n {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.annotations.pollutant.label`,\r\n ref: `monitorPollutants`,\r\n isActive: isRouteSelected(`annotations`, `monitorPollutants`)\r\n }\r\n ]\r\n };\r\n groups = [...groups, annotationsGroup];\r\n }\r\n\r\n const modellingGroup = {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.heading`,\r\n ref: `modelling`,\r\n items: []\r\n };\r\n\r\n if (accessControls[`app.modelling.run-aermod-modelling`]) {\r\n modellingGroup.items = [...modellingGroup.items, {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.aermet.label`,\r\n ref: `aermet`\r\n }];\r\n }\r\n\r\n if (accessControls[`app.config.modelling`]) {\r\n modellingGroup.items = [...modellingGroup.items, {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.models.label`,\r\n ref: `models`\r\n }];\r\n }\r\n\r\n if (accessControls[`app.config.modelling.emission-data`]) {\r\n modellingGroup.items = [...modellingGroup.items, {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.emissionsData.label`,\r\n ref: `emissionsData`\r\n }];\r\n }\r\n\r\n if (accessControls[`app.config.modelling.run-models`]) {\r\n modellingGroup.items = [...modellingGroup.items, {\r\n label: `app.ui.features.configuration.leftPanel.navigation.company.menuItems.modelling.modelStatus.label`,\r\n ref: `${vm.appSettings.mvcHostUri}${vm.appSettings.site.facility.es1RouteName}/plume/getmodelstatus`,\r\n target: `_blank`,\r\n isActive: false\r\n }];\r\n }\r\n\r\n groups = [...groups, modellingGroup];\r\n\r\n return groups;\r\n }\r\n\r\n function getCompanyRoute(groupRef, itemRef) {\r\n return $state.href(`app.configuration.company.${groupRef}.${itemRef}`, { companyAlias: vm.appSettings.site.company.alias, facilityAlias: vm.appSettings.site.facility.alias });\r\n }\r\n\r\n function isRouteSelected(groupRef, itemRef) {\r\n return $state.current.state.indexOf(`app.configuration.company.${groupRef}${itemRef ? `.${itemRef}` : ``}`) === 0;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.configuration.state`\r\n ];\r\n function appRun(routeHelper, configurationState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n abstract: true,\r\n state: `app.configuration`,\r\n url: `/configuration`,\r\n views: {\r\n leftPanel: {\r\n templateUrl: `/App/ui/features/configuration/LeftPanel.html`,\r\n controller: `app.ui.features.configuration.LeftPanel as vm`\r\n },\r\n contentPanel: {\r\n templateUrl: `/App/ui/features/configuration/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.ContentPanel as vm`\r\n }\r\n },\r\n data: {\r\n requiredAccessControl: `app.config`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/i18n/configuration`,\r\n `/App/ui/core/controls/i18n/esList`\r\n ]\r\n },\r\n resolve: {\r\n configurationState: configurationState\r\n }\r\n },\r\n {\r\n state: `app.configuration.system`,\r\n url: `/system`,\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/configuration/system/i18n/system`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.configuration.company`,\r\n url: `/{companyAlias}/{facilityAlias}`\r\n }\r\n ];\r\n }\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration`)\r\n .factory(`app.ui.features.configuration.state`, configurationStateFactory);\r\n\r\n configurationStateFactory.$inject = [];\r\n\r\n /* istanbul ignore next */ // Remove if\\when more logic is added\r\n function configurationStateFactory() {\r\n return function () {\r\n return {};\r\n };\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.system`)\r\n .controller(`app.ui.features.configuration.system.modelling.modelRuns.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `promiseTracker`,\r\n `app.core.services.configuration.modellingService`,\r\n `app.core.services.dateTimeService`,\r\n `notifier`,\r\n `i18n`,\r\n `moment`\r\n ];\r\n function ContentPanel(promiseTracker, modellingService, dateTimeService, notifier, i18n, moment) {\r\n const vm = this;\r\n vm.busyLoading = promiseTracker();\r\n vm.busySaving = promiseTracker();\r\n\r\n vm.wrfConfigurationNames = [];\r\n vm.selectedWrfConfigurationName = ``;\r\n\r\n vm.forecastRunNames = [];\r\n vm.selectedForecastRunName = ``;\r\n \r\n vm.datePicker = getDatePicker();\r\n vm.run = run;\r\n\r\n activate();\r\n\r\n ///////////\r\n\r\n function activate() {\r\n const loadPromise = loadConfigurationNames();\r\n vm.busyLoading.addPromise(loadPromise);\r\n }\r\n\r\n function loadConfigurationNames() {\r\n const loadPromise = modellingService.getWrfConfiguration().then(configuration => {\r\n vm.wrfConfigurationNames = configuration.names;\r\n vm.forecastRunNames = configuration.forecastRuns;\r\n });\r\n return loadPromise;\r\n }\r\n\r\n function run() {\r\n const runDate = moment(vm.datePicker.date).startOf(`day`).toDate();\r\n const runPromise = modellingService.runCalModelling(vm.selectedWrfConfigurationName, runDate, vm.selectedForecastRunName)\r\n .then(() => {\r\n notifier.info(\r\n i18n.i10n(`app.ui.features.configuration.system.modelling.modelRuns.contentPanel.notifications.running.message`),\r\n i18n.i10n(`app.ui.features.configuration.system.modelling.modelRuns.contentPanel.notifications.running.heading`)\r\n );\r\n });\r\n vm.busySaving.addPromise(runPromise);\r\n }\r\n\r\n function getDatePicker() {\r\n const today = moment(new Date()).endOf(`day`).toDate();\r\n return {\r\n options: {\r\n max: today,\r\n format: dateTimeService.formats.kendo.date\r\n },\r\n date: today\r\n };\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.configuration.system`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.configuration.state`\r\n ];\r\n function appRun(routeHelper, configurationState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n abstract: true,\r\n state: `app.configuration.system.modelling`,\r\n url: `/modelling`,\r\n data : {\r\n requiredAccessControl: `app.config.modelling`\r\n }\r\n },\r\n {\r\n state: `app.configuration.system.modelling.modelRuns`,\r\n url: `/modelruns`,\r\n views: {\r\n 'contentPanel@app': { // https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#view-names---relative-vs-absolute-names\r\n templateUrl: `/App/ui/features/configuration/system/modelling/modelRuns/ContentPanel.html`,\r\n controller: `app.ui.features.configuration.system.modelling.modelRuns.ContentPanel as vm`\r\n }\r\n }\r\n }\r\n ];\r\n }\r\n }\r\n})();\r\n","(function () {\n `use strict`;\n\n angular\n .module(`app.ui.features.dashboard`)\n .controller(`app.ui.features.dashboard.ContentPanel`, ContentPanel);\n\n ContentPanel.$inject = [\n `$scope`,\n `$timeout`,\n `$log`,\n `lodash`,\n `jQuery`,\n `app.core.services.dashboardService`,\n `dashboardState`,\n `Mousetrap`,\n `notifier`,\n `i18n`\n ];\n function ContentPanel($scope, $timeout, $log, _, $, dashboardService, dashboardState, Mousetrap, notifier, i18n) {\n const vm = this;\n\n let dashboardCopy = dashboardState.dashboard;\n vm.dashboard = dashboardState.dashboard;\n vm.widgetFilter = dashboardService.canAccessWidget;\n\n activate();\n\n //////////////////////////\n\n function activate() {\n moveDashboardTitleInclude();\n registerForEvents();\n setupKeyboardShortcuts();\n $scope.$on(`$destroy`, removeDashboardTitleInclude);\n }\n\n function moveDashboardTitleInclude() {\n $(`#module-view-body`).hide();\n\n $timeout(() => {\n const dashboardTitle = $(`[src=\"model.titleTemplateUrl\"]`);\n const actionsPanel = $(`[ui-view=\"actionsPanel\"]`);\n actionsPanel.append(dashboardTitle.contents());\n $(`#module-view-body`).show();\n });\n }\n\n function removeDashboardTitleInclude() {\n const actionsPanel = $(`[ui-view=\"actionsPanel\"]`);\n actionsPanel.empty();\n }\n\n function setupKeyboardShortcuts() {\n const dashboardResetKeyboardSequence = `capslock capslock d r`;\n\n Mousetrap.bind(dashboardResetKeyboardSequence, resetDashboard);\n\n $scope.$on(`$destroy`, () => {\n Mousetrap.unbind(dashboardResetKeyboardSequence);\n });\n\n function resetDashboard() {\n dashboardService.deleteDashboard();\n $timeout(()=> { // the timeout is needed to ensure the local storage has been written to.\n dashboardCopy = vm.dashboard = dashboardState.dashboard = dashboardService.getDashboard();\n notifier.info(\n i18n.i10n(`app.ui.features.dashboard.contentPanel.notifications.dashboardReset.message`),\n i18n.i10n(`app.ui.features.dashboard.contentPanel.notifications.dashboardReset.title`)\n );\n });\n }\n }\n\n function registerForEvents() {\n let unwatchDashboard = angular.noop;\n\n /*\n * We have modified the DashboardActions.html to provide the dashboard.editMode property.\n * When the dashboard model is modified we want to persist the changes to local storage.\n * Ideally we could $watch the dashboard model BUT the act of setting the dashboard.editMode\n * property triggers the watch and causes the model to be persisted even thought the user has\n * not actually modified the model yet. So this code here watches for editMode changes, only adding\n * a $watch on the dashboard model when in editMode.\n */\n $scope.$watch(() => vm.dashboard.editMode, editMode => {\n const log = _.debounce(dashboard => {\n $log.info(`The dashboard was changed.
        Details:
        ${JSON.stringify(dashboard) }`);\n }, 30000); // bundle up changes to the dashboard before logging.\n\n if (!editMode) {\n unwatchDashboard();\n return;\n }\n\n unwatchDashboard = $scope.$watch(() => vm.dashboard, (oldValue, newValue) => {\n if (angular.equals(oldValue, newValue)) { // make sure we don't persist the default dashboard.\n return;\n }\n\n decorateColumnsWithCssSizingClasses();\n\n dashboardService.persistDashboard(vm.dashboard);\n log(vm.dashboard);\n\n }, true);\n\n });\n\n // the `adfDAshboardChanged` event is fired when the user exits `edit` mode.\n $scope.$on(`adfDashboardChanged`, () => {\n dashboardCopy = vm.dashboard;\n });\n\n $scope.$on(`adfDashboardEditsCancelled`, () => {\n vm.dashboard = dashboardCopy;\n if (vm.dashboard.isDefault) {\n dashboardService.deleteDashboard();\n }\n });\n\n $scope.$on(`adfWidgetAdded`, (event, name, model, widget) => {\n widget.titleTemplateUrl = `/App/ui/features/dashboard/WidgetHeader.html`;\n });\n\n $scope.$on(`resizePage`, decorateColumnsWithCssSizingClasses);\n\n function decorateColumnsWithCssSizingClasses() {\n $scope.$broadcast(`dashboard-layout-changed`);\n\n _.forEach($(`[column=\"column\"]`), column => {\n const $column = $(column);\n const width = $column.width();\n $column.removeClass((index, cssClass) => /^widget-column-.+/.test(cssClass));\n if (width >= 1200) {\n $column.addClass(`widget-column-lg`);\n return;\n }\n if (width >= 992) {\n $column.addClass(`widget-column-md`);\n return;\n }\n if (width >= 768) {\n $column.addClass(`widget-column-sm`);\n return;\n }\n if (width >= 480) {\n $column.addClass(`widget-column-xs`);\n return;\n }\n\n $column.addClass(`widget-column-xxs`);\n });\n }\n }\n }\n})();","(function() {\r\n `use strict`;\r\n\r\n const widgetName = `esBlastScenariosDashboardWidget`;\r\n\r\n angular\r\n .module(`app.ui.features.dashboard`)\r\n .config([`dashboardProvider`, dashboardProvider => {\r\n dashboardProvider.widget(widgetName, {\r\n name: `${widgetName}.heading`,\r\n description: `${widgetName}.description`,\r\n templateUrl: `/App/ui/features/dashboard/controls/blasting/${widgetName}View.html`,\r\n controller: widgetName,\r\n controllerAs: `vm`,\r\n version: `1.0`,\r\n accessControls: [`app.blasting`],\r\n route: `app.blasting.scenarios`\r\n });\r\n }])\r\n .controller(widgetName, controller);\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `promiseTracker`,\r\n `app.core.appSettings`,\r\n `app.core.services.blastingService`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n function controller($scope, $state, promiseTracker, appSettings, blastingService, dateTimeService) {\r\n const vm = this;\r\n\r\n vm.appSettings = appSettings;\r\n vm.busyLoading = promiseTracker();\r\n vm.navigateToScenario = navigateToScenario;\r\n vm.dateTimeService = dateTimeService;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n const getScenarios = blastingService.getScenarios();\r\n vm.busyLoading.addPromise(getScenarios);\r\n getScenarios.then(scenarios => vm.scenarios = scenarios.data.slice(0, 5));\r\n }\r\n\r\n function navigateToScenario(scenarioAlias) {\r\n $state.go(`app.blasting.scenarios.scenario`, {\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias,\r\n scenarioAlias\r\n });\r\n }\r\n\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n const widgetName = `esDailyModelsDashboardWidget`;\r\n\r\n angular\r\n .module(`app.ui.features.dashboard`)\r\n .config([`dashboardProvider`, dashboardProvider => {\r\n dashboardProvider.widget(widgetName, {\r\n name: `${widgetName}.heading`,\r\n description: `${widgetName}.heading`,\r\n templateUrl: `/App/ui/features/dashboard/controls/modelling/${widgetName}View.html`,\r\n controller: widgetName,\r\n controllerAs: `vm`,\r\n version: `1.0`,\r\n accessControls: [`app.modelling`],\r\n route: `app.modelling.gisModelling`\r\n });\r\n }])\r\n .controller(widgetName, controller);\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `$q`,\r\n `$state`,\r\n `promiseTracker`,\r\n `app.core.appSettings`,\r\n `app.ui.features.modelling.hashParser`,\r\n `app.core.services.gisModelService`\r\n ];\r\n function controller($scope, $q, $state, promiseTracker, appSettings, hashParser, gisModelService) {\r\n const vm = this;\r\n const oneDayInMinutes = 24 * 60;\r\n\r\n vm.appSettings = appSettings;\r\n vm.linkHandlers = {\r\n last24hrs: modelId => navigateToModel(modelId, `last24hrs`),\r\n midnight: modelId => navigateToModel(modelId, `today`)\r\n };\r\n vm.busyLoading = promiseTracker();\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n const getModels = appSettings.site.accessControls[`app.modelling`] ? gisModelService.getAllModels() : $q.when([]);\r\n vm.busyLoading.addPromise(getModels);\r\n getModels.then(models => {\r\n vm.models = models;\r\n });\r\n }\r\n\r\n function navigateToModel(modelId, from) {\r\n $state.go(`app.modelling.gisModelling`, {\r\n companyAlias: appSettings.site.company.alias,\r\n facilityAlias: appSettings.site.facility.alias,\r\n modelhash: hashParser.buildModelRunOptionsHash(modelId, from, 0, oneDayInMinutes)\r\n });\r\n }\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n const widgetName = `esMonitorGraphsDashboardWidget`;\r\n const controllerName = `${widgetName}Controller`;\r\n const editControllerName = `${widgetName}EditController`;\r\n\r\n angular\r\n .module(`app.ui.features.dashboard`)\r\n .config(widget)\r\n .controller(controllerName, controller)\r\n .controller(editControllerName, editController);\r\n\r\n widget.$inject = [`dashboardProvider`];\r\n\r\n function widget(dashboardProvider) {\r\n const widgetDefinition = {\r\n name: `${widgetName}.heading`,\r\n description: `${widgetName}.description`,\r\n templateUrl: `/App/ui/features/dashboard/controls/monitoring/${widgetName}View.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n majorVersion: 1,\r\n accessControls: [`app.monitoring`],\r\n route: `app.monitoring`,\r\n edit: {\r\n controller: editController,\r\n controllerAs: `vm`,\r\n templateUrl: `/App/ui/features/dashboard/controls/monitoring/${widgetName}Edit.html`\r\n }\r\n };\r\n\r\n dashboardProvider.widget(widgetName, widgetDefinition);\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `jQuery`,\r\n `app.core.services.settingsService`,\r\n `app.core.services.monitoringService`\r\n ];\r\n\r\n function controller($scope, $timeout, $, settingsService, monitoringService) {\r\n const vm = this;\r\n let refreshMonitorDataTimeout;\r\n\r\n vm.config = $scope.config;\r\n vm.contentBounds = { height: 400, width: 320 };\r\n vm.setContentBounds = setContentBoundsWidth;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n $scope.$on(`dashboard-layout-changed`, setContentBoundsWidth);\r\n $timeout(setContentBoundsWidth);\r\n if (vm.config.selectedMonitorId) {\r\n loadGraphs();\r\n monitoringService.getGraphVariables(vm.config.selectedMonitorId).then(processVariableIds => {\r\n vm.processVariableIds = processVariableIds;\r\n //re-calculate widget size in next digest cycle.\r\n $timeout(setContentBoundsWidth);\r\n });\r\n }\r\n }\r\n\r\n function setContentBoundsWidth() {\r\n const $widgetContent = $(`#monitoring-popup-monitor-${vm.config.selectedMonitorId}`);\r\n\r\n if (!$widgetContent.length) {\r\n return;\r\n }\r\n\r\n vm.contentBounds.width = $widgetContent.width() - 20;\r\n }\r\n\r\n function loadGraphs() {\r\n vm.sampleDateTime = settingsService.getSampleDateTime();\r\n refreshMonitorDataTimeout = $timeout(loadGraphs, getTimeoutMillis());\r\n }\r\n\r\n function getTimeoutMillis() {\r\n let refreshTimeoutSeconds = 60 - new Date().getSeconds();\r\n if (refreshTimeoutSeconds < 10) {\r\n refreshTimeoutSeconds += 60;\r\n }\r\n\r\n return refreshTimeoutSeconds * 1000;\r\n }\r\n\r\n $scope.$on(`$destroy`, () => {\r\n $timeout.cancel(refreshMonitorDataTimeout);\r\n });\r\n }\r\n\r\n editController.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `i18n`,\r\n `app.core.services.configuration.monitoringService`,\r\n `promiseTracker`\r\n ];\r\n\r\n function editController($scope, _, i18n, monitoringService, promiseTracker) {\r\n const vm = this;\r\n\r\n vm.busyLoading = promiseTracker();\r\n vm.config = $scope.config;\r\n vm.availableMonitors = undefined;\r\n vm.optionLabel = {\r\n monitorId: null,\r\n name: i18n.i10n(`esMonitorGraphsDashboardWidget.selectMonitor.label`)\r\n };\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n loadAvailableMonitors();\r\n\r\n $scope.$watch(() => vm.config.selectedMonitorId, () => {\r\n if (!vm.config.selectedMonitorId || !vm.availableMonitors) {\r\n $scope.model.title = null;\r\n return;\r\n }\r\n\r\n const selectedMonitor = _.find(vm.availableMonitors, { monitorId: vm.config.selectedMonitorId });\r\n $scope.model.title = selectedMonitor ? selectedMonitor.name : null;\r\n });\r\n\r\n }\r\n\r\n function loadAvailableMonitors() {\r\n const promise = monitoringService.getMonitors(true).then(monitors => {\r\n vm.availableMonitors = monitors;\r\n });\r\n\r\n vm.busyLoading.addPromise(promise);\r\n }\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n const widgetName = `esMonitorHealthDashboardWidget`;\r\n\r\n const controllerName = `${widgetName}Controller`;\r\n const editControllerName = `${widgetName}EditController`;\r\n\r\n angular\r\n .module(`app.ui.features.dashboard`)\r\n .config(widget)\r\n .controller(controllerName, controller)\r\n .controller(editControllerName, editController);\r\n\r\n widget.$inject = [`dashboardProvider`];\r\n\r\n function widget(dashboardProvider) {\r\n const widgetDefinition = {\r\n name: `${widgetName}.heading`,\r\n description: `${widgetName}.description`,\r\n templateUrl: `/App/ui/features/dashboard/controls/monitoring/${widgetName}View.html`,\r\n controller: controller,\r\n controllerAs: `vm`,\r\n majorVersion: 1,\r\n accessControls: [`app.monitoring`],\r\n route: `app.monitoring`,\r\n edit: {\r\n controller: editController,\r\n controllerAs: `vm`,\r\n templateUrl: `/App/ui/features/dashboard/controls/monitoring/${widgetName}Edit.html`,\r\n reload: false\r\n }\r\n };\r\n\r\n dashboardProvider.widget(widgetName, widgetDefinition);\r\n }\r\n\r\n controller.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `promiseTracker`,\r\n `app.core.services.settingsService`,\r\n `app.core.services.monitoringService`\r\n ];\r\n\r\n function controller($scope, $timeout, promiseTracker, settingsService, monitoringService) {\r\n const vm = this;\r\n vm.busyLoading = promiseTracker();\r\n\r\n vm.config = $scope.config;\r\n vm.monitorDataAlarms = [];\r\n vm.hasSelectedMonitorTypes = false;\r\n\r\n let refreshMonitorDataAlarmsTimeout;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n $scope.$watch(() => vm.config.selectedMonitorTypes, onSelectedMonitorTypesChanged);\r\n\r\n function onSelectedMonitorTypesChanged(selectedMonitorTypes) {\r\n cancelMonitorDataAlarmsTimeout();\r\n\r\n vm.hasSelectedMonitorTypes = selectedMonitorTypes && selectedMonitorTypes.length;\r\n getMonitorDataAlarms();\r\n }\r\n }\r\n\r\n function getMonitorDataAlarms() {\r\n if (!vm.hasSelectedMonitorTypes) {\r\n return;\r\n }\r\n\r\n const loadMonitorDataAlarmsPromise = monitoringService.getMonitorDataAlarms(vm.config.selectedMonitorTypes, settingsService.getSampleDateTime());\r\n vm.busyLoading.addPromise(loadMonitorDataAlarmsPromise);\r\n\r\n loadMonitorDataAlarmsPromise.then(monitorDataAlarms => {\r\n vm.monitorDataAlarms = monitorDataAlarms;\r\n scheduleMonitorDataAlarmsTimeout();\r\n });\r\n }\r\n\r\n function scheduleMonitorDataAlarmsTimeout() {\r\n let refreshTimeoutSeconds = 60 - new Date().getSeconds();\r\n if (refreshTimeoutSeconds < 10) {\r\n refreshTimeoutSeconds += 60;\r\n }\r\n\r\n const refreshTimeoutMillis = refreshTimeoutSeconds * 1000;\r\n\r\n refreshMonitorDataAlarmsTimeout = $timeout(getMonitorDataAlarms, refreshTimeoutMillis);\r\n }\r\n\r\n function cancelMonitorDataAlarmsTimeout() {\r\n if (!refreshMonitorDataAlarmsTimeout) {\r\n return;\r\n }\r\n\r\n $timeout.cancel(refreshMonitorDataAlarmsTimeout);\r\n refreshMonitorDataAlarmsTimeout = null;\r\n }\r\n\r\n $scope.$on(`$destroy`, () => {\r\n $timeout.cancel(refreshMonitorDataAlarmsTimeout);\r\n });\r\n }\r\n\r\n editController.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.services.monitoringService`\r\n ];\r\n\r\n function editController($scope, _, promiseTracker, monitoringService) {\r\n const vm = this;\r\n vm.config = $scope.config;\r\n vm.availableMonitorTypes = [];\r\n\r\n vm.isMonitorTypeSelected = isMonitorTypeSelected;\r\n vm.toggleMonitorType = toggleMonitorType;\r\n vm.busyLoading = promiseTracker();\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n if (!vm.config.selectedMonitorTypes) {\r\n vm.config.selectedMonitorTypes = [];\r\n }\r\n\r\n loadMonitorTypes();\r\n\r\n ////////////////////\r\n\r\n function loadMonitorTypes() {\r\n const getMonitorTypesPromise = monitoringService.getMonitorTypes();\r\n vm.busyLoading.addPromise(getMonitorTypesPromise);\r\n\r\n getMonitorTypesPromise.then(availableMonitorTypes => {\r\n vm.availableMonitorTypes = availableMonitorTypes;\r\n });\r\n }\r\n }\r\n\r\n function isMonitorTypeSelected(monitorType) {\r\n return vm.config.selectedMonitorTypes.indexOf(monitorType) >= 0;\r\n }\r\n\r\n function toggleMonitorType(monitorType) {\r\n const index = _.indexOf(vm.config.selectedMonitorTypes, monitorType);\r\n\r\n if (index >= 0) {\r\n vm.config.selectedMonitorTypes.splice(index, 1);\r\n vm.config.selectedMonitorTypes = [...vm.config.selectedMonitorTypes];\r\n } else {\r\n vm.config.selectedMonitorTypes = vm.config.selectedMonitorTypes.concat(monitorType);\r\n }\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.dashboard`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [`routeHelper`, `app.ui.features.dashboard.state`];\r\n function appRun(routeHelper, dashboardState) {\r\n\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app.dashboard`,\r\n url: `/dashboard/{companyAlias}/{facilityAlias}?dateTime`,\r\n views : {\r\n contentPanel: {\r\n templateUrl: `/App/ui/features/dashboard/ContentPanel.html`,\r\n controller: `app.ui.features.dashboard.ContentPanel as vm`\r\n }\r\n },\r\n data : {\r\n requiredAccessControl: `app.dashboard`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/dashboard/i18n/dashboard`,\r\n `/App/ui/features/dashboard/controls/blasting/i18n/esBlastScenariosDashboardWidget`,\r\n `/App/ui/features/dashboard/controls/modelling/i18n/esDailyModelsDashboardWidget`,\r\n `/App/ui/features/dashboard/controls/monitoring/i18n/esMonitorGraphsDashboardWidget`,\r\n `/App/ui/features/dashboard/controls/monitoring/i18n/esMonitorHealthDashboardWidget`,\r\n `/App/ui/features/monitoring/controls/i18n/esMonitoringWidget`,\r\n `/App/i18n/Shared`\r\n ]\r\n },\r\n resolve: {\r\n dashboardState: dashboardState\r\n }\r\n }\r\n ];\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.dashboard`)\r\n .factory(`app.ui.features.dashboard.state`, dashboardStateFactory);\r\n\r\n dashboardStateFactory.$inject = [\r\n `app.core.services.dashboardService`\r\n ];\r\n function dashboardStateFactory(dashboardService) {\r\n\r\n return () => {\r\n return {\r\n dashboard: dashboardService.getDashboard()\r\n };\r\n };\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.extras`)\r\n .controller(`app.ui.features.extras.about.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `i18n`,\r\n `app.core.appSettings`,\r\n `app.core.services.diagnosticsService`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function ContentPanel(i18n, appSettings, diagnosticsService, dateTimeService) {\r\n const vm = this;\r\n\r\n vm.appSettings = appSettings;\r\n vm.processDataLastReceived;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n updateProcessDataLastReceived(`loading`);\r\n\r\n diagnosticsService.getLatestProcessDataEndTime().then(endTime => {\r\n if (endTime) {\r\n const localEndTime = dateTimeService.formatAs.dateTime(endTime);\r\n updateProcessDataLastReceived(`lastReceived`, { endTime: localEndTime });\r\n\r\n } else {\r\n updateProcessDataLastReceived(`neverReceived`);\r\n }\r\n });\r\n }\r\n\r\n function updateProcessDataLastReceived(labelKeySuffix, formattingArgs) {\r\n const labelKey = `app.ui.features.extras.about.contentPanel.diagnostics.processData.${labelKeySuffix}`;\r\n vm.processDataLastReceived = i18n.i10n(labelKey, formattingArgs || {});\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.extras`)\r\n .controller(`app.ui.features.extras.help.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `app.core.appSettings`\r\n ];\r\n function ContentPanel(appSettings) {\r\n const vm = this;\r\n vm.appSettings = appSettings;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.extras`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [`routeHelper`];\r\n\r\n function appRun(routeHelper) {\r\n routeHelper.configureRoutes(getRoutes());\r\n }\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app.about`,\r\n url: `/about`,\r\n views: {\r\n contentPanel: {\r\n templateUrl: `/App/ui/features/extras/about/ContentPanel.html`,\r\n controller: `app.ui.features.extras.about.ContentPanel as vm`\r\n }\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/extras/about/i18n/about`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.help`,\r\n url: `/help`,\r\n views: {\r\n contentPanel: {\r\n templateUrl: `/App/ui/features/extras/help/ContentPanel.html`,\r\n controller: `app.ui.features.extras.help.ContentPanel as vm`\r\n }\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/extras/help/i18n/help`\r\n ]\r\n }\r\n }\r\n ];\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .controller(`app.ui.features.incidentIntelligence.artifacts.ActionsPanel`, ActionsPanel);\r\n\r\n ActionsPanel.$inject = [\r\n ];\r\n\r\n function ActionsPanel() {\r\n const vm = this;\r\n vm.actions = {\r\n fullScreen: {\r\n isEnabled: false\r\n }\r\n };\r\n\r\n\r\n activate();\r\n\r\n /////////////////////\r\n \r\n function activate() {\r\n }\r\n\r\n }\r\n})();\r\n","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.features.incidentIntelligence`)\n .controller(`app.ui.features.incidentIntelligence.artifacts.ContentPanel`, ContentPanel);\n\n ContentPanel.$inject = [\n `$q`,\n `lodash`,\n `notifier`,\n `i18n`,\n `$state`,\n `app.core.services.dateTimeService`,\n `app.core.datetime.timeZoneDateTime`,\n `app.core.services.locationService`,\n `state`,\n `app.core.mapDefaults`,\n `app.ui.core.mapping.mapLayerRenderer`,\n `app.core.services.incidentIntelligenceService`,\n `app.core.services.mappingService`,\n `esLeafletData`\n ];\n\n /* istanbul ignore next */\n function ContentPanel(\n $q,\n _,\n notifier,\n i18n,\n $state,\n dateTimeService,\n timeZoneService,\n locationService,\n state,\n mapDefaults,\n mapLayerRenderer,\n incidentIntelligenceService,\n mappingService,\n esLeafletData) {\n\n const vm = this;\n\n vm.state = state;\n vm.map = getMap();\n vm.mapLayerDatasets = [];\n vm.isReady = false;\n\n vm.showOverControls = false;\n\n activate();\n\n //////////////////////\n\n function activate() {\n locationService.updatePageHeading({ ticketId: $state.params.ticketId });\n\n incidentIntelligenceService.getPathModel($state.params.ticketId, $state.params.ticketActivityId)\n .then(updateViewModel)\n .then(loadOverlays)\n .catch(processError)\n .finally(() => vm.isReady = true);\n }\n\n function loadOverlays() {\n return mappingService.getKmls().then(overlays => {\n vm.map.overlayProvider = overlays;\n vm.showOverlayControls = overlays && overlays.length;\n });\n }\n\n function updateViewModel(result) {\n\n const facilityTimeZoneStartTime = timeZoneService.convertDateTimeToFacilityTimeZone(result.startTime);\n locationService.updatePageHeading({ ticketId: $state.params.ticketId, startTime: dateTimeService.formatAs.dateTime(facilityTimeZoneStartTime) });\n\n optimiseMapBounds(result.primaryTrack.data);\n\n const primaryTrackDataPoints = renderDataPoints(result.primaryTrack, result.isForwardTrajectory);\n vm.mapLayerDatasets.push(primaryTrackDataPoints);\n\n //////////////////\n\n function renderDataPoints(dataPoint, isForwardTrajectory) {\n mapLayerRenderer.renderPathLayer(dataPoint, isForwardTrajectory);\n delete dataPoint.data;\n return dataPoint;\n }\n\n function optimiseMapBounds(dataPoints) {\n return esLeafletData.getMap(vm.map.id)\n .then(map => {\n map.fitBounds(getBounds(dataPoints));\n });\n\n function getBounds(dataPoints) {\n return _.map(dataPoints, dataPoint => [ dataPoint.latitude, dataPoint.longitude ]);\n }\n }\n }\n\n function processError(error) {\n if (error.status === 404) {\n notifier.error(\n i18n.i10n(`app.ui.features.incidentIntelligence.artifacts.contentPanel.errors.notFound.message`, { ticketActivityId : $state.params.ticketActivityId }),\n i18n.i10n(`app.ui.features.incidentIntelligence.artifacts.contentPanel.errors.notFound.title`)\n );\n error.handled = true;\n }\n }\n\n function getMap() {\n return {\n id : `map-canvas`,\n defaultCentre: state.facilityLocation,\n centre: state.facilityLocation,\n isColor: false,\n defaults: {\n settings: mapDefaults.settings\n },\n layers: {\n baselayers: mapDefaults.baselayers\n },\n overlayProvider: {}\n };\n }\n }\n})();\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .factory(`app.ui.features.incidentIntelligence.hashParser`, hashParser);\r\n\r\n hashParser.$inject = [];\r\n\r\n /* istanbul ignore next */\r\n function hashParser() {\r\n return {\r\n buildOptionsHash,\r\n configureOptionsFromHash\r\n };\r\n\r\n ////////////////////\r\n\r\n function buildOptionsHash(modelCategory) {\r\n return `${modelCategory}`;\r\n }\r\n\r\n function configureOptionsFromHash(hash, modelsState) {\r\n const options = parseHashString(hash);\r\n\r\n modelsState.selectedModel = options.model;\r\n }\r\n\r\n function parseHashString(hash = ``) {\r\n const parts = hash.split(`|`);\r\n\r\n return {\r\n model: parts[0]\r\n };\r\n }\r\n }\r\n\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.incidentIntelligence.state`,\r\n `app.ui.features.incidentIntelligence.summary.state`\r\n ];\r\n /* istanbul ignore next */\r\n function appRun(routeHelper, state, summaryState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app.incidentIntelligence`,\r\n abstract: true,\r\n url: `/incident-intelligence/:companyAlias/:facilityAlias`,\r\n data: {\r\n requiredAccessControl: `app.incident-intelligence`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/incidentIntelligence/i18n/incidentIntelligence`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.incidentIntelligence.tickets`,\r\n abstract: true,\r\n url: `/tickets`\r\n },\r\n {\r\n state : `app.incidentIntelligence.tickets.summary`,\r\n abstract: true,\r\n url : `/summary`,\r\n views: {\r\n 'actionsPanel@app': {\r\n template: ``\r\n },\r\n\r\n 'leftPanel@app': {\r\n template: ``\r\n },\r\n\r\n 'contentPanel@app': {\r\n template: ``\r\n }\r\n },\r\n data: {\r\n layoutType: `split`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/mapping/i18n/mapLayerRenderer`,\r\n `/App/ui/core/mapping/controls/i18n/esMapKml`,\r\n `/App/ui/core/mapping/controls/i18n/esMapTiles`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCredits`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCentre`,\r\n `/App/ui/core/mapping/controls/i18n/esMapType`,\r\n `/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries`,\r\n `/App/ui/features/incidentIntelligence/summary/i18n/LeftPanel`,\r\n `/App/ui/features/incidentIntelligence/summary/i18n/ContentPanel`,\r\n `/App/ui/features/incidentIntelligence/summary/i18n/ActionsPanel`\r\n ]\r\n },\r\n resolve: {\r\n summaryState\r\n }\r\n },\r\n\r\n ////////////////////////\r\n\r\n {\r\n state : `app.incidentIntelligence.tickets.summary.heat`,\r\n url : `/heat?fullScreen&mapType`,\r\n onEnter : onSummaryRouteEnter\r\n },\r\n {\r\n state : `app.incidentIntelligence.tickets.summary.cluster`,\r\n url : `/cluster?fullScreen&mapType`,\r\n onEnter : onSummaryRouteEnter\r\n },\r\n\r\n ////////////////////////\r\n\r\n {\r\n state: `app.incidentIntelligence.tickets.ticket`,\r\n abstract: true,\r\n url: `/:ticketId`\r\n },\r\n {\r\n state: `app.incidentIntelligence.tickets.ticket.artifacts`,\r\n url: `/artifacts/:ticketActivityId?fullScreen&mapType`,\r\n views: {\r\n 'actionsPanel@app': {\r\n templateUrl: `/App/ui/features/incidentIntelligence/artifacts/ActionsPanel.html`,\r\n controller: `app.ui.features.incidentIntelligence.artifacts.ActionsPanel as vm`\r\n },\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/incidentIntelligence/artifacts/ContentPanel.html`,\r\n controller: `app.ui.features.incidentIntelligence.artifacts.ContentPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n state\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/mapping/i18n/mapLayerRenderer`,\r\n `/App/ui/core/mapping/controls/i18n/esMapKml`,\r\n `/App/ui/core/mapping/controls/i18n/esMapTiles`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCredits`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCentre`,\r\n `/App/ui/core/mapping/controls/i18n/esMapType`,\r\n `/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries`\r\n ]\r\n }\r\n }\r\n ];\r\n }\r\n\r\n ////////////////////////\r\n\r\n onSummaryRouteEnter.$inject = [`summaryState`];\r\n function onSummaryRouteEnter(summaryState) {\r\n summaryState.map.isCluster = this.name === `app.incidentIntelligence.tickets.summary.cluster`;\r\n }\r\n }\r\n})();","/* istanbul ignore next */\r\n(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .factory(`app.ui.features.incidentIntelligence.state`, stateFactory);\r\n\r\n stateFactory.$inject = [\r\n `$q`,\r\n `app.core.services.companyService`\r\n ];\r\n\r\n function stateFactory($q, companyService) {\r\n return function stateFactoryResolver() {\r\n const loaders = [\r\n companyService.getFacilityLocation()\r\n ];\r\n\r\n return $q.all(loaders).then(results => {\r\n const [facilityLocation] = results;\r\n return new State(facilityLocation);\r\n });\r\n };\r\n\r\n function State(facilityLocation) {\r\n const self = this;\r\n self.facilityLocation = facilityLocation;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .component(`incidentIntelligence.summary.actionsPanel`,{\r\n controller: ActionsPanelController,\r\n templateUrl: `App/ui/features/incidentIntelligence/summary/ActionsPanel.html`,\r\n controllerAs: `vm`,\r\n bindings: {\r\n }\r\n });\r\n\r\n ActionsPanelController.$inject = [];\r\n\r\n function ActionsPanelController() {\r\n const vm = this;\r\n\r\n vm.$onInit = () => {\r\n vm.actions = {\r\n fullScreen: {\r\n isEnabled: false\r\n }\r\n };\r\n };\r\n\r\n }\r\n})();\r\n","(function () {\n `use strict`;\n\n angular\n .module(`app.ui.features.incidentIntelligence`)\n .component(`incidentIntelligence.summary.contentPanel`, {\n controller: ContentPanelController,\n templateUrl: `/App/ui/features/incidentIntelligence/summary/ContentPanel.html`,\n controllerAs: `vm`,\n bindings: {\n state: `=`\n }\n });\n\n ContentPanelController.$inject = [\n `$window`,\n `$state`,\n `app.core.appSettings`,\n `app.core.mapDefaults`,\n `i18n`,\n `app.core.services.mappingService`\n ];\n\n function ContentPanelController($window, $state, appSettings, mapDefaults, i18n, mappingService) {\n const vm = this;\n\n vm.$window = $window;\n vm.$state = $state;\n vm.map = getMap();\n vm.routes = getRoutes();\n vm.showOverlayControls = false;\n vm.onclick = onclick;\n\n\n activate();\n\n ////////////////////\n\n function activate() {\n loadOverlays();\n }\n\n function getMap() {\n return {\n defaultCentre: vm.state.facilityLocation,\n centre: vm.state.facilityLocation,\n isColor: false,\n defaults: {\n settings: mapDefaults.settings\n },\n layers: {\n baselayers: mapDefaults.baselayers\n },\n overlayProvider: {},\n bounds: vm.state.map.bounds\n };\n }\n\n function loadOverlays() {\n return mappingService.getKmls().then(overlays => {\n vm.map.overlayProvider = overlays;\n vm.showOverlayControls = overlays && overlays.length;\n });\n }\n\n function onclick(marker) {\n if (appSettings.site.facility.ticketingSystem) {\n vm.$window.open(appSettings.site.facility.ticketingSystem.ticketUrl(marker.ticketId), `_blank`);\n }\n }\n\n function getRoutes() {\n return [\n {\n name: i18n.i10n(`app.ui.features.incidentIntelligence.summary.contentPanel.routes.heatmap.label`),\n routeName: `app.incidentIntelligence.tickets.summary.heat`\n },\n {\n name: i18n.i10n(`app.ui.features.incidentIntelligence.summary.contentPanel.routes.cluster.label`),\n routeName: `app.incidentIntelligence.tickets.summary.cluster`\n }\n ];\n }\n }\n})();\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .component(`incidentIntelligence.summary.leftPanel`, {\r\n controller: LeftPanelController,\r\n templateUrl: `/App/ui/features/incidentIntelligence/summary/LeftPanel.html`,\r\n controllerAs: `vm`,\r\n bindings: {\r\n state: `=`\r\n }\r\n });\r\n\r\n LeftPanelController.$inject = [\r\n `$window`,\r\n `$timeout`,\r\n `lodash`,\r\n `moment`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.incidentIntelligenceService`\r\n ];\r\n\r\n function LeftPanelController($window, $timeout, _, moment, dateTimeService, timeZoneDateTime, incidentIntelligenceService) {\r\n const vm = this;\r\n\r\n const search = _.debounce(() => {\r\n $timeout(searchSummaryValues);\r\n }, 1000);\r\n\r\n vm.toggleStatus = toggleStatus;\r\n vm.toggleType = toggleType;\r\n vm.criteriaChanged = search;\r\n\r\n vm.$onInit = () => {\r\n\r\n buildControls();\r\n\r\n searchSummaryValues();\r\n\r\n /////////////////////\r\n\r\n function buildControls() {\r\n const maxDate = vm.state.ticket.facilityTimeZoneToDate;\r\n vm.controls = {\r\n fromDate: buildDatePicker(vm.state.ticket.facilityTimeZoneFromDate, maxDate),\r\n toDate: buildDatePicker(vm.state.ticket.facilityTimeZoneToDate, maxDate)\r\n };\r\n\r\n function buildDatePicker(dateTime) {\r\n return {\r\n formattedString: dateTimeService.formatAs.date(dateTime),\r\n options: {\r\n format: dateTimeService.formats.kendo.date,\r\n max: maxDate\r\n }\r\n };\r\n }\r\n }\r\n };\r\n\r\n /////////////////////\r\n\r\n function toggleStatus(item) {\r\n toggleItem(vm.state.ticket.selectedStatuses, item);\r\n search();\r\n }\r\n\r\n function toggleType(item) {\r\n toggleItem(vm.state.ticket.selectedTypes, item);\r\n search();\r\n }\r\n\r\n function toggleItem(selectedItems, item) {\r\n if (item.isSelected) {\r\n selectedItems.push(item);\r\n } else {\r\n _.remove(selectedItems, { id: item.id });\r\n }\r\n }\r\n\r\n function searchSummaryValues() {\r\n if (vm.form && vm.form.$invalid) {\r\n return;\r\n }\r\n if (vm.state.ticket.selectedTypes.length && vm.state.ticket.selectedStatuses.length) {\r\n const fromDate = getDateInLocalTimeZone(moment(vm.state.ticket.facilityTimeZoneFromDate).startOf(`day`).toDate());\r\n const toDate = getDateInLocalTimeZone(moment(vm.state.ticket.facilityTimeZoneToDate).endOf(`day`).toDate());\r\n return incidentIntelligenceService.getTicketSummaryLocations(\r\n {\r\n fromDate: fromDate,\r\n toDate: toDate,\r\n selectedCategoryId: vm.state.ticket.selectedCategoryId,\r\n selectedTypes: _.map(vm.state.ticket.selectedTypes, `id`),\r\n selectedStatuses: _.map(vm.state.ticket.selectedStatuses, `id`)\r\n }\r\n ).then(mapResults);\r\n } else {\r\n vm.state.ticketLocations = [];\r\n }\r\n }\r\n\r\n ////////////////////\r\n\r\n function getDateInLocalTimeZone(date) {\r\n return timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(date);\r\n }\r\n\r\n function mapResults(data) {\r\n vm.state.ticketLocations = _.map(data, result => ({\r\n ticketId: result.ticketId,\r\n lat: result.latitude,\r\n long: result.longitude,\r\n tooltip: result.ticketId\r\n }));\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.incidentIntelligence`)\r\n .factory(`app.ui.features.incidentIntelligence.summary.state`, summaryStateFactory);\r\n\r\n summaryStateFactory.$inject = [\r\n `$q`,\r\n `lodash`,\r\n `app.core.services.companyService`,\r\n `app.core.services.incidentIntelligenceService`,\r\n `app.core.datetime.timeZoneDateTime`\r\n ];\r\n\r\n function summaryStateFactory($q, _, companyService, incidentIntelligenceService, timeZoneDateTime) {\r\n\r\n return function() {\r\n const loaders = [\r\n companyService.getFacilityLocation(),\r\n incidentIntelligenceService.getSummaryLookupValues(),\r\n companyService.getDomainBoundaries(false, false, true)\r\n ];\r\n\r\n return $q.all(loaders).then(results => {\r\n const [facilityLocation, lookupValues, domainBoundaries] = results;\r\n return createState(facilityLocation, lookupValues, domainBoundaries);\r\n });\r\n };\r\n\r\n function createState(facilityLocation, lookupValues, domainBoundaries) {\r\n const nowTime = new Date();\r\n return {\r\n facilityLocation : facilityLocation,\r\n map: {\r\n isCluster: undefined, // this value is set in the route.onEnter event function\r\n bounds: getMapBounds()\r\n },\r\n ticketLocations: [],\r\n ticket : {\r\n categories: lookupValues.categories,\r\n selectedCategoryId: lookupValues.categories[0].id,\r\n\r\n types: _.map(lookupValues.types, type => { type.isSelected = true; return type; }),\r\n selectedTypes: [...lookupValues.types],\r\n\r\n statuses: _.map(lookupValues.statuses, status => { status.isSelected = true; return status; }),\r\n selectedStatuses: [...lookupValues.statuses],\r\n\r\n facilityTimeZoneFromDate: timeZoneDateTime.getFacilityStartOfDay(nowTime),\r\n facilityTimeZoneToDate: timeZoneDateTime.getFacilityEndOfDay(nowTime)\r\n }\r\n };\r\n\r\n function getMapBounds() {\r\n return domainBoundaries &&\r\n _.reduce(domainBoundaries, (memo, boundary) => {\r\n const coordinates = [boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight];\r\n return memo.concat(_.map(coordinates, coordinate => [coordinate.latitude, coordinate.longitude]));\r\n }, []);\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .controller(`app.ui.features.modelling.ActionsPanel`, ActionsPanel);\r\n\r\n ActionsPanel.$inject = [`$scope`, `modellingState`];\r\n\r\n function ActionsPanel($scope, modellingState) {\r\n const vm = this;\r\n\r\n vm.map = modellingState.map;\r\n vm.actions = {\r\n fullScreen: {\r\n isEnabled: false\r\n }\r\n };\r\n\r\n activate();\r\n\r\n /////////////////////\r\n \r\n function activate() {\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .controller(`app.ui.features.modelling.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `moment`,\r\n `app.ui.features.modelling.mediator`,\r\n `app.ui.features.modelling.timeStepCalculator`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.dateTimeService`,\r\n `modellingState`,\r\n `app.core.services.mappingService`,\r\n `app.core.services.gisModelService`,\r\n `app.core.models.monitoring.createMonitorMapMarker`\r\n ];\r\n\r\n /* istanbul ignore next */\r\n function ContentPanel(\r\n $scope,\r\n _,\r\n moment,\r\n ModellingMediator,\r\n timeStepCalculator,\r\n timeZoneDateTime,\r\n dateTimeService,\r\n modellingState,\r\n mappingService,\r\n gisModelService,\r\n createMonitorMapMarker\r\n ) {\r\n const millisPerMinute = 60 * 1000;\r\n\r\n const vm = this;\r\n const mediator = new ModellingMediator(modellingState, onModelDataRefreshed);\r\n\r\n vm.map = modellingState.map;\r\n vm.mapLayerDatasets = [];\r\n vm.overlayProvider = {};\r\n vm.showControls = false;\r\n vm.modellingState = modellingState;\r\n\r\n vm.timeSliderStart = null;\r\n vm.timeSliderEnd = null;\r\n vm.timeSliderStepSize = 0;\r\n vm.onActiveTimeStepChanged = onActiveTimeStepChanged;\r\n\r\n vm.hasTimeSteps = false;\r\n vm.hasSelectedModels = false;\r\n vm.hasModellingParameters = false;\r\n vm.hasDataForAnySelectedModel = false;\r\n vm.modelDataAvailability = modellingState.modelDataAvailability;\r\n\r\n vm.activeTimeStepStart = null;\r\n vm.activeTimeStepEnd = null;\r\n\r\n const discreteReceptorDisplayOptions = {\r\n monitorNames: false,\r\n units: false,\r\n heroMode: false,\r\n thresholdExceeded: false,\r\n dataValue: false,\r\n icons: true\r\n };\r\n\r\n activate();\r\n\r\n //////////////////////\r\n\r\n function activate() {\r\n refreshWhenDateRangeChanges();\r\n refreshWhenChangingRealTimeModellingMode();\r\n refreshWhenSelectedModelsChange();\r\n watchTimeSlider();\r\n\r\n enableTimeSliderWhenSelectedModelsHaveData();\r\n destroyMediatorOnDeactivate();\r\n loadOverlays();\r\n }\r\n\r\n function watchTimeSlider() {\r\n $scope.$watchGroup([\r\n () => vm.hasSelectedModels,\r\n () => vm.isSingleTimeStep\r\n ], () => {\r\n vm.showTimeSlider = vm.hasSelectedModels && !vm.isSingleTimeStep;\r\n triggerMapResize();\r\n });\r\n }\r\n\r\n function loadOverlays() {\r\n mappingService.getKmls()\r\n .then(overlays => {\r\n vm.overlayProvider = overlays;\r\n vm.showControls = overlays && overlays.length > 0;\r\n });\r\n }\r\n\r\n function onModelDataRefreshed() {\r\n evaluateIfSelectedModelsHaveData();\r\n bindEnabledTimeStepDataToMap();\r\n }\r\n\r\n function onActiveTimeStepChanged(endTime) {\r\n const intervalMinutes = vm.modellingState.selectedInterval.minutes;\r\n const activeTimeRange = timeStepCalculator.calculateTimeStepRange(endTime, intervalMinutes, 0, intervalMinutes);\r\n\r\n if (Date.equals(vm.activeTimeStepStart, activeTimeRange.fromDate) &&\r\n Date.equals(vm.activeTimeStepEnd, activeTimeRange.toDate)) {\r\n return;\r\n }\r\n\r\n vm.activeTimeStepStart = activeTimeRange.fromDate;\r\n vm.activeTimeStepEnd = activeTimeRange.toDate;\r\n\r\n bindEnabledTimeStepDataToMap();\r\n }\r\n\r\n function bindEnabledTimeStepDataToMap() {\r\n if (vm.activeTimeStepEnd) {\r\n vm.mapLayerDatasets = modellingState.modellingDataStore.getTimeStepDataForEnabledModels(vm.activeTimeStepEnd);\r\n renderDiscreteReceptors(modellingState.modellingDataStore.getTimeStepDiscreteReceptorDataForEnabledModels(vm.activeTimeStepEnd));\r\n }\r\n }\r\n\r\n function renderDiscreteReceptors(discreteReceptors) {\r\n vm.map.markers = discreteReceptors && discreteReceptors.map(discreteReceptor =>\r\n createMonitorMapMarker(discreteReceptor, discreteReceptorDisplayOptions, getReportUri(vm.modellingState.alertPointReports, discreteReceptor))\r\n );\r\n\r\n function getReportUri(reports, discreteReceptor) {\r\n if (!reports){\r\n return null;\r\n }\r\n const report = reports.find(report => report.processVariableIds.find(pv => pv === discreteReceptor.processVariable.id));\r\n if (!(report && report.uri)) {\r\n return null;\r\n }\r\n\r\n const { id: monitorId } = discreteReceptor;\r\n\r\n if (report && report.uri) {\r\n const startDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.modellingState.dataSetStartDate);\r\n const endDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.modellingState.dataSetEndDate);\r\n\r\n\r\n return `${report.uri}?s=${dateTimeService.formatAs.iso(startDate)}&e=${dateTimeService.formatAs.iso(endDate)}&m=${monitorId}`;\r\n }\r\n }\r\n }\r\n\r\n function refreshWhenDateRangeChanges() {\r\n $scope.$watch(\r\n () => modellingState.dataSetStartDate + `-` + modellingState.dataSetEndDate,\r\n () => {\r\n if (!(modellingState.dataSetStartDate && modellingState.dataSetEndDate)) { return; }\r\n adjustActiveTimeStepToDataSetDateRange();\r\n updateTimeSliderParameters();\r\n mediator.refresh();\r\n });\r\n }\r\n\r\n function refreshWhenChangingRealTimeModellingMode() {\r\n $scope.$watch(\r\n () => `${modellingState.dataSetStartDate}-${modellingState.dataSetEndDate}-${modellingState.autoUpdateEnabled}`,\r\n () => {\r\n const currentRealTimeMode = modellingState.realTimeMode;\r\n modellingState.realTimeMode = isRealTimeMode();\r\n if (currentRealTimeMode !== modellingState.realTimeMode) {\r\n vm.modellingState.clear();\r\n mediator.refresh();\r\n }\r\n }\r\n );\r\n\r\n function isRealTimeMode() {\r\n return modellingState.dataSetStartDate &&\r\n modellingState.dataSetEndDate &&\r\n modellingState.dataSetStartDate.getTime() === modellingState.dataSetEndDate.getTime() &&\r\n modellingState.autoUpdateEnabled;\r\n }\r\n }\r\n\r\n function adjustActiveTimeStepToDataSetDateRange() {\r\n if (!(modellingState.dataSetStartDate && modellingState.dataSetEndDate)) {\r\n return;\r\n }\r\n\r\n const intervalMillis = vm.modellingState.selectedInterval.minutes * millisPerMinute;\r\n const startMillis = modellingState.dataSetStartDate.getTime();\r\n const endMillis = modellingState.dataSetEndDate.getTime();\r\n let activeEndMillis = vm.activeTimeStepEnd ? vm.activeTimeStepEnd.getTime() : 0;\r\n\r\n let isUpdateRequired = false;\r\n\r\n if (activeEndMillis <= startMillis) {\r\n activeEndMillis = startMillis + intervalMillis;\r\n isUpdateRequired = true;\r\n }\r\n\r\n // We need to also check against the end time in case the user is looking at a \"0 => 0\" interval -\r\n // in this case, adjusting to startMillis + intervalMillis will have put us over the endMillis.\r\n if (activeEndMillis >= endMillis) {\r\n activeEndMillis = endMillis;\r\n isUpdateRequired = true;\r\n }\r\n\r\n if (isUpdateRequired) {\r\n onActiveTimeStepChanged(activeEndMillis);\r\n }\r\n }\r\n\r\n function refreshWhenSelectedModelsChange() {\r\n $scope.$watchCollection(() => modellingState.selectedModels, (selectedModels, oldSelectedModels) => {\r\n if (selectedModels === oldSelectedModels) {\r\n return;\r\n }\r\n\r\n const newModelIds = _.map(selectedModels, `modelId`);\r\n const oldModelIds = _.map(oldSelectedModels, `modelId`);\r\n\r\n _.difference(oldModelIds, newModelIds)\r\n .forEach(modelId => modellingState.modellingDataStore.disableModel(modelId));\r\n _.difference(newModelIds, oldModelIds)\r\n .forEach(modelId => modellingState.modellingDataStore.enableModel(modelId));\r\n\r\n vm.hasSelectedModels = !!newModelIds.length;\r\n\r\n mediator.refresh();\r\n\r\n bindEnabledTimeStepDataToMap();\r\n evaluateIfSelectedModelsHaveData();\r\n });\r\n }\r\n\r\n function triggerMapResize() {\r\n $scope.$broadcast(`resizePage`);\r\n }\r\n\r\n function enableTimeSliderWhenSelectedModelsHaveData() {\r\n $scope.$watch(() => modellingState.modelLoadingStatuses, evaluateIfSelectedModelsHaveData, true);\r\n }\r\n\r\n function evaluateIfSelectedModelsHaveData() {\r\n const dateRange = modellingState.getDataSetDateRange();\r\n const intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\r\n\r\n vm.hasDataForAnySelectedModel = _.some(modellingState.selectedModels, model => {\r\n const modelDataAvailability = modellingState.modelDataAvailability[model.modelId];\r\n if (!modelDataAvailability) {\r\n return false;\r\n }\r\n\r\n for (let timeStepMillis = dateRange.toMillis; timeStepMillis > dateRange.fromMillis; timeStepMillis -= intervalMillis) {\r\n const hasData = modelDataAvailability[timeStepMillis];\r\n if (hasData) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n });\r\n }\r\n\r\n function updateTimeSliderParameters() {\r\n vm.isSingleTimeStep = modellingState.dataSetStartDate.getTime() === modellingState.dataSetEndDate.getTime();\r\n\r\n const getTimeMillis = date => date ? date.getTime() : 0;\r\n\r\n vm.timeSliderStart = getTimeMillis(vm.modellingState.dataSetStartDate);\r\n vm.timeSliderEnd = getTimeMillis(vm.modellingState.dataSetEndDate);\r\n vm.timeSliderStepSize = vm.modellingState.selectedInterval.minutes * millisPerMinute;\r\n\r\n vm.timeSliderTooltip = {\r\n template: data => {\r\n return moment(data.value)\r\n .add(timeZoneDateTime.getFacilityTimeZoneOffsetDifferenceFromLocal(new Date(data.value)), `minutes`)\r\n .format(dateTimeService.formats.moment.dateTime);\r\n }\r\n };\r\n }\r\n\r\n function destroyMediatorOnDeactivate() {\r\n $scope.$on(`$destroy`, mediator.dispose);\r\n }\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .directive(`esMapModels`, esMapModels);\r\n\r\n esMapModels.$inject = [`leafletLib`, `lodash`];\r\n function esMapModels(L, _) {\r\n\r\n return {\r\n restrict: `E`,\r\n require: `^esLeaflet`,\r\n scope: {\r\n mapId: `@`,\r\n models: `=`\r\n },\r\n link: link\r\n };\r\n\r\n function link($scope, $element, attrs, esLeafletData) {\r\n esLeafletData.getMap($scope.mapId).then(map => {\r\n\r\n let modelLayerIndex = {}; // eslint-disable-line no-unused-vars\r\n const baseLayer = new L.LayerGroup();\r\n baseLayer.addTo(map);\r\n map.createPane(`path-std-deviation`);\r\n\r\n $scope.$watchCollection(() => $scope.models, toggleActiveLayers);\r\n $scope.$on(`$destroy`, () => modelLayerIndex = {});\r\n\r\n function toggleActiveLayers(currentDataPoints, previousDataPoints) {\r\n if (previousDataPoints) {\r\n previousDataPoints.forEach(dataPoint => {\r\n _.forEach(dataPoint.labels, label => label.closeTooltip());\r\n baseLayer.removeLayer(dataPoint.layerGroup);\r\n });\r\n }\r\n\r\n if (currentDataPoints) {\r\n currentDataPoints.forEach(dataPoint => {\r\n baseLayer.addLayer(dataPoint.layerGroup);\r\n _.forEach(dataPoint.labels, label => {\r\n label.openTooltip();\r\n });\r\n });\r\n }\r\n }\r\n });\r\n }\r\n }\r\n})();\r\n","(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .directive(`esModellingDurationSelect`, esModellingDurationSelect)\r\n .controller(`esModellingDurationSelectController`, esModellingDurationSelectController);\r\n\r\n function esModellingDurationSelect() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n selectedDuration: `=`,\r\n availableDurations: `=`,\r\n textPrefix: `=`\r\n },\r\n templateUrl: `/App/ui/features/modelling/controls/esModellingDurationSelect.html`,\r\n controller: esModellingDurationSelectController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esModellingDurationSelectController.$inject = [`$scope`, `i18n`, `lodash`];\r\n function esModellingDurationSelectController($scope, i18n, _) {\r\n const vm = this;\r\n vm.select = null;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updateSelectableDurationsWhenAvailableDurationsChange();\r\n }\r\n\r\n function updateSelectableDurationsWhenAvailableDurationsChange() {\r\n $scope.$watch(\r\n () => vm.availableDurations,\r\n () => {\r\n vm.formattedDurations = _.map(vm.availableDurations, val => {\r\n return {\r\n text: vm.textPrefix + minutesToText(val),\r\n value: val\r\n };\r\n });\r\n }\r\n );\r\n }\r\n\r\n function minutesToText(minutes) {\r\n if (minutes <= 90) {\r\n return `${minutes} ${i18n.i10n(`esModellingDurationSelect.labels.minutes`)}`;\r\n }\r\n\r\n let hours = minutes / 60;\r\n if (hours !== Math.floor(hours)) {\r\n hours = hours.toFixed(2);\r\n }\r\n\r\n return `${hours} ${i18n.i10n(`esModellingDurationSelect.labels.hours`)}`;\r\n }\r\n }\r\n})();\r\n","(function(){\r\n\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .directive(`esModellingModelSelect`, esModellingModelSelect)\r\n .controller(`esModellingModelSelectController`, esModellingModelSelectController);\r\n\r\n function esModellingModelSelect() {\r\n return {\r\n restrict: `E`,\r\n scope: {\r\n state: `=`,\r\n textPrefix: `=`\r\n },\r\n templateUrl: `/App/ui/features/modelling/controls/esModellingModelSelect.html`,\r\n controller: esModellingModelSelectController,\r\n controllerAs: `vm`,\r\n bindToController: true\r\n };\r\n }\r\n\r\n esModellingModelSelectController.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `lodash`,\r\n `app.core.models.modelLoadingStatus`\r\n ];\r\n\r\n function esModellingModelSelectController($scope, $timeout, _, modelLoadingStatus) {\r\n const vm = this;\r\n let unwatchLegends = [];\r\n\r\n vm.toggleModel = _.debounce(args => $timeout(toggleModel(args)), 500);\r\n vm.toggleLegend = toggleLegend;\r\n\r\n vm.modelLegendClasses = {};\r\n vm.modelLegendTooltips = {};\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n updateModelLegendClassesAndTooltipsWhenDataSetChanges();\r\n updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges();\r\n }\r\n\r\n function updateModelLegendClassesAndTooltipsWhenDataSetChanges() {\r\n const dataSetDateWatchers = [\r\n () => vm.state.dataSetStartDate,\r\n () => vm.state.dataSetEndDate\r\n ];\r\n\r\n $scope.$watchGroup(dataSetDateWatchers, rebuildAllLegendClassesAndTooltips);\r\n\r\n $scope.$watch(() => vm.state.modelLoadingStatuses, rebuildAllLegendClassesAndTooltips, true);\r\n $scope.$watch(() => vm.state.selectedInterval, updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges);\r\n }\r\n\r\n function updateModelLegendClassesAndTooltipsWhenLegendVisibilityChanges() {\r\n unwatchLegends.forEach(unwatch => unwatch());\r\n\r\n unwatchLegends = vm.state.selectedInterval.models.map(model => {\r\n return $scope.$watch(\r\n () => model.legend.visible,\r\n () => rebuildLegendClassesAndTooltipForModel(model));\r\n });\r\n }\r\n\r\n function rebuildAllLegendClassesAndTooltips() {\r\n vm.state.selectedInterval.models.forEach(rebuildLegendClassesAndTooltipForModel);\r\n }\r\n\r\n function rebuildLegendClassesAndTooltipForModel(model) {\r\n const modelId = model.modelId;\r\n const status = vm.state.getModelLoadingStatus(modelId);\r\n const isLoading = status === modelLoadingStatus.loading;\r\n const hasFailed = status === modelLoadingStatus.failed;\r\n\r\n const classes = [`fa`];\r\n let tooltip;\r\n\r\n if (!(isLoading || hasFailed)) {\r\n classes.push(model.legend.visible ? `fa-caret-down` : `fa-caret-right`);\r\n tooltip = `legend`;\r\n\r\n } else if (!isLoading) {\r\n classes.push(`fa-exclamation-circle`);\r\n tooltip = `loadingFailed`;\r\n\r\n } else {\r\n classes.push(`fa-circle-o-notch fa-spin`);\r\n tooltip = `loadingModel`;\r\n }\r\n\r\n vm.modelLegendClasses[modelId] = classes.join(` `);\r\n vm.modelLegendTooltips[modelId] = `esModellingModelSelect.${tooltip}.tooltip`;\r\n }\r\n\r\n function toggleModel(model) {\r\n vm.state.setModelSelected(model, model.isSelected);\r\n }\r\n\r\n function toggleLegend(legend) {\r\n legend.visible = !legend.visible;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .factory(`app.ui.features.modelling.hashParser`, hashParser);\r\n\r\n hashParser.$inject = [\r\n `lodash`,\r\n `moment`,\r\n `app.core.services.dateTimeService`\r\n ];\r\n\r\n function hashParser(_, moment, dateTimeService) {\r\n const AUTO_UPDATE = `auto`;\r\n const KNOWN_DATES = [`yesterday`, `last24hrs`, `today`, `now`, `tomorrow`];\r\n\r\n return {\r\n buildModelRunOptionsHash,\r\n configureModelRunOptionsFromHash\r\n };\r\n\r\n ////////////////////\r\n\r\n function buildModelRunOptionsHash(modelIds, date = `now`, durationFrom = 0, durationTo = 0, autoUpdate = false) {\r\n if (modelIds === undefined || modelIds === null) {\r\n throw new Error(`A model id must be provided.`);\r\n }\r\n\r\n const hashDate = buildHashDate(date, autoUpdate);\r\n\r\n const modelIdList = modelIds instanceof Array ? modelIds.join(`,`) : modelIds;\r\n return autoUpdate\r\n ? `${modelIdList}|${hashDate}|0|0`\r\n : `${modelIdList}|${hashDate}|${durationFrom}|${durationTo}`;\r\n }\r\n\r\n function buildHashDate(date, autoUpdate) {\r\n if (autoUpdate) {\r\n return AUTO_UPDATE;\r\n }\r\n\r\n if (date instanceof Date) {\r\n return dateTimeService.formatAs.iso(date);\r\n }\r\n\r\n if (moment.isMoment(date)) {\r\n return dateTimeService.formatAs.iso(date.toDate());\r\n }\r\n\r\n return KNOWN_DATES.find(knownDate => knownDate === date) && date || `now`;\r\n }\r\n\r\n function configureModelRunOptionsFromHash(hash, leftPanelController) {\r\n const parsedHash = parseHashString(hash);\r\n\r\n setSelectedModelDetails(parsedHash, leftPanelController);\r\n setSelectedDateDetails(parsedHash, leftPanelController);\r\n }\r\n\r\n function setSelectedDateDetails(parsedHash, leftPanelController) {\r\n if (parsedHash.autoUpdate) {\r\n leftPanelController.modellingState.autoUpdateEnabled = true;\r\n return;\r\n }\r\n\r\n const availableIntervals = leftPanelController.modellingState.selectedInterval.durationRanges;\r\n\r\n leftPanelController.durationTo = getClosestMatchingInterval(parsedHash.durationTo);\r\n leftPanelController.durationFrom = getClosestMatchingInterval(parsedHash.durationFrom);\r\n\r\n if (!isNaN(+parsedHash.date)) {\r\n leftPanelController.datePicker.date = parsedHash.date;\r\n leftPanelController.datePicker.dateString = dateTimeService.formatAs.dateTime(parsedHash.date);\r\n }\r\n\r\n function getClosestMatchingInterval(requestedInterval) {\r\n requestedInterval = Math.abs(requestedInterval || 0);\r\n\r\n for (let i = 0; i < availableIntervals.length; i++) {\r\n const interval = availableIntervals[i];\r\n if (interval >= requestedInterval) {\r\n return interval;\r\n }\r\n }\r\n\r\n return _.last(availableIntervals);\r\n }\r\n }\r\n\r\n function setSelectedModelDetails(parsedHash, leftPanelController) {\r\n const modellingState = leftPanelController.modellingState;\r\n\r\n for (let i = 0; i < modellingState.intervals.length; i++) {\r\n const interval = modellingState.intervals[i];\r\n const validModels = getIntervalModelsFoundInHash(parsedHash.modelIds, interval);\r\n\r\n if (!(validModels && validModels.length)) {\r\n continue;\r\n }\r\n\r\n Array.prototype.push.apply(modellingState.selectedModels, validModels);\r\n modellingState.selectedInterval = interval;\r\n\r\n _.forEach(validModels, model => model.isSelected = true);\r\n break;\r\n }\r\n }\r\n\r\n function getIntervalModelsFoundInHash(modelIds, interval) {\r\n return _.filter(interval.models, model => _.includes(modelIds, model.modelId));\r\n }\r\n\r\n function parseHashString(hash = ``) {\r\n if (!hash) {\r\n return {};\r\n }\r\n\r\n const parts = hash.split(`|`);\r\n const modelIds = (parts[0] || ``).split(`,`).map(modelId => { return modelId.toLowerCase(); });\r\n const date = parts.length > 1 && parts[1];\r\n\r\n return {\r\n modelIds,\r\n autoUpdate: date && date.toLocaleLowerCase() === AUTO_UPDATE,\r\n date: getDate(date),\r\n durationFrom: parts.length > 2 && parseInt(parts[2]),\r\n durationTo: parts.length > 3 && parseInt(parts[3])\r\n };\r\n\r\n function getDate(dateString = ``) {\r\n switch (dateString.toLowerCase()) {\r\n case `yesterday`:\r\n return moment().add(-1, `day`).startOf(`day`).toDate();\r\n\r\n case `last24hrs`:\r\n return moment().add(-1, `day`).startOf(`hour`).toDate();\r\n\r\n case `now`:\r\n case AUTO_UPDATE:\r\n return new Date();\r\n\r\n case `today`:\r\n return moment().startOf(`day`).toDate();\r\n\r\n case `tomorrow`:\r\n return moment().add(1, `day`).startOf(`day`).toDate();\r\n\r\n default:\r\n return new Date(dateString);\r\n }\r\n }\r\n }\r\n\r\n\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .controller(`app.ui.features.modelling.LeftPanel`, LeftPanel);\r\n\r\n LeftPanel.$inject = [\r\n `$scope`,\r\n `$timeout`,\r\n `$state`,\r\n `$location`,\r\n `$log`,\r\n `i18n`,\r\n `lodash`,\r\n `Mousetrap`,\r\n `notifier`,\r\n `app.core.appSettings`,\r\n `app.core.models.jobs.Job`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.gisModelService`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.signalR.jobs.state`,\r\n `app.ui.features.modelling.timeStepCalculator`,\r\n `app.ui.features.modelling.hashParser`,\r\n `modellingState`,\r\n `kendo`\r\n ];\r\n\r\n function LeftPanel($scope, $timeout, $state, $location, $log, i18n, _, Mousetrap, notifier, appSettings, Job, timeZoneDateTime,\r\n gisModelService, dateTimeService, jobState, timeStepCalculator, hashParser, modellingState, kendo) {\r\n\r\n const vm = this;\r\n\r\n let trackModelDurationWarnings = false;\r\n const modelDurationTimeStepWarningCount = 240;\r\n\r\n const millisPerMinute = 60 * 1000;\r\n let autoUpdateTimeout = null;\r\n\r\n vm.modellingState = modellingState;\r\n vm.datePicker = getDatePicker();\r\n vm.durationFrom = 0;\r\n vm.durationTo = 0;\r\n vm.onAutoUpdateChanged = onAutoUpdateChanged;\r\n vm.appSettings = appSettings;\r\n vm.warningClassName = null;\r\n\r\n const updateModelHashUrlParameter = _.debounce(modelHash => {\r\n const toParams = { modelhash: modelHash };\r\n $timeout(() => $state.go(`app.modelling.gisModelling`, toParams, { notify: false }));\r\n }, 50);\r\n\r\n activate();\r\n\r\n function activate() {\r\n hashParser.configureModelRunOptionsFromHash($location.search().modelhash, vm);\r\n\r\n subscribeToDateChanges();\r\n subscribeToIntervalChanges();\r\n\r\n updateModelHashIfAutoUpdateChanges();\r\n updateModelHashIfSelectedModelsChange();\r\n }\r\n\r\n function onAutoUpdateChanged() {\r\n $timeout.cancel(autoUpdateTimeout);\r\n\r\n if (modellingState.autoUpdateEnabled) {\r\n scheduleNextAutoUpdateOfSelectedDate();\r\n }\r\n\r\n function scheduleNextAutoUpdateOfSelectedDate() {\r\n const lastInterval = rebaseSelectedTimeToLastInterval();\r\n\r\n const intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\r\n const nextIntervalAt = new Date(lastInterval.getTime() + intervalMillis);\r\n const now = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date());\r\n const timeUntilNextIntervalMillis = nextIntervalAt.getTime() - now.getTime();\r\n\r\n const seconds = parseInt(timeUntilNextIntervalMillis / 1000);\r\n $log.debug(`Next tick scheduled in: ${parseInt(seconds / 60)}m ${parseInt(seconds % 60)}s.`);\r\n\r\n autoUpdateTimeout = $timeout(() => {\r\n if (modellingState.autoUpdateEnabled) {\r\n scheduleNextAutoUpdateOfSelectedDate();\r\n }\r\n }, timeUntilNextIntervalMillis);\r\n }\r\n\r\n function rebaseSelectedTimeToLastInterval() {\r\n const now = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date());\r\n\r\n const lastIntervalMillis = timeStepCalculator.getLastIntervalMillis(now, modellingState.selectedInterval.minutes);\r\n const lastInterval = new Date(lastIntervalMillis);\r\n\r\n $log.debug(`Current date time set to last interval: ${lastInterval}.`);\r\n\r\n return vm.datePicker.date = lastInterval;\r\n }\r\n }\r\n\r\n function subscribeToDateChanges() {\r\n const i10nWarningPrefix = `app.ui.features.modelling.leftPanel.model.duration.warning`;\r\n\r\n $scope.$watch(() => vm.durationFrom + `-` + vm.durationTo + `-` + vm.datePicker.date, () => {\r\n if (vm.form && vm.form.date && vm.form.date.$invalid) {\r\n return;\r\n }\r\n\r\n const intervalMinutes = modellingState.selectedInterval.minutes;\r\n const selectedDate = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.datePicker.date);\r\n\r\n const timeRange = timeStepCalculator.calculateTimeStepRange(selectedDate, vm.durationFrom, vm.durationTo, intervalMinutes);\r\n if (trackModelDurationWarnings) {\r\n if (timeRange.timeStepCount > modelDurationTimeStepWarningCount) {\r\n const suffix = modellingState.selectedModels.length ? i18n.i10n(`${i10nWarningPrefix}.existing-models.label`) : ``;\r\n const prefix = i18n.i10n(`${i10nWarningPrefix}.label`);\r\n modellingState.modelDurationWarning = `${prefix} ${suffix}`;\r\n\r\n vm.warningClassName = modellingState.selectedModels.length ? `duration-warning-models` : `duration-warning`;\r\n\r\n modellingState.selectedModels.length = 0;\r\n modellingState.selectedInterval.models.forEach(model => model.isSelected = false);\r\n } else {\r\n modellingState.modelDurationWarning = null;\r\n }\r\n }\r\n trackModelDurationWarnings = true;\r\n\r\n vm.modellingState.dataSetStartDate = timeRange.fromDate;\r\n vm.modellingState.dataSetEndDate = timeRange.toDate;\r\n\r\n recalculateModelHash();\r\n });\r\n }\r\n\r\n function subscribeToIntervalChanges() {\r\n $scope.$watch(() => modellingState.selectedInterval, (interval, oldInterval) => {\r\n modellingState.modelDurationWarning = interval.minutes === oldInterval.minutes ? modellingState.modelDurationWarning : null;\r\n resetSelectedModels(interval, oldInterval);\r\n updateTimePickerDropdownTimeIntervals(interval);\r\n\r\n if (!modellingState.autoUpdateEnabled) {\r\n rebaseSelectedTimeToIntervalBoundary();\r\n } else {\r\n onAutoUpdateChanged();\r\n }\r\n\r\n recalculateModelHash();\r\n });\r\n\r\n function resetSelectedModels(interval, oldInterval) {\r\n if (interval === oldInterval) {\r\n return;\r\n }\r\n\r\n modellingState.selectedModels.length = 0;\r\n modellingState.selectedInterval.models.forEach(model => model.isSelected = false);\r\n\r\n vm.durationFrom = 0;\r\n vm.durationTo = 0;\r\n }\r\n\r\n function updateTimePickerDropdownTimeIntervals(interval) {\r\n // ensure the date - picker has been rendered before doing this.\r\n if (!vm.datePicker.kendoDatePicker) {\r\n return;\r\n }\r\n\r\n angular.extend(vm.datePicker.options, { interval: interval.minutes });\r\n vm.datePicker.kendoDatePicker.setOptions(vm.datePicker.options);\r\n }\r\n }\r\n\r\n function updateModelHashIfAutoUpdateChanges() {\r\n $scope.$watch(() => modellingState.autoUpdateEnabled, (current, previous) => {\r\n if (current !== previous) {\r\n recalculateModelHash();\r\n }\r\n });\r\n }\r\n\r\n function updateModelHashIfSelectedModelsChange() {\r\n $scope.$watch(() => modellingState.selectedModels.length, (current, previous) => {\r\n if (current !== previous) {\r\n recalculateModelHash();\r\n }\r\n });\r\n }\r\n\r\n function recalculateModelHash() {\r\n const {\r\n selectedModels,\r\n autoUpdateEnabled\r\n } = modellingState;\r\n\r\n const {\r\n datePicker: {\r\n date: selectedDate\r\n },\r\n durationFrom,\r\n durationTo\r\n } = vm;\r\n\r\n const modelIds = selectedModels.map(model => model.modelId);\r\n const modelHash = hashParser.buildModelRunOptionsHash(modelIds, selectedDate, durationFrom, durationTo, autoUpdateEnabled);\r\n\r\n updateModelHashUrlParameter(modelHash);\r\n }\r\n\r\n function getDatePicker() {\r\n const initialDate = timeZoneDateTime.convertDateTimeToFacilityTimeZone(new Date());\r\n return {\r\n hasFocus: false,\r\n date: initialDate,\r\n dateString: dateTimeService.formatAs.dateTime(initialDate),\r\n options: {\r\n // note: anything provided in here is angular bound. don't put an event handler in here otherwise you have to run $scope.$apply()\r\n format: dateTimeService.formats.kendo.dateTime,\r\n timeFormat: dateTimeService.formats.kendo.time,\r\n interval: modellingState.selectedInterval.minutes\r\n },\r\n onChange: () => {\r\n if (!vm.form || !vm.form.date || vm.form.date.$invalid) {\r\n return;\r\n }\r\n\r\n vm.datePicker.dateString = kendo.toString(vm.datePicker.date, dateTimeService.formats.kendo.dateTime);\r\n\r\n rebaseSelectedTimeToIntervalBoundary();\r\n vm.datePicker.onBlur();\r\n },\r\n onFocus: () => {\r\n vm.datePicker.hasFocus = true;\r\n },\r\n onBlur: () => {\r\n vm.datePicker.hasFocus = false;\r\n }\r\n };\r\n }\r\n\r\n function rebaseSelectedTimeToIntervalBoundary() {\r\n const intervalMillis = timeStepCalculator.getLastIntervalMillis(vm.datePicker.date, modellingState.selectedInterval.minutes);\r\n\r\n vm.datePicker.date = new Date(intervalMillis);\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .factory(`app.ui.features.modelling.ModellingDataStore`, modellingDataStore);\r\n\r\n modellingDataStore.$inject = [\r\n `lodash`,\r\n `app.core.models.mapping.dataPointFactory`,\r\n `app.ui.core.mapping.mapLayerRenderer`\r\n ];\r\n\r\n function modellingDataStore(_, dataPointFactory, mapLayerRenderer) {\r\n\r\n function ModellingDataStore() {\r\n // Used by consumer to get the current modelDataPoints for specific `active` date\r\n this._dateIndex = {};\r\n\r\n // Used by consumer to get all the imported time steps for a specific model\r\n // so missing periods can be retrieved from server\r\n this._importedTimeSteps = {};\r\n\r\n // Used internally so that if the same dataPoints happen to be\r\n // provided twice, it is only processed once\r\n this._availableTimeStepDataIds = {};\r\n\r\n // Used internally to ascertain which models have been flagged as disabled\r\n // so that when #getTimeStepDataForEnabledModels() is invoked, only those that are active are retrieved.\r\n // This is to allow us to retain dataPoints even if toggled off in case it is toggled straight back on\r\n this._disabledModels = {};\r\n\r\n // Used by consumer to get all discrete receptor values at a specific `active` date\r\n this._discreteReceptorValues = {};\r\n }\r\n\r\n ModellingDataStore.prototype.importDiscreteReceptorData = function(modelId, discreteReceptorData) {\r\n const self = this;\r\n\r\n if (_.isEmpty(discreteReceptorData)) {\r\n return;\r\n }\r\n\r\n Object.entries(discreteReceptorData).forEach(([key, value]) => {\r\n const dateKey = new Date(key).getTime();\r\n const bucket = self._discreteReceptorValues[dateKey] || (self._discreteReceptorValues[dateKey] = {});\r\n bucket[modelId] = value;\r\n });\r\n };\r\n\r\n ModellingDataStore.prototype.getTimeStepDiscreteReceptorDataForEnabledModels = function(date) {\r\n const self = this;\r\n const dateKey = date.getTime();\r\n const bucket = self._discreteReceptorValues[dateKey];\r\n if (!bucket) {\r\n return;\r\n }\r\n\r\n return Object.keys(bucket).reduce((data, key) => {\r\n if (!self._disabledModels[key]) {\r\n data.push(...bucket[key]);\r\n }\r\n\r\n return data;\r\n }, []);\r\n };\r\n\r\n ModellingDataStore.prototype.importModelDataSets = function(modelDataSets) {\r\n const self = this;\r\n\r\n return _.chain(modelDataSets)\r\n .map(importTimeStepData)\r\n .flatten()\r\n .value();\r\n\r\n ////////////////////\r\n\r\n function importTimeStepData(dataSet) {\r\n const timeStepDataSet = dataSet.temporalData;\r\n if (!(timeStepDataSet && timeStepDataSet.data.length)) { // we may not have time step data for this model.\r\n return [];\r\n }\r\n\r\n const modelId = dataSet.modelId;\r\n const modelType = timeStepDataSet.type;\r\n\r\n return timeStepDataSet.data.map(timeStepData => {\r\n const timeStepEndDate = new Date(timeStepData.utcEndTime);\r\n const timeStepMillis = timeStepEndDate.getTime();\r\n const dataPointId = `${modelId}-${timeStepMillis}`;\r\n\r\n const dataPoint = dataPointFactory.create(modelType, timeStepData);\r\n dataPoint.id = dataPointId;\r\n dataPoint.modelId = modelId;\r\n\r\n mapLayerRenderer.renderLayer(dataPoint);\r\n delete dataPoint.data;\r\n\r\n addToDateIndex(timeStepEndDate, dataPoint);\r\n addToImportedTimeSteps(modelId, timeStepMillis);\r\n addToModelDataPointIndex(dataPointId);\r\n\r\n return timeStepMillis;\r\n });\r\n }\r\n\r\n function addToDateIndex(date, dataPoint) {\r\n const key = date.getTime();\r\n const bucket = self._dateIndex[key] || (self._dateIndex[key] = []);\r\n\r\n // overwrite old data\r\n let itemAdded = false;\r\n\r\n for (let i = 0; !itemAdded && i < bucket.length; i++) {\r\n const existingDataPoint = bucket[i];\r\n\r\n if (existingDataPoint.modelId === dataPoint.modelId &&\r\n existingDataPoint.id === dataPoint.id &&\r\n existingDataPoint.type === dataPoint.type) {\r\n bucket[i] = dataPoint;\r\n itemAdded = true;\r\n }\r\n }\r\n\r\n if (!itemAdded) {\r\n bucket.push(dataPoint);\r\n }\r\n }\r\n\r\n function addToImportedTimeSteps(modelId, timeStepMillis) {\r\n const bucket = self._importedTimeSteps[modelId] || (self._importedTimeSteps[modelId] = {});\r\n bucket[timeStepMillis] = true;\r\n }\r\n\r\n function addToModelDataPointIndex(timeStepDataId) {\r\n self._availableTimeStepDataIds[timeStepDataId] = true;\r\n }\r\n };\r\n\r\n ModellingDataStore.prototype.enableModel = function(modelId) {\r\n delete this._disabledModels[modelId];\r\n rebuildRenderingLayers(modelId);\r\n\r\n function rebuildRenderingLayers(modelId) {\r\n _.forEach(self._dateIndex, dataPoint => {\r\n //TODO: 28/04/2016 - bpriebe - investigate how this got in\r\n if (item.modelId !== modelId) { // eslint-disable-line no-undef\r\n return;\r\n }\r\n mapLayerRenderer.addLayer(dataPoint);\r\n });\r\n }\r\n };\r\n\r\n ModellingDataStore.prototype.disableModel = function(modelId) {\r\n this._disabledModels[modelId] = modelId;\r\n releaseRenderingLayers(modelId);\r\n\r\n function releaseRenderingLayers(modelId) {\r\n _.forEach(self._dateIndex, dataPoint => {\r\n //TODO: 28/04/2016 - bpriebe - investigate how this got in\r\n if (item.modelId !== modelId) { // eslint-disable-line no-undef\r\n return;\r\n }\r\n mapLayerRenderer.removeLayer(dataPoint);\r\n });\r\n }\r\n };\r\n\r\n ModellingDataStore.prototype.getTimeStepDataForEnabledModels = function(date) {\r\n const self = this;\r\n\r\n const key = date.getTime();\r\n if (!self._dateIndex[key]) {\r\n return null;\r\n }\r\n\r\n return self._dateIndex[key].filter(item => !self._disabledModels[item.modelId]);\r\n\r\n };\r\n\r\n ModellingDataStore.prototype.getImportedTimeStepsForModel = function(modelId) {\r\n const self = this;\r\n\r\n if (!self._importedTimeSteps[modelId]) {\r\n return [];\r\n }\r\n\r\n const timeSteps = Object.keys(self._importedTimeSteps[modelId]).map(key => parseInt(key));\r\n timeSteps.sort((left, right) => left - right);\r\n\r\n return timeSteps;\r\n };\r\n\r\n ModellingDataStore.prototype.modelHasDataAt = function(modelId, timeMillis) {\r\n const self = this;\r\n\r\n return _.has(self._dateIndex, timeMillis);\r\n };\r\n\r\n return ModellingDataStore;\r\n }\r\n})();\r\n\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .factory(`app.ui.features.modelling.mediator`, modellingMediatorFactory);\r\n\r\n modellingMediatorFactory.$inject = [\r\n `$q`,\r\n `lodash`,\r\n `postal`,\r\n `moment`,\r\n `app.core.services.gisModelService`,\r\n `app.core.signalR.jobs.state`,\r\n `app.core.signalR.jobs.events`,\r\n `app.core.models.jobs.jobCompletionStatus`,\r\n `app.core.models.modelLoadingStatus`\r\n ];\r\n\r\n function modellingMediatorFactory($q, _, postal, moment, gisModelService, jobState, jobEvents, jobCompletionStatus, modelLoadingStatus) {\r\n const millisPerMinute = 60 * 1000;\r\n\r\n return function ModellingMediator(modellingState, onMediatorRefreshed) {\r\n let subscriptions;\r\n\r\n let currentState = {\r\n selectedModelIds: [],\r\n fromMillis: 0,\r\n toMillis: 0\r\n };\r\n\r\n this.refresh = _.debounce(refresh, 0);\r\n this.dispose = dispose;\r\n\r\n activate();\r\n\r\n ////////////////////\r\n\r\n function activate() {\r\n if (!modellingState) {\r\n throw new Error(`You must provide the modelling state.`);\r\n }\r\n\r\n const channel = postal.channel(jobEvents.channelName);\r\n\r\n subscriptions = [\r\n channel.subscribe(jobEvents.topics.jobStale, onJobStale),\r\n channel.subscribe(jobEvents.topics.jobCompleted, onJobCompleted),\r\n channel.subscribe(jobEvents.topics.jobDismissed, onJobDismissed)\r\n ];\r\n }\r\n\r\n function refresh() {\r\n let modelIdsToLoad;\r\n\r\n const selectedModelIds = _.map(modellingState.selectedModels, `modelId`);\r\n const fromMillis = modellingState.dataSetStartDate && modellingState.dataSetStartDate.getTime();\r\n const toMillis = modellingState.dataSetEndDate && modellingState.dataSetEndDate.getTime();\r\n const autoUpdateEnabled = modellingState.autoUpdateEnabled;\r\n\r\n // No point trying to refresh until we have at least one model selected and a valid date/time range.\r\n const canRefresh = selectedModelIds.length && fromMillis && toMillis;\r\n\r\n let isRefreshRequired = false;\r\n if (canRefresh) {\r\n isRefreshRequired = currentState.fromMillis !== fromMillis || currentState.toMillis !== toMillis || currentState.autoUpdateEnabled !== autoUpdateEnabled;\r\n if (isRefreshRequired) {\r\n modelIdsToLoad = selectedModelIds;\r\n\r\n } else {\r\n modelIdsToLoad = _.difference(selectedModelIds, currentState.selectedModelIds);\r\n isRefreshRequired = !!modelIdsToLoad.length;\r\n }\r\n }\r\n\r\n // Store the current state at the point the mediator is refreshing so we can determine if anything\r\n // has changed the next time something calls `refresh`.\r\n currentState = {\r\n selectedModelIds,\r\n fromMillis,\r\n toMillis,\r\n autoUpdateEnabled\r\n };\r\n\r\n if (isRefreshRequired) {\r\n loadDataForModels(modelIdsToLoad);\r\n } else {\r\n resyncModelDataAvailability();\r\n }\r\n }\r\n\r\n function loadDataForModels(modelIds) {\r\n const loaders = [];\r\n\r\n const dateRange = modellingState.getDataSetDateRange();\r\n const intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\r\n\r\n _.forEach(modelIds, modelId => {\r\n const indexedTimeSteps = modellingState.modellingDataStore.getImportedTimeStepsForModel(modelId);\r\n let latestUnindexedTimeStepMillis = null;\r\n\r\n // Work through the entire data set time range to work out the parts that need to be loaded. For example, if the time range\r\n // is from 12 PM - 9 PM, and we already have data from 3 PM - 6 PM, this will end up asking for two sets of data to be loaded\r\n // (from 6 PM - 9 PM, and 12 PM - 3 PM).\r\n for (let timeStepMillis = dateRange.toMillis; timeStepMillis > dateRange.fromMillis; timeStepMillis -= intervalMillis) {\r\n if (isTimeStepIndexed(timeStepMillis) && latestUnindexedTimeStepMillis) {\r\n loadTimeRangeIfRequired(timeStepMillis, latestUnindexedTimeStepMillis);\r\n latestUnindexedTimeStepMillis = null;\r\n\r\n } else if (!latestUnindexedTimeStepMillis) {\r\n latestUnindexedTimeStepMillis = timeStepMillis;\r\n }\r\n }\r\n\r\n if (latestUnindexedTimeStepMillis) {\r\n loadTimeRangeIfRequired(dateRange.fromMillis, latestUnindexedTimeStepMillis);\r\n }\r\n\r\n function isTimeStepIndexed(timeStepMillis) {\r\n return indexedTimeSteps.indexOf(timeStepMillis) >= 0;\r\n }\r\n\r\n function loadTimeRangeIfRequired(fromMillis, toMillis) {\r\n if (!doesActiveJobExist(modelId, fromMillis, toMillis, true)) {\r\n // We need to ask for the data again UNLESS we already have a job running for this exact time range\r\n if (modellingState.realTimeMode) {\r\n // In this scenario we want to show the plume/wind model for the latest data we have, not the exact time.\r\n loaders.push(loadTimeAdjustedDataForModel(modelId, fromMillis, toMillis));\r\n } else {\r\n loaders.push(loadDataForModel(modelId, fromMillis, toMillis));\r\n }\r\n\r\n // Update data availability for this model to reflect the fact there are unloaded data segments\r\n updateModelDataAvailability(modelId);\r\n\r\n } else {\r\n // We are already loading data, so make sure the loading state reflects this (caters for the\r\n // user asking for the same set of data after refreshing the screen and there is an active\r\n // job already running).\r\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.loading, fromMillis, toMillis);\r\n }\r\n }\r\n });\r\n\r\n if (!loaders.length) {\r\n return;\r\n }\r\n\r\n $q.all(loaders).then(() => onMediatorRefreshed());\r\n }\r\n\r\n function loadTimeAdjustedDataForModel(modelId, fromMillis, toMillis) {\r\n const intervalMillis = modellingState.selectedInterval.minutes * millisPerMinute;\r\n const oneHourBeforeToTimeMillis = toMillis - millisPerMinute * 60;\r\n\r\n return gisModelService.getModelDataAvailability(modelId)\r\n .then(availability => {\r\n const latestModelAvailabilityMillis = availability.latestTime.getTime();\r\n const adjustedToMillis = latestModelAvailabilityMillis < oneHourBeforeToTimeMillis\r\n ? toMillis\r\n : Math.min(toMillis, availability.latestTime.getTime());\r\n const adjustedFromMillis = adjustedToMillis - intervalMillis;\r\n const adjustedOffsetMilliseconds = Math.abs(toMillis - adjustedToMillis);\r\n console.log(\r\n `modelId`, modelId,\r\n `latest available data`, moment(latestModelAvailabilityMillis).format(`YYYY-MM-DDTHH:mm:ssZ`),\r\n `-- requested ---->`,\r\n `from`, moment(fromMillis).format(`YYYY-MM-DDTHH:mm:ssZ`),\r\n `to`, moment(toMillis).format(`YYYY-MM-DDTHH:mm:ssZ`),\r\n `-- offsetting ${adjustedOffsetMilliseconds / millisPerMinute / 60} hours ---->`,\r\n `from`, moment(adjustedFromMillis).format(`YYYY-MM-DDTHH:mm:ssZ`),\r\n `to`, moment(adjustedToMillis).format(`YYYY-MM-DDTHH:mm:ssZ`)\r\n );\r\n\r\n return loadDataForModel(modelId, adjustedFromMillis, adjustedToMillis, adjustedOffsetMilliseconds);\r\n });\r\n }\r\n\r\n function doesActiveJobExist(modelId, fromMillis, toMillis, clearStaleJobs = false) {\r\n const existingJobs = _.filter(jobState.jobs, job =>\r\n job.requesterId === modelId &&\r\n job.fromMillis === fromMillis &&\r\n job.toMillis === toMillis &&\r\n !job.hasCompleted);\r\n\r\n if (!existingJobs.length) {\r\n return false;\r\n }\r\n\r\n let hasActiveJob = false;\r\n\r\n _.forEach(existingJobs, job => {\r\n if (!job.isStale) {\r\n hasActiveJob = true;\r\n\r\n } else if (clearStaleJobs) {\r\n gisModelService.dismissJob(job.jobId);\r\n }\r\n });\r\n\r\n return hasActiveJob;\r\n }\r\n\r\n function loadDataForModel(modelId, fromMillis, toMillis, offsetMillis = 0) {\r\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.loading, fromMillis, toMillis);\r\n\r\n const fromDate = new Date(fromMillis);\r\n const toDate = new Date(toMillis);\r\n\r\n const promises$ = [];\r\n\r\n const discreteReceptor$ = gisModelService\r\n .getDiscreteReceptorData(modelId, fromDate, toDate)\r\n .then(processDiscreteReceptorData)\r\n .catch(angular.noop);\r\n\r\n promises$.push(discreteReceptor$);\r\n\r\n const model$ = gisModelService.getModelDataSet([modelId], fromDate, toDate)\r\n .then(processModelDataSet)\r\n .catch(processModelDataSetErrors);\r\n\r\n promises$.push(model$);\r\n return $q.all(promises$);\r\n\r\n ////////////////////\r\n\r\n function processDiscreteReceptorData(response) {\r\n modellingState.modellingDataStore.importDiscreteReceptorData(modelId, offsetResponseData(response));\r\n\r\n /////\r\n\r\n function offsetResponseData(response) {\r\n const adjustedResponse = {};\r\n for (const key of Object.keys(response)) {\r\n const value = response[key];\r\n const offsetAdjustedKey = new Date(new Date(key).getTime() + offsetMillis).toISOString();\r\n adjustedResponse[offsetAdjustedKey] = value;\r\n }\r\n return adjustedResponse;\r\n }\r\n\r\n }\r\n\r\n function processModelDataSet(response) {\r\n const adjustedGisModels = offsetResponseData(response.availableGisModels);\r\n const importedTimeSteps = modellingState.modellingDataStore.importModelDataSets(adjustedGisModels);\r\n setStatusForImportedTimeStepsToLoaded(importedTimeSteps);\r\n updateModelDataAvailability(modelId);\r\n\r\n const activeJobs = response.activeJobsForGisModels;\r\n if (activeJobs && _.has(activeJobs, modelId)) {\r\n addActiveJobsToJobState(activeJobs, modelId);\r\n }\r\n\r\n ////\r\n\r\n function offsetResponseData(gisModels = []) {\r\n _.forEach(gisModels, gisModel => {\r\n _.forEach(gisModel.temporalData.data, dataPoint => {\r\n dataPoint.utcEndTime = new Date(new Date(dataPoint.utcEndTime).getTime() + offsetMillis).toISOString();\r\n });\r\n });\r\n return gisModels;\r\n }\r\n }\r\n\r\n function setStatusForImportedTimeStepsToLoaded(importedTimeSteps) {\r\n if (!(importedTimeSteps && importedTimeSteps.length)) {\r\n return;\r\n }\r\n\r\n // Note - this is an ideal candidate for currying, but currying is not good for unit testing (it\r\n // breaks if you try to spy on the function being curried).\r\n const setStatusToLoaded = timeStep => modellingState.setModelLoadingStatusForSingleTimeStep(modelId, modelLoadingStatus.loaded, timeStep);\r\n\r\n _.forEach(importedTimeSteps, setStatusToLoaded);\r\n }\r\n\r\n function processModelDataSetErrors() {\r\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.failed, fromMillis, toMillis);\r\n }\r\n }\r\n\r\n function addActiveJobsToJobState(activeJobs, modelId) {\r\n _.forEach(activeJobs, job => {\r\n // Sanity check that this job belongs to the nominated model\r\n if (job.requesterId !== modelId) {\r\n return;\r\n }\r\n\r\n // We also need to check if we are already tracking this job - depends on if the SignalR JobCreated\r\n // event was received before the call returned.\r\n const existingJob = _.find(jobState.jobs, { jobId: job.jobId });\r\n if (!existingJob) {\r\n jobState.jobs.push(job);\r\n }\r\n });\r\n }\r\n\r\n function getModelById(modelId) {\r\n // Most likely to be in the selected interval\r\n const model = _.find(modellingState.selectedInterval.models, { modelId });\r\n\r\n // _.find returns undefined if not found.\r\n return model || null;\r\n }\r\n\r\n function onJobCompleted(job) {\r\n if (!(job && job.requesterId)) {\r\n return;\r\n }\r\n\r\n const modelId = job.requesterId;\r\n const model = getModelById(modelId);\r\n if (model === null) {\r\n return;\r\n }\r\n\r\n processJobCompleted(job, modelId, model);\r\n }\r\n\r\n function processJobCompleted(job, modelId, model) {\r\n const status = job.hasFailed ? modelLoadingStatus.failed : modelLoadingStatus.pending;\r\n modellingState.setModelLoadingStatus(modelId, status, job.fromMillis, job.toMillis);\r\n\r\n if (job.hasFailed) {\r\n return;\r\n }\r\n\r\n const dataSetDateRange = modellingState.getDataSetDateRange();\r\n const isJobForCurrentDateRange = dataSetDateRange.fromMillis <= job.fromMillis && dataSetDateRange.toMillis >= job.toMillis;\r\n if (!isJobForCurrentDateRange) {\r\n return;\r\n }\r\n\r\n const isModelStillSelected = model && _.find(modellingState.selectedModels, { modelId: modelId });\r\n if (!isModelStillSelected) {\r\n return;\r\n }\r\n\r\n loadDataForModels([modelId]);\r\n }\r\n\r\n function onJobDismissed(job) {\r\n if (!job.isStale) {\r\n return;\r\n }\r\n\r\n const modelId = job.requesterId;\r\n if (!modelId) {\r\n return;\r\n }\r\n\r\n const currentLoadingStatus = modellingState.getModelLoadingStatus(modelId, job.fromMillis, job.toMillis);\r\n if (currentLoadingStatus !== modelLoadingStatus.loading) {\r\n return;\r\n }\r\n\r\n const hasActiveJob = doesActiveJobExist(modelId, job.fromMillis, job.toMillis);\r\n if (!hasActiveJob) {\r\n modellingState.setModelLoadingStatus(modelId, modelLoadingStatus.failed, job.fromMillis, job.toMillis);\r\n }\r\n }\r\n\r\n function resyncModelDataAvailability() {\r\n _.forEach(modellingState.selectedInterval.models, model => {\r\n updateModelDataAvailability(model.modelId);\r\n });\r\n }\r\n\r\n function updateModelDataAvailability(modelId) {\r\n const isSelected = _.find(modellingState.selectedModels, { modelId });\r\n if (!isSelected) {\r\n delete modellingState.modelDataAvailability[modelId];\r\n return;\r\n }\r\n\r\n const dateRange = modellingState.getDataSetDateRange();\r\n if (!dateRange) {\r\n return;\r\n }\r\n\r\n const availability = {};\r\n const tickStep = modellingState.selectedInterval.minutes * millisPerMinute;\r\n\r\n for (let tick = dateRange.fromMillis; tick <= dateRange.toMillis; tick += tickStep) {\r\n availability[tick] = modellingState.modellingDataStore.modelHasDataAt(modelId, tick);\r\n }\r\n\r\n modellingState.modelDataAvailability[modelId] = availability;\r\n }\r\n\r\n function onJobStale(job) {\r\n if (!(job && job.requesterId)) {\r\n return;\r\n }\r\n\r\n const modelId = job.requesterId;\r\n const model = getModelById(modelId);\r\n if (model === null) {\r\n return;\r\n }\r\n\r\n // Cater for SignalR crapping itself by manually checking the job status\r\n gisModelService.getStatus(job.jobId).then(status => {\r\n job.progress = status.progress;\r\n\r\n if (!status.hasCompleted) {\r\n job.completionStatus = jobCompletionStatus.incomplete;\r\n\r\n } else {\r\n job.completionStatus = jobCompletionStatus.calculate(status.jobSucceededCount, status.jobFailedCount);\r\n processJobCompleted(job, modelId, model);\r\n }\r\n });\r\n }\r\n\r\n function dispose() {\r\n _.invokeMap(subscriptions, `unsubscribe`);\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.modelling.state`\r\n ];\r\n function appRun(routeHelper, modellingState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app.modelling`,\r\n abstract : true\r\n },\r\n {\r\n state: `app.modelling.gisModelling`,\r\n url: `/modelling/{companyAlias}/{facilityAlias}?modelhash`,\r\n views: {\r\n 'actionsPanel@app': {\r\n templateUrl: `/App/ui/features/modelling/ActionsPanel.html`,\r\n controller: `app.ui.features.modelling.ActionsPanel as vm`\r\n },\r\n 'leftPanel@app': {\r\n templateUrl: `/App/ui/features/modelling/LeftPanel.html`,\r\n controller: `app.ui.features.modelling.LeftPanel as vm`\r\n },\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/modelling/ContentPanel.html`,\r\n controller: `app.ui.features.modelling.ContentPanel as vm`\r\n }\r\n },\r\n reloadOnSearch: false, // allows us to set the ?modelhash parameter without reloading the resolvers.\r\n data: {\r\n requiredAccessControl: `app.modelling`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/core/controls/i18n/esTimeSlider`,\r\n `/App/ui/features/modelling/i18n/modelling`,\r\n `/App/ui/features/modelling/controls/i18n/esModellingDurationSelect`,\r\n `/App/ui/features/modelling/controls/i18n/esModellingModelSelect`,\r\n `/App/ui/features/modelling/controls/i18n/esModellingTimeSlider`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCentre`,\r\n `/App/ui/core/mapping/controls/i18n/esMapKml`,\r\n `/App/ui/core/mapping/controls/i18n/esMapDomainBoundaries`,\r\n `/App/ui/core/mapping/controls/i18n/esMapEmissionSources`,\r\n `/App/ui/core/mapping/controls/i18n/esMapCredits`,\r\n `/App/ui/core/mapping/controls/i18n/esMapTiles`,\r\n `/App/ui/core/mapping/controls/i18n/esMapType`\r\n ]\r\n },\r\n resolve: {\r\n modellingState: modellingState\r\n }\r\n }\r\n ];\r\n }\r\n\r\n }\r\n\r\n\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .factory(`app.ui.features.modelling.state`, modellingStateFactory);\r\n\r\n modellingStateFactory.$inject = [\r\n `$q`,\r\n `lodash`,\r\n `app.core.mapDefaults`,\r\n `app.core.services.companyService`,\r\n `app.core.services.gisModelService`,\r\n `app.core.services.reportsService`,\r\n `app.core.models.modelLoadingStatus`,\r\n `app.ui.features.modelling.ModellingDataStore`\r\n ];\r\n\r\n function modellingStateFactory(\r\n $q,\r\n _,\r\n mapDefaults,\r\n companyService,\r\n gisModelService,\r\n reportsService,\r\n modelLoadingStatus,\r\n ModellingDataStore\r\n ) {\r\n function modellingStateFactoryResolver() {\r\n const facilityLocation = companyService.getFacilityLocation();\r\n const intervals = gisModelService.getIntervals();\r\n const alertPointReports = reportsService.getAlertPointReports();\r\n const domainBoundaries = companyService.getDomainBoundaries(true);\r\n\r\n return $q.all([facilityLocation, intervals, alertPointReports, domainBoundaries]).then(result => {\r\n const [mapLocation, intervals, alertPointReports, domainBoundaries] = result;\r\n\r\n const mappedIntervals = intervals\r\n .map(interval => {\r\n return {\r\n minutes: interval.durationInMinutes,\r\n durationRanges: interval.intervalOptionMinutes,\r\n models: interval.models\r\n };\r\n });\r\n\r\n return new ModellingState(mappedIntervals, mapLocation, alertPointReports, domainBoundaries);\r\n });\r\n }\r\n\r\n function ModellingState(mappedIntervals, mapLocation, alertPointReports, domainBoundaries) {\r\n const self = this;\r\n const millisPerMinute = 60 * 1000;\r\n\r\n this.intervals = mappedIntervals;\r\n this.autoUpdateEnabled = false;\r\n this.dataSetStartDate = null;\r\n this.dataSetEndDate = null;\r\n this.alertPointReports = alertPointReports;\r\n\r\n let selectedInterval;\r\n if (mappedIntervals.length > 0) {\r\n selectedInterval = mappedIntervals[0];\r\n } else {\r\n selectedInterval = {\r\n durationRanges: [],\r\n minutes: 60,\r\n models: []\r\n };\r\n }\r\n\r\n const selectedModels = [];\r\n let modellingDataStore = new ModellingDataStore();\r\n const modelDataAvailability = {};\r\n\r\n this.realTimeMode = false;\r\n\r\n // Contains the loading status for each model at the end-time of each interval\r\n // e.g:\r\n // {\r\n // \"model-1\": {\r\n // \"146000\": loading,\r\n // \"147000\": loaded\r\n // }\r\n // }\r\n const modelLoadingStatuses = {};\r\n\r\n this.map = {\r\n defaultCentre: mapLocation,\r\n centre: mapLocation,\r\n defaults: {\r\n settings: mapDefaults.settings\r\n },\r\n isColor: false,\r\n bounds: getMapBounds(),\r\n layers: {\r\n baselayers: mapDefaults.baselayers,\r\n overlays: {\r\n discreteReceptor: {\r\n type: `group`,\r\n visible: true,\r\n name: `DiscreteReceptor`\r\n }\r\n }\r\n }\r\n };\r\n\r\n Object.defineProperty(this, `selectedInterval`, {\r\n get: () => selectedInterval,\r\n set: value => {\r\n selectedInterval = value;\r\n clearData(self.modelDataAvailability);\r\n }\r\n });\r\n\r\n Object.defineProperty(this, `selectedModels`, { get: () => selectedModels });\r\n Object.defineProperty(this, `modellingDataStore`, { get: () => modellingDataStore });\r\n Object.defineProperty(this, `modelLoadingStatuses`, { get: () => modelLoadingStatuses });\r\n Object.defineProperty(this, `modelDataAvailability`, { get: () => modelDataAvailability });\r\n\r\n this.modelDurationWarning = null;\r\n this.getDataSetDateRange = getDataSetDateRange;\r\n this.getModelLoadingStatus = getModelLoadingStatus;\r\n this.setModelLoadingStatus = setModelLoadingStatus;\r\n this.setModelLoadingStatusForSingleTimeStep = setModelLoadingStatusForSingleTimeStep;\r\n this.setModelSelected = setModelSelected;\r\n\r\n this.clear = () => {\r\n clearData(self.modelDataAvailability);\r\n modellingDataStore = new ModellingDataStore();\r\n\r\n };\r\n\r\n ////////////////////\r\n\r\n function clearData(dataObject) {\r\n _.forEach(dataObject, (value, key) => delete dataObject[key]);\r\n }\r\n\r\n function getModelLoadingStatus(modelId, fromMillis = null, toMillis = null) {\r\n if (!_.has(modelLoadingStatuses, modelId)) {\r\n return modelLoadingStatus.pending;\r\n }\r\n\r\n if (!(fromMillis && toMillis)) {\r\n const dataSetDateRangeMillis = getDataSetDateRange();\r\n fromMillis = dataSetDateRangeMillis.fromMillis;\r\n toMillis = dataSetDateRangeMillis.toMillis;\r\n }\r\n\r\n let result = modelLoadingStatus.pending;\r\n\r\n const intervalStatuses = modelLoadingStatuses[modelId];\r\n const intervalStepMillis = selectedInterval.minutes * millisPerMinute;\r\n\r\n for (let stepMillis = toMillis; stepMillis > fromMillis; stepMillis -= intervalStepMillis) {\r\n const intervalStatus = _.has(intervalStatuses, stepMillis) ? intervalStatuses[stepMillis] : modelLoadingStatus.pending;\r\n if (intervalStatus === modelLoadingStatus.pending) {\r\n continue;\r\n }\r\n\r\n // The model is loading if even one interval is loading.\r\n if (intervalStatus === modelLoadingStatus.loading) {\r\n return intervalStatus;\r\n }\r\n\r\n // Always chose failed over loaded\r\n if (result !== modelLoadingStatus.failed) {\r\n result = intervalStatus;\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n function setModelLoadingStatus(modelId, state, fromMillis = null, toMillis = null) {\r\n if (!(fromMillis && toMillis)) {\r\n const dataSetDateRangeMillis = getDataSetDateRange();\r\n fromMillis = dataSetDateRangeMillis.fromMillis;\r\n toMillis = dataSetDateRangeMillis.toMillis;\r\n }\r\n\r\n const modelLoadingStatusByTimeStep = getModelLoadingStatusByTimeStep(modelId);\r\n const intervalStepMillis = selectedInterval.minutes * millisPerMinute;\r\n\r\n for (let stepMillis = toMillis; stepMillis > fromMillis; stepMillis -= intervalStepMillis) {\r\n updateLoadingStatus(modelLoadingStatusByTimeStep, stepMillis, state);\r\n }\r\n }\r\n\r\n function setModelLoadingStatusForSingleTimeStep(modelId, state, timeStepEndMillis) {\r\n const modelLoadingStatusByTimeStep = getModelLoadingStatusByTimeStep(modelId);\r\n updateLoadingStatus(modelLoadingStatusByTimeStep, timeStepEndMillis, state);\r\n }\r\n\r\n function getModelLoadingStatusByTimeStep(modelId) {\r\n return _.has(modelLoadingStatuses, modelId) && modelLoadingStatuses[modelId] || (modelLoadingStatuses[modelId] = {});\r\n }\r\n\r\n function updateLoadingStatus(loadingStatusByTimeStep, timeStepMillis, state) {\r\n // Never overwrite `loaded`.\r\n if (loadingStatusByTimeStep[timeStepMillis] === modelLoadingStatus.loaded) {\r\n return;\r\n }\r\n\r\n loadingStatusByTimeStep[timeStepMillis] = state;\r\n }\r\n\r\n function getDataSetDateRange() {\r\n const toMillis = self.dataSetEndDate && self.dataSetEndDate.getTime();\r\n let fromMillis = self.dataSetStartDate && self.dataSetStartDate.getTime();\r\n if (!(toMillis && fromMillis)) {\r\n return null;\r\n }\r\n\r\n if (fromMillis === toMillis && selectedInterval && selectedInterval.minutes) {\r\n fromMillis -= selectedInterval.minutes * millisPerMinute;\r\n }\r\n\r\n return { fromMillis, toMillis };\r\n }\r\n\r\n function setModelSelected(model, isSelected) {\r\n const modelId = model.modelId;\r\n\r\n if (isSelected) {\r\n // If the model previously loaded with an error, then reset it to allow the user to attempt loading it again.\r\n const dateRange = getDataSetDateRange();\r\n if (dateRange && getModelLoadingStatus(modelId, dateRange.fromMillis, dateRange.toMillis) === modelLoadingStatus.failed) {\r\n setModelLoadingStatus(modelId, modelLoadingStatus.pending, dateRange.fromMillis, dateRange.toMillis);\r\n }\r\n\r\n selectedModels.push(model);\r\n\r\n } else {\r\n _.remove(selectedModels, { modelId });\r\n delete modelDataAvailability[modelId];\r\n }\r\n }\r\n\r\n function getMapBounds() {\r\n return domainBoundaries &&\r\n _.reduce(domainBoundaries, (memo, boundary) => {\r\n const coordinates = [boundary.bottomLeft, boundary.bottomRight, boundary.topLeft, boundary.topRight];\r\n return memo.concat(_.map(coordinates, coordinate => [coordinate.latitude, coordinate.longitude]));\r\n }, []);\r\n }\r\n }\r\n\r\n return modellingStateFactoryResolver;\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.modelling`)\r\n .factory(`app.ui.features.modelling.timeStepCalculator`, timeStepCalculator);\r\n\r\n timeStepCalculator.$inject = [`lodash`];\r\n\r\n function timeStepCalculator(_) {\r\n const millisPerMinute = 60 * 1000;\r\n\r\n return {\r\n calculateTimeStepRange,\r\n getLastIntervalMillis\r\n };\r\n\r\n ////////////////////\r\n\r\n function calculateTimeStepRange(baseDate, fromMinutes, toMinutes, intervalMinutes) {\r\n if (!isIntervalValid(intervalMinutes)) {\r\n throw new Error(`The interval must be a divisor or multiple of one hour.`);\r\n }\r\n\r\n const baseDateMillis = getLastIntervalMillis(baseDate, intervalMinutes);\r\n const fromTicks = baseDateMillis - parseInt(fromMinutes) * millisPerMinute;\r\n const toTicks = baseDateMillis + parseInt(toMinutes) * millisPerMinute;\r\n\r\n const intervalMillis = parseInt(intervalMinutes) * millisPerMinute;\r\n const timeStepCount = Math.round((toTicks - fromTicks) / intervalMillis);\r\n return {\r\n timeStepCount,\r\n fromDate: new Date(fromTicks),\r\n toDate: new Date(toTicks)\r\n };\r\n }\r\n\r\n function isIntervalValid(intervalMinutes) {\r\n if (intervalMinutes === 0) {\r\n return false;\r\n }\r\n\r\n const remainder = intervalMinutes < 60 ? 60 % intervalMinutes : intervalMinutes % 60;\r\n\r\n return remainder === 0;\r\n }\r\n\r\n function getLastIntervalMillis(date, intervalMinutes) {\r\n const intervalMillis = parseInt(intervalMinutes) * millisPerMinute;\r\n\r\n let baseDateMillis;\r\n if (date instanceof Date) {\r\n baseDateMillis = date.getTime();\r\n } else if (_.isNumber(date)) {\r\n baseDateMillis = date;\r\n } else {\r\n baseDateMillis = new Date(date).getTime();\r\n }\r\n\r\n //javascript.about.com/od/problemsolving/a/modulobug.htm\r\n const delta = (baseDateMillis % intervalMillis + intervalMillis) % intervalMillis;\r\n\r\n return baseDateMillis - delta;\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .controller(`app.ui.features.monitoring.ActionsPanel`, ActionsPanel);\r\n\r\n ActionsPanel.$inject = [`monitoringState`];\r\n\r\n function ActionsPanel(monitoringState) {\r\n const vm = this;\r\n vm.map = monitoringState.map;\r\n\r\n vm.actions = {\r\n fullScreen: {\r\n isEnabled: false\r\n }\r\n };\r\n\r\n activate();\r\n\r\n /////////////////////\r\n \r\n function activate() {\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .controller(`app.ui.features.monitoring.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$scope`,\r\n `$interval`,\r\n `$q`,\r\n `lodash`,\r\n `promiseTracker`,\r\n `app.core.appSettings`,\r\n `app.core.services.monitoringService`,\r\n `monitoringState`,\r\n `app.core.states.monitoringTimeState`,\r\n `app.core.services.mappingService`\r\n ];\r\n\r\n function ContentPanel($scope, $interval, $q, _, promiseTracker, appSettings, monitoringService, monitoringState, monitoringTimeState, mappingService) {\r\n const realTimeTickTimeout = 60000;\r\n const vm = this;\r\n let pollingMonitorsPromise = null;\r\n\r\n vm.isRealTime = false;\r\n vm.isLoading = promiseTracker();\r\n vm.map = monitoringState.map;\r\n vm.overlayProvider = {};\r\n vm.showControls = false;\r\n vm.temporalEventGroups = [];\r\n\r\n vm.state = monitoringState;\r\n\r\n activate();\r\n\r\n /////////////////////\r\n\r\n function activate() {\r\n\r\n loadOverlays();\r\n\r\n const hasAccessToSourceIdentification = appSettings.site.accessControls[`app.monitoring.source-identification`];\r\n\r\n $scope.$watch(() => monitoringTimeState.dateTime, dateTime => {\r\n if (!dateTime) {\r\n return;\r\n }\r\n\r\n refreshDataForAllMonitors();\r\n if (hasAccessToSourceIdentification) {\r\n refreshDataForAllSourceAreas();\r\n }\r\n });\r\n\r\n _.forEach(monitoringState.monitorsByType, monitorGrouping => {\r\n $scope.$watch(() => monitorGrouping.selectedMeasurementGroupId, (newValue, oldValue) => {\r\n if (newValue && newValue !== oldValue) {\r\n refreshDataForMonitorType(monitorGrouping.monitorIds, newValue);\r\n }\r\n });\r\n });\r\n\r\n if (hasAccessToSourceIdentification) {\r\n $scope.$watch(() => vm.state.map.switches.sourceIdentification, () => {\r\n //temp workaround till the next ticket where this will move into its own widget.\r\n if (vm.state.map.layers && vm.state.map.layers.overlays.areaSources){\r\n vm.state.map.layers.overlays.areaSources.visible = vm.state.map.switches.sourceIdentification;\r\n }\r\n });\r\n\r\n $scope.$watch(() => vm.state.map.switches.sourceIdentificationDebug, () => {\r\n $scope.$watch(() => monitoringTimeState.dateTime, refreshTemporalEventGroups);\r\n });\r\n\r\n } else if (appSettings.site.accessControls[`app.monitoring.temporal-map-layers`]) {\r\n $scope.$watch(() => monitoringTimeState.dateTime, refreshTemporalEventGroups);\r\n }\r\n\r\n addIsRealTimeWatcher();\r\n\r\n function refreshTemporalEventGroups(dateTime) {\r\n if (!dateTime) {\r\n return;\r\n }\r\n\r\n mappingService.getActiveTemporalEventGroups(dateTime).then(eventGroups => {\r\n // Include/exclude the source identification groups - we will use these fixed names initially.\r\n if (!vm.state.map.switches.sourceIdentificationDebug) {\r\n eventGroups = _.pickBy(eventGroups, group => group.name !== `source-identification-debug`);\r\n }\r\n\r\n vm.temporalEventGroups = eventGroups;\r\n });\r\n }\r\n }\r\n\r\n function loadOverlays() {\r\n mappingService.getKmls().then(overlays => {\r\n vm.overlayProvider = overlays;\r\n vm.showControls = overlays && overlays.length > 0;\r\n });\r\n }\r\n\r\n function getMonitorData() {\r\n if (!(monitoringState.monitorsByType && _.keys(monitoringState.monitorsByType).length)) {\r\n return $q.when([]);\r\n }\r\n\r\n const dataCalls = _.map(monitoringState.monitorsByType, (monitorGrouping, monitorType) => {\r\n return monitoringService.getMonitorData(monitorGrouping.monitorIds, monitoringState.monitorsByType[monitorType].selectedMeasurementGroupId, monitoringTimeState.dateTime);\r\n });\r\n\r\n return $q.all(dataCalls)\r\n .then(_.flatten)\r\n .catch(angular.noop);\r\n }\r\n\r\n function getSourceAreaData() {\r\n return monitoringService.getSourceAreaData(monitoringTimeState.dateTime);\r\n }\r\n\r\n function refreshDataForAllMonitors() {\r\n const getMonitorDataPromise = getMonitorData();\r\n\r\n const updatingPromise = getMonitorDataPromise.then(renderMonitorMapMarkers);\r\n\r\n vm.isLoading.addPromise(updatingPromise);\r\n }\r\n\r\n function refreshDataForMonitorType(monitorIds, measurementGroupId) {\r\n const getMonitorDataPromise = monitoringService.getMonitorData(monitorIds, measurementGroupId, monitoringTimeState.dateTime);\r\n\r\n const updatingPromise = getMonitorDataPromise\r\n .then(renderMonitorMapMarkers)\r\n .catch(() => {});\r\n\r\n vm.isLoading.addPromise(updatingPromise);\r\n }\r\n\r\n function refreshDataForAllSourceAreas() {\r\n const updatingPromise = getSourceAreaData()\r\n .then(renderAreaSources)\r\n .catch(angular.noop);\r\n vm.isLoading.addPromise(updatingPromise);\r\n }\r\n\r\n function addIsRealTimeWatcher() {\r\n $scope.$watch(\r\n () => vm.isRealTime,\r\n isRealTime => {\r\n if (isRealTime && !isPolling()) {\r\n pollingMonitorsPromise = $interval(() => {\r\n monitoringTimeState.dateTime = new Date();\r\n monitoringTimeState.isRealTime = true;\r\n }, realTimeTickTimeout);\r\n } else {\r\n stopPollingMonitoringData();\r\n }\r\n }\r\n );\r\n\r\n vm.isRealTime = true;\r\n }\r\n\r\n function isPolling() {\r\n return pollingMonitorsPromise !== null;\r\n }\r\n\r\n function stopPollingMonitoringData() {\r\n $interval.cancel(pollingMonitorsPromise);\r\n pollingMonitorsPromise = null;\r\n }\r\n\r\n function renderMonitorMapMarkers(monitors) {\r\n mergeResultsWithState(vm.state.monitors, monitors);\r\n monitoringState.map.renderMonitorMapMarkers();\r\n }\r\n\r\n function renderAreaSources(areaSources) {\r\n mergeResultsWithState(vm.state.areaSources, areaSources);\r\n monitoringState.map.renderSourceAreaSources();\r\n }\r\n\r\n function mergeResultsWithState(target, source) {\r\n _.forEach(source, item => {\r\n const exists = _.find(target, { id: item.id });\r\n if (exists) {\r\n _.merge(exists, item);\r\n\r\n } else {\r\n target.push(item);\r\n }\r\n });\r\n }\r\n\r\n $scope.$on(`$destroy`, stopPollingMonitoringData);\r\n }\r\n})();\r\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .directive(`esMetSummary`, esMetSummary)\r\n .controller(`esMetSummaryController`, esMetSummaryController);\r\n\r\n esMetSummary.$inject = [];\r\n function esMetSummary() {\r\n return {\r\n scope: {},\r\n restrict: `E`,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: esMetSummaryController,\r\n templateUrl: `/App/ui/features/monitoring/controls/esMetSummary.html`\r\n };\r\n }\r\n\r\n esMetSummaryController.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `browserStorage`,\r\n `promiseTracker`,\r\n `app.core.services.monitoringService`,\r\n `app.core.states.monitoringTimeState`,\r\n `app.core.appSettings`\r\n ];\r\n \r\n function esMetSummaryController($scope, _, browserStorage, promiseTracker, monitoringService, monitoringTimeState, appSettings) {\r\n\r\n const vm = this;\r\n const storageKey = `preferred-met-station`;\r\n const storageBucketKey = `${appSettings.site.facility.alias}-${appSettings.userId}`;\r\n\r\n vm.busyLoading = promiseTracker();\r\n vm.metSummaries = [];\r\n vm.metSummary = getMetSummary();\r\n vm.changeSelectedMetStation = changeSelectedMetStation;\r\n\r\n activate();\r\n\r\n function activate() {\r\n $scope.$watch(() => monitoringTimeState.dateTime, getMetSummary);\r\n }\r\n\r\n function getMetSummary(dateTime) {\r\n const promise = monitoringService.getMetSummary(dateTime)\r\n .then(metSummaries => {\r\n vm.metSummaries = metSummaries;\r\n vm.metSummary = _.find(vm.metSummaries, { metStation: { isDefault: true } }) || _.first(vm.metSummaries);\r\n\r\n const storedMetStationId = getPreferredMetStationStore();\r\n if (!!storedMetStationId) {\r\n const metSummary = _.find(vm.metSummaries, { metStation: { id: storedMetStationId } });\r\n if (!!metSummary) {\r\n vm.metSummary = metSummary;\r\n }\r\n }\r\n }).catch(() => { /* ignore requestManager rejections */ });\r\n\r\n vm.busyLoading.addPromise(promise);\r\n }\r\n\r\n function changeSelectedMetStation(metStationId) {\r\n vm.metSummary = _.find(vm.metSummaries, { metStation: { id: metStationId } });\r\n browserStorage.persistBucket(storageKey, storageBucketKey, metStationId);\r\n }\r\n\r\n function getPreferredMetStationStore() {\r\n return browserStorage.getBucket(storageKey, storageBucketKey) || {};\r\n }\r\n\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .directive(`esMonitoringDateTimeSelector`, esMonitoringDateTimeSelector)\r\n .controller(`esMonitoringDateTimeSelectorController`, esMonitoringDateTimeSelectorController);\r\n\r\n esMonitoringDateTimeSelector.$inject = [\r\n `app.core.services.dateTimeService`,\r\n `moment`\r\n ];\r\n\r\n function esMonitoringDateTimeSelector(dateTimeService, moment) {\r\n\r\n //NOTE:\r\n // The number one gotcha with Kendo controls is that setting invalid values in a control does not give you an error message/indication by default.\r\n // If you set the value and it is invalid (e.g. greater than max date), you get no warning, the value just doesn't set.\r\n\r\n const directive = {\r\n restrict: `E`,\r\n scope: {\r\n isRealTime: `=`,\r\n isLoading: `=`\r\n },\r\n controller: `esMonitoringDateTimeSelectorController`,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n templateUrl: `/App/ui/features/monitoring/controls/esMonitoringDateTimeSelector.html`,\r\n link: link\r\n };\r\n\r\n /* istanbul ignore next */\r\n function link($scope) {\r\n const vm = $scope.vm;\r\n // events\r\n $scope.$on(`resizePage`, resize);\r\n $scope.$on(`kendoWidgetCreated`, activate);\r\n\r\n /////////////////////////\r\n\r\n function activate() {\r\n if (!vm.timeSlider.kendoSlider) {\r\n return;\r\n }\r\n\r\n renameSliderStepLabels();\r\n }\r\n\r\n function renameSliderStepLabels() {\r\n const stepContainer = vm.timeSlider.kendoSlider.element.siblings(`.k-slider-items`)[0];\r\n\r\n if (!stepContainer) {\r\n return;\r\n }\r\n\r\n const steps = stepContainer.children;\r\n const startOfDay = moment().startOf(`day`).valueOf();\r\n\r\n for (let i = 0; i < steps.length; i += 12) {\r\n const step = steps[i];\r\n\r\n if (step.title.length <= 2) { // dodgy workaround, to make sure we aren't updating, UPDATED, labels. this happens when the renameSliderStepLables() method is called multiple times due to a resize event.\r\n return;\r\n }\r\n\r\n const value = startOfDay + i / 12 * 60 * 60 * 1000;\r\n step.title = dateTimeService.formatAs.hour(value);\r\n angular.element(step).find(`span`).text(step.title);\r\n }\r\n }\r\n\r\n function resize() {\r\n if (!vm.timeSlider.kendoSlider) {\r\n return;\r\n }\r\n vm.timeSlider.kendoSlider.resize();\r\n renameSliderStepLabels();\r\n }\r\n }\r\n\r\n return directive;\r\n }\r\n\r\n esMonitoringDateTimeSelectorController.$inject = [\r\n `$scope`,\r\n `$interval`,\r\n `$timeout`,\r\n `$state`,\r\n `$log`,\r\n `moment`,\r\n `lodash`,\r\n `i18n`,\r\n `notifier`,\r\n `app.ui.core.keyboardShortcuts`,\r\n `app.core.datetime.timeZoneDateTime`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.services.settingsService`,\r\n `app.core.states.monitoringTimeState`\r\n ];\r\n\r\n function esMonitoringDateTimeSelectorController($scope, $interval, $timeout, $state, $log, moment, _, i18n, notifier, keyboardShortcuts, timeZoneDateTime, dateTimeService, settingsService, monitoringTimeState) {\r\n const vm = this;\r\n const millisPerMinute = 1000 * 60;\r\n const fiveMinuteInterval = 5 * millisPerMinute;\r\n const sixtyMinuteInterval = 60 * millisPerMinute;\r\n\r\n const debouncedTimeChanged = _.debounce(notifyTimeChanged, 100);\r\n\r\n const shortcutKeys = {\r\n forwardOneDay: `k`,\r\n backwardOneDay: `j`,\r\n focusDatePicker: `g d`,\r\n focusTimeSlider: `g t`\r\n };\r\n\r\n const shortcuts = {};\r\n let shortcutBindings;\r\n\r\n let updateWidgetsInterval;\r\n\r\n vm.is24Hours = dateTimeService.formats.is24Hour;\r\n vm.isRealTime = false;\r\n vm.dateTime = new Date();\r\n vm.datePicker = getDatePicker();\r\n vm.timeSlider = getTimeSlider();\r\n vm.switchBackToRealTimeMode = enableRealTimeMode;\r\n\r\n activate();\r\n\r\n function activate() {\r\n bindKeyboardShortcuts();\r\n startClock();\r\n }\r\n\r\n //////////////////////////////////\r\n\r\n function startClock() {\r\n if ($state.params.dateTime) {\r\n try {\r\n enableHistoricalMode(settingsService.getSampleDateTime());\r\n }\r\n catch (error) {\r\n enableRealTimeMode();\r\n generateErrorMessage();\r\n }\r\n } else {\r\n enableRealTimeMode();\r\n }\r\n\r\n updateWidgetsInterval = $interval(setDateTimeToNow, 1000);\r\n\r\n function generateErrorMessage() {\r\n const message = i18n.i10n(`esMonitoringDateTimeSelector.params.error.message`, {\r\n dateTime: $state.params.dateTime\r\n });\r\n\r\n const title = i18n.i10n(`esMonitoringDateTimeSelector.params.error.title`);\r\n notifier.error(message, title);\r\n $log.warn(message);\r\n }\r\n\r\n function setDateTimeToNow() {\r\n if (vm.isRealTime) {\r\n vm.dateTime = new Date(); // this triggers the watch on vm.dateTime which updates widgets\r\n } else {\r\n setDatePickerMaxDate(); // as the time ticks over midnight we need to make sure the max. date a user can choose is updated.\r\n }\r\n }\r\n }\r\n\r\n function updateDateTimeUrlParameter(dateTime) {\r\n dateTime = dateTime && dateTimeService.formatAs.iso(timeZoneDateTime.convertDateTimeToFacilityTimeZone(dateTime));\r\n const toParams = {\r\n dateTime\r\n };\r\n\r\n $state.go(`app.monitoring`, toParams, {\r\n notify: false\r\n });\r\n }\r\n\r\n function enableRealTimeMode() {\r\n vm.datePicker.hasFocus = false;\r\n vm.dateTime = new Date();\r\n vm.isRealTime = true;\r\n updateDateTimeUrlParameter();\r\n debouncedTimeChanged(true);\r\n }\r\n\r\n function enableHistoricalMode(dateTime) {\r\n vm.dateTime = dateTime;\r\n vm.isRealTime = false;\r\n debouncedTimeChanged(false);\r\n }\r\n\r\n function getDatePicker() {\r\n const date = new Date();\r\n return {\r\n hasFocus: false,\r\n date: date,\r\n options: {\r\n // note: anything provided in here is angular bound. don't put an event handler in here otherwise you have to run $scope.$apply()\r\n max: moment(calculateFacilityLocalTime(new Date())).endOf(`day`).toDate(), // evening midnight\r\n format: dateTimeService.formats.kendo.date\r\n },\r\n onChange: function() {\r\n vm.datePicker.onBlur();\r\n $timeout(updateDateTimeFromWidgetValues);\r\n },\r\n onFocus: function() {\r\n vm.datePicker.hasFocus = true;\r\n },\r\n onBlur: function() {\r\n vm.datePicker.hasFocus = false;\r\n }\r\n };\r\n }\r\n\r\n function getTimeSlider() {\r\n const min = moment().startOf(`day`); // morning midnight - ticks value\r\n const max = moment(min).add(1, `d`); // 24 hours later\r\n\r\n return {\r\n time: max.valueOf(),\r\n options: {\r\n // note: anything provided in here is angular bound. don't put an event handler in here otherwise you have to run $scope.$apply()\r\n min: min.valueOf(),\r\n max: max.valueOf(),\r\n smallStep: fiveMinuteInterval, // arrow keys\r\n largeStep: sixtyMinuteInterval, // page up/down\r\n tooltip: {\r\n template: `#= moment(value).format('${dateTimeService.formats.moment.timeWithSeconds}') #`\r\n },\r\n tickPlacement: `topLeft`\r\n },\r\n\r\n onChange: function() {\r\n $timeout(updateDateTimeFromWidgetValues);\r\n }\r\n };\r\n }\r\n\r\n function setDatePickerMaxDate() {\r\n const datePickerMax = moment(calculateFacilityLocalTime(new Date())).endOf(`day`);\r\n if (vm.datePicker.kendoDatePicker && vm.datePicker.kendoDatePicker.max() < datePickerMax.toDate()) {\r\n vm.datePicker.kendoDatePicker.max(datePickerMax.toDate());\r\n }\r\n }\r\n\r\n // update our model using the latest widget values\r\n function updateDateTimeFromWidgetValues() {\r\n const dateTime = readDateTimeFromWidgets(); // append the relative ticks to the start of the selected date\r\n\r\n if (dateTime < new Date()) {\r\n enableHistoricalMode(dateTime);\r\n } else {\r\n enableRealTimeMode();\r\n }\r\n\r\n function readDateTimeFromWidgets() {\r\n const selectedDate = moment(vm.datePicker.date);\r\n\r\n const millisAtMorningMidnightOfSelectedDate = selectedDate.valueOf(); // the vm.datePicker.date has a 00:00:00 time.\r\n const timeMillis = vm.timeSlider.time - vm.timeSlider.options.min;\r\n\r\n const result = moment(millisAtMorningMidnightOfSelectedDate + timeMillis + (-1 * timeZoneDateTime.getFacilityTimeZoneOffsetDifferenceFromLocal(selectedDate.toDate()) * 60 * 1000)).toDate(); //eslint-disable-line no-extra-parens\r\n return result;\r\n }\r\n }\r\n\r\n function notifyTimeChanged(isRealTime = false) {\r\n monitoringTimeState.dateTime = vm.dateTime;\r\n monitoringTimeState.isRealTime = isRealTime;\r\n }\r\n\r\n // update widgets using our the latest model values\r\n $scope.$watch(\r\n () => vm.dateTime,\r\n () => {\r\n if (!vm.isRealTime) {\r\n updateDateTimeUrlParameter(vm.dateTime);\r\n }\r\n\r\n const facilityDateTime = calculateFacilityLocalTime(vm.dateTime);\r\n\r\n vm.digitalClockTime = dateTimeService.formatAs.timeWithSeconds(facilityDateTime);\r\n\r\n updateWidgets(); // the vm.dateTime was probably changed by the interval ticking over so we need to update the widgets; in historical mode the widget state is correct.\r\n\r\n function updateWidgets() {\r\n const dateTime = moment(facilityDateTime);\r\n const dateTimeMorningMidnight = moment(facilityDateTime).startOf(`day`);\r\n\r\n updateDatePicker();\r\n updateTimeSlider();\r\n\r\n function updateDatePicker() {\r\n setDatePickerMaxDate();\r\n if (!vm.datePicker.hasFocus) {\r\n vm.datePicker.date = dateTimeMorningMidnight.toDate();\r\n if (vm.datePicker && vm.datePicker.kendoDatePicker) {\r\n vm.datePicker.kendoDatePicker.value(vm.datePicker.date);\r\n }\r\n }\r\n }\r\n\r\n function updateTimeSlider() {\r\n const millisSinceMorningMidnight = dateTime.valueOf() - dateTimeMorningMidnight.valueOf();\r\n vm.timeSlider.time = vm.timeSlider.options.min + millisSinceMorningMidnight;\r\n if (vm.timeSlider && vm.timeSlider.kendoSlider) {\r\n vm.timeSlider.kendoSlider.value(vm.timeSlider.time);\r\n }\r\n }\r\n }\r\n });\r\n\r\n function calculateFacilityLocalTime(date) {\r\n return timeZoneDateTime.convertDateTimeToFacilityTimeZone(date);\r\n }\r\n\r\n function bindKeyboardShortcuts() {\r\n shortcuts[shortcutKeys.focusDatePicker] = {\r\n description: i18n.i10n(`esMonitoringDateTimeSelector.shortcuts.datepicker.focus`),\r\n action: evnt => {\r\n vm.datePicker.kendoDatePicker.open();\r\n vm.datePicker.kendoDatePicker.element.focus();\r\n\r\n // We have to prevent the default behaviour for the combo, otherwise the date textbox\r\n // gets the letter 'd' appended to its date.\r\n evnt.preventDefault();\r\n }\r\n };\r\n\r\n shortcuts[shortcutKeys.focusTimeSlider] = {\r\n description: i18n.i10n(`esMonitoringDateTimeSelector.shortcuts.timeslider.focus`),\r\n action: focusTimeSlider\r\n };\r\n shortcuts[shortcutKeys.forwardOneDay] = {\r\n description: i18n.i10n(`esMonitoringDateTimeSelector.shortcuts.datepicker.forward`),\r\n action: () => moveDateTimeBy(1, `days`)\r\n };\r\n shortcuts[shortcutKeys.backwardOneDay] = {\r\n description: i18n.i10n(`esMonitoringDateTimeSelector.shortcuts.datepicker.backward`),\r\n action: () => moveDateTimeBy(-1, `days`)\r\n };\r\n\r\n shortcutBindings = keyboardShortcuts.add(i18n.i10n(`esMonitoringDateTimeSelector.shortcuts.description`), shortcuts);\r\n\r\n ////////////////////\r\n\r\n function moveDateTimeBy(delta, period) {\r\n if (!vm.dateTime) {\r\n return;\r\n }\r\n\r\n $scope.$apply(() => {\r\n const now = moment();\r\n const targetDate = moment(vm.dateTime).add(delta, period);\r\n\r\n if (targetDate.isSameOrAfter(now)) {\r\n if (vm.isRealTime) {\r\n return;\r\n }\r\n\r\n enableRealTimeMode();\r\n } else {\r\n enableHistoricalMode(targetDate.toDate());\r\n }\r\n\r\n focusTimeSlider();\r\n });\r\n }\r\n\r\n function focusTimeSlider() {\r\n if (!vm.timeSlider.kendoSlider) {\r\n return;\r\n }\r\n vm.timeSlider.kendoSlider.element.parent().find(`.k-draghandle`).focus();\r\n }\r\n }\r\n\r\n $scope.$on(`$destroy`, () => {\r\n if (updateWidgetsInterval) {\r\n $interval.cancel(updateWidgetsInterval);\r\n updateWidgetsInterval = null;\r\n }\r\n\r\n if (vm.datePicker.kendoDatePicker) {\r\n vm.datePicker.kendoDatePicker.destroy();\r\n }\r\n\r\n if (vm.timeSlider.timeSlider) {\r\n vm.timeSlider.timeSlider.destroy();\r\n }\r\n\r\n shortcutBindings.remove();\r\n });\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .directive(`esMonitoringPopups`, esMonitoringPopups)\r\n .controller(`esMonitoringPopupsController`, esMonitoringPopupsController);\r\n\r\n esMonitoringPopups.$inject = [];\r\n\r\n /* istanbul ignore next */\r\n function esMonitoringPopups() {\r\n\r\n const directive = {\r\n restrict: `E`,\r\n scope: {\r\n mapId: `@`\r\n },\r\n require: `^esLeaflet`,\r\n link: link,\r\n controller: `esMonitoringPopupsController`,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n templateUrl: `/App/ui/features/monitoring/controls/esMonitoringPopup.html`\r\n };\r\n\r\n return directive;\r\n\r\n function link($scope, $element, attrs, leafletController) {\r\n $scope.vm.subscribeToLeafletMarkerClick($scope, leafletController);\r\n }\r\n }\r\n\r\n esMonitoringPopupsController.$inject = [\r\n `$rootScope`,\r\n `$scope`,\r\n `$compile`,\r\n `$timeout`,\r\n `$templateCache`,\r\n `jQuery`,\r\n `leafletLib`,\r\n `esLeafletData`,\r\n `lodash`,\r\n `i18n`,\r\n `app.ui.core.keyboardShortcuts`,\r\n `app.core.appSettings`,\r\n `app.core.states.monitoringTimeState`\r\n ];\r\n\r\n function esMonitoringPopupsController(\r\n $rootScope,\r\n $scope,\r\n $compile,\r\n $timeout,\r\n $templateCache,\r\n $,\r\n L,\r\n esLeafletData,\r\n _,\r\n i18n,\r\n keyboardShortcuts,\r\n appSettings,\r\n monitoringTimeState) {\r\n\r\n const vm = this;\r\n\r\n const defaultSize = `small`;\r\n const popupSizes = {\r\n small: {\r\n height: 280,\r\n width: 320\r\n },\r\n medium: {\r\n height: 280,\r\n width: 680\r\n },\r\n large: {\r\n height: 400,\r\n width: 840\r\n }\r\n };\r\n\r\n vm.companyAlias = appSettings.site.company.alias;\r\n vm.facilityAlias = appSettings.site.facility.alias;\r\n vm.canAccessConfiguration = appSettings.site.accessControls[`app.config`];\r\n vm.subscribeToLeafletMarkerClick = subscribeToLeafletMarkerClick;\r\n\r\n function subscribeToLeafletMarkerClick($scope, leafletController) {\r\n\r\n const openPopups = new Set([]);\r\n let _map;\r\n\r\n subscribeToLeafletClickEvents();\r\n setupKeyboardShortcuts();\r\n\r\n ////////////////////\r\n\r\n function subscribeToLeafletClickEvents() {\r\n const unsubscribeFromMarkerClick = $rootScope.$on(`leafletDirectiveMarker.${vm.mapId}.click`, onLeafletElementClick);\r\n const unsubscribeFromPathClick = $rootScope.$on(`leafletDirectivePath.${vm.mapId}.click`, onLeafletElementClick);\r\n\r\n $scope.$on(`$destroy`, () => {\r\n unsubscribeFromMarkerClick();\r\n unsubscribeFromPathClick();\r\n });\r\n\r\n function onLeafletElementClick(event, leafletElementEvent, popupToClone) {\r\n const marker = _.find(event.targetScope.markers, { monitorId: leafletElementEvent.model && leafletElementEvent.model.monitor.id }) || leafletElementEvent.leafletEvent.target.options;\r\n\r\n const $widgetScope = buildViewModel(marker, popupToClone && popupToClone.size || defaultSize);\r\n marker.monitor.getGraphProcessVariables().then(setGraphVariables);\r\n\r\n function setGraphVariables(variables) {\r\n $widgetScope.graphProcessVariables = variables;\r\n const $element = getCompiledElement($widgetScope);\r\n leafletController\r\n .getMap()\r\n .then(setMapInstance)\r\n .then(getPopup)\r\n .then(enableFocus)\r\n .then(enableDragAndDrop)\r\n .then(setResizePopupMethod)\r\n .then(setCloseMethod)\r\n .then(setCloneMethod);\r\n\r\n function setMapInstance(map) {\r\n return _map = map;\r\n }\r\n\r\n function getPopup(map) {\r\n let offset = [100, -15];\r\n let latlng = [marker.lat, marker.lng];\r\n\r\n popupToClone = popupToClone || _.findLast([...openPopups], popup => popup.monitorId === marker.monitorId);\r\n\r\n if (popupToClone) {\r\n const [left, top] = popupToClone.options.offset;\r\n offset = [left + $element.width() + 30, top];\r\n latlng = map.layerPointToLatLng(popupToClone._container._leaflet_pos);\r\n }\r\n const options = {\r\n closeOnClick: false,\r\n autoPan: true,\r\n autoPanPadding: L.point(50, 50),\r\n zoomAnimation: true,\r\n className: `es-monitoring-graph-popup`,\r\n closeButton: false,\r\n autoClose: false,\r\n offset\r\n };\r\n\r\n const popup = L.popup(options)\r\n .setLatLng(latlng)\r\n .setContent($element[0]);\r\n\r\n popup.monitorId = marker.monitorId;\r\n popup.size = $widgetScope.popupSize;\r\n\r\n map.addLayer(popup);\r\n\r\n $element.height(`100%`);\r\n\r\n popup.removeTracking = () => {\r\n openPopups.delete(popup);\r\n };\r\n\r\n bringToFront(popup);\r\n return popup;\r\n }\r\n\r\n function enableFocus(popup) {\r\n const debouncedBringToFront = _.debounce(bringToFront, 50);\r\n $(popup._wrapper)\r\n .on(`mouseenter`, () => debouncedBringToFront(popup))\r\n .on(`click`, () => debouncedBringToFront(popup));\r\n return popup;\r\n }\r\n\r\n function bringToFront(popup) {\r\n if (!!popup.isClosing) { return; }\r\n popup.bringToFront();\r\n openPopups.delete(popup);\r\n openPopups.add(popup);\r\n }\r\n\r\n function enableDragAndDrop(popup) {\r\n const draggable = new L.Draggable(popup._container, popup._wrapper);\r\n draggable.enable();\r\n return popup;\r\n }\r\n\r\n function setCloseMethod(popup) {\r\n $widgetScope.closePopup = () => {\r\n popup.isClosing = true;\r\n popup.removeTracking();\r\n _map.closePopup(popup);\r\n };\r\n\r\n return popup;\r\n }\r\n\r\n function setResizePopupMethod(popup) {\r\n $widgetScope.resizePopup = size => {\r\n const newContentBounds = getContentBounds(size);\r\n popup.size = size;\r\n $widgetScope.popupSize = size;\r\n $widgetScope.contentBounds = newContentBounds;\r\n $element.height(`100%`);\r\n $element.width(newContentBounds.width);\r\n popup.update();\r\n };\r\n return popup;\r\n }\r\n\r\n function setCloneMethod(popup) {\r\n $widgetScope.clonePopup = () => {\r\n onLeafletElementClick(event, leafletElementEvent, popup);\r\n };\r\n return popup;\r\n }\r\n }\r\n }\r\n\r\n function buildViewModel(marker, size = defaultSize) {\r\n const monitor = marker.monitor;\r\n\r\n const $widgetScope = $scope.$new();\r\n $widgetScope.popupSize = size;\r\n $widgetScope.name = monitor.name;\r\n $widgetScope.monitorId = monitor.id;\r\n $widgetScope.processVariableId = monitor.processVariable && monitor.processVariable.id;\r\n $widgetScope.contentBounds = getContentBounds(size);\r\n $widgetScope.monitoringTimeState = monitoringTimeState;\r\n $widgetScope.showUnits = monitor.showUnitsOnPopup;\r\n $widgetScope.showConfigButton = vm.canAccessConfiguration && monitor.canAccessConfiguration;\r\n return $widgetScope;\r\n }\r\n\r\n function getCompiledElement($widgetScope) {\r\n const compiledTemplate = $compile($templateCache.get(`esMonitoringPopupTemplate.html`));\r\n const $element = compiledTemplate($widgetScope);\r\n $element.height(estimatePopupHeight());\r\n $element.width($widgetScope.contentBounds.width);\r\n return $element;\r\n\r\n function estimatePopupHeight() {\r\n const pvRowHeight = 30;\r\n const graphHeight = 200;\r\n const paddingHeight = 50;\r\n const chromeHeight = 40;\r\n const isPortrait = $widgetScope.contentBounds.width <= 320;\r\n\r\n return isPortrait\r\n ? chromeHeight + $widgetScope.graphProcessVariables.length * pvRowHeight + graphHeight + paddingHeight\r\n : $widgetScope.contentBounds.height;\r\n }\r\n }\r\n\r\n function getContentBounds(size = defaultSize) {\r\n return popupSizes[size];\r\n }\r\n }\r\n\r\n function setupKeyboardShortcuts() {\r\n\r\n const shortcuts = {\r\n [`esc`]: {\r\n description: i18n.i10n(`esMonitoringPopup.shortcuts.close`),\r\n action: () => {\r\n if (!openPopups.size) {\r\n return;\r\n }\r\n const lastOpenedPopup = [...openPopups].pop();\r\n _map.closePopup(lastOpenedPopup);\r\n lastOpenedPopup.removeTracking();\r\n }\r\n }\r\n };\r\n const shortcutBindings = keyboardShortcuts.add(i18n.i10n(`esMonitoringPopup.shortcuts.description`), shortcuts);\r\n $scope.$on(`$destroy`, () => {\r\n shortcutBindings.remove();\r\n });\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\n `use strict`;\n\n angular\n .module(`app.ui.features.monitoring`)\n .directive(`esMonitoringWidget`, directive)\n .controller(`esMonitoringWidgetController`, controller);\n\n directive.$inject = [];\n\n const palette = [\n `#90c9da`,\n `#ed7572`,\n `#986fac`,\n `#569176`,\n `#849eae`,\n `#f39e63`,\n `#facd53`,\n `#ae9dcc`,\n `#526077`,\n `#af4570`,\n `#817f6f`,\n `#91c58b`,\n `#e895b1`,\n `#ae9997`\n ];\n\n /* istanbul ignore next */\n function directive() {\n return {\n restrict: `A`,\n scope: {\n monitorId: `=`,\n contentBounds: `=`,\n sampleDateTime: `=`,\n showUnits: `=`,\n selectedProcessVariableId: `=`,\n processVariableIds: `=`,\n isRealTime: `=`,\n context: `=`\n },\n controller: controller,\n controllerAs: `vm`,\n bindToController: true,\n templateUrl: `/App/ui/features/monitoring/controls/esMonitoringWidget.html`\n };\n }\n\n controller.$inject = [\n `$scope`,\n `$q`,\n `$timeout`,\n `promiseTracker`,\n `notifier`,\n `jQuery`,\n `lodash`,\n `d3`,\n `moment`,\n `i18n`,\n `MG`,\n `app.core.datetime.timeZoneDateTime`,\n `app.core.services.monitoringService`,\n `app.core.services.dateTimeService`,\n `app.core.services.mathService`\n ];\n\n function controller(\n $scope,\n $q,\n $timeout,\n promiseTracker,\n notifier,\n $,\n _,\n d3,\n moment,\n i18n,\n MG,\n timeZoneDateTime,\n monitoringService,\n dateTimeService,\n mathService) {\n\n const dblClickDelay = 400;\n let initialLoad = true;\n let abortSingleClick = false;\n\n const vm = this;\n vm.instanceId = new Date().getTime();\n vm.selectedProcessVariableIds = [];\n vm.onClickProcessVariable = debouncedOnClickProcessVariable;\n vm.onMultiSelectProcessVariable = onMultiSelectProcessVariable;\n vm.sensorData = [];\n vm.isPortrait = vm.contentBounds.width <= 320;\n\n vm.busyLoadingSensors = promiseTracker();\n vm.busyLoadingGraphDataSeries = promiseTracker();\n\n vm.selectedHighlight = pvId => {\n const isSelected = _.find(vm.selectedProcessVariableIds, sId => pvId === sId);\n return isSelected\n ? palette[_.findIndex(vm.processVariableIds, id => id === pvId) % palette.length]\n : undefined;\n };\n\n const prevDataSeries = {};\n let graphsNeedRerendering;\n\n activate();\n\n /////////////////////\n\n function activate() {\n\n $scope.$watch(() => vm.sampleDateTime, loadWidget);\n\n function loadWidget() {\n graphsNeedRerendering =\n !vm.currentlySelectedDateTime || // first render\n vm.isRealTime ||\n hasChangedDays();\n\n vm.sampleTime = vm.currentlySelectedDateTime = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.sampleDateTime);\n const promise = monitoringService.getMonitorSensorData(vm.monitorId, vm.processVariableIds, vm.sampleDateTime)\n .then(onSuccess, onFail);\n\n vm.busyLoadingSensors.addPromise(promise);\n\n function hasChangedDays() {\n const sampleDate = moment(timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.sampleDateTime)).startOf(`d`);\n const currentDate = moment(vm.currentlySelectedDateTime).startOf(`d`);\n\n return Math.abs(sampleDate.diff(currentDate, `d`)) >= 1;\n }\n\n function onSuccess(sensorData) {\n if (!vm.sensorData.length) {\n vm.sensorData = sensorData;\n } else {\n _.forEach(vm.sensorData, pv => {\n _.merge(pv, _.find(sensorData, { id: pv.id }));\n });\n\n if (sensorData.length !== vm.sensorData.length) {\n graphsNeedRerendering = true;\n }\n }\n\n if (initialLoad) {\n const selectedProcessVariable = _.find(sensorData, { id: vm.selectedProcessVariableId });\n const defaultSensorId = selectedProcessVariable && selectedProcessVariable.id || vm.sensorData[0].id;\n onClickProcessVariable(defaultSensorId);\n $scope.$watch(() => vm.contentBounds, () => {\n vm.isPortrait = vm.contentBounds.width <= 320;\n vm.graphHeight = vm.contentBounds.height - 80;\n vm.graphWidth = vm.contentBounds.width <= 320 || vm.context === `dashboard` ? vm.contentBounds.width - 20 : vm.contentBounds.width - 340;\n renderSelectedSensorGraphs();\n }, true);\n\n } else {\n renderSelectedSensorGraphs();\n }\n\n initialLoad = false;\n }\n\n function onFail(response) {\n // Don't notify of a failure if the reason for failure is that the request expired or was cancelled\n // - this is a result of us buffering using the requestManager.\n if (response && response.reason && (response.reason === `expired` || response.reason === `cancelled`)) {\n return;\n }\n\n notifier.error(\n i18n.i10n(`esMonitoringWidget.graph.error.text`),\n i18n.i10n(`esMonitoringWidget.graph.error.heading`));\n\n if (response) {\n response.handled = true;\n }\n }\n }\n\n function renderSelectedSensorGraphs() {\n ensureSensorAlwaysSelectedForLandscapeWidgets();\n\n const promise = $q.all(_.map(vm.processVariableIds, loadSensorDataSeries));\n vm.busyLoadingGraphDataSeries.addPromise(promise);\n promise.then(renderSensorGraphs);\n\n function ensureSensorAlwaysSelectedForLandscapeWidgets() {\n if (!vm.isPortrait && vm.selectedProcessVariableIds.length === 0) {\n onClickProcessVariable(vm.sensorData[0].id);\n }\n }\n }\n }\n\n function debouncedOnClickProcessVariable(processVariableId, event) {\n $timeout(() => {\n if (!abortSingleClick) {\n onClickProcessVariable(processVariableId, event);\n $timeout(renderSensorGraphs); // ensure graph container is mounted before rendering.\n }\n }, dblClickDelay);\n }\n\n function onClickProcessVariable(processVariableId, event) {\n if (event && event.ctrlKey) {\n onMultiSelectProcessVariable(processVariableId, event);\n } else {\n const isSelected = _.includes(vm.selectedProcessVariableIds, processVariableId);\n const processVariable = _.find(vm.sensorData, { id: processVariableId });\n processVariable.isSelected = !isSelected;\n\n if (isSelected && vm.isPortrait && vm.selectedProcessVariableIds.length === 1) {\n vm.selectedProcessVariableIds = [];\n } else {\n vm.selectedProcessVariableIds = [processVariableId];\n }\n _.forEach(vm.sensorData, pv => {\n pv.isSelected = pv.id === processVariableId;\n });\n }\n }\n\n function onMultiSelectProcessVariable(processVariableId) {\n abortSingleClick = true;\n $timeout(() => abortSingleClick = false, dblClickDelay);\n\n const isSelected = _.includes(vm.selectedProcessVariableIds, processVariableId);\n const processVariable = _.find(vm.sensorData, { id: processVariableId });\n processVariable.isSelected = !isSelected;\n\n if (isSelected && (vm.selectedProcessVariableIds.length === 1 && vm.isPortrait || vm.selectedProcessVariableIds.length > 1)) {\n _.pull(vm.selectedProcessVariableIds, processVariableId);\n } else if (!isSelected) {\n vm.selectedProcessVariableIds = [...vm.selectedProcessVariableIds, processVariableId];\n }\n _.forEach(vm.sensorData, pv => {\n pv.isSelected = _.includes(vm.selectedProcessVariableIds, pv.id);\n });\n\n $timeout(renderSensorGraphs); // ensure the graph container dom element is mounted first\n }\n\n function loadSensorDataSeries(processVariableId) {\n const processVariable = _.find(vm.sensorData, { id: processVariableId });\n\n if (!processVariable) {\n return $q.when();\n }\n\n if (!graphsNeedRerendering) {\n return updateGraphDetails(processVariable, prevDataSeries[processVariable.id]);\n }\n\n const windowStart = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(timeZoneDateTime.getFacilityStartOfDay(vm.sampleDateTime));\n const windowEnd = moment(windowStart)\n .add(1, `d`)\n .toDate();\n\n return monitoringService\n .getSensorDataSeries(windowStart, windowEnd, processVariable.id)\n .then(dataSeries => {\n prevDataSeries[processVariable.id] = dataSeries;\n return updateGraphDetails(processVariable, dataSeries);\n })\n .finally(() => graphsNeedRerendering = false);\n\n /////////////////\n\n function updateGraphDetails(processVariable, dataSet) {\n const pvThresholds = _.sortBy(dataSet.exceedanceThresholds, [`valueInBaseUnit`]);\n\n processVariable.graphDetails = {\n unit: dataSet.units,\n title: dataSet.processName,\n readings: [dataSet.processVariableName],\n data: dataSet.values.map(convertDatumToFacilityDateTime)\n };\n\n processVariable.graphDetails.markers = [\n {\n date: vm.currentlySelectedDateTime,\n label: dateTimeService.formatAs.time(vm.currentlySelectedDateTime)\n }\n ];\n\n const { min, max } = getMinMaxThresholdValuesToShow(dataSet.values, pvThresholds);\n\n processVariable.graphDetails.baselines = _.chain(pvThresholds)\n .filter(pvThreshold => pvThreshold.valueInDisplayUnit >= min && pvThreshold.valueInDisplayUnit <= max)\n .map(pvThreshold => {\n // MetricGraphics library doesn't seem to handle numbers greater than a 32bit float.\n const baseLineValue = Math.min(\n mathService.floatMaxValue,\n Math.max(pvThreshold.valueInDisplayUnit, mathService.floatMinValue)\n );\n\n return {\n value: baseLineValue,\n label: mathService.round(baseLineValue, 1),\n colour: intToHexColor(pvThreshold.color)\n };\n })\n .value();\n\n return processVariable;\n\n function intToHexColor(int) {\n /* eslint-disable no-bitwise */\n return `#` + (int >>> 0).toString(16).slice(-6);\n }\n\n function convertDatumToFacilityDateTime(dataPoint) {\n return {\n date: timeZoneDateTime.convertDateTimeToFacilityTimeZone(dataPoint.date),\n value: dataPoint.valueInDisplayUnit,\n thresholdColour: getThresholdColour(dataPoint.valueInBaseUnit)\n };\n }\n\n function getThresholdColour(value) {\n const matchingThreshold = _.findLast(pvThresholds, threshold => value >= threshold.valueInBaseUnit);\n const defaultColor = `#679B38`;\n if (matchingThreshold == null) {\n return defaultColor;\n }\n\n return intToHexColor(matchingThreshold.color);\n }\n\n function getMinMaxThresholdValuesToShow(pvValues = [], pvThresholds = []) {\n // get the minimum and maximum pv data point values.\n let max = Number.MIN_SAFE_INTEGER;\n let min = Number.MAX_SAFE_INTEGER;\n for (const pvValue of pvValues)\n {\n max = Math.max(max, pvValue.valueInDisplayUnit);\n min = Math.min(min, pvValue.valueInDisplayUnit);\n }\n\n // now include all the thresholds within the min/max range and\n // ALSO include one extra on either side of min/max range\n // UNLESS those extraneous values are floatMinValue or floatMaxValue\n let lower = min;\n let upper = max;\n for (const pvThreshold of pvThresholds) {\n const thresholdValue = pvThreshold.valueInDisplayUnit;\n if (thresholdValue < min && thresholdValue > Number.MIN_SAFE_INTEGER) {\n lower = thresholdValue;\n } else if (thresholdValue > max && thresholdValue < Number.MAX_SAFE_INTEGER) {\n upper = thresholdValue;\n break;\n }\n }\n\n return {\n min: lower,\n max: upper\n };\n }\n }\n }\n\n function renderSensorGraphs() {\n const targetAccessor = `#o-${vm.instanceId} .es-monitoring-graph-content`;\n const $targetAccessor = $(targetAccessor);\n\n // if the widget has been removed from the DOM we don't need to render the graph.\n if (!$targetAccessor.length) {\n return;\n }\n\n const selectedSensors = _.filter(vm.sensorData, pv => pv.isSelected);\n const isSingleSelectMode = selectedSensors.length === 1;\n\n const selectedGraphs = _.filter(selectedSensors, pv => pv.graphDetails)\n .map(pv => pv.graphDetails);\n\n let hasDstAdjustment = false;\n\n const data = selectedGraphs.map(graphDetails => {\n const seen = new Set();\n\n const data = graphDetails.data.filter(item => {\n // This is a hack to filter out duplicates due to DST adjustments - metrics-graphics doesn't like\n // duplicate datetimes.\n const key = item.date.toLocaleTimeString();\n return seen.has(key) ? false : seen.add(key);\n });\n\n if(data.length > 0) {\n const first = data[0].date.getTimezoneOffset();\n const last = data[data.length - 1].date.getTimezoneOffset();\n\n hasDstAdjustment = hasDstAdjustment || first !== last;\n }\n\n return data;\n });\n\n if (hasDstAdjustment) {\n // Second hack - shift everything back one so the data is not on a day that has a timezone adjustment.\n // The metrics-graphics chart cannot graph a time-series that crosses multiple timezones.\n data.forEach(series => {\n series.forEach(item => {\n item.date = moment(item.date)\n .add(-1, `day`)\n .toDate();\n });\n });\n }\n\n if (isDataMissing()) {\n renderMissingData();\n } else {\n renderTrend();\n }\n\n function isDataMissing() {\n return !_.flatten(data).length;\n }\n\n function renderMissingData() {\n $targetAccessor.empty();\n\n let missingText = i18n.i10n(`esMonitoringWidget.graph.labels.noDataAvailable`);\n if (isSingleSelectMode && selectedSensors[0].isValueStale) {\n missingText = `${i18n.i10n(`esMonitoringWidget.graph.labels.stale`) } ${dateTimeService.formatAs.dateTime(timeZoneDateTime.convertDateTimeToFacilityTimeZone(selectedSensors[0].valueTime)) }`;\n }\n\n /* eslint-disable camelcase */\n MG.data_graphic({\n chart_type: `missing-data`,\n missing_text: missingText,\n target: targetAccessor,\n full_width: true,\n full_height: true\n });\n /* eslint-enable camelcase */\n }\n\n function renderTrend() {\n $targetAccessor.empty();\n\n const min = !hasDstAdjustment\n ? timeZoneDateTime.getFacilityStartOfDay(vm.sampleDateTime)\n : timeZoneDateTime.getFacilityStartOfDay(moment(vm.sampleDateTime).add(-1, `day`).toDate());\n const max = moment(min)\n .add(1, `d`)\n .toDate();\n\n const markers = selectedGraphs[0].markers;\n\n if (hasDstAdjustment) {\n markers.forEach(marker => {\n marker.date = moment(marker.date).add(-1, `day`).toDate();\n });\n }\n\n const baselines = selectedGraphs.length === 1 ? selectedGraphs[0].baselines : null;\n\n const indices = _.sortBy(_.map(vm.selectedProcessVariableIds, sId => _.findIndex(vm.processVariableIds, pvId => pvId === sId)));\n const adjustedPalette = _.map(indices, index => palette[index % palette.length]);\n\n /* eslint-disable camelcase */\n MG.data_graphic({\n target: targetAccessor,\n animate_on_load: graphsNeedRerendering,\n min_x: min,\n max_x: max,\n x_accessor: `date`,\n xax_format: dateTimeService.formatAs.hour,\n y_accessor: `value`,\n yax_format: value => `${value}`,\n yax_count: 5,\n y_extended_ticks: true,\n show_secondary_x_label: false,\n show_rollover_text: false,\n interpolate: d3.curveMonotoneX,\n aggregate_rollover: !isSingleSelectMode,\n full_width: true,\n full_height: true,\n missing_is_zero: true,\n top: 20,\n bottom: 20,\n colors: adjustedPalette,\n area: true,\n flip_area_under_y_value: 0,\n\n data: data,\n markers,\n baselines,\n\n mouseover: (dataPoint, i) => {\n const values = dataPoint.values || [dataPoint];\n vm.sampleTime = values[0].date;\n const millis = vm.sampleTime.getTime();\n $timeout(() => {\n _.forEach(vm.sensorData, sensor => {\n const selectedDataPoint = _.findLast(sensor.graphDetails.data, dataPoint => dataPoint.date.getTime() <= millis);\n sensor.graphDetails.selectedDataPoint = selectedDataPoint;\n });\n });\n },\n mouseout: () => {\n vm.sampleTime = timeZoneDateTime.convertDateTimeToFacilityTimeZone(vm.sampleDateTime);\n $timeout(() => {\n _.forEach(vm.sensorData, sensor => {\n sensor.graphDetails.selectedDataPoint = null;\n });\n });\n }\n });\n /* eslint-enable camelcase */\n\n // Some on-premise clients are reporting that the graphs are not appearing.\n // This may catch that situation and log an error to the console that can be reported.\n // This is very low level because the situation in which this might occur is vague.\n if ($targetAccessor.html().indexOf(`es-monitoring-graph-content`) < 0) {\n throw `The graph area does not contain the expected graph content. Content is:\\n${$targetAccessor.html()}`;\n } \n\n _.forEach(baselines, (baseline, index) => {\n const $baseline = $(`.mg-baselines line:nth-child(${index + 1})`);\n\n $baseline\n .css(`stroke`, baseline.colour)\n .css(`stroke-dasharray`, `2,5`);\n });\n }\n }\n }\n})();\n","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .directive(`esMonitorTypeSelectionCriteria`, directive);\r\n\r\n directive.$inject = [];\r\n function directive() {\r\n return {\r\n scope: {\r\n monitorType: `@`,\r\n state: `=`\r\n },\r\n restrict: `E`,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: controller,\r\n templateUrl: `/App/ui/features/monitoring/controls/esMonitorTypeSelectionCriteria.html`,\r\n transclude: true\r\n };\r\n }\r\n\r\n controller.$inject = [`app.core.services.configuration.monitoringService`];\r\n function controller(monitoringService) {\r\n const vm = this;\r\n vm.icon = monitoringService.getMonitorTypeIcon(vm.monitorType);\r\n }\r\n\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .directive(`esSourceIdentificationPanel`, directive);\r\n\r\n directive.$inject = [];\r\n\r\n function directive() {\r\n return {\r\n scope: {\r\n state: `=`\r\n },\r\n restrict: `E`,\r\n controllerAs: `vm`,\r\n bindToController: true,\r\n controller: function() {},\r\n templateUrl: `/App/ui/features/monitoring/controls/esSourceIdentificationPanel.html`\r\n };\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.monitoring`)\r\n .controller(`app.ui.features.monitoring.LeftPanel`, LeftPanel);\r\n\r\n LeftPanel.$inject = [\r\n `$scope`,\r\n `lodash`,\r\n `monitoringState`\r\n ];\r\n\r\n function LeftPanel($scope, _, monitoringState) {\r\n const vm = this;\r\n\r\n vm.state = monitoringState;\r\n\r\n activate();\r\n\r\n /////////////////////\r\n\r\n function activate() {\r\n renderMarkers();\r\n addWatchersToDisplaySwitches();\r\n addWatchersToSensorSwitches();\r\n }\r\n\r\n function renderMarkers() {\r\n monitoringState.map.renderMonitorMapMarkers();\r\n }\r\n\r\n function addWatchersToDisplaySwitches() {\r\n $scope.$watch(\r\n () => vm.state.map.switches.display,\r\n () => renderMarkers(),\r\n true);\r\n\r\n $scope.$watch(\r\n () => vm.state.map.switches.influenceArcs,\r\n newValue => {\r\n getSensorTypes()\r\n .map(mapSensorNameToSensorArcTuple)\r\n .forEach(toggleInfluenceArcVisibility);\r\n\r\n function mapSensorNameToSensorArcTuple(sensorType) {\r\n const influenceArcOverlayBySensor = getInfluenceArcsOverlayForSensor(sensorType);\r\n\r\n return {\r\n arc: influenceArcOverlayBySensor,\r\n sensor: vm.state.map.layers.overlays[sensorType]\r\n };\r\n }\r\n\r\n function toggleInfluenceArcVisibility(overlay) {\r\n if (!overlay.arc) {\r\n return;\r\n }\r\n\r\n overlay.arc.visible = newValue && overlay.sensor.visible;\r\n }\r\n });\r\n }\r\n\r\n function addWatchersToSensorSwitches() {\r\n const sensorTypes = getSensorTypes();\r\n _.forEach(sensorTypes, watchSensorVisibilityToggle);\r\n\r\n function watchSensorVisibilityToggle(sensorType) {\r\n\r\n $scope.$watch(() => vm.state.map.switches.sensorTypes[sensorType], toggleSensorVisibility);\r\n\r\n function toggleSensorVisibility(newValue) {\r\n vm.state.map.layers.overlays[sensorType].visible = newValue;\r\n getInfluenceArcsOverlayForSensor(sensorType).visible = newValue && vm.state.map.switches.influenceArcs;\r\n }\r\n }\r\n }\r\n\r\n function getSensorTypes() {\r\n return _.keys(vm.state.map.switches.sensorTypes);\r\n }\r\n\r\n function getInfluenceArcsOverlayForSensor(sensorType) {\r\n return vm.state.map.layers.overlays[`influenceArcs-${sensorType}`];\r\n }\r\n\r\n }\r\n})();","(function() {\n `use strict`;\n\n angular\n .module(`app.ui.features.monitoring`)\n .run(appRun);\n\n appRun.$inject = [\n `routeHelper`,\n `app.ui.features.monitoring.state`\n ];\n\n function appRun(routeHelper, monitoringState) {\n routeHelper.configureRoutes(getRoutes());\n\n function getRoutes() {\n return [{\n state: `app.monitoring`,\n url: `/monitoring/{companyAlias}/{facilityAlias}?dateTime&fullScreen`,\n views: {\n actionsPanel: {\n templateUrl: `/App/ui/features/monitoring/ActionsPanel.html`,\n controller: `app.ui.features.monitoring.ActionsPanel as vm`\n },\n leftPanel: {\n templateUrl: `/App/ui/features/monitoring/LeftPanel.html`,\n controller: `app.ui.features.monitoring.LeftPanel as vm`\n },\n contentPanel: {\n templateUrl: `/App/ui/features/monitoring/ContentPanel.html`,\n controller: `app.ui.features.monitoring.ContentPanel as vm`\n }\n },\n reloadOnSearch: false, // allows us to set the ?dateTime parameter without reloading the resolvers.\n data: {\n requiredAccessControl: `app.monitoring`\n },\n settings: {\n i18n: [\n `/App/ui/features/monitoring/i18n/monitoring`,\n `/App/ui/features/monitoring/controls/i18n/esMonitoringDateTimeSelector`,\n `/App/ui/features/monitoring/controls/i18n/esMonitoringWidget`,\n `/App/ui/features/monitoring/controls/i18n/esMonitoringPopup`,\n `/App/ui/features/monitoring/controls/i18n/esMonitorTypeSelectionCriteria`,\n `/App/ui/features/monitoring/controls/i18n/esSourceIdentificationPanel`,\n `/App/ui/core/mapping/controls/i18n/esMapCentre`,\n `/App/ui/core/mapping/controls/i18n/esMapKml`,\n `/App/ui/core/mapping/controls/i18n/esMapCredits`,\n `/App/ui/core/mapping/controls/i18n/esMapTiles`,\n `/App/ui/core/mapping/controls/i18n/esMapType`\n ]\n },\n resolve: {\n monitoringState: monitoringState\n }\n }];\n }\n }\n})();\n","(function () {\n `use strict`;\n\n angular\n .module(`app.ui.features.monitoring`)\n .factory(`app.ui.features.monitoring.state`, monitoringStateFactory);\n\n monitoringStateFactory.$inject = [\n `$q`,\n `lodash`,\n `app.core.appSettings`,\n `app.core.mapDefaults`,\n `app.core.services.companyService`,\n `app.core.services.monitoringService`,\n `app.core.services.configuration.monitoringService`,\n `app.core.models.monitoring.createMonitorMapMarker`,\n `app.core.models.monitoring.createMonitorMapPath`,\n `app.core.models.monitoring.createMonitorMapFenceline`\n ];\n\n function monitoringStateFactory(\n $q, _, appSettings, mapDefaults, companyService, monitoringService,\n monitoringConfigurationService, createMonitorMapMarker, createMonitorMapPath, createMonitorMapFenceline) {\n\n return function () {\n const getFacilityLocation = companyService.getFacilityLocation();\n const getMonitorsByType = monitoringService.getMonitorsByType();\n const getMonitorTypes = monitoringConfigurationService.getMonitorTypes();\n\n return $q.all([getFacilityLocation, getMonitorsByType, getMonitorTypes]).then(result => {\n const [facilityLocation, monitorsByType, monitorTypes] = result;\n\n const state = {\n accessControls: {\n sourceIdentification: !!appSettings.site.accessControls[`app.monitoring.source-identification`],\n sourceIdentificationDebug: !!appSettings.site.accessControls[`app.monitoring.source-identification-debug`]\n },\n monitorTypes: monitorTypes,\n monitorsByType: monitorsByType,\n monitors: [],\n areaSources: [],\n map: {\n defaultCentre: facilityLocation,\n centre: facilityLocation,\n defaults: {\n settings: mapDefaults.settings\n },\n isColor: false,\n paths: {},\n layers: {\n baselayers: mapDefaults.baselayers,\n overlays: buildLayers(monitorTypes)\n }\n }\n };\n\n const sensorTypes = {};\n _.forEach(monitorTypes, monitorType => {\n sensorTypes[monitorType.type] = true;\n });\n\n state.map.switches = {\n boundaries: true,\n influenceArcs: true,\n sourceIdentification: true,\n sourceIdentificationDebug: false,\n display: {\n monitorNames: false,\n units: false,\n heroMode: false,\n thresholdExceeded: false,\n icons: true\n },\n sensorTypes: sensorTypes\n };\n\n state.map.renderMonitorMapMarkers = () => {\n state.map.markers = _.map(state.monitors, monitor =>\n createMonitorMapMarker(\n monitor,\n { ...state.map.switches.display, dataValue: true }\n )\n );\n setInfluenceArcs();\n state.map.bounds = _.map(state.monitors, monitor => [ monitor.latitude, monitor.longitude ]);\n\n const fencelines = _.chain(state.monitors)\n .filter(monitor => monitor.fencelineLocations && monitor.fencelineLocations.length >= 2)\n .map(monitor => createMonitorMapFenceline(monitor, state.map.switches.display))\n .flatten()\n .reduce((obj, fenceline) => {\n obj[fenceline.id] = fenceline;\n return obj;\n }, {})\n .value();\n\n state.map.paths = { ...state.map.paths, ...fencelines };\n };\n\n if (state.accessControls.sourceIdentification) {\n const areaSourcesLayerName = `areaSources`;\n\n state.map.layers.overlays[areaSourcesLayerName] = {\n type: `group`,\n visible: true,\n name: areaSourcesLayerName\n };\n\n state.map.renderSourceAreaSources = () => {\n let areaSources = _.map(state.areaSources, process => createMonitorMapPath(process,\n {\n layer: areaSourcesLayerName,\n showUnitsOnPopup: false,\n graphProcessVariables: process.dataPoints.map(dp => dp.id),\n canAccessConfiguration: false\n }));\n\n areaSources = _.reduce(areaSources, (obj, areaSource) => {\n obj[areaSource.id] = areaSource;\n return obj;\n }, {});\n\n state.map.paths = { ...state.map.paths, ...areaSources };\n };\n }\n\n function setInfluenceArcs() {\n state.map.influenceArcs = state.monitors.map(monitor => {\n const influenceArc = monitor.influenceArc || {};\n\n influenceArc.monitorId = monitor.id;\n influenceArc.latitude = monitor.latitude;\n influenceArc.longitude = monitor.longitude;\n influenceArc.monitorType = monitor.monitorType;\n influenceArc.thresholdColour = monitor.influenceArc ? monitor.influenceArc.thresholdColour : ``;\n influenceArc.unrender = !monitor.influenceArc || state.map.switches.display.thresholdExceeded && !monitor.processVariable.hasValueExceededFirstThreshold;\n\n return influenceArc;\n });\n }\n\n return state;\n });\n };\n\n function buildLayers(monitorTypes) {\n const layers = {};\n _.forEach(monitorTypes, monitorType => {\n layers[monitorType.type] = {\n type: `group`,\n visible: true,\n name: monitorType.name\n };\n\n layers[`influenceArcs-${monitorType.type}`] = {\n type: `group`,\n visible: true,\n name: `${monitorType.name} Influence Arcs`\n };\n });\n return layers;\n }\n }\n\n})();\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.reporting`)\r\n .controller(`app.ui.features.reporting.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$state`,\r\n `$window`,\r\n `$location`,\r\n `promiseTracker`,\r\n `app.core.services.reportsService`\r\n ];\r\n\r\n function ContentPanel($state, $window, $location, promiseTracker, reportsService) {\r\n const vm = this;\r\n vm.busyLoading = promiseTracker();\r\n\r\n activate();\r\n\r\n //////////////////////////\r\n\r\n function activate() {\r\n vm.listOptions = getListOptions();\r\n\r\n loadReports().then(reports => {\r\n reports\r\n .filter(report => report.isEs2Report)\r\n .forEach(report => {\r\n report.uri = $state.href(report.uri, report.params);\r\n });\r\n vm.listOptions.items = reports;\r\n });\r\n\r\n //////////////////////////\r\n\r\n function loadReports() {\r\n const loadingPromise = reportsService.getListOfReports();\r\n vm.busyLoading.addPromise(loadingPromise);\r\n\r\n return loadingPromise;\r\n }\r\n\r\n function getListOptions() {\r\n return {\r\n columnDefs: [\r\n {\r\n heading: {\r\n i18n: {\r\n key: `app.ui.features.reporting.ContentPanel.list.columns.name.heading`\r\n }\r\n },\r\n field: `name`\r\n },\r\n {\r\n heading: {\r\n i18n: {\r\n key: `app.ui.features.reporting.ContentPanel.list.columns.description.heading`\r\n }\r\n },\r\n field: `description`\r\n }\r\n ],\r\n busyLoading: vm.busyLoading,\r\n onItemSelected: onReportSelected\r\n };\r\n }\r\n\r\n function onReportSelected(report) {\r\n window.location = report.uri;\r\n }\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.reporting`)\r\n .controller(`app.ui.features.reporting.reports.ProcessDataReport`, ProcessDataReport);\r\n\r\n ProcessDataReport.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `$q`,\r\n `lodash`,\r\n `i18n`,\r\n `promiseTracker`,\r\n `FileSaver`,\r\n `notifier`,\r\n `app.core.services.reportsService`,\r\n `app.core.services.dateTimeService`,\r\n `app.core.errorService`,\r\n `app.core.datetime.timeZoneDateTime`\r\n ];\r\n\r\n function ProcessDataReport($scope, $state, $q, _, i18n, promiseTracker, saveFile, notifier, reportsService, dateTimeService, errorService, timeZoneDateTime) {\r\n const vm = this;\r\n\r\n // See: http://stackoverflow.com/a/18925211\r\n const utf8EncodingHeader = `\\ufeff`;\r\n\r\n const stateParamsKeys = {\r\n processId: `processId`,\r\n startTime: `start`,\r\n endTime: `end`\r\n };\r\n\r\n const hasAllStateParams = _.every(stateParamsKeys, key => _.has($state.params, key) && $state.params[key]);\r\n\r\n let lastProcessIdUsedToLoadColumns = null;\r\n let hasColumns = false;\r\n\r\n vm.busyLoading = promiseTracker();\r\n vm.reportId = $state.params.reportId;\r\n\r\n vm.parameters = {};\r\n vm.processes = [];\r\n vm.controls = {};\r\n\r\n vm.onRefreshed = onRefreshed;\r\n vm.export = exportReport;\r\n\r\n activate();\r\n\r\n //////////////////////////\r\n\r\n function activate() {\r\n buildControls();\r\n revalidateStartAndEndTimeWhenParametersChange();\r\n const loadingPromise = loadLookupValues().then(loadReportDataIfParametersSpecified);\r\n vm.busyLoading.addPromise(loadingPromise);\r\n\r\n //////////////////////////\r\n\r\n function buildControls() {\r\n vm.controls = {\r\n startTime: buildDatePicker(),\r\n endTime: buildDatePicker(),\r\n dataGrid: buildDataGrid()\r\n };\r\n\r\n //////////////////////////\r\n\r\n function buildDatePicker() {\r\n return {\r\n options: {\r\n format: dateTimeService.formats.kendo.dateTime,\r\n timeFormat: dateTimeService.formats.kendo.time\r\n }\r\n };\r\n }\r\n\r\n function buildDataGrid() {\r\n return {\r\n options: {\r\n dataProvider: loadReportData,\r\n filterable: false\r\n }\r\n };\r\n }\r\n }\r\n\r\n function loadLookupValues() {\r\n return reportsService.getProcessDataReportLookupValues(vm.reportId)\r\n .then(importLookupValues)\r\n .catch(redirectBackToReports);\r\n\r\n ////////////////////\r\n\r\n function importLookupValues(lookups) {\r\n vm.processes = lookups.processes;\r\n\r\n if (hasAllStateParams) {\r\n vm.parameters = {\r\n processId: $state.params[stateParamsKeys.processId],\r\n startTime: createDateModel($state.params[stateParamsKeys.startTime]),\r\n endTime: createDateModel($state.params[stateParamsKeys.endTime])\r\n };\r\n\r\n } else {\r\n vm.parameters = {\r\n processId: lookups.processes && lookups.processes.length && lookups.processes[0].id,\r\n startTime: createDateModel(lookups.utcStartTime),\r\n endTime: createDateModel(lookups.utcEndTime)\r\n };\r\n }\r\n\r\n lastProcessIdUsedToLoadColumns = null;\r\n }\r\n\r\n ////////////////////\r\n\r\n function createDateModel(utcTime) {\r\n const localDateTime = convertUtcToFacilityTime(utcTime);\r\n return {\r\n date: localDateTime,\r\n formattedString: dateTimeService.formatAs.dateTime(localDateTime)\r\n };\r\n }\r\n\r\n function redirectBackToReports(ex) {\r\n if (ex.status !== 404) {\r\n return;\r\n }\r\n\r\n // The reportId does not exist - most likely this is because the user changed facilities.\r\n ex.handled = true;\r\n $state.go(`app.reporting`);\r\n }\r\n }\r\n\r\n function loadReportDataIfParametersSpecified() {\r\n if (!hasAllStateParams) {\r\n return;\r\n }\r\n\r\n const unsubscribe = $scope.$watch(\r\n () => vm.controls.dataGrid.grid,\r\n gridApi => {\r\n if (!gridApi) {\r\n return;\r\n }\r\n\r\n unsubscribe();\r\n updateGrid();\r\n });\r\n }\r\n }\r\n\r\n function revalidateStartAndEndTimeWhenParametersChange() {\r\n const watches = [\r\n () => vm.parameters.startTime && vm.parameters.startTime.date,\r\n () => vm.parameters.endTime && vm.parameters.endTime.date\r\n ];\r\n\r\n $scope.$watchGroup(watches, () => {\r\n vm.$form.startTime.$validate();\r\n vm.$form.endTime.$validate();\r\n });\r\n }\r\n\r\n function onRefreshed() {\r\n updateStateParams();\r\n updateGrid();\r\n }\r\n\r\n function updateStateParams() {\r\n const toParams = {\r\n [stateParamsKeys.processId]: vm.parameters.processId,\r\n [stateParamsKeys.startTime]: convertFacilityDateTimeToShortISOString(vm.parameters.startTime.date),\r\n [stateParamsKeys.endTime]: convertFacilityDateTimeToShortISOString(vm.parameters.endTime.date)\r\n };\r\n\r\n $state.go(`app.reporting.processData`, toParams, { notify: false });\r\n }\r\n\r\n function updateGrid() {\r\n // If the grid columns haven`t changed (i.e. the user hasn`t changed the process they want to\r\n // see the data for) then we only need to refresh the grid.\r\n if (vm.parameters.processId === lastProcessIdUsedToLoadColumns) {\r\n vm.controls.dataGrid.grid.refreshData();\r\n return;\r\n }\r\n\r\n // Otherwise we need to rebuild the grid with the columns for the new process id.\r\n const loadingColumnsPromise = reportsService.getProcessDataReportColumns(vm.parameters.processId).then(columns => {\r\n hasColumns = true;\r\n\r\n // Rebuilding the grid also causes the data to be refreshed.\r\n const gridColumns = buildGridColumns(columns);\r\n vm.controls.dataGrid.grid.rebuildGrid(gridColumns);\r\n\r\n lastProcessIdUsedToLoadColumns = vm.parameters.processId;\r\n });\r\n\r\n vm.busyLoading.addPromise(loadingColumnsPromise);\r\n\r\n ////////////////////\r\n\r\n function buildGridColumns(processVariables) {\r\n const timeColumn = {\r\n field: `key`,\r\n title: i18n.i10n(`app.ui.features.reporting.reports.processDataReport.date.label`),\r\n format: `{0:${dateTimeService.formats.kendo.dateTimeWithSeconds}}`,\r\n dataType: `date`\r\n };\r\n\r\n const columns = _.map(processVariables, processVariable => {\r\n return {\r\n field: `value[\"${processVariable.id}\"]`,\r\n title: processVariable.name,\r\n format: `{0:n1}`,\r\n dataType: `number`\r\n };\r\n });\r\n\r\n return [timeColumn, ...columns];\r\n }\r\n }\r\n\r\n function loadReportData(searchCriteria) {\r\n if (!hasColumns) {\r\n return $q.resolve();\r\n }\r\n\r\n return getParametersWithLocalTimes()\r\n .then(parameters => reportsService.getProcessDataReport(parameters.processId, parameters.localStartTime, parameters.localEndTime, searchCriteria))\r\n .then(report => {\r\n notifyIfNoDataAvailable(report && report.data);\r\n return report;\r\n })\r\n .catch(errorService.processError);\r\n }\r\n\r\n function exportReport() {\r\n getParametersWithLocalTimes()\r\n .then(getReportDataAsCsv)\r\n .then(notifyIfNoDataAvailable)\r\n .then(saveCsvFile)\r\n .catch(errorService.processError);\r\n\r\n ////////////////////\r\n\r\n function getReportDataAsCsv(parameters) {\r\n const searchCriteria = vm.controls.dataGrid.grid.getSearchCriteria();\r\n const getReportDataAsCsvPromise = reportsService.exportProcessDataReport(parameters.processId, parameters.localStartTime, parameters.localEndTime, searchCriteria);\r\n vm.busyLoading.addPromise(getReportDataAsCsvPromise);\r\n\r\n return getReportDataAsCsvPromise;\r\n }\r\n\r\n function saveCsvFile(csvData) {\r\n if (!csvData) {\r\n return;\r\n }\r\n\r\n const textBlob = new Blob([utf8EncodingHeader, csvData], { type: `text/csv;charset=UTF8` });\r\n const process = _.find(vm.processes, { id: vm.parameters.processId });\r\n\r\n const fileName = `${dateTimeService.formatAs.iso(vm.parameters.startTime.date)}-${dateTimeService.formatAs.iso(vm.parameters.endTime.date)}-${process.name}-ProcessDataReport.csv`;\r\n saveFile(textBlob, fileName);\r\n }\r\n }\r\n\r\n function getParametersWithLocalTimes() {\r\n if (!(vm.parameters.processId && vm.parameters.startTime.date && vm.parameters.endTime.date)) {\r\n return $q.reject();\r\n }\r\n\r\n const localStartTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.parameters.startTime.date);\r\n const localEndTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(vm.parameters.endTime.date);\r\n\r\n const parameters = {\r\n processId: vm.parameters.processId,\r\n localStartTime: localStartTime,\r\n localEndTime: localEndTime\r\n };\r\n\r\n return $q.resolve(parameters);\r\n }\r\n\r\n function convertUtcToFacilityTime(utcDateTimeString) {\r\n const localDateTime = new Date(utcDateTimeString);\r\n return timeZoneDateTime.convertDateTimeToFacilityTimeZone(localDateTime);\r\n }\r\n\r\n function convertFacilityDateTimeToShortISOString(dateTime) {\r\n const localDateTime = timeZoneDateTime.convertFacilityDateTimeToLocalTimeZone(dateTime);\r\n const iso = localDateTime.toISOString();\r\n\r\n // Chop off seconds and milliseconds\r\n return iso.replace(/:\\d{2}\\.\\d{3}Z$/, `Z`);\r\n }\r\n\r\n function notifyIfNoDataAvailable(data) {\r\n const hasData = data && data.length;\r\n if (hasData) {\r\n return data;\r\n }\r\n\r\n const warning = `app.ui.features.reporting.reports.processDataReport.warnings.noDataAvailable`;\r\n\r\n notifier.info(\r\n i18n.i10n(`${warning}.message`),\r\n i18n.i10n(`${warning}.heading`)\r\n );\r\n\r\n return data;\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.reporting`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`\r\n ];\r\n\r\n function appRun(routeHelper) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n state: `app.reporting`,\r\n url: `/reporting/{companyAlias}/{facilityAlias}`,\r\n views: {\r\n contentPanel: {\r\n templateUrl: `/App/ui/features/reporting/ContentPanel.html`,\r\n controller: `app.ui.features.reporting.ContentPanel as vm`\r\n }\r\n },\r\n data: {\r\n requiredAccessControl: `app.reports`\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/reporting/i18n/reporting`,\r\n `/App/ui/features/reporting/i18n/ContentPanel`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.reporting.processData`,\r\n url: `/processData/{reportId}?processId&start&end`,\r\n views: {\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/reporting/reports/ProcessDataReport.html`,\r\n controller: `app.ui.features.reporting.reports.ProcessDataReport as vm`\r\n }\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/reporting/i18n/reports/ProcessDataReport`\r\n ]\r\n }\r\n }\r\n ];\r\n }\r\n }\r\n})();\r\n","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.user`)\r\n .controller(`app.ui.features.user.profile.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `userTabs`\r\n ];\r\n function ContentPanel(userTabs) {\r\n const vm = this;\r\n\r\n vm.tabs = userTabs;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.user`)\r\n .controller(`app.ui.features.user.profile.PasswordTab`, PasswordTab);\r\n\r\n PasswordTab.$inject = [\r\n `$scope`,\r\n `$state`,\r\n `$q`,\r\n `promiseTracker`,\r\n `notifier`,\r\n `i18n`,\r\n `app.core.appSettings`,\r\n `app.core.services.userService`,\r\n `userTabs`\r\n ];\r\n function PasswordTab($scope, $state, $q, promiseTracker, notifier, i18n, appSettings, userService, userTabs) {\r\n const vm = this;\r\n vm.busySaving = promiseTracker();\r\n\r\n vm.save = save;\r\n vm.cancel = clearForm;\r\n\r\n activate();\r\n\r\n function activate() {\r\n $scope.$watch(() => vm.$form.$dirty, () => userTabs.password.isDirty = vm.$form.$dirty);\r\n }\r\n\r\n function save() {\r\n const savingPromise = updatePassword();\r\n savingPromise.then(saveSuccess);\r\n\r\n vm.busySaving.addPromise(savingPromise);\r\n\r\n function updatePassword() {\r\n return userService.updatePassword(appSettings.user.username, vm.currentPassword, vm.newPassword);\r\n }\r\n\r\n function saveSuccess() {\r\n clearForm();\r\n const title = i18n.i10n(`app.ui.features.user.profile.passwordTab.notifications.passwordUpdated.heading`);\r\n const message = i18n.i10n(`app.ui.features.user.profile.passwordTab.notifications.passwordUpdated.message`);\r\n notifier.info(message, title);\r\n }\r\n }\r\n\r\n function clearForm() {\r\n vm.$form.$setPristine();\r\n $state.go(`app.user.profile.password`, {}, { reload: true });\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.user`)\r\n .factory(`app.ui.features.user.profile.state`, stateFactory);\r\n\r\n stateFactory.$inject = [\r\n `$state`,\r\n `app.ui.core.controls.Tab`\r\n ];\r\n\r\n function stateFactory($state, Tab) {\r\n\r\n return {\r\n userTabs\r\n };\r\n\r\n //////////////////\r\n\r\n function userTabs() {\r\n return {\r\n details: new Tab(\r\n `app.ui.features.user.profile.contentPanel.tabs.profile.heading`,\r\n () => $state.href(`app.user.profile.details`),\r\n () => $state.$current.name === `app.user.profile.details`\r\n ),\r\n password: new Tab(\r\n `app.ui.features.user.profile.contentPanel.tabs.password.heading`,\r\n () => $state.href(`app.user.profile.password`),\r\n () => $state.$current.name === `app.user.profile.password`\r\n )\r\n };\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.user`)\r\n .controller(`app.ui.features.user.profile.UserDetailsTab`, UserDetailsTab);\r\n\r\n UserDetailsTab.$inject = [\r\n `$scope`,\r\n `promiseTracker`,\r\n `app.core.services.userService`,\r\n `userTabs`\r\n ];\r\n function UserDetailsTab($scope, promiseTracker, userService, userTabs) {\r\n const vm = this;\r\n\r\n vm.busySaving = promiseTracker();\r\n vm.busyLoading = promiseTracker();\r\n\r\n vm.profile = {};\r\n vm.save = save;\r\n vm.cancel = cancel;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n const loadPromise = loadUserDetails();\r\n vm.busyLoading.addPromise(loadPromise);\r\n\r\n $scope.$watch(() => vm.$form.$dirty, () => userTabs.details.isDirty = vm.$form.$dirty);\r\n $scope.$watch(()=> vm.busyLoading.active(), isBusyLoading => userTabs.details.isBusyLoading = isBusyLoading);\r\n }\r\n\r\n function loadUserDetails() {\r\n const loadPromise = userService.getUserDetails(true).then(profile => vm.profile = profile);\r\n return loadPromise;\r\n }\r\n\r\n function save() {\r\n const savingPromise = persistUserDetails();\r\n savingPromise.then(saveSuccess);\r\n vm.busySaving.addPromise(savingPromise);\r\n\r\n function persistUserDetails() {\r\n return userService.updateUserDetails(vm.profile);\r\n }\r\n\r\n function saveSuccess() {\r\n vm.$form.$setPristine();\r\n activate();\r\n }\r\n }\r\n\r\n function cancel() {\r\n activate();\r\n vm.$form.$setPristine();\r\n }\r\n }\r\n})();","(function() {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.user`)\r\n .run(appRun);\r\n\r\n appRun.$inject = [\r\n `routeHelper`,\r\n `app.ui.features.user.profile.state`\r\n ];\r\n\r\n function appRun(routeHelper, userState) {\r\n routeHelper.configureRoutes(getRoutes());\r\n\r\n function getRoutes() {\r\n return [\r\n {\r\n abstract: true,\r\n state: `app.user`,\r\n url: `/user`\r\n },\r\n {\r\n // provides details panel responsible for managing the tabs.\r\n abstract: true,\r\n state: `app.user.profile`,\r\n url: `/profile`,\r\n views: {\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/user/profile/ContentPanel.html`,\r\n controller: `app.ui.features.user.profile.ContentPanel as vm`\r\n }\r\n },\r\n resolve: {\r\n userTabs: userState.userTabs\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/user/profile/i18n/profile`\r\n ]\r\n }\r\n },\r\n {\r\n state: `app.user.profile.details`,\r\n url: `/details`,\r\n views: {\r\n 'tab@app.user.profile': {\r\n templateUrl: `/App/ui/features/user/profile/UserDetailsTab.html`,\r\n controller: `app.ui.features.user.profile.UserDetailsTab as vm`\r\n }\r\n }\r\n },\r\n {\r\n state: `app.user.profile.password`,\r\n url: `/password`,\r\n views: {\r\n 'tab@app.user.profile': {\r\n templateUrl: `/App/ui/features/user/profile/PasswordTab.html`,\r\n controller: `app.ui.features.user.profile.PasswordTab as vm`\r\n }\r\n }\r\n },\r\n {\r\n state: `app.user.settings`,\r\n url: `/settings`,\r\n views: {\r\n 'contentPanel@app': {\r\n templateUrl: `/App/ui/features/user/settings/ContentPanel.html`,\r\n controller: `app.ui.features.user.settings.ContentPanel as vm`\r\n }\r\n },\r\n settings: {\r\n i18n: [\r\n `/App/ui/features/user/settings/i18n/settings`\r\n ]\r\n }\r\n }\r\n ];\r\n }\r\n }\r\n})();","(function () {\r\n `use strict`;\r\n\r\n angular\r\n .module(`app.ui.features.user`)\r\n .controller(`app.ui.features.user.settings.ContentPanel`, ContentPanel);\r\n\r\n ContentPanel.$inject = [\r\n `$window`,\r\n `lodash`,\r\n `app.core.services.settingsService`,\r\n `app.core.appSettings`\r\n ];\r\n function ContentPanel($window, _, settingsService, appSettings) {\r\n const vm = this;\r\n vm.setLanguage = setLanguage;\r\n vm.appSettings = appSettings;\r\n\r\n activate();\r\n\r\n //////////////////\r\n\r\n function activate() {\r\n vm.languages = settingsService.getSupportedLanguages();\r\n\r\n settingsService.getSelectedLanguage().then(selectedLanguage => {\r\n vm.selectedLanguage = selectedLanguage;\r\n });\r\n }\r\n\r\n function setLanguage(language) {\r\n settingsService.setLanguage(language).then(() => {\r\n $window.location.reload(true);\r\n });\r\n }\r\n }\r\n})();"],"sourceRoot":"/dist/js/"}