1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { BaseElement, element } from '../../../../base-ui/BaseElement'; 17import '../../../../base-ui/select/LitSelect'; 18import '../../../../base-ui/select/LitSelectOption'; 19import '../../../../base-ui/icon/LitIcon'; 20import { LitIcon } from '../../../../base-ui/icon/LitIcon'; 21import '../../../../base-ui/popover/LitPopoverV'; 22import { LitCheckBox } from '../../../../base-ui/checkbox/LitCheckBox'; 23import { LitSelect } from '../../../../base-ui/select/LitSelect'; 24import { queryTransferList } from '../../../database/sql/Perf.sql'; 25import { TabPaneFilterHtml } from './TabPaneFilter.html'; 26import { SpSystemTrace } from '../../SpSystemTrace'; 27 28export interface FilterData { 29 inputValue: string; 30 firstSelect: string | null | undefined; 31 secondSelect: string | null | undefined; 32 thirdSelect: string | null | undefined; 33 mark: boolean | null | undefined; 34 icon: string | null; 35 type: string; 36} 37 38export interface MiningData { 39 type: string; 40 item: unknown | null | undefined; 41 remove?: Array<unknown> | null | undefined; 42} 43 44export class CpuStatus { 45 cpu: number = 0; 46 small: boolean = false; 47 medium: boolean = false; 48 large: boolean = false; 49} 50 51@element('tab-pane-filter') 52export class TabPaneFilter extends BaseElement { 53 private filterInputEL: HTMLInputElement | null | undefined; 54 private firstSelectEL: HTMLSelectElement | null | undefined; 55 private secondSelectEL: HTMLSelectElement | null | undefined; 56 private thirdSelectEL: LitSelect | null | undefined; 57 private markButtonEL: HTMLButtonElement | null | undefined; 58 private iconEL: LitIcon | null | undefined; 59 private statisticsName: HTMLDivElement | null | undefined; 60 private getFilter: ((e: FilterData) => void) | undefined; 61 private getMining: ((e: MiningData) => void) | undefined; 62 private getLibrary: ((e: MiningData) => void) | undefined; 63 private getCallTree: ((e: unknown) => void) | undefined; 64 private getCallTreeConstraints: ((e: unknown) => void) | undefined; 65 private getStatisticsType: ((e: unknown) => void) | undefined; 66 private getCallTransfer: ((e: unknown) => void) | undefined; 67 68 private cutList: Array<unknown> | undefined; 69 private libraryList: Array<unknown> | undefined; 70 private transferChecked: string | undefined; 71 private isStatisticsMem: boolean = false; 72 73 get isStatisticsMemory(): boolean { 74 return this.isStatisticsMem; 75 } 76 set isStatisticsMemory(value) { 77 let hideThreadEL = this.shadowRoot?.querySelector('.popover .tree-check:nth-child(4)'); 78 if (value) { 79 hideThreadEL?.classList.add('hide'); 80 } else { 81 if (hideThreadEL!.classList.contains('hide')) { 82 hideThreadEL!.classList.remove('hide'); 83 } 84 } 85 } 86 87 filterData( 88 type: string, 89 data: object = {} 90 ): { 91 type: string; 92 inputValue: string; 93 firstSelect: string | undefined; 94 secondSelect: string | undefined; 95 thirdSelect: string | undefined; 96 mark: boolean; 97 icon: string; 98 } { 99 return { 100 type: type, 101 inputValue: this.filterInputEL!.value, 102 firstSelect: this.firstSelectEL?.value, 103 secondSelect: this.secondSelectEL?.value, 104 thirdSelect: this.thirdSelectEL?.value, 105 mark: false, 106 icon: this.icon, 107 ...data, 108 }; 109 } 110 111 showThird(b: boolean): void { 112 if (b) { 113 if (this.thirdSelectEL?.value) { 114 this.setAttribute('third', ''); 115 } else { 116 this.removeAttribute('third'); 117 } 118 } else { 119 this.removeAttribute('third'); 120 } 121 } 122 123 disabledTransfer(b: boolean, str?: string): void { 124 if (b) { 125 this.setAttribute('disableTransfer', ''); 126 } else { 127 if (str === 'perf') { 128 this.setAttribute('perf', 'perf'); 129 } 130 this.removeAttribute('disableTransfer'); 131 } 132 } 133 134 initElements(): void { 135 this.cutList = []; 136 this.libraryList = []; 137 this.filterInputEL = this.shadowRoot?.querySelector('#pane-filter-input'); 138 this.markButtonEL = this.shadowRoot?.querySelector('#mark'); 139 this.iconEL = this.shadowRoot?.querySelector<LitIcon>('#icon'); 140 this.statisticsName = this.shadowRoot?.querySelector<HTMLDivElement>('.statistics-name'); 141 let transferEL = this.shadowRoot?.querySelector<HTMLDivElement>('.transfer-text'); 142 transferEL!.onclick = (): void => { 143 this.getTransferList(); 144 }; 145 this.setSelectList(); 146 this.initializeCallTree(); 147 this.initializeTreeConstraints(); 148 this.initializeMining(); 149 this.initializeLibrary(); 150 this.initBaseElListener(); 151 this.queryElListener(); 152 this.filterInputEL?.addEventListener('keydown', (ev) => { 153 if (ev.key === 'Enter') { 154 ev.stopPropagation(); 155 } 156 }); 157 } 158 159 private queryElListener(): void { 160 this.shadowRoot!.querySelectorAll<HTMLDivElement>('.mining-button').forEach( 161 (e: HTMLDivElement, idx: number): void => { 162 this.miningButtonClickListener(e, idx); 163 } 164 ); 165 this.shadowRoot!.querySelector<HTMLDivElement>('.library-button')!.onclick = (ev): void => { 166 // @ts-ignore 167 const restoreList = this.libraryList!.filter((item) => item.highlight === true); 168 // @ts-ignore 169 const list = this.libraryList!.filter((item) => item.highlight === false); 170 this.libraryList = list; 171 if (this.getLibrary) { 172 this.getLibrary({ 173 type: 'button', 174 item: 'restore', 175 remove: restoreList, 176 }); 177 } 178 this.initializeLibrary(); 179 }; 180 this.shadowRoot!.querySelector<HTMLDivElement>('#data-mining')!.onclick = (e): void => { 181 if (this.getMining) { 182 this.getMining({ type: 'button', item: 'symbol' }); 183 } 184 }; 185 this.shadowRoot!.querySelector<HTMLDivElement>('#data-library')!.onclick = (e): void => { 186 if (this.getLibrary) { 187 this.getLibrary({ type: 'button', item: 'library' }); 188 } 189 }; 190 this.shadowRoot!.querySelector<HTMLDivElement>('.sort')!.onclick = (e): void => { 191 let statisticsType = this.statisticsName!.textContent === 'Statistics by Operation'; 192 this.statisticsName!.textContent = statisticsType ? 'Statistics by Thread' : 'Statistics by Operation'; 193 if (this.getStatisticsType) { 194 this.getStatisticsType(statisticsType ? 'thread' : 'operation'); 195 } 196 }; 197 } 198 199 private initBaseElListener(): void { 200 this.iconEL!.onclick = (): void => { 201 if (this.iconEL!.name === 'statistics') { 202 this.iconEL!.name = 'menu'; 203 this.iconEL!.size = 18; 204 if (this.getFilter) { 205 this.getFilter(this.filterData('icon')); 206 } 207 if (this.getAttribute('perf') === 'perf') { 208 this.disabledTransfer(false); 209 } 210 } else if (this.iconEL!.name === 'menu') { 211 this.iconEL!.name = 'statistics'; 212 this.iconEL!.size = 16; 213 if (this.getFilter) { 214 this.getFilter(this.filterData('icon')); 215 } 216 if (this.getAttribute('perf') === 'perf') { 217 this.disabledTransfer(true); 218 } 219 } 220 }; 221 this.markButtonEL!.onclick = (): void => { 222 if (this.getFilter) { 223 this.getFilter(this.filterData('mark', { mark: true })); 224 } 225 }; 226 this.filterInputEL?.addEventListener('keyup', (event: unknown): void => { 227 // @ts-ignore 228 if (event.keyCode === 13 && this.getFilter) { 229 this.getFilter( 230 this.filterData('inputValue', { 231 // @ts-ignore 232 inputValue: event.target.value, 233 }) 234 ); 235 } 236 // @ts-ignore 237 event.stopPropagation(); 238 }); 239 this.filterInputEL?.addEventListener('keypress', (event: unknown): void => { 240 // @ts-ignore 241 event.stopPropagation(); 242 }); 243 } 244 245 private miningButtonClickListener(e: HTMLDivElement, idx: number): void { 246 e!.onclick = (ev): void => { 247 if (idx === 0) { 248 // @ts-ignore 249 const restoreList = this.cutList!.filter((item: unknown): boolean => item.highlight === true); 250 // @ts-ignore 251 const list = this.cutList!.filter((item): boolean => item.highlight === false); 252 this.cutList = list; 253 if (this.getMining) { 254 this.getMining({ 255 type: 'button', 256 item: 'restore', 257 remove: restoreList, 258 }); 259 } 260 this.initializeMining(); 261 } 262 }; 263 } 264 265 set firstSelect(value: string) { 266 this.firstSelectEL!.value = value; 267 } 268 269 get firstSelect(): string { 270 return this.firstSelectEL?.value || ''; 271 } 272 273 set secondSelect(value: string) { 274 this.secondSelectEL!.value = value; 275 } 276 277 get secondSelect(): string { 278 return this.secondSelectEL?.value || ''; 279 } 280 281 set filterValue(value: string) { 282 this.filterInputEL!.value = value; 283 } 284 285 get filterValue(): string { 286 return this.filterInputEL!.value; 287 } 288 289 set thirdSelect(value: string) { 290 this.thirdSelectEL!.value = value; 291 } 292 293 get thirdSelect(): string { 294 return this.thirdSelectEL?.value || ''; 295 } 296 297 get inputPlaceholder(): string { 298 return this.getAttribute('inputPlaceholder') || 'Detail Filter'; 299 } 300 301 get icon(): string { 302 if (this.getAttribute('icon') !== 'false') { 303 if (this.iconEL!.name === 'statistics') { 304 return 'tree'; 305 } else if (this.iconEL!.name === 'menu') { 306 return 'block'; 307 } else { 308 return ''; 309 } 310 } else { 311 return ''; 312 } 313 } 314 315 set icon(value: string) { 316 if (value === 'block') { 317 this.iconEL!.name = 'menu'; 318 this.iconEL!.size = 18; 319 } else if (value === 'tree') { 320 this.iconEL!.name = 'statistics'; 321 this.iconEL!.size = 16; 322 } 323 } 324 325 get disabledMining(): boolean { 326 return this.hasAttribute('disabledMining'); 327 } 328 329 set disabledMining(value: boolean) { 330 if (value) { 331 this.setAttribute('disabledMining', ''); 332 } else { 333 this.removeAttribute('disabledMining'); 334 } 335 } 336 337 setFilterModuleSelect(module: string, styleName: unknown, value: unknown): void { 338 // @ts-ignore 339 this.shadowRoot!.querySelector<HTMLDivElement>(module)!.style[styleName] = value; 340 } 341 342 getCallTreeData(getCallTree: (v: unknown) => void): void { 343 this.getCallTree = getCallTree; 344 } 345 346 getCallTransferData(getCallTransfer: (v: unknown) => void): void { 347 this.getCallTransfer = getCallTransfer; 348 } 349 350 getCallTreeConstraintsData(getCallTreeConstraints: (v: unknown) => void): void { 351 this.getCallTreeConstraints = getCallTreeConstraints; 352 } 353 354 getFilterData(getFilter: (v: FilterData) => void): void { 355 this.getFilter = getFilter; 356 } 357 358 getStatisticsTypeData(getStatisticsType: (v: unknown) => void): void { 359 this.getStatisticsType = getStatisticsType; 360 } 361 362 setSelectList( 363 firstList: Array<unknown> | null | undefined = ['All Allocations', 'Created & Existing', 'Created & Destroyed'], 364 secondList: Array<unknown> | null | undefined = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM'], 365 firstTitle = 'Allocation Lifespan', 366 secondTitle = 'Allocation Type', 367 thirdList: Array<unknown> | null | undefined = null, 368 thirdTitle = 'Responsible Library' 369 ): void { 370 let sLE = this.shadowRoot?.querySelector('#load'); 371 let html = ''; 372 html = this.getSelectFirstListHtml(firstTitle, firstList, html); 373 html = this.getSelectSecondListHtml(secondTitle, secondList, html); 374 let thtml = this.getSelectThirdListHtml(thirdTitle, thirdList); 375 if (!firstList && !secondList) { 376 this.thirdSelectEL!.outerHTML = thtml; 377 this.thirdSelectEL = this.shadowRoot?.querySelector('#third-select'); 378 this.thirdSelectEL!.onchange = (e): void => { 379 if (this.getFilter) { 380 this.getFilter(this.filterData('thirdSelect')); 381 } 382 }; 383 return; 384 } 385 if (!firstList) { 386 this.secondSelectEL!.outerHTML = html; 387 } else if (!secondList) { 388 this.firstSelectEL!.outerHTML = html; 389 } else { 390 sLE!.innerHTML = html + thtml; 391 } 392 this.thirdSelectEL = this.shadowRoot?.querySelector('#third-select'); 393 this.thirdSelectEL!.outerHTML = thtml; 394 this.thirdSelectEL = this.shadowRoot?.querySelector('#third-select'); 395 396 this.firstSelectEL = this.shadowRoot?.querySelector('#first-select'); 397 this.secondSelectEL = this.shadowRoot?.querySelector('#second-select'); 398 this.initSelectElListener(); 399 } 400 401 private getSelectThirdListHtml(thirdTitle: string, thirdList: Array<unknown> | null | undefined): string { 402 let thtml = ''; 403 if (thirdList) { 404 this.setAttribute('third', ''); 405 } 406 thtml += `<lit-select show-search default-value="" id="third-select" class="spacing" placeholder="please choose">`; 407 if (thirdList) { 408 if (thirdTitle !== '') { 409 thtml += `<lit-select-option value="${thirdTitle}" disabled>${thirdTitle}</lit-select-option>`; 410 } 411 thirdList!.forEach((a, b) => { 412 thtml += `<lit-select-option value="${b}">${a}</lit-select-option>`; 413 }); 414 } 415 thtml += '</lit-select>'; 416 return thtml; 417 } 418 419 private getSelectSecondListHtml( 420 secondTitle: string, 421 secondList: Array<unknown> | null | undefined, 422 html: string 423 ): string { 424 if (secondList) { 425 html += `<lit-select default-value="" id="second-select" class="spacing" placeholder="please choose" tabselect>`; 426 if (secondTitle !== '') { 427 html += `<lit-select-option value="${secondTitle}" disabled>${secondTitle}</lit-select-option>`; 428 } 429 secondList!.forEach((a, b) => { 430 html += `<lit-select-option value="${b}">${a}</lit-select-option>`; 431 }); 432 html += `</lit-select>`; 433 } 434 return html; 435 } 436 437 private getSelectFirstListHtml( 438 firstTitle: string, 439 firstList: Array<unknown> | null | undefined, 440 html: string 441 ): string { 442 if (firstList) { 443 html += `<lit-select default-value="" id="first-select" class="spacing" placeholder="please choose" tabselect>`; 444 if (firstTitle !== '') { 445 html += `<lit-select-option value="${firstTitle}" disabled>${firstTitle}</lit-select-option>`; 446 } 447 firstList!.forEach((a, b) => { 448 html += `<lit-select-option value="${b}">${a}</lit-select-option>`; 449 }); 450 html += `</lit-select>`; 451 } 452 return html; 453 } 454 455 private initSelectElListener(): void { 456 this.firstSelectEL!.onchange = (e): void => { 457 if (this.getFilter) { 458 this.getFilter(this.filterData('firstSelect')); 459 } 460 }; 461 this.secondSelectEL!.onchange = (e): void => { 462 if (this.getFilter) { 463 this.getFilter(this.filterData('secondSelect')); 464 } 465 }; 466 this.thirdSelectEL!.onchange = (e): void => { 467 if (this.getFilter) { 468 this.getFilter(this.filterData('thirdSelect')); 469 } 470 }; 471 } 472 473 setOptionsList(list: Array<unknown>): void { 474 let divEl = this.shadowRoot!.querySelector('#check-popover > div'); 475 divEl!.innerHTML = ''; 476 for (let text of list) { 477 // @ts-ignore 478 let idName = text.replace(/\s/g, ''); 479 idName = idName[0].toLocaleLowerCase() + idName.slice(1); 480 divEl!.innerHTML += `<div class="check-wrap"><lit-check-box class="lit-check-box" id=${idName} not-close></lit-check-box><div>${text}</div></div>`; 481 } 482 } 483 484 //添加cpu列表 485 setCoreConfigList(count: number, small: Array<number>, mid: Array<number>, large: Array<number>): void { 486 let divEl = this.shadowRoot!.querySelector('#data-core-popover > div > #tb_core_setting'); 487 divEl!.innerHTML = ''; 488 this.createCoreHeaderDiv(divEl); 489 for (let i = 0; i < count; i++) { 490 let obj = { 491 cpu: i, 492 // @ts-ignore 493 small: small.includes(i), 494 // @ts-ignore 495 medium: mid.includes(i), 496 // @ts-ignore 497 large: large.includes(i), 498 }; 499 this.createCheckBoxLine(divEl, obj, small, mid, large); 500 } 501 } 502 503 createCoreHeaderDiv(tab: unknown): void { 504 let cpuIdLine = document.createElement('div'); 505 cpuIdLine.className = 'core_line'; 506 cpuIdLine.style.fontWeight = 'bold'; 507 cpuIdLine.style.fontSize = '12px'; 508 cpuIdLine.textContent = 'Cpu'; 509 cpuIdLine.style.textAlign = 'center'; 510 let smallLine = document.createElement('div'); 511 smallLine.className = 'core_line'; 512 smallLine.style.fontWeight = 'bold'; 513 smallLine.textContent = 'S'; 514 smallLine.style.fontSize = '12px'; 515 smallLine.style.textAlign = 'center'; 516 let mediumLine = document.createElement('div'); 517 mediumLine.className = 'core_line'; 518 mediumLine.style.fontWeight = 'bold'; 519 mediumLine.textContent = 'M'; 520 mediumLine.style.fontSize = '12px'; 521 mediumLine.style.textAlign = 'center'; 522 let largeLine = document.createElement('div'); 523 largeLine.className = 'core_line'; 524 largeLine.style.fontWeight = 'bold'; 525 largeLine.textContent = 'L'; 526 largeLine.style.fontSize = '12px'; 527 largeLine.style.textAlign = 'center'; 528 // @ts-ignore 529 tab?.append(...[cpuIdLine, smallLine, mediumLine, largeLine]); 530 } 531 532 //添加对应的cpu checkbox,并添加对应的监听事件 533 createCheckBoxLine( 534 divEl: unknown, 535 cpuStatus: CpuStatus, 536 small: Array<number>, 537 mid: Array<number>, 538 large: Array<number> 539 ): void { 540 let div = document.createElement('div'); 541 div.textContent = cpuStatus.cpu + ''; 542 div.style.textAlign = 'center'; 543 div.style.fontWeight = 'normal'; 544 let smallCheckBox: LitCheckBox = new LitCheckBox(); 545 smallCheckBox.checked = cpuStatus.small; 546 smallCheckBox.setAttribute('not-close', ''); 547 smallCheckBox.style.textAlign = 'center'; 548 smallCheckBox.style.marginLeft = 'auto'; 549 smallCheckBox.style.marginRight = 'auto'; 550 let midCheckBox: LitCheckBox = new LitCheckBox(); 551 midCheckBox.checked = cpuStatus.medium; 552 midCheckBox.setAttribute('not-close', ''); 553 midCheckBox.style.textAlign = 'center'; 554 midCheckBox.style.marginLeft = 'auto'; 555 midCheckBox.style.marginRight = 'auto'; 556 let largeCheckBox: LitCheckBox = new LitCheckBox(); 557 largeCheckBox.checked = cpuStatus.large; 558 largeCheckBox.setAttribute('not-close', ''); 559 largeCheckBox.style.marginLeft = 'auto'; 560 largeCheckBox.style.marginRight = 'auto'; 561 smallCheckBox.addEventListener('change', (e: unknown) => { 562 midCheckBox.checked = false; 563 largeCheckBox.checked = false; 564 // @ts-ignore 565 cpuStatus.small = e.detail.checked; 566 // @ts-ignore 567 this.canUpdateCheckList(e.detail.checked, small, cpuStatus.cpu); 568 mid = mid.filter((it) => it !== cpuStatus.cpu); 569 large = large.filter((it) => it !== cpuStatus.cpu); 570 }); 571 midCheckBox.addEventListener('change', (e: unknown) => { 572 largeCheckBox.checked = false; 573 smallCheckBox.checked = false; 574 // @ts-ignore 575 cpuStatus.medium = e.detail.checked; 576 // @ts-ignore 577 this.canUpdateCheckList(e.detail.checked, mid, cpuStatus.cpu); 578 large = large.filter((it) => it !== cpuStatus.cpu); 579 small = small.filter((it) => it !== cpuStatus.cpu); 580 }); 581 largeCheckBox.addEventListener('change', (e: unknown) => { 582 midCheckBox.checked = false; 583 smallCheckBox.checked = false; 584 // @ts-ignore 585 cpuStatus.large = e.detail.checked; 586 // @ts-ignore 587 this.canUpdateCheckList(e.detail.checked, large, cpuStatus.cpu); 588 mid = mid.filter((it) => it !== cpuStatus.cpu); 589 small = small.filter((it) => it !== cpuStatus.cpu); 590 }); 591 // @ts-ignore 592 divEl!.append(...[div, smallCheckBox, midCheckBox, largeCheckBox]); 593 } 594 595 //判断checkList数组是否需要push数据或删除数据 596 canUpdateCheckList(check: boolean, coreArr: Array<number>, cpu: number): void { 597 if (check) { 598 const isFalse = coreArr.includes(cpu); 599 if (!isFalse) { 600 coreArr.push(cpu); 601 } 602 } else { 603 const index = coreArr.indexOf(cpu); 604 if (index !== -1) { 605 coreArr.splice(index, 1); 606 } 607 } 608 } 609 610 private treeCheckClickSwitch(idx: number, check: boolean, row: NodeListOf<Element>): void { 611 let checkList = []; 612 for (let index = 0; index < 6; index++) { 613 if (idx === index) { 614 checkList.push(check); 615 } else { 616 checkList.push(row[index].querySelector<LitCheckBox>('lit-check-box')!.checked); 617 } 618 } 619 this.getCallTree!({ 620 checks: checkList, 621 value: idx, 622 }); 623 } 624 625 initializeCallTree(): void { 626 let row = this.shadowRoot!.querySelectorAll('.tree-check'); 627 row.forEach((e, idx): void => { 628 let check = e.querySelector<LitCheckBox>('lit-check-box'); 629 e.querySelector('div')!.onclick = (ev): void => { 630 if (this.getCallTree) { 631 this.treeCheckClickSwitch(idx, !check!.checked, row); 632 } 633 check!.checked = !check!.checked; 634 }; 635 check!.onchange = (ev: unknown): void => { 636 if (this.getCallTree) { 637 // @ts-ignore 638 this.treeCheckClickSwitch(idx, ev.target.checked, row); 639 } 640 }; 641 }); 642 } 643 644 initializeTreeTransfer(): void { 645 let radioList = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.radio'); 646 let divElement = this.shadowRoot!.querySelectorAll<HTMLDivElement>('.tree-radio'); 647 648 if (this.transferChecked && this.transferChecked !== 'count') { 649 radioList![Number(this.transferChecked)].checked = true; 650 } else if (this.transferChecked && this.transferChecked === 'count') { 651 radioList![radioList.length - 1].checked = true; 652 } 653 654 divElement!.forEach((divEl, idx) => { 655 divEl.addEventListener('click', () => { 656 let filterData = this.getFilterTreeData(); 657 if (filterData.callTree[0] === true || filterData.callTree[1] === true) { 658 let row = this.shadowRoot!.querySelectorAll<LitCheckBox>('.tree-check lit-check-box'); 659 row[0].checked = false; 660 row[1].checked = false; 661 } 662 if (filterData.callTreeConstraints.checked === true) { 663 let check = this.shadowRoot!.querySelector<LitCheckBox>('#constraints-check'); 664 let inputs = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.constraints-input'); 665 check!.checked = false; 666 inputs[0].value = '0'; 667 inputs[1].value = '∞'; 668 } 669 this.filterInputEL!.value = ''; 670 this.transferChecked = radioList![idx].value; 671 radioList![idx].checked = true; 672 if (this.getCallTransfer) { 673 this.getCallTransfer({ 674 value: radioList![idx].value, 675 }); 676 } 677 }); 678 }); 679 } 680 681 refreshTreeTransfer(): void { 682 let radioList = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.radio'); 683 if (this.transferChecked && this.transferChecked !== 'count') { 684 radioList![Number(this.transferChecked)].checked = false; 685 } else if (this.transferChecked && this.transferChecked === 'count') { 686 radioList![radioList.length - 1].checked = false; 687 } 688 this.transferChecked = ''; 689 } 690 691 initializeTreeConstraints(): void { 692 let inputs = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.constraints-input'); 693 let check = this.shadowRoot!.querySelector<LitCheckBox>('#constraints-check'); 694 check!.onchange = (ev: unknown): void => { 695 inputs.forEach((e: unknown, idx: number): void => { 696 if (inputs[idx].value === '') { 697 inputs[idx].value = idx === 0 ? '0' : '∞'; 698 } 699 // @ts-ignore 700 ev.target.checked ? e.removeAttribute('disabled') : e.setAttribute('disabled', ''); 701 }); 702 if (this.getCallTreeConstraints) { 703 this.getCallTreeConstraints({ 704 // @ts-ignore 705 checked: ev.target.checked, 706 min: inputs[0].value, 707 max: inputs[1].value, 708 }); 709 } 710 }; 711 inputs.forEach((e: HTMLInputElement, idx: number): void => { 712 e.oninput = function (): void { 713 // @ts-ignore 714 this.value = this.value.replace(/\D/g, ''); 715 }; 716 e.addEventListener('keyup', (event: unknown): void => { 717 // @ts-ignore 718 event.stopPropagation(); 719 // @ts-ignore 720 if (event.keyCode === 13) { 721 // @ts-ignore 722 if (event?.target.value === '') { 723 inputs[idx].value = idx === 0 ? '0' : '∞'; 724 } 725 if (this.getCallTreeConstraints) { 726 this.getCallTreeConstraints({ 727 checked: check!.checked, 728 // @ts-ignore 729 min: idx === 0 ? event?.target.value : inputs[0].value, 730 // @ts-ignore 731 max: idx === 1 ? event?.target.value : inputs[1].value, 732 }); 733 } 734 } 735 }); 736 }); 737 } 738 739 initializeMining(): void { 740 let html = ''; 741 this.cutList!.forEach((a: unknown, b: number): void => { 742 // @ts-ignore 743 html += `<div style="display: flex;padding: 4px 7px;" class="mining-checked" ${a.highlight ? 'highlight' : ''}> 744 <lit-check-box class="lit-check-box" not-close ${ 745 // @ts-ignore 746 a.checked ? 'checked' : '' 747 } style="display: flex"></lit-check-box> 748 749 <div id="title" title="${ 750 // @ts-ignore 751 a.name 752 }">${ 753 // @ts-ignore 754 a.name 755 }</div></div>`; 756 }); 757 758 this.shadowRoot!.querySelector<HTMLDivElement>('#mining-row')!.innerHTML = html; 759 760 let row = this.shadowRoot!.querySelector('#mining-row')!.childNodes; 761 row!.forEach((e: unknown, idx: number): void => { 762 // @ts-ignore 763 e!.querySelector('#title')!.onclick = (ev: unknown): void => { 764 // @ts-ignore 765 if (e.getAttribute('highlight') === '') { 766 // @ts-ignore 767 e.removeAttribute('highlight'); 768 // @ts-ignore 769 this.cutList![idx].highlight = false; 770 } else { 771 // @ts-ignore 772 e.setAttribute('highlight', ''); 773 // @ts-ignore 774 this.cutList![idx].highlight = true; 775 } 776 }; 777 // @ts-ignore 778 e!.querySelector<LitCheckBox>('lit-check-box')!.onchange = (ev): void => { 779 // @ts-ignore 780 this.cutList[idx].checked = e!.querySelector<LitCheckBox>('lit-check-box')!.checked; 781 if (this.getMining) { 782 this.getMining({ type: 'check', item: this.cutList![idx] }); 783 } 784 }; 785 }); 786 } 787 788 initializeLibrary(): void { 789 let html = ''; 790 this.libraryList!.forEach((a: unknown, b: number): void => { 791 // @ts-ignore 792 html += `<div style="display: flex;padding: 4px 7px;" class="library-checked" ${a.highlight ? 'highlight' : ''}> 793 <lit-check-box class="lit-check-box" not-close ${ 794 // @ts-ignore 795 a.checked ? 'checked' : '' 796 } style="display: flex"></lit-check-box> 797 <div id="title" title="${ 798 // @ts-ignore 799 a.name 800 }">${ 801 // @ts-ignore 802 a.name 803 }</div></div>`; 804 }); 805 806 this.shadowRoot!.querySelector<HTMLDivElement>('#library-row')!.innerHTML = html; 807 808 let row = this.shadowRoot!.querySelector('#library-row')!.childNodes; 809 row!.forEach((e: unknown, idx: number): void => { 810 // @ts-ignore 811 e!.querySelector('#title')!.onclick = (ev: unknown): void => { 812 // @ts-ignore 813 if (e.getAttribute('highlight') === '') { 814 // @ts-ignore 815 e.removeAttribute('highlight'); 816 // @ts-ignore 817 this.libraryList![idx].highlight = false; 818 } else { 819 // @ts-ignore 820 e.setAttribute('highlight', ''); 821 // @ts-ignore 822 this.libraryList![idx].highlight = true; 823 } 824 }; 825 826 // @ts-ignore 827 e!.querySelector<LitCheckBox>('lit-check-box')!.onchange = (ev: unknown): void => { 828 // @ts-ignore 829 this.libraryList[idx].checked = e!.querySelector<LitCheckBox>('lit-check-box')!.checked; 830 if (this.getLibrary) { 831 this.getLibrary({ 832 type: 'check', 833 item: this.libraryList![idx], 834 }); 835 } 836 }; 837 }); 838 } 839 840 getDataMining(getMining: (v: MiningData) => void): void { 841 this.getMining = getMining; 842 } 843 844 getDataLibrary(getLibrary: (v: MiningData) => void): void { 845 this.getLibrary = getLibrary; 846 } 847 848 addDataMining(data: unknown, type: string): number { 849 let list: Array<unknown> = (type === 'symbol' ? this.cutList : this.libraryList) || []; 850 // @ts-ignore 851 let idx = list!.findIndex((e) => e.name === data.name); 852 if (idx === -1) { 853 list!.push({ 854 type: type, 855 // @ts-ignore 856 name: data.name, 857 checked: true, 858 select: '1', 859 data: data, 860 highlight: false, 861 }); 862 } else { 863 list![idx] = { 864 type: type, 865 // @ts-ignore 866 name: data.name, 867 checked: true, 868 select: '1', 869 data: data, 870 highlight: false, 871 }; 872 } 873 this.initializeMining(); 874 this.initializeLibrary(); 875 return idx; 876 } 877 878 getFilterTreeData(): { 879 callTree: boolean[]; 880 callTreeConstraints: { 881 checked: boolean; 882 inputs: string[]; 883 }; 884 dataMining: unknown[] | undefined; 885 dataLibrary: unknown[] | undefined; 886 } { 887 let row = this.shadowRoot!.querySelectorAll<LitCheckBox>('.tree-check lit-check-box'); 888 let inputs = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.constraints-input'); 889 let check = this.shadowRoot!.querySelector<LitCheckBox>('#constraints-check'); 890 let data = { 891 callTree: [row[0]!.checked, row[1]!.checked, row[2]!.checked, row[3]!.checked, row[4]!.checked, row[5]!.checked], 892 callTreeConstraints: { 893 checked: check!.checked, 894 inputs: [inputs[0].value === '' ? '0' : inputs[0].value, inputs[1].value === '' ? '∞' : inputs[1].value], 895 }, 896 dataMining: this.cutList, 897 dataLibrary: this.libraryList, 898 }; 899 return data; 900 } 901 902 async getTransferList(): Promise<void> { 903 let dataCmd: { id: number; cmdStr: string }[] = (await queryTransferList()) as { id: number; cmdStr: string }[]; 904 let html = ''; 905 dataCmd.forEach((item: { id: number; cmdStr: string }): void => { 906 html += `<div id="cycles-btn" class="tree-radio"> 907 <input name="transfer" class="radio" type="radio" value="${item.id}" style="margin-right:8px" />${item.cmdStr}</div>`; 908 }); 909 html += `<div id="cycles-btn" class="tree-radio"> 910 <input name="transfer" class="radio" type="radio" value="count" style="margin-right:8px" />Count</div>`; 911 this.shadowRoot!.querySelector<HTMLDivElement>('#transfer-list')!.innerHTML = html; 912 this.initializeTreeTransfer(); 913 } 914 915 initializeFilterTree(callTree: boolean = true, treeConstraints: boolean = true, mining: boolean = true): void { 916 if (callTree) { 917 let row = this.shadowRoot!.querySelectorAll('.tree-check'); 918 row.forEach((e: Element, idx: number): void => { 919 let check = e.querySelector<LitCheckBox>('lit-check-box'); 920 check!.checked = false; 921 }); 922 } 923 if (treeConstraints) { 924 let inputs = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.constraints-input'); 925 if (inputs.length > 0) { 926 inputs[0].value = '0'; 927 inputs[1].value = '∞'; 928 } 929 let check = this.shadowRoot!.querySelector<LitCheckBox>('#constraints-check'); 930 check!.checked = false; 931 } 932 if (mining) { 933 this.cutList = []; 934 this.libraryList = []; 935 this.initializeMining(); 936 this.initializeLibrary(); 937 } 938 } 939 940 initHtml(): string { 941 return TabPaneFilterHtml(this.inputPlaceholder); 942 } 943} 944