1 2/*****************************/ 3/****** Report Manager *******/ 4/*****************************/ 5function Report() { 6 let this_ = this; 7 let actualThis = null; 8 9 let model = { 10 latestReportView: REPORT_VIEW.TABLE, 11 reportView: INITIAL_REPORT_VIEW, //current report view 12 } 13 14 this_.modelValid = null 15 this_.pageContainer = null 16 this_.reportControlsConfig = null 17 this_.reportConcreteName = null; //pageName 18 this_.reportsValidator = null; 19 20 this.regionCombobox = null; 21 this.targetCombobox = null; 22 this.ownerCombobox = null; 23 this.stationsAndMonitorsControl = null; 24 this.fromDatePicker = null; 25 this.toDatePicker = null; 26 this.fromTimePicker = null; 27 this.toTimePicker = null; 28 29 /** 30 * Overridable factory for the control configured as REPORT_CONTROL.stationsAndMonitors. 31 * Concrete reports receive the configured containers as jQuery objects, in configuration 32 * order, and return the report-specific station/monitor control instance. 33 */ 34 this.createStationsAndMonitorsControls = (a, b, c, d = null) => { } 35 36 /** 37 * Stores the API returned by ReportUtils.createAllStationsTreeViewControl for reports that 38 * opt in. Report implementations use it to apply or inspect the All state and to synchronize 39 * the checkbox after TreeView or programmatic station-selection changes. 40 * @type {Object|null} 41 */ 42 this.selectAllTreeViewStationsCheckboxControl = null; 43 44 /** 45 * Enables the reusable All Stations TreeView checkbox for a report. The default is false; 46 * supporting reports set it to true before controls are created. Reports that override the 47 * station selector are responsible for creating and assigning the shared control themselves. 48 * @type {boolean} 49 */ 50 this.useSelectAllTreeViewStationsCheckbox = false; 51 52 this.selectTimeBase = null; 53 this.selectUseFilter = null; 54 this.selectEditType = null; 55 this.selectDescription = null; 56 this.selectSharedTimebases = null; 57 58 this.selectProvince = null; 59 this.selectDistrict = null; 60 this.selectMunicipality = null; 61 this.selectIncidentType = null; 62 this.selectCalibrationType = null; 63 this.selectMetadataType = null; 64 65 this.textInput = null; 66 this.selectParameter = null; 67 68 const EURegulations = configManager.read(webConfigs.EURegulations); 69 this.stationTypeCombobox = null; 70 this.stationAreaTypeCombobox = null; 71 72 /*****************************/ 73 /*Report API data global vars*/ 74 let elemetBuilder 75 /*****************************/ 76 /*****************************/ 77 78 this.fromTimeBaseCombobox = null; 79 this.toTimeBaseCombobox = null; 80 81 this.typeCombobox = null 82 this.reportPresentationBtnGroup = null 83 this.groupIdComboBox = null; 84 this.prevReportPeriod = INITIAL_REPORT_PERIOD; 85 let m_CurReportPeriod = INITIAL_REPORT_PERIOD; 86 87 this.allDefinedTimeBases = null 88 this.inPopup = null 89 this.firstTime; 90 91 let isTimeEnding = configManager.read(webConfigs.TimeEnding) 92 93 let controls = null; 94 let authControls = null; 95 96 this.init = function (concreteManager, config) { 97 this_.firstTime = true; 98 actualThis = concreteManager; 99 this_.allDefinedTimeBases = SiteUtils.getAllDefinedTimeBases(); 100 this_.inPopup = config.popup; 101 this_.pageContainer = config.pageContainer; 102 this_.reportConcreteName = config.concreteName; 103 controls = config.controls; 104 actualThis.createControls(config.controls) 105 actualThis.populateControls(); 106 this_.setReportsValidator(); 107 actualThis.initEvents(); 108 109 if (config.hasOwnProperty('authControls')) { 110 authControls = config.authControls; 111 } 112 } 113 114 this.filterAvailableToTimebases = function (timebases, fromTimebase) { 115 return timebases; 116 } 117 118 this.filterAvailableFromTimebases = function (timebases) { 119 return timebases; 120 } 121
122 this.createControls = function (controls) { 123 $.each(controls, function (controlName, controlSelector) { 124 125 createControl(parseInt(controlName), controlSelector) 126 }); 127 128 function createControl(controlName, controlSelector) { 129 switch (controlName) { 130 case REPORT_CONTROL.target: 131 actualThis.createTargetComboBox($(controlSelector)); 132 break; 133 case REPORT_CONTROL.regions: 134 actualThis.createRegionComboBox($(controlSelector)) 135 break; 136 case REPORT_CONTROL.owner: 137 actualThis.createOwnerComboBox($(controlSelector)) 138 break; 139 case REPORT_CONTROL.fromDate: 140 actualThis.createFromDatePicker($(controlSelector)) 141 break; 142 case REPORT_CONTROL.fromTime: 143 actualThis.createFromTimePicker($(controlSelector)) 144 break; 145 case REPORT_CONTROL.toDate: 146 actualThis.createToDatePicker($(controlSelector)) 147 break; 148 case REPORT_CONTROL.toTime: 149 actualThis.createToTimePicker($(controlSelector)) 150 break; 151 case REPORT_CONTROL.fromTimebase: 152 actualThis.createFromTimeBaseComboBox($(controlSelector)) 153 break; 154 case REPORT_CONTROL.toTimebase: 155 actualThis.createToTimeBaseComboBox($(controlSelector)) 156 break; 157 case REPORT_CONTROL.type: 158 actualThis.createTypeCombobox($(controlSelector)) 159 break; 160 case REPORT_CONTROL.period: 161 actualThis.createReportPeriod($(controlSelector)) 162 break; 163 case REPORT_CONTROL.presentation: 164 actualThis.createReportPresentation($(controlSelector)); 165 break; 166 case REPORT_CONTROL.reducePresentation: 167 actualThis.createReducedReportPresentation($(controlSelector)) 168 break; 169 case REPORT_CONTROL.roseType: 170 actualThis.createRoseType($(controlSelector)) 171 break; 172 case REPORT_CONTROL.roseSectors: 173 actualThis.createRoseSectors($(controlSelector[0]), $(controlSelector[1]), $(controlSelector[2]), $(controlSelector[3]), $(controlSelector[4])) 174 break; 175 case REPORT_CONTROL.stations: 176 this_.stationsAndMonitorsControl = actualThis.createStationsControl($(controlSelector[0]), $(controlSelector[1])) 177 break; 178 case REPORT_CONTROL.stationsAndMonitors: 179 this_.stationsAndMonitorsControl = 180 actualThis.createStationsAndMonitorsControls(...controlSelector.map(control => $(control))); 181 break; 182 case REPORT_CONTROL.groupID: 183 actualThis.populateGroupsComboBox($(controlSelector)) 184 //actualThis.createGroupIdComboBox($(controlSelector)); 185 break; 186 case REPORT_CONTROL.stationsAndWindMonitors: 187 this_.stationsAndMonitorsControl = actualThis.createStationsAndWindMonitorsControls($(controlSelector[0]), $(controlSelector[1]), $(controlSelector[2]), $(controlSelector[3])) 188 break; 189 case REPORT_CONTROL.timebase: 190 actualThis.createTimebaseControl(); 191 break; 192 case REPORT_CONTROL.useFilter: 193 actualThis.createUseFilterControl(); 194 break; 195 case REPORT_CONTROL.editType: 196 actualThis.createEditTypeControl(); 197 break; 198 case REPORT_CONTROL.description: 199 actualThis.createDescriptionControl(); 200 break; 201 case REPORT_CONTROL.sharedTimebases: 202 actualThis.createSharedTimebasesControl(); 203 break; 204 case REPORT_CONTROL.windBlowDirection: 205 actualThis.creatWindDirectionControl($(controlSelector)); 206 break; 207 case REPORT_CONTROL.province: 208 actualThis.createProvinceControl($(controlSelector)); 209 break; 210 case REPORT_CONTROL.district: 211 actualThis.createDistrictControl($(controlSelector)); 212 break; 213 case REPORT_CONTROL.municipality: 214 actualThis.createMunicipalityControl($(controlSelector)); 215 break; 216 case REPORT_CONTROL.incidentType: 217 actualThis.createIncidentTypeControl($(controlSelector)); 218 break; 219 case REPORT_CONTROL.textInput: 220 actualThis.createTextInputControl($(controlSelector)); 221 break; 222 case REPORT_CONTROL.calibrationType: 223 actualThis.createCalibrationTypeControl(); 224 break; 225 case REPORT_CONTROL.metadataType: 226 actualThis.createMetadataDropDown($(controlSelector)); 227 break; 228 case REPORT_CONTROL.parameters: 229 actualThis.createParametersControl(); 230 break; 231 case REPORT_CONTROL.stationType: 232 actualThis.createStationTypeControl($(controlSelector)); 233 break; 234 case REPORT_CONTROL.stationAreaType: 235 actualThis.createStationAreaTypeControl($(controlSelector)); 236 break; 237 } 238 } 239 } 240 241 this.populateControls = function () { 242 this_.setFromTimeBaseComboboxDs(this_.allDefinedTimeBases) 243 this_.setToTimeBaseComboboxDs(this_.allDefinedTimeBases) 244 245 this_.populateTargetCombobox() 246 this_.populateRegionComboboxByTarget() 247 this_.populateOwnersComboBox() 248 249 if (EURegulations) {
250 initEUStationTypeWhenReady(); 251 initEUStationAreaTypeWhenReady(); 252 } 253 254 this_.populateStationsAndMonitorsControl() 255 this_.setDateTimePickersByReportPeriod() 256 this_.firstTime = false; 257 } 258 259 this.initEvents = function () { 260 261 if (this_.inPopup) { 262 $(".closeReportFormBtn").click(function () { 263 PopupManager.closeReportForm() 264 }); 265 } 266 267 $(this_.pageContainer).find("#showResultsBtn").click(function () { 268 actionBtnClicked(); 269 }); 270 } 271 272 //like pure functions 273 this.showResult = function () { } 274 this.exportToExcel = function () { } 275 this.createReportTitle = function () { } 276 this.getStationsFilter = function () { return {} } 277 this.setRawData = function () { return {} } 278 279 this.getReportName = function () { 280 return actualThis.reportName 281 } 282 283 this.getReportConcreteName = function () { 284 return actualThis.reportConcreteName 285 } 286 287 // Controls Creators 288 /** 289 * Creates the target multiselect. 290 * The widget displays translated labels from `displayName` 291 * while keeping the original `name` field intact for filtering logic. 292 */ 293 this.createTargetComboBox = function (container) { 294 295 let extensionConfig = { 296 dataTextField: "displayName", 297 dataValueField: "id", 298 } 299 300 extensionConfig.select = function (e) { 301 this_.targetCombobox._prevValues = e.sender.value() || []; 302 }; 303 304 let targetCombobox = KendoFactory.createMultiSelect(container, undefined, undefined, onTargetChanged, undefined, extensionConfig, "targetCombobox"); 305 306 this_.targetCombobox = $(targetCombobox).data("kendoMultiSelect"); 307 this_.targetCombobox._prevValues = []; 308 return targetCombobox; 309 } 310 /** 311 * createGroupIdComboBox 312 * @param {any} groupContainer 313 */ 314 this.createGroupIdComboBox = (groupContainer) => { 315 let extensionConfig = { 316 dataTextField: "GRD_Name", 317 dataValueField: "GRD_GroupCode", 318 } 319 320 let params = { isDropDown: true } 321 var combobox = new kCombobox(groupContainer, extensionConfig, params); 322 $(".k-list-filter").find("input").attr("placeholder", SiteUtils.translate("select..")); 323 return combobox 324 } 325 326 327 /** 328 * Creates the region multiselect. 329 * The selected value is still the stable `id`, and the visible text comes from 330 * `displayName` so region names can be translated without affecting comparisons. 331 */ 332 this.createRegionComboBox = function (container) { 333 let extensionConfig = { 334 dataTextField: "displayName", 335 dataValueField: "id", 336 } 337 338 extensionConfig.select = function (e) { 339 this_.regionCombobox._prevValues = e.sender.value() || []; 340 }; 341 342 let regionCombobox = KendoFactory.createMultiSelect(container, undefined, undefined, onRegionChanged, undefined, extensionConfig); 343 this_.regionCombobox = $(regionCombobox).data("kendoMultiSelect"); 344 this_.regionCombobox._prevValues = []; 345 } 346 347 /** 348 * Creates the owner multiselect. 349 * Owner filtering downstream relies on the original `name` from the datasource, 350 * so the UI must render from `displayName` instead of mutating `name`. 351 */ 352 this.createOwnerComboBox = function (container, onChange) { 353 354 let extensionConfig = { 355 dataTextField: "displayName", 356 dataValueField: "id", 357 } 358 359 const onOwnerChange = function (ownersAfterChange) { 360 const ownersBeforeChange = this_.ownerCombobox._prevValues; 361 applyStationFiltersAllExclusiveSelection(this_.ownerCombobox, ownersAfterChange, ownersBeforeChange); 362 refreshDependentFilters(); 363 }; 364 365 extensionConfig.select = function (e) { 366 this_.ownerCombobox._prevValues = e.sender.value() || []; 367 }; 368 369 let regionCombobox = KendoFactory.createMultiSelect(container, undefined, undefined, onOwnerChange, undefined, extensionConfig); 370 this_.ownerCombobox = $(regionCombobox).data("kendoMultiSelect"); 371 this_.ownerCombobox._prevValues = []; 372 }; 373 374 /** 375 * Enforces exclusive behavior for the "All" option (-1) 376 * in Station Filters MultiSelect controls. 377 * 378 * Rules: 379 * - If nothing is selected â selects "All". 380 * - If "All" is selected with other values: 381 * ⢠If "All" was previously selected â removes "All". 382 * ⢠Otherwise â keeps only "All". 383 * - Otherwise â keeps default behavior. 384 */ 385 function applyStationFiltersAllExclusiveSelection(multiSelect, valuesAfterChange, valuesBeforeChange) { 386 if (!multiSelect) return; 387 const ALL_VALUE = "-1" 388 const before = (valuesBeforeChange ?? []).map(v => String(v));
389 const after = (valuesAfterChange ?? []).map(v => String(v)); 390 391 const beforeHadAll = before.includes(ALL_VALUE); 392 const afterHasAll = after.includes(ALL_VALUE); 393 394 if (after.length === 0) { 395 multiSelect.value([ALL_VALUE]); 396 return; 397 } 398 399 if (afterHasAll && after.length > 1) { 400 if (beforeHadAll) { 401 multiSelect.value(after.filter(v => v !== ALL_VALUE)); 402 return; 403 } 404 multiSelect.value([ALL_VALUE]); 405 return; 406 } 407 } 408 409 this.createTypeCombobox = function (container, config) { 410 if (config == null) { 411 let ds = SiteUtils.getTranslatedObject(REPORT_TYPE); 412 ds = filterNotForDisplay(ds, webConfigs.NotForDisplayTypes); 413 config = { 414 change: onTypeChanged, 415 value: INITIAL_REPORT_TYPE, 416 dataSource: ds 417 } 418 } 419 config.filter = "none"; 420 421 let params = { isDropDown: true } 422 423 this_.typeCombobox = new kCombobox(container, config, params) 424 425 // not set default value for Pollutant/Wind Rose report 426 if (actualThis.reportName !== REPORTS.pollutantRose) { 427 setDefaultValueByConfig(this_.typeCombobox, webConfigs.DefaultType, config.dataSource); 428 } 429 } 430 431 this.createFromTimePicker = function (container) { 432 var isToTime = false; 433 this_.fromTimePicker = KendoFactory.timepicker(container, true, (val) => onChangeTimePicker(val, isToTime), () => onClickTimePicker(isToTime)); 434 } 435 436 this.createToTimePicker = function (container) { 437 var isToTime = true; 438 this_.toTimePicker = KendoFactory.timepicker(container, true, (val) => onChangeTimePicker(val, isToTime), () => onClickTimePicker(isToTime)); 439 } 440 441 function onClickTimePicker(isToTime) { 442 var display; 443 if (isToTime) { 444 display = $("#toTimeTimePicker_timeview").closest(".k-animation-container").css('display'); 445 display == 'none' || JsUtils.isEmpty(display) ? this_.toTimePicker.open() : this_.toTimePicker.close(); 446 } else { 447 display = $("#fromTimeTimePicker_timeview").closest(".k-animation-container").css('display'); 448 display == 'none' || JsUtils.isEmpty(display) ? this_.fromTimePicker.open() : this_.fromTimePicker.close(); 449 } 450 } 451 452 function onChangeTimePicker(val, isToTime) { 453 if (isTimeEnding) { 454 var timeList = isToTime ? this_.toTimePicker.timeView.list : this_.fromTimePicker.timeView.list; 455 if (val == '24:00') { 456 timeList.find("li").removeClass("k-selected"); 457 timeList.find("li:last").addClass("k-selected"); 458 isToTime ? this_.toTimePicker.value(null) : this_.fromTimePicker.value(null); 459 isToTime ? this_.toTimePicker.element.val(val) : this_.fromTimePicker.element.val(val); 460 } else { 461 timeList.find("li:last").removeClass("k-selected"); 462 } 463 } 464 } 465 466 this.createFromDatePicker = function (container, initialDate) { 467 let config = { 468 change: onFromDateChange, 469 value: initialDate, 470 max: new Date(), 471 }; 472 473 this_.fromDatePicker = KendoFactory.datepicker(container, config) 474 } 475 476 477 /** 478 * set the report "from" date picker element from an external source 479 * @param {kendoObject} inputElement 480 */ 481 this.setFromDatePickerElement = function (inputElement) { 482 this_.fromDatePicker = inputElement 483 } 484 485 this.createToDatePicker = function (container) { 486 let config = { 487 change: onToDateChange, 488 }; 489 490 this_.toDatePicker = KendoFactory.datepicker(container, config) 491 } 492 493 /** 494 * set the report "to" date picker element from an external source 495 * @param {kendoObject} inputElement 496 */ 497 this.setToDatePickerElement = function (inputElement) { 498 this_.toDatePicker = inputElement 499 } 500 501 this.createReportPeriod = function (container) { 502 503 $(container).kendoButtonGroup({ 504 index: 0 505 }); 506 507 // register to event handlers 508 $("#selectReportPeriod .reportPeriod").click(function () { 509 m_CurReportPeriod = $(this).attr("period-type") 510 onReportPeriodChanged(m_CurReportPeriod) 511 }); 512 513 } 514 515 /** 516 * receive a list of report view types and assemble the html required to build the view selector 517 * @param {number[]} config 518 * @returns {string} a string representation of html 519 */ 520 function generatePresentationHtmlByConfig(config) { 521 const reportViewNames = { 522 [REPORT_VIEW.TABLE]: "Table", 523 [REPORT_VIEW.GRAPH]: "Graph", 524 [REPORT_VIEW.EXCEL]: "Excel", 525 [REPORT_VIEW.HORIZONTAL_TABLE]: "Horizontal Table", 526 [REPORT_VIEW.MAP]: "Map", 527 [REPORT_VIEW.PDF]: "PDF" 528 } 529 let innerHtml = ""; 530 config.forEach((viewType) => { 531 innerHtml += '<li class=reportPresentation viewType=' + viewType + ' >' + 532 SiteUtils.translate(reportViewNames[viewType]) + 533 '</li>' 534 535 }) 536 return innerHtml; 537 } 538 539 this.createReportPresentation = function (container, onChanged, presentationConfig = actualThis.INITIAL_REPORT_PRESENTATION_CONFIG) { 540 let innerHtml = generatePresentationHtmlByConfig(presentationConfig); 541 $(container).append(innerHtml) 542 543 this_.reportPresentationBtnGroup = $(container).kendoButtonGroup({ 544 index: presentationConfig.indexOf(this_.getReportView()) 545 }).data("kendoButtonGroup"); 546 547 $("#selectReportPresentation .reportPresentation").click(function () { 548
549 let curView = parseInt($(this).attr("viewType")) 550 this_.setReportView(curView); 551 552 if (onChanged != null) { 553 onChanged(curView) 554 } 555 }); 556 } 557 558 /** 559 * Updates the state (enabled/disabled) of report presentation buttons based on the allowed views, 560 * and ensures that a valid view is selected. If the currently selected view is not in the allowed list, 561 * the first available allowed view will be selected instead. 562 * @function 563 * @param {number[]} allowedViews - An array of allowed view types, each corresponding to a value from the `REPORT_VIEW` enum. 564 * Example: [REPORT_VIEW.TABLE, REPORT_VIEW.SUMMARY, REPORT_VIEW.PDF] 565 * @example 566 * updateReportPresentationButtons([REPORT_VIEW.TABLE, REPORT_VIEW.SUMMARY]); 567 * 568 * @see REPORT_VIEW for possible view type constants. 569 */ 570 this.updateReportPresentationButtons = function (allowedViews, mode = "disable") { 571 const buttonGroup = this_.reportPresentationBtnGroup; 572 const buttons = buttonGroup ?._buttons || []; 573 574 const toggleClassName = mode == "hide" ? "hidden" : "disabled"; 575 576 buttons.forEach(function (btn) { 577 const btnElement = $(btn.element); 578 const viewType = parseInt(btnElement.attr("viewtype")); 579 const isEnabled = allowedViews.includes(viewType); 580 581 btnElement.toggleClass(toggleClassName, !isEnabled); 582 }); 583 584 const selectedIndex = buttonGroup.selectedIndices ?.[0]; 585 const selectedBtn = buttons[selectedIndex]; 586 const selectedViewType = selectedBtn ? parseInt($(selectedBtn.element).attr("viewtype")) : null; 587 this_.setReportView(selectedViewType); 588 589 if (!allowedViews.includes(selectedViewType)) { 590 const firstAllowedIndex = buttons.findIndex(btn => allowedViews.includes(parseInt($(btn.element).attr("viewtype")))); 591 if (firstAllowedIndex >= 0) { 592 buttonGroup.select(firstAllowedIndex); 593 this_.setReportView(parseInt($(buttons[firstAllowedIndex].element).attr("viewtype"))); 594 } 595 } 596 } 597 598 /** 599 * createReducedReportPresentation 600 * @param {any} container 601 * @param {any} onChanged 602 */ 603 this.createReducedReportPresentation = (container, onChanged) => { 604 let innerHtml = '<li class=reportPresentation viewType=' + REPORT_VIEW.TABLE + ' >' + 605 SiteUtils.translate("Table") + 606 '</li>' + 607 '<li class=reportPresentation viewType=' + REPORT_VIEW.EXCEL + ' >' + 608 SiteUtils.translate("Excel") + 609 '</li>'; 610 $(container).append(innerHtml) 611 this_.reportPresentationBtnGroup = $(container).kendoButtonGroup({ 612 index: this_.getReportView() 613 }).data("kendoButtonGroup"); 614 615 $("#selectReportPresentation .reportPresentation").click(function () { 616 617 let curView = parseInt($(this).attr("viewType")) 618 this_.setReportView(curView); 619 620 if (onChanged != null) { 621 onChanged(curView) 622 } 623 }); 624 625 } 626 627 this.createFromTimeBaseComboBox = function (container) { 628 629 let extensionConfig = { 630 change: onFromTimeBaseChanged, 631 filter: "none" 632 } 633 634 let params = { isDropDown: true } 635 636 this_.fromTimeBaseCombobox = new kCombobox(container, extensionConfig, params) 637 } 638 639 this.createToTimeBaseComboBox = function (container) { 640 641 let extensionConfig = { 642 change: onToTimeBaseChanged, 643 filter: "none" 644 } 645 646 let params = { isDropDown: true } 647 648 this_.toTimeBaseCombobox = new kCombobox(container, extensionConfig, params) 649 } 650 651 652 /** 653 * Create the time base control. 654 */ 655 this.createTimebaseControl = () => { 656 this_.selectTimeBase = new SelectTimeBase(); 657 let extensionConfig = { 658 change: setTimePickersByTimebase, 659 filter: "none" 660 } 661 662 this_.selectTimeBase.init(extensionConfig); 663 } 664 665 /** 666 * Create the use filter control. 667 */ 668 this.createUseFilterControl = () => { 669 this_.selectUseFilter = new SelectUseFilter(); 670 671 this_.selectUseFilter.init(); 672 } 673 674 /** 675 * Create the edit type control. 676 */ 677 this.createEditTypeControl = () => { 678 this_.selectEditType = new SelectEditType(); 679 680 this_.selectEditType.init(); 681 } 682 683 /** 684 * Create the description control. 685 */ 686 this.createDescriptionControl = () => { 687 this_.selectDescription = new SelectDescription(); 688 689 this_.selectDescription.init(); 690 } 691 692 /** 693 * Create the shared timebases control 694 */ 695 this.createSharedTimebasesControl = () => { 696 this_.selectSharedTimebases = new SelectSharedTimebases(); 697 698 this_.selectSharedTimebases.init(); 699 } 700 701 /** 702 * Create the province control. 703 */ 704 this.createProvinceControl = () => { 705 this_.selectProvince = new SelectProvince(); 706 707 let extensionConfig = { 708 change: onProvinceChanged, 709 filter: "contains", 710 dataValueField: "ID", 711 dataTextField: "Name", 712 } 713 714 this_.selectProvince.init(extensionConfig); 715 } 716 717 /** 718 * Create the District control. 719 */ 720 this.createDistrictControl = () => { 721 this_.selectDistrict = new SelectDistrict(); 722 723 let extensionConfig = { 724 change: onDistrictChanged, 725 filter: "contains", 726 dataValueField: "ID", 727 dataTextField: "Name", 728 } 729 730 this_.selectDistrict.init(extensionConfig); 731 } 732 733 /** 734 * Create the Municipality control. 735 */ 736 this.createMunicipalityControl = () => { 737 this_.selectMunicipality = new SelectMunicipality(); 738 739 let extensionConfig = { 740 filter: "contains", 741 dataValueField: "ID", 742 dataTextField: "Name", 743 } 744 745 this_.selectMunicipality.init(extensionConfig); 746 } 747 748 /** 749 * Create the IncidentType control. 750 */ 751 this.createIncidentTypeControl = () => { 752 this_.selectIncidentType = new SelectIncidentType(); 753 754 let extensionConfig = { 755 filter: "contains", 756 dataValueField: "ID", 757 dataTextField: "Name", 758 } 759 760 this_.selectIncidentType.init(extensionConfig); 761 } 762 763 /** 764 * Create the CalibrationType control. 765 */ 766 this.createCalibrationTypeControl = () => { 767 this_.selectCalibrationType = new SelectCalibrationType(); 768 769 this_.selectCalibrationType.init(); 770 } 771 772 /** 773 * Create the Metadata DropDown 774 */ 775 this.createMetadataDropDown = function () { 776 this_.selectMetadataType = new SelectMetadataType(); 777 778 let extensionConfig = { 779 dataTextField: "name", 780 dataValueField: "id", 781 filter: "none", 782 change: function () { 783 this_.stationsAndMonitorsControl.populateControls() 784 } 785 } 786 787 this_.selectMetadataType.init(extensionConfig); 788 } 789 790 791 /** 792 * Create the Parameters options 793 */ 794 this.createParametersControl = function () { 795 this_.selectParameter = new SelectParameter(); 796 } 797 798 /** 799 * Create the Text Input control. 800 */ 801 this.createTextInputControl = () => { 802 this_.textInput = new TextInput(); 803 } 804 805 /** 806 * Creates the Station Type multiselect used in the EU regulations flow. 807 * Stores the previous selection so the "All" option can be handled exclusively on change. 808 * @param {JQuery} container 809 */ 810 this.createStationTypeControl = (container) => { 811 let extensionConfig = { 812 dataTextField: "displayName", 813 dataValueField: "id", 814 } 815 816 extensionConfig.select = function (e) { 817 this_.stationTypeCombobox._prevValues = e.sender.value() || []; 818 }; 819 820 let stationTypeCombobox = KendoFactory.createMultiSelect(container, undefined, undefined, onStationTypeChanged, undefined, extensionConfig); 821 this_.stationTypeCombobox = $(stationTypeCombobox).data("kendoMultiSelect"); 822 this_.stationTypeCombobox._prevValues = []; 823 } 824 825 /** 826 * Creates the Station Area multiselect used in the EU regulations flow. 827 * Stores the previous selection so the "All" option can be handled exclusively on change. 828 * @param {JQuery} container 829 */ 830 this.createStationAreaTypeControl = (container) => { 831 let extensionConfig = { 832 dataTextField: "displayName", 833 dataValueField: "id", 834 } 835 836 extensionConfig.select = function (e) { 837 this_.stationAreaTypeCombobox._prevValues = e.sender.value() || []; 838 }; 839 840 let stationAreaTypeCombobox = KendoFactory.createMultiSelect(container, undefined, undefined, onStationAreaTypeChanged, undefined, extensionConfig); 841 this_.stationAreaTypeCombobox = $(stationAreaTypeCombobox).data("kendoMultiSelect"); 842 this_.stationAreaTypeCombobox._prevValues = []; 843 844 } 845 846 // Controls Populators 847 /** 848 * Loads the target datasource for reports. 849 * Each item gets a translated `displayName`, but the raw `name` is preserved 850 * because later filters compare against the original non-translated value. 851 */ 852 this.populateTargetCombobox = function () { 853 let stationsFilter = actualThis.getStationsFilter(); 854 let relevantTargets = dataManager.getTargetsBy(stationsFilter); 855 relevantTargets = filterNotForDisplay(relevantTargets, webConfigs.NotForDisplayTargets); 856 relevantTargets = buildDisplayItems(relevantTargets); 857 this_.targetCombobox.setDataSource(relevantTargets); 858 859 setDefaultValueByConfig(this_.targetCombobox, webConfigs.DefaultTarget, relevantTargets); 860 } 861 862 /** 863 * Rebuilds the region datasource after target changes. 864 * Regions follow the same display/value split: translated `displayName` for UI, 865 * original `name` for any business logic that consumes datasource items. 866 */ 867 this.populateRegionComboboxByTarget = function () { 868 let stationsFilter = { 869 target: this_.getTarget() 870 }; 871 872 $.extend(stationsFilter, actualThis.getStationsFilter()) 873 let relevantRegions = dataManager.getRegionsBy(stationsFilter); 874 relevantRegions = filterNotForDisplay(relevantRegions, webConfigs.NotForDisplayRegions); 875 relevantRegions = buildDisplayItems(relevantRegions); 876 this_.regionCombobox.setDataSource(relevantRegions); 877 878 setDefaultValueByConfig(this_.regionCombobox, webConfigs.DefaultRegion, relevantRegions); 879 } 880 881 /** 882 * Rebuilds the owner datasource from the active upstream filters. 883 * The dropdown renders `displayName`, while report filtering continues to use 884 * the raw `name` returned by the datasource. 885 */ 886 this.populateOwnersComboBox = function () { 887 let stationsFilter = { 888 target: this_.getTarget(), 889 regionId: this_.getRegion() 890 }; 891 892 $.extend(stationsFilter, actualThis.getStationsFilter()); 893 let relevantOwners = dataManager.getOwnersBy(stationsFilter); 894 relevantOwners = filterNotForDisplay(relevantOwners, webConfigs.NotForDisplayOwners); 895 relevantOwners = buildDisplayItems(relevantOwners); 896 this_.ownerCombobox.setDataSource(relevantOwners); 897 898 setDefaultValueByConfig(this_.ownerCombobox, webConfigs.DefaultOwner, relevantOwners); 899 } 900 901 this.populateStationsAndMonitorsControl = function () { 902 if (this_.stationsAndMonitorsControl != null) { 903 this_.stationsAndMonitorsControl.populateControls() 904 } 905 } 906 907 /** 908 * Rebuilds the Station Type data source from the stations that match the upstream filters. 909 * This dropdown is downstream of Target, Region and Owner and must not filter itself. 910 */ 911 this.populateTypeOfStationCombobox = function () { 912 if (!EURegulations || !this_.stationTypeCombobox || !EUConfigurationManager.isStationTypeLoaded) { 913 return; 914 } 915 916 let stationsFilter = { 917 target: this_.getTarget(), 918 regionId: this_.getRegion(), 919 owner: this_.getOwner(), 920 }; 921 922 $.extend(stationsFilter, actualThis.getStationsFilter()); 923 let relevantStationTypes = dataManager.getStationTypesBy(stationsFilter); 924 relevantStationTypes = buildDisplayItems(relevantStationTypes); 925 this_.stationTypeCombobox.setDataSource(relevantStationTypes); 926 setDefaultValueByConfig(this_.stationTypeCombobox, '', relevantStationTypes); 927 }; 928 929 /** 930 * Rebuilds the Station Area data source from the stations that match the active filters. 931 * Station Area depends on the selected Station Type, so the current station type is included 932 * while the area dropdown itself is excluded inside the data-manager lookup. 933 */ 934 this.populateTypeOfStationAreaCombobox = function () { 935 if (!EURegulations || !this_.stationAreaTypeCombobox || !EUConfigurationManager.isStationAreaTypeLoaded) { 936 return; 937 } 938 939 let stationsFilter = { 940 target: this_.getTarget(), 941 regionId: this_.getRegion(), 942 owner: this_.getOwner(), 943 stationType: this_.getStationType() 944 }; 945 946 $.extend(stationsFilter, actualThis.getStationsFilter()); 947 let relevantStationAreaTypes = dataManager.getStationAreaTypesBy(stationsFilter); 948 relevantStationAreaTypes = buildDisplayItems(relevantStationAreaTypes); 949 this_.stationAreaTypeCombobox.setDataSource(relevantStationAreaTypes); 950 setDefaultValueByConfig(this_.stationAreaTypeCombobox, '', relevantStationAreaTypes); 951 } 952 953 /** 954 * Enables and populates Station Type as soon as its EU master list is ready. 955 * The handler is removed after the first completion to avoid duplicate refreshes. 956 */
957 function initEUStationTypeWhenReady() { 958 if (!this_.stationTypeCombobox) { 959 return; 960 } 961 962 EventBus.off(EventBus.EventNames.STATION_TYPE_DATA_LOADED, onStationTypeDataLoaded); 963 EventBus.off(EventBus.EventNames.STATION_TYPE_DATA_FAILED, onStationTypeDataFailed); 964 965 if (EUConfigurationManager.isStationTypeLoaded) { 966 this_.stationTypeCombobox.enable(true); 967 this_.populateTypeOfStationCombobox(); 968 return; 969 } 970 971 if (EUConfigurationManager.isStationTypeLoadFailed) { 972 this_.stationTypeCombobox.enable(false); 973 return; 974 } 975 976 this_.stationTypeCombobox.enable(false); 977 EventBus.on(EventBus.EventNames.STATION_TYPE_DATA_LOADED, onStationTypeDataLoaded); 978 EventBus.on(EventBus.EventNames.STATION_TYPE_DATA_FAILED, onStationTypeDataFailed); 979 } 980 981 /** 982 * Enables and populates Station Area as soon as its EU master list is ready. 983 * This keeps the two EU dropdowns independent while preserving the cascade logic. 984 */
985 function initEUStationAreaTypeWhenReady() { 986 if (!this_.stationAreaTypeCombobox) { 987 return; 988 } 989 990 EventBus.off(EventBus.EventNames.STATION_AREA_TYPE_DATA_LOADED, onStationAreaTypeDataLoaded); 991 EventBus.off(EventBus.EventNames.STATION_AREA_TYPE_DATA_FAILED, onStationAreaTypeDataFailed); 992 993 if (EUConfigurationManager.isStationAreaTypeLoaded) { 994 this_.stationAreaTypeCombobox.enable(true); 995 this_.populateTypeOfStationAreaCombobox(); 996 return; 997 } 998 999 if (EUConfigurationManager.isStationAreaTypeLoadFailed) { 1000 this_.stationAreaTypeCombobox.enable(false); 1001 return; 1002 } 1003 1004 this_.stationAreaTypeCombobox.enable(false); 1005 EventBus.on(EventBus.EventNames.STATION_AREA_TYPE_DATA_LOADED, onStationAreaTypeDataLoaded); 1006 EventBus.on(EventBus.EventNames.STATION_AREA_TYPE_DATA_FAILED, onStationAreaTypeDataFailed); 1007 } 1008 1009 /** 1010 * Handles the Station Type lookup-ready event. 1011 * Re-enables the dropdown, removes the one-time listeners, 1012 * and rebuilds the datasource from the current upstream filters. 1013 */ 1014 function onStationTypeDataLoaded() { 1015 EventBus.off(EventBus.EventNames.STATION_TYPE_DATA_LOADED, onStationTypeDataLoaded); 1016 EventBus.off(EventBus.EventNames.STATION_TYPE_DATA_FAILED, onStationTypeDataFailed); 1017 1018 if (this_.stationTypeCombobox) { 1019 this_.stationTypeCombobox.enable(true); 1020 this_.populateTypeOfStationCombobox(); 1021 } 1022 } 1023 1024 /** 1025 * Handles a Station Type lookup-load failure. 1026 * The dropdown stays disabled because the EU master list is unavailable. 1027 */ 1028 function onStationTypeDataFailed() { 1029 EventBus.off(EventBus.EventNames.STATION_TYPE_DATA_LOADED, onStationTypeDataLoaded); 1030 EventBus.off(EventBus.EventNames.STATION_TYPE_DATA_FAILED, onStationTypeDataFailed); 1031 1032 if (this_.stationTypeCombobox) { 1033 this_.stationTypeCombobox.enable(false); 1034 } 1035 } 1036 1037 /** 1038 * Handles the Station Area lookup-ready event. 1039 * Re-enables the dropdown, removes the one-time listeners, 1040 * and rebuilds the datasource from the current active filters. 1041 */ 1042 function onStationAreaTypeDataLoaded() { 1043 EventBus.off(EventBus.EventNames.STATION_AREA_TYPE_DATA_LOADED, onStationAreaTypeDataLoaded); 1044 EventBus.off(EventBus.EventNames.STATION_AREA_TYPE_DATA_FAILED, onStationAreaTypeDataFailed); 1045 1046 if (this_.stationAreaTypeCombobox) { 1047 this_.stationAreaTypeCombobox.enable(true); 1048 this_.populateTypeOfStationAreaCombobox(); 1049 } 1050 } 1051 1052 /** 1053 * Handles a Station Area lookup-load failure. 1054 * Removes the temporary EventBus listeners for this load cycle and keeps 1055 * the TypeOfArea dropdown disabled because its master list is unavailable. 1056 */ 1057 function onStationAreaTypeDataFailed() { 1058 EventBus.off(EventBus.EventNames.STATION_AREA_TYPE_DATA_LOADED, onStationAreaTypeDataLoaded); 1059 EventBus.off(EventBus.EventNames.STATION_AREA_TYPE_DATA_FAILED, onStationAreaTypeDataFailed); 1060 1061 if (this_.stationAreaTypeCombobox) { 1062 this_.stationAreaTypeCombobox.enable(false); 1063 } 1064 } 1065 1066 // Refresh all dependent dropdowns that rely on upstream filters (Target, Region, Owner). 1067 // TypeOfStation depends on the dropdowns above it, so refresh it before rebuilding stations. 1068 function refreshStationsByCurrentFilters() { 1069 this_.populateStationsAndMonitorsControl(); 1070 } 1071 1072 // Keeps cascading filters in sync with currently available stations. 1073 function refreshDependentFilters() { 1074 if (EURegulations) { 1075 this_.populateTypeOfStationCombobox(); 1076 this_.populateTypeOfStationAreaCombobox(); 1077 } 1078 1079 refreshStationsByCurrentFilters(); 1080 } 1081 1082 // Event Handlers 1083 1084 /** 1085 * Show result button clicked handler 1086 */ 1087 function actionBtnClicked() { 1088 if (validationChecks()) { 1089 const fromMainShowResultButton = true; 1090 actualThis.showResult(fromMainShowResultButton); 1091 } 1092 } 1093 1094 function onTargetChanged(target) { 1095 const targetBeforeChange = this_.targetCombobox._prevValues; 1096 applyStationFiltersAllExclusiveSelection(this_.targetCombobox, this_.targetCombobox.value(
1096), targetBeforeChange); 1097 1098 this_.populateRegionComboboxByTarget(target) 1099 onRegionChanged() 1100 } 1101 1102 function onRegionChanged() { 1103 const regionBeforeChange = this_.regionCombobox._prevValues; 1104 applyStationFiltersAllExclusiveSelection(this_.regionCombobox, this_.regionCombobox.value(), regionBeforeChange); 1105 1106 this_.populateOwnersComboBox() 1107 onOwnerChanged() 1108 } 1109 1110 function onOwnerChanged() { 1111 this_.ownerCombobox.trigger("change"); 1112 } 1113 1114 /** 1115 * Handles Station Type selection changes. 1116 * Refreshes the dependent Station Area dropdown first and then rebuilds the station list. 1117 */ 1118 function onStationTypeChanged() { 1119 if (!EURegulations || !this_.stationTypeCombobox) { 1120 return; 1121 } 1122 1123 applyStationFiltersAllExclusiveSelection( 1124 this_.stationTypeCombobox, 1125 this_.stationTypeCombobox.value(), 1126 this_.stationTypeCombobox._prevValues 1127 ); 1128 1129 // TypeOfArea depends on the selected TypeOfStation, so refresh it before stations. 1130 this_.populateTypeOfStationAreaCombobox(); 1131 1132 // TypeOfStation is a downstream filter: refresh dependent dropdowns and stations only, 1133 // and do not trigger owner flow that rebuilds upstream controls. 1134 this_.populateStationsAndMonitorsControl(); 1135 } 1136 1137 /** 1138 * Handles Station Area selection changes. 1139 * This is a downstream filter, so only the station list is refreshed. 1140 */ 1141 function onStationAreaTypeChanged() { 1142 if (!EURegulations || !this_.stationAreaTypeCombobox) { 1143 return; 1144 } 1145 1146 applyStationFiltersAllExclusiveSelection( 1147 this_.stationAreaTypeCombobox, 1148 this_.stationAreaTypeCombobox.value(), 1149 this_.stationAreaTypeCombobox._prevValues 1150 ); 1151 1152 // StationArea is also a downstream filter: refresh stations only. 1153 this_.populateStationsAndMonitorsControl(); 1154 } 1155 1156 function onFromDateChange() { 1157 if (this_.toDatePicker != null && m_CurReportPeriod != PERIOD_TYPE.CUSTOM) { 1158 var fromDatePicker = this_.getFromDate(); 1159 var toDatePicker = getToDatePickerValue(fromDatePicker); 1160 actualThis.setNewFromDatePickerValue(new DateTime(fromDatePicker).dformat()); 1161 actualThis.setNewToDatePickerValue(toDatePicker); 1162 } 1163 } 1164 1165 function onToDateChange() { 1166 1167 } 1168 1169 function onReportPeriodChanged(reportPeriod) { 1170 1171 this_.setDateTimePickersByReportPeriod(reportPeriod) 1172 } 1173 1174 this.onFromTimeBaseChanged = function (fromTimebase) { 1175 onFromTimeBaseChanged(fromTimebase) 1176 } 1177 1178 function onFromTimeBaseChanged(fromTimebase) { 1179 let relevantTimeBases = getToTimeBases(fromTimebase) 1180 relevantTimeBases = actualThis.filterAvailableToTimebases(relevantTimeBases, fromTimebase) 1181 let relevantTimeBasesDict = ReportUtils.getTimeBaseTextsByTimebases(relevantTimeBases) 1182 this_.toTimeBaseCombobox.setDataSource(relevantTimeBasesDict) 1183 this_.toTimeBaseCombobox.value(Object.keys(relevantTimeBasesDict)[0]) 1184 setTimePickersByTimebase(fromTimebase) 1185 } 1186 1187 function onToTimeBaseChanged(newToTimebase) { 1188 setTimePickersByTimebase(newToTimebase) 1189 } 1190 1191 function onTypeChanged(reportType) { 1192 if (ReportUtils.isMinOrMaxReport(reportType)) { 1193 $("#pr-input-checkbox").data("kendoCheckBox").check(false); 1194 $("#pr-input-checkbox").data("kendoCheckBox").enable(false); 1195 } 1196 else { 1197 $("#pr-input-checkbox").data("kendoCheckBox").enable(true); 1198 } 1199 setFromTimePickerValue() 1200 } 1201 1202 function onProvinceChanged(provinceType) { 1203 actualThis.onProvinceChanged(provinceType); 1204 } 1205 1206 function onDistrictChanged(districtType) { 1207 actualThis.onDistrictChanged(districtType); 1208 } 1209 1210 // Setters 1211 1212 this.setReportsValidator = function (reportValidatorNew = null) { 1213 this_.reportsValidator = JsUtils.isNotEmpty(reportValidatorNew) ? reportValidatorNew : reportsValidator; 1214 } 1215 1216 this.setDateTimePickersByReportPeriod = function (reportPeriod) { 1217 var from = getFromDatePickerValue(); 1218 var to = getToDatePickerValue(from); 1219 this_.setNewFromDatePickerValue(from); 1220 this_.setNewToDatePickerValue(to); 1221 1222 if (this_.fromTimePicker != null && this_.toTimePicker != null) { 1223 if (reportPeriod == PERIOD_TYPE.CUSTOM) { 1224 this_.fromTimePicker.enable(true) 1225 this_.toTimePicker.enable(true) 1226 } 1227 else { 1228 this_.fromTimePicker.enable(false); 1229 this_.toTimePicker.enable(false); 1230 1231 if (JsUtils.isNotEmpty(this_.fromTimeBaseCombobox) || JsUtils.isNotEmpty(this_.selectTimeBase)) { 1232 let timebase = this_.fromTimeBaseCombobox != null ? this_.fromTimeBaseCombobox.value(
1232) : this_.selectTimeBase.getValue(); 1233 setToTimePickerByTimebase(timebase); 1234 setFromTimePickerValue(); 1235 } 1236 1237 if (actualThis.getReportName() == "index report") { 1238 let timebase = IndexUtils.getIndexTimeStep(); 1239 if (JsUtils.isNotEmpty(timebase)) { 1240 setToTimePickerByTimebase(timebase); 1241 setFromTimePickerValue(); 1242 } 1243 } 1244 } 1245 } 1246 } 1247 1248 function setTimePickersByTimebase(currentTimebase) { 1249 setToTimePickerByTimebase(currentTimebase) 1250 setFromTimePickerValue() 1251 } 1252 1253 function setToTimePickerByTimebase(timebase) { 1254 if (JsUtils.isNotEmpty(timebase)) { 1255 // Workaround for Kendo bug: setOption re-enables the time picker element 1256 let enable = JsUtils.isEmpty(this_.toTimePicker.element.attr('disabled')); 1257 this_.toTimePicker.setOptions({ interval: timebase }); 1258 this_.toTimePicker.enable(enable); 1259 1260 let endTime = new DateTime(ReportUtils.getToTime(timebase)); 1261 1262 if (isTimeEnding) { 1263 var newDateMin = new DateTime(endTime).addMinutes(timebase); 1264 this_.toTimePicker.min(new Date(newDateMin.getYear(), newDateMin.getMonth() - 1, newDateMin.getDay(), newDateMin.getHour(), newDateMin.getMinutes(), 0)); 1265 1266 setLastTimeListElementByTimeEnding(); 1267 } 1268 else { 1269 this_.toTimePicker.value(new DateTime(endTime).tformat()); 1270 } 1271 } 1272 } 1273 1274 function setLastTimeListElementByTimeEnding() { 1275 var timeList = this_.toTimePicker.timeView.list; 1276 var lastItem = timeList.find("li:last"); 1277 if (lastItem.text() != '00:00') { 1278 lastItem = timeList.find("li:last")[0].cloneNode(true); 1279 timeList.find("ul").append(lastItem); 1280 } 1281 $(lastItem).text("24:00"); 1282 1283 this_.toTimePicker.value('00:00'); //this is only the value, not the text, otherwise this_.toTimePicker.value() is null!! 1284 this_.toTimePicker.element.val('24:00'); 1285 1286 timeList.find("li").removeClass("k-selected"); 1287 timeList.find("li:last").addClass("k-selected"); 1288 this_.toTimePicker.trigger("change"); 1289 } 1290 1291 this.setFromTimeBaseComboboxDs = function (ds) { 1292 if (this_.fromTimeBaseCombobox != null) { 1293 this_.fromTimeBaseCombobox.setDataSource(ds) 1294 } 1295 } 1296 1297 this.setToTimeBaseComboboxDs = function (ds) { 1298 if (this_.toTimeBaseCombobox != null) { 1299 this_.toTimeBaseCombobox.setDataSource(ds) 1300 } 1301 } 1302 1303 function setFromTimePickerValue() { 1304 let timebase; 1305 let curReportType = JsUtils.isNotEmpty(this_.typeCombobox) ? this_.typeCombobox.value() : null; 1306 1307 if (actualThis.getReportName() == "index report") { 1308 timebase = IndexUtils.getIndexTimeStep(); 1309 } else if (JsUtils.isEmpty(curReportType)) {// for EditBlock timebase value 1310 timebase = this_.selectTimeBase.getValue(); 1311 } else if (ReportUtils.isRunningReport(curReportType)) { 1312 timebase = this_.fromTimeBaseCombobox.value() 1313 } else { 1314 timebase = this_.toTimeBaseCombobox.value() 1315 } 1316 1317 let startTime = ReportUtils.getFromTime(timebase); 1318 1319 if (JsUtils.isNotEmpty(timebase)) { 1320 // Workaround for Kendo bug: setOption re-enables the time picker element 1321 let enable = JsUtils.isEmpty(this_.fromTimePicker.element.attr('disabled')); 1322 this_.fromTimePicker.setOptions({ interval: timebase }); 1323 this_.fromTimePicker.enable(enable); 1324 } 1325 1326 if (isTimeEnding) { 1327 this_.fromTimePicker.min(new Date(startTime.year(), startTime.month() + 1, startTime.date(), startTime.hour(), startTime.minute(), 0)); 1328 this_.fromTimePicker.value(new DateTime(startTime).tformat()); 1329 var timeList = this_.fromTimePicker.timeView.list; 1330 var lastItemClone = timeList.find("li:last"); 1331 if (lastItemClone.text() != '00:00') { 1332 lastItemClone = timeList.find("li:last")[0].cloneNode(true); 1333 this_.fromTimePicker.timeView.list.find("ul").append(lastItemClone); 1334 } 1335 $(lastItemClone).text("24:00"); 1336 } else { 1337 this_.fromTimePicker.value("00:00"); 1338 } 1339 } 1340 1341 function getFromDatePickerValue() { 1342 if (m_CurReportPeriod != PERIOD_TYPE.CUSTOM) { 1343 return ReportUtils.getFromDateByPeriod(m_CurReportPeriod); 1344 } 1345 } 1346 1347 function getToDatePickerValue(from) { 1348 if (this_.toDatePicker != null) { 1349 if (m_CurReportPeriod != PERIOD_TYPE.CUSTOM) { 1350 this_.toDatePicker.enable(false); 1351 let to = ReportUtils.getToDatePickerValue(m_CurReportPeriod, from); 1352 return to; 1353 } 1354 else { 1355 this_.toDatePicker.enable(true); 1356 } 1357 } 1358 } 1359 1360 /** 1361 * set new From date 1362 * @param {String} from 1363 */ 1364 this.setNewFromDatePickerValue = function (from) { 1365 if (JsUtils.isNotEmpty(this_.fromDatePicker) && JsUtils.isNotEmpty(this_.fromDatePicker.value)) { 1366 this_.fromDatePicker.value(from); 1367 } 1368 } 1369 1370 /** 1371 * set new To date 1372 * @param {String} to 1373 */ 1374 this.setNewToDatePickerValue = function (to) { 1375 if (JsUtils.isNotEmpty(this_.toDatePicker) && JsUtils.isNotEmpty(this_.toDatePicker.value)) { 1376 this_.toDatePicker.value(to); 1377 } 1378 } 1379 1380 this.setFromTimeBase = function (val) { 1381 this_.fromTimeBaseCombobox.value(val) 1382 } 1383 this.setToTimeBase = function (val) { 1384 this_.toTimeBaseCombobox.value(val) 1385 } 1386 1387 this.updateFromTimebaseCombobox = function (timebases, preferredTimebase) { 1388 let relevantTimebases = ArrayUtils.getArraysIntersection(this_.allDefinedTimeBases, timebases) 1389 let timeBaseTextsByTimebases = ReportUtils.getTimeBaseTextsByTimebases(relevantTimebases) 1390 1391 this_.fromTimeBaseCombobox.setDataSource(timeBaseTextsByTimebases) 1392 1393 let curValue = Object.keys(timeBaseTextsByTimebases).map(Number).includes(preferredTimebase) 1394 ? preferredTimebase 1395 : Object.keys(timeBaseTextsByTimebases)[0]; 1396 1397 this_.fromTimeBaseCombobox.value(curValue) 1398 this_.onFromTimeBaseChanged(curValue) 1399 } 1400 1401 // Getters 1402 1403 this.getControls = () => { 1404 return controls; 1405 } 1406 1407 this.getAuthControls = () => { 1408 return authControls; 1409 } 1410 1411 this.getFromDateTime = function () { 1412 let fromDateTime = dateTimeUtils.toDateTime(actualThis.getFromDate(), actualThis.getFromTime()); 1413 fromDateTime = validateAndShiftDate(fromDateTime); 1414 return fromDateTime.dtformat(); 1415 } 1416 1417 this.getToDateTime = function () { 1418 let toDateTime = dateTimeUtils.toDateTime(actualThis.getToDate(), actualThis.getToTime()); 1419 toDateTime = validateAndShiftDate(toDateTime); 1420 1421 return toDateTime.dtformat(); 1422 } 1423 1424 function validateAndShiftDate(_date) { 1425 if (isTimeEnding && _date.isTimeAtMidnight()) { 1426 _date = _date.addDay(); 1427 } 1428 return _date; 1429 } 1430 1431 this.getPeriod = function () { 1432 return m_CurReportPeriod 1433 } 1434 1435 this.getReportType = function () { 1436 if (this_.typeCombobox != null) {
1437 return this_.typeCombobox.value() 1438 } 1439 1440 } 1441 1442 //Set the default values(target, region and owner) to "All" - in the reports that opens through the station dashboard 1443 //while the chosen station not includes in the data source of the configuration 1444 this.setToAll = function () { 1445 this_.targetCombobox.value("-1"); 1446 this_.regionCombobox.value("-1"); 1447 this_.ownerCombobox.value("-1"); 1448 } 1449 1450 /** 1451 * Returns the selected owner raw names from the datasource. 1452 * Use datasource items instead of the visible text so translated labels 1453 * never leak into filtering comparisons. 1454 */ 1455 this.getOwner = function () { 1456 1457 if (this_.ownerCombobox != null) { 1458 return this_.ownerCombobox.dataItems().map(item => item.name); 1459 } 1460 else { 1461 console.log("bug") 1462 } 1463 } 1464 1465 this.getRegion = function () { 1466 1467 if (this_.regionCombobox != null) { 1468 return this_.regionCombobox.value() 1469 } 1470 else { 1471 console.log("bug") 1472 } 1473 } 1474 1475 /** 1476 * Returns the selected target raw names from the datasource. 1477 * The widget shows `displayName`, but the reports layer must keep using 1478 * the original `name` values for stable filtering. 1479 */ 1480 this.getTarget = function () { 1481 if (this_.targetCombobox != null) { 1482 return this_.targetCombobox.dataItems().map(item => item.name); 1483 } 1484 else { 1485 console.log("bug") 1486 } 1487 } 1488 1489 /** 1490 * Returns the selected Station Type ids as an array. 1491 * Returns [-1] when EU regulations are disabled or when the "All" option is selected. 1492 * @returns {number[]|null} 1493 */ 1494 this.getStationType = function () { 1495 if (!EURegulations) { 1496 return [EUConfigurationManager.getAllEUConfigId()]; 1497 } 1498 1499 if (!this_.stationTypeCombobox) { 1500 console.log("bug"); 1501 return null; 1502 } 1503 1504 const selectedValues = this_.stationTypeCombobox.value() || []; 1505 const allId = EUConfigurationManager.getAllEUConfigId(); 1506 1507 if (!selectedValues.length || selectedValues.includes(allId.toString()) || selectedValues.includes(allId)) { 1508 return [allId]; 1509 } 1510 1511 const selectedIds = selectedValues 1512 .map(value => Number(value)) 1513 .filter(value => !Number.isNaN(value)); 1514 1515 if (!selectedIds.length) { 1516 return [allId]; 1517 } 1518 1519 return selectedIds; 1520 } 1521 1522 /** 1523 * Returns the selected Station Area ids as an array. 1524 * Returns [-1] when EU regulations are disabled or when the "All" option is selected. 1525 * @returns {number[]|null} 1526 */ 1527 this.getStationAreaType = function () { 1528 if (!EURegulations) { 1529 return [EUConfigurationManager.getAllEUConfigId()]; 1530 } 1531 1532 if (!this_.stationAreaTypeCombobox) { 1533 console.log("bug") 1534 return null; 1535 } 1536 const selectedValues = this_.stationAreaTypeCombobox.value() || []; 1537 const allId = EUConfigurationManager.getAllEUConfigId(); 1538 1539 if (!selectedValues.length || selectedValues.includes(allId.toString()) || selectedValues.includes(allId)) { 1540 return [allId]; 1541 } 1542 1543 const selectedIds = selectedValues 1544 .map(value => Number(value)) 1545 .filter(value => !Number.isNaN(value)); 1546 1547 if (!selectedIds.length) { 1548 return [allId]; 1549 } 1550 1551 return selectedIds; 1552 } 1553 1554 this.getToTimeBase = function () { 1555 1556 if (this_.toTimeBaseCombobox != null) { 1557 return this_.toTimeBaseCombobox.value() 1558 } 1559 else { 1560 console.log("bug") 1561 } 1562 1563 } 1564 /** 1565 *Gets tome base from combo box 1566 * Used by single station initialization 1567 * 1568 */ 1569 this.getFromTimeBase = function () { 1570 1571 if (this_.fromTimeBaseCombobox != null) {
1572 return this_.fromTimeBaseCombobox.value() 1573 } 1574 else { 1575 console.log("Cannot get time base from combo box") 1576 } 1577 } 1578 1579 this.getToTimeBaseAsText = function () { 1580 1581 let toTb = actualThis.getToTimeBase() 1582 return ReportUtils.getTimeBaseTextByTimebase(toTb) 1583 } 1584 1585 this.getFromDate = function () { 1586 if (this_.fromDatePicker != null) { 1587 return new DateTime(this_.fromDatePicker.value()); 1588 } 1589 else { 1590 console.log("reportManager_bug"); 1591 } 1592 } 1593 1594 this.getToDate = function () { 1595 if (this_.toDatePicker != null) { 1596 return this_.toDatePicker.value() 1597 } 1598 else { 1599 console.log("reportManager_bug") 1600 } 1601 } 1602 1603 this.getToTime = function () { 1604 if (this_.toTimePicker != null) { 1605 let time = this_.toTimePicker.value(); 1606 return time; 1607 } 1608 else { 1609 console.log("reportManager_bug") 1610 } 1611 } 1612 1613 this.getFromTime = function () { 1614 if (this_.fromTimePicker != null) { 1615 return this_.fromTimePicker.value() 1616 } 1617 else { 1618 console.log("reportManager_bug") 1619 } 1620 } 1621 1622 //Helpers 1623 this.validationChecks = validationChecks; 1624 /** 1625 * Reports validation checks 1626 */ 1627 function validationChecks() { 1628 if (!this_.reportsValidator.isValid(actualThis)) { 1629 const reportContext = REPORT_CONTEXT.REPORT_FORM; 1630 // Get the error message from reportsValidator 1631 let errMsg = SiteUtils.translate(this_.reportsValidator.getErrMsg()); 1632 1633 this_.showErrorMessageHandler(reportContext, errMsg); 1634 1635 return false; 1636 } 1637 else if (!authValidator.isValid(actualThis)) { 1638 const reportContext = REPORT_CONTEXT.REPORT_FORM; 1639 // Get the error message from authValidator 1640 let errMsg = SiteUtils.translate(authValidator.getErrMsg()); 1641 1642 this_.showErrorMessageHandler(reportContext, errMsg); 1643 1644 return false; 1645 } 1646 1647 return true; 1648 } 1649 1650 this.isInPopup = function () { 1651 return this_.inPopup; 1652 } 1653 1654 function getToTimeBases(fromTimebase) { 1655 return this_.allDefinedTimeBases.filter(function (tb) { return parseInt(fromTimebase) <= tb }) 1656 } 1657 1658 this.notifyNoReportData = function (pageContainer) { 1659 PopupManager.closeWindowByPageContainer(pageContainer) 1660 this_.showErrorMessage(ERROR_MESSAGES.No_Report_Data) 1661 1662 } 1663 1664 this.notifyModelNotValid = function () { 1665 this_.modelValid = false; 1666 $("#showResultsBtn").addClass('disabled'); 1667 } 1668 1669 this.notifyModelValid = function () { 1670 this_.modelValid = true; 1671 $("#showResultsBtn").removeClass('disabled'); 1672 } 1673 1674 this.showErrorMessageHandler = function (reportContext, errorMessage) { 1675 AjaxLoader.hide(); 1676 WindowManager.closeWindowById("report_result"); 1677 if (reportContext == REPORT_CONTEXT.REPORT_RESULT) { 1678 this_.showErrorMessageInPopup(errorMessage) 1679 } 1680 else if (reportContext == REPORT_CONTEXT.REPORT_FORM) { 1681 this_.showErrorMessage(errorMessage) 1682 } 1683 } 1684 1685 this.showErrorMessage = function (msg, persistent) { 1686 1687 $("#errorInputsMessage").css("visibility", "visible") 1688 1689 $("#errorInputsMessage").text(SiteUtils.translate(msg)) 1690 1691 if (!persistent) { 1692 if (this.lastTimeout != null) { 1693 clearTimeout(this.lastTimeout) 1694 } 1695 1696 this.lastTimeout = setTimeout(this_.hideErrorMessage, ERROR_MESSAGE_SHOW_MILISEC) 1697 } 1698 } 1699 1700 this.hideErrorMessage = function () { 1701 $("#errorInputsMessage").css("visibility", "hidden") 1702 1703 } 1704 1705 this.showErrorMessageInPopup = function (msg) { 1706 PopupManager.ErrorAlert(msg) 1707 } 1708 /** 1709 * getReportConfig 1710 * This is the base for getting configuration from user 1711 * 1712 */ 1713 this.getReportConfig = function () { 1714 let config = { 1715 reportName: actualThis.getReportName(), 1716 reportType: actualThis.getReportType(), 1717 actualReportType: actualThis.getReportType(), 1718 startDate: this_.getFromDateTime(), 1719 endDate: this_.getToDateTime(), 1720 startDateAbsolute: this_.getFromDateTime(), 1721 endDateAbsolute: this_.getToDateTime(), 1722 } 1723 1724 if (actualThis.reportName == REPORTS.editBlock) { 1725 config.fromTb = this_.selectTimeBase.getValue(); 1726 config.toTb = this_.selectTimeBase.getValue(); 1727 } else { 1728 config.fromTb = parseInt(actualThis.getFromTimeBase()); 1729 config.toTb = parseInt(actualThis.getToTimeBase()); 1730 } 1731 1732 return config; 1733 } 1734
1735 this.disableTimebasesControls = function () { 1736 1737 if (this_.fromTimeBaseCombobox != null && this_.toTimeBaseCombobox != null) { 1738 this_.fromTimeBaseCombobox.enable(false) 1739 this_.toTimeBaseCombobox.enable(false) 1740 } 1741 } 1742 1743 this.enableTimebasesControls = function () { 1744 1745 if (this_.fromTimeBaseCombobox != null && this_.toTimeBaseCombobox != null) { 1746 this_.fromTimeBaseCombobox.enable(true) 1747 this_.toTimeBaseCombobox.enable(true) 1748 } 1749 } 1750 1751 /** 1752 * Filter the NotForDisplay configuration from the data source 1753 * @param {any} dataSource 1754 * @param {any} config 1755 */ 1756 function filterNotForDisplay(dataSource, config) { 1757 if (JsUtils.isEmpty(configManager.read(config))) { 1758 return dataSource; 1759 } 1760 1761 let notForDisplayConfig = configManager.read(config).split(',').map(id => { 1762 return isNaN(id) ? id : parseInt(id); 1763 }); 1764 if (JsUtils.isNotEmpty(notForDisplayConfig)) { 1765 if (JsUtils.isArray(dataSource)) { 1766 dataSource = dataSource.filter(data => !notForDisplayConfig.includes(data.id)); 1767 } else { 1768 let filteredData = Object.entries(dataSource).filter(data => !notForDisplayConfig.includes(data[0])); 1769 1770 dataSource = Object.fromEntries(filteredData); 1771 } 1772 } 1773 1774 return dataSource; 1775 } 1776 1777 /** 1778 * Sets the default value for the given combobox by the given config. 1779 * If the config is empty, the default value will be the first element from the given data source. 1780 * @param {any} combobox 1781 * @param {any} config 1782 * @param {any} dataSource 1783 */ 1784 function setDefaultValueByConfig(combobox, config, dataSource) { 1785 let defaultValue = configManager.read(config); 1786 var dsNotEmpty = JsUtils.isNotEmpty(dataSource); 1787 let value; 1788 if (JsUtils.isNotEmpty(defaultValue) && dsNotEmpty && this_.firstTime) { 1789 if (config == webConfigs.DefaultType) { 1790 value = JsUtils.isNotEmpty(Object.keys(dataSource).includes(defaultValue)) ? defaultValue : Object.keys(dataSource)[0]; 1791 } else { 1792 value = JsUtils.isNotEmpty(dataSource.find(ds => ds.id == defaultValue)) ? defaultValue : dataSource[0].id; 1793 } 1794 } else if (dsNotEmpty) { 1795 value = config == webConfigs.DefaultType ? Object.keys(dataSource)[0] : dataSource[0].id; 1796 1797 } 1798 combobox.value(value); 1799 } 1800 1801 /** 1802 * Clones datasource items with a translated `displayName` field for UI rendering. 1803 * This prevents accidental mutation of `name`, which is the raw logical value 1804 * used later by report filters and data-manager lookups. 1805 */ 1806 function buildDisplayItems(items) { 1807 return items.map(item => ({ 1808 ...item, 1809 displayName: SiteUtils.translate(item.name) 1810 })); 1811 } 1812 1813 //model 1814 this.setReportView = function (reportView) { 1815 model.reportView = reportView; 1816 1817 if (JsUtils.isNotEmpty(this_.reportPresentationBtnGroup)) { 1818 //updateReportViewUI 1819 this_.reportPresentationBtnGroup.select(actualThis.INITIAL_REPORT_PRESENTATION_CONFIG.indexOf(reportView)); 1820 } 1821 } 1822 1823 this.getReportView = function (reportView) { 1824 return model.reportView; 1825 } 1826 1827 1828 this.setLatestReportView = function (latestReportView) { 1829 model.latestReportView = latestReportView; 1830 } 1831 1832 this.getLatestReportView = function () { 1833 return model.latestReportView; 1834 } 1835 1836 /** 1837 * compare between current and latest view type. 1838 * if the types are different the result popup will close so that new one can open and update latestReportType. 1839 * @param {number} compareTo - current view type 1840 */ 1841 this.compareLatestAndCurrentViewType = function (compareTo, id = "report_result") { 1842 if (this_.getLatestReportView() != compareTo) { 1843 WindowManager.closeWindowById(id); 1844 } 1845 this_.setLatestReportView(compareTo); 1846 } 1847 1848 //filter by pollutant - irregularity and multistation 1849 function createMonitorItem(itemContainer, monitor, callBackChangePollutant) { 1850 let item = $("<div class=monitorItemBox>") 1851 .append(`<input class="monitorCheckboxItem" id="checkbox_${monitor.pollutantId}" />`) 1852
1853 $(itemContainer).append(item) 1854 1855 $(`#checkbox_${monitor.pollutantId}`).kendoCheckBox({ 1856 label: monitor.text, 1857 change: function (e) { 1858 if (e.checked == false) { 1859 var isAdd = false; 1860 callBackChangePollutant(e.sender.element[0], isAdd); 1861 } 1862 else { 1863 callBackChangePollutant(e.sender.element[0]); 1864 } 1865 } 1866 }); 1867 } 1868 1869 this.onFilterMonitors = function (value) { 1870 var data = $(".monitorItemBox").find("label"); 1871 for (let i = 0; i < data.length; i++) { 1872 if (data[i].innerText.toLowerCase().includes(value)) { 1873 $($(".monitorItemBox")[i]).show(); 1874 } else { 1875 $($(".monitorItemBox")[i]).hide(); 1876 } 1877 } 1878 } 1879 this.onFilterStations = function (value) { 1880 var data = $(".stationItemBox").find("label"); 1881 for (let i = 0; i < data.length; i++) { 1882 if (data[i].innerText.toLowerCase().includes(value)) { 1883 $($(".stationItemBox")[i]).show(); 1884 } else { 1885 $($(".stationItemBox")[i]).hide(); 1886 } 1887 } 1888 } 1889 1890 1891 this.changeCheckboxStation = function (isAdd, data, monitorDic) { 1892 monitorDic.forEach(function (monitor) { 1893 var station = $.grep(data, function (d) { 1894 return d.stationId == monitor.stationId; 1895 }); 1896 var pollutant = $.grep(station[0].items, function (d) { 1897 return d.pollutantId == monitor.pollutantId; 1898 }); 1899 pollutant[0].set('checked', isAdd); 1900 }) 1901 } 1902 1903 this.onFilterCheckboxChangeReport = function (checkboxIsChecked, pollutantContainer, stationContainer, m_MonitorsDictionary, changeCheckboxStation) { 1904 if (checkboxIsChecked) { 1905 if ($(pollutantContainer).children().length == 0) { 1906 this.createPollutantControl(pollutantContainer, m_MonitorsDictionary, changeCheckboxStation); 1907 } 1908 $(pollutantContainer).show(); 1909 $(stationContainer).hide(); 1910 } 1911 else { 1912 $(pollutantContainer).hide(); 1913 $(stationContainer).show(); 1914 } 1915 } 1916 1917 this.createPollutantControl = function (pollutantContainer, m_MonitorsDictionary, changeCheckboxStation) { 1918 for (var key in m_MonitorsDictionary) { 1919 createMonitorItem(pollutantContainer, m_MonitorsDictionary[key][0], changeCheckboxStation); 1920 } 1921 } 1922 1923 this.filterByStationName = async function (dataSource, query) { 1924 return filterByStatioChildrennName(dataSource, query); 1925 } 1926 async function itemHide(item, query, hasVisibleChildren) { 1927 1928 var text = item.text.toLowerCase(); 1929 var itemVisible = 1930 query === true // parent already matches 1931 || query === "" // query is empty 1932 || text.indexOf(query) >= 0; // item text matches query 1933 1934 var anyVisibleChildren = filterByStatioChildrennName(item.children, itemVisible || query); // pass true if parent matches 1935 1936 hasVisibleChildren = hasVisibleChildren || anyVisibleChildren || itemVisible; 1937 1938 item.hidden = !itemVisible && !anyVisibleChildren; 1939 } 1940 1941 1942 function filterByStatioChildrennName(dataSource, query) { 1943 1944 var hasVisibleChildren = false; 1945 var data = dataSource instanceof kendo.data.HierarchicalDataSource && dataSource.data(); 1946 1947 for (var i = 0; i < data.length; i++) { 1948 1949 var item = data[i]; 1950 itemHide(item, query, hasVisibleChildren) 1951 } 1952 1953 if (data) { 1954 // Re-apply the filter on the children. 1955 dataSource.filter({ field: "hidden", operator: "neq", value: true }); 1956 } 1957 1958 return hasVisibleChildren; 1959 } 1960 1961 /** 1962 * setDsData 1963 * @param {any} data 1964 * @param {any} callback 1965 * The purpose of this conditions are to insure there is only one api call per config 1966 * Check if the configure of the request is different 1967 * If the configures are equal return complete data 1968 * Else make api call 1969 * Gets api data for Table 1970 */ 1971 this.getRawDataFromApi = (url, requestType, callback_config, stationId, resolvedCallback) => { 1972 let promiseList = []; 1973 const validationPromise = prValidationManager.getApiValidationData(callback_config, stationId); 1974 const callbackPromise = createRawDataRquest(url, requestType, callback_config, stationId); 1975 1976 promiseList.push(validationPromise); 1977 promiseList.push(callbackPromise); 1978 Promise.all(promiseList).then((data) => { 1979 //if we will need at the feature 1980 resolvedCallback(data); 1981 }); 1982 1983 } 1984 1985 function createRawDataRquest(url, requestType, callback_config, stationId) { 1986 let apiData = JsUtils.isNotEmpty(callback_config.m_ReportConfig.apiData) ? callback_config.m_ReportConfig.apiData : null; 1987 1988 let errorCallback = JsUtils.isNotEmpty(callback_config.m_ReportConfig.apiData) ? onRawDataFailed : null; 1989 1990 return new Promise((resolve) => { 1991 API.createRequest(url, requestType, (response) => { 1992 onRawDataSuccess(response, resolve, callback_config, stationId); 1993 }, true, apiData, errorCallback); 1994 }); 1995 } 1996 1997 function onRawDataSuccess(res, resolve, callback_config, stationId) { 1998 let completeData = this_.kendoElemetCallback(res, callback_config, stationId); 1999 resolve(completeData); 2000 } 2001 2002 function onRawDataFailed(res) { 2003 let pageContainer = "detailedReportGrid"; 2004 PopupManager.closeWindowByPageContainer(pageContainer); 2005 let errorMsg = JsUtils.isEmpty(res) ? ERROR_MESSAGES.Unexpected_Error : ERROR_MESSAGES.Higher_Privileges_Permissions; 2006 this_.showErrorMessage(errorMsg); 2007 AjaxLoader.hide(); 2008 } 2009 2010 /** 2011 * getApiData 2012 * @param {any} url 2013 * @param {any} callback_config 2014 * @param {any} report_config 2015 * @param {any} resolve 2016 * @param {any} complete_response 2017 * Gets api data for graph and excel and summary 2018 */
2019 this.getStationApiData = (url, config, resolvedCallback) => { 2020 //check what happens in chart 2021 let promiseList = []; 2022 let stationId = config["stationId"] 2023 const validationPromise = prValidationManager.getApiValidationData(config, stationId); 2024 const callbackPromise = new Promise((resolve) => { 2025 API.createRequest(url, TYPE.GET, (response) => { 2026 let completeData = this.kendoElemetCallback(response, config, stationId); 2027 resolve(completeData); 2028 }, true) 2029 }) 2030 promiseList.push(validationPromise); 2031 promiseList.push(callbackPromise); 2032 Promise.all(promiseList).then((data) => { 2033 2034 resolvedCallback(data); 2035 2036 }) 2037 2038 } 2039 /** 2040 * kendoElemetCallback 2041 * @param {Object} response 2042 * @param {Object} config 2043 * @param {String} stationId 2044 * Callback for report api call 2045 * checks if response is undefined(status 204)-if so display error message 2046 * if there is a response- check what kind of report view(table/graph/excel) 2047 * ðð½ in report view of table- make the data processing right away 2048 * ðð½ other report views- save and return the response 2049 */ 2050 this.kendoElemetCallback = (response, config, stationId) => { 2051 if (config.m_ReportConfig.reportName == REPORTS.index) { 2052 response = IndexUtils.filterResponseDataByTimeStep(response); 2053 } 2054 response = defaulatSummaryHandler(response, config, stationId); 2055 if (JsUtils.isEmpty(response)) { 2056 return null; 2057 } 2058 let rawData = response 2059 rawData['stationId'] = stationId; 2060 elemetBuilder = new kendoElementDataBuilder(rawData, config) 2061 switch (config.kendoElementType) { 2062 case REPORT_VIEW.TABLE: 2063 return handleTableDataResponse(config, rawData, elemetBuilder, stationId) 2064 case REPORT_VIEW.HORIZONTAL_TABLE: 2065 reportApiManager.apiDataManager.setRawData(rawData, stationId) 2066 return rawData; 2067 case REPORT_VIEW.GRAPH: 2068 return rawData; 2069 case REPORT_VIEW.EXCEL: 2070 reportApiManager.apiDataManager.setRawData(rawData, stationId) 2071 return rawData; 2072 case REPORT_VIEW.SUMMARY: 2073 reportApiManager.apiDataManager.setRawSummaryData(rawData.summary, stationId) 2074 elemetBuilder.buildFormattedData(REPORT_VIEW.SUMMARY); 2075 return elemetBuilder.formmated_summary_data 2076 case REPORT_VIEW.HORIZONTAL_TABLE_SUMMARY: 2077 reportApiManager.apiDataManager.setRawSummaryData(rawData.summary, stationId); 2078 return rawData.summary; 2079 default: 2080 return rawData 2081 } 2082 } 2083 2084 /** 2085 * handleTableDataResponse 2086 * @param {any} config 2087 * @param {any} rawData 2088 * @param {any} elemetBuilder 2089 * @param {any} stationId 2090 */ 2091 function handleTableDataResponse(config, rawData, elemetBuilder, stationId) { 2092 if (config.m_ReportManager.reportName == REPORTS.event) { 2093 reportApiManager.apiDataManager.setNumberOfRecords(rawData.data) 2094 } 2095 reportApiManager.apiDataManager.setRawData(rawData, stationId) 2096 if (JsUtils.isEmpty(rawData)) { 2097 return null; 2098 } 2099 elemetBuilder.buildFormattedData(REPORT_VIEW.TABLE); 2100 return elemetBuilder.formatted_data 2101 } 2102 2103 2104 2105 /** 2106 * checkDataAndNotifyIfEmpty 2107 * @param {any} formattedData 2108 */ 2109 this.checkDataAndNotifyIfEmpty = (formattedData) => { 2110 elemetBuilder.checkDataAndNotifyIfEmpty(formattedData) 2111 } 2112 /** 2113 * defaulatSummaryHandler 2114 * @param {any} response 2115 * @param {any} stationId 2116 */ 2117 function defaulatSummaryHandler(response, config, stationId) { 2118 let res = []; 2119 if (config.kendoElementType == REPORT_VIEW.SUMMARY && JsUtils.isEmpty(response)) { 2120 let monitors = config.m_ReportConfig.monitorChannelsByStationId[stationId]; 2121 2122 for (let monitor of monitors) { 2123 //in the exceedance report there is a summary column for each pair of monitor and 2124 //exceedance value so we must create a default item per exceedance. 2125 if (config.m_ReportConfig.reportName === REPORTS.exceedance) {
2126 config.m_ReportConfig.exceedances.forEach(exceedance => { 2127 let defaultItem = createNewObject(monitor, true); 2128 defaultItem.stationId = stationId;//for excel 2129 defaultItem.exceedanceValue = exceedance; 2130 res.push(defaultItem); 2131 }) 2132 continue; 2133 } 2134 let defaultItem = createNewObject(monitor) 2135 defaultItem.stationId = stationId;//for excel 2136 res.push(defaultItem) 2137 } 2138 response = { 2139 data: [], 2140 summary: res, 2141 } 2142 } 2143 else if (config.kendoElementType == REPORT_VIEW.TABLE && JsUtils.isEmpty(response)) { 2144 return []; 2145 } 2146 return response; 2147 } 2148 /** 2149 * createNewObject 2150 * @param {any} monitorId 2151 * @param {boolean} isExceedance indicate whether the summary is for an exceedance report 2152 */ 2153 function createNewObject(monitorId, isExceedance = false) { 2154 let newObject = Object.assign({}, isExceedance ? DEFAULT_EXCEEDANCE_SUMMARY_OBJECT : DEFAULT_SUMMARY_OBJECT) 2155 newObject.ChannelId = monitorId; 2156 return newObject 2157 } 2158 2159 /* 2160 hideMobileStation 2161 * hides the mobile-Station container and reveal period and presentation 2162 */ 2163 this.hideMobileStation = () => { 2164 $('#reportPresentationBox').show(); 2165 $('#reportPeriodBox').show(); 2166 $('#reportSelectMobileStaionsContainer').hide(); 2167 } 2168 2169 /* 2170 handleMobileStationSelection 2171 *@ param {string} mobileStationId 2172 * hides the mobile-Station container and reveal period and presentation 2173 */ 2174 this.handleMobileStationSelection = (mobileStationId) => { 2175 $("#reportSelectMobileStaionsContainer").remove() 2176 $.ajax({
2177 type: "POST", 2178 url: baseUrl + "report/SelectMobileStation", 2179 contentType: "application/json; charset=utf-8", 2180 data: JSON.stringify({ mobileStationId: mobileStationId }), 2181 success: function (partialView) { 2182 $("#reportPresentationAndPeriodSection").append(partialView) 2183 }, 2184 error: function (err) { 2185 console.log(err) 2186 }, 2187 }); 2188 } 2189}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.