• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  little: boolean = false;
47  medium: boolean = false;
48  big: 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, little: Array<number>, mid: Array<number>, big: 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        little: little.includes(i),
494        // @ts-ignore
495        medium: mid.includes(i),
496        // @ts-ignore
497        big: big.includes(i),
498      };
499      this.createCheckBoxLine(divEl, obj, little, mid, big);
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 littleLine = document.createElement('div');
511    littleLine.className = 'core_line';
512    littleLine.style.fontWeight = 'bold';
513    littleLine.textContent = 'L';
514    littleLine.style.fontSize = '12px';
515    littleLine.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 bigLine = document.createElement('div');
523    bigLine.className = 'core_line';
524    bigLine.style.fontWeight = 'bold';
525    bigLine.textContent = 'B';
526    bigLine.style.fontSize = '12px';
527    bigLine.style.textAlign = 'center';
528    // @ts-ignore
529    tab?.append(...[cpuIdLine, littleLine, mediumLine, bigLine]);
530  }
531
532  //添加对应的cpu checkbox,并添加对应的监听事件
533  createCheckBoxLine(
534    divEl: unknown,
535    cpuStatus: CpuStatus,
536    little: Array<number>,
537    mid: Array<number>,
538    big: 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 littleCheckBox: LitCheckBox = new LitCheckBox();
545    littleCheckBox.checked = cpuStatus.little;
546    littleCheckBox.setAttribute('not-close', '');
547    littleCheckBox.style.textAlign = 'center';
548    littleCheckBox.style.marginLeft = 'auto';
549    littleCheckBox.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 bigCheckBox: LitCheckBox = new LitCheckBox();
557    bigCheckBox.checked = cpuStatus.big;
558    bigCheckBox.setAttribute('not-close', '');
559    bigCheckBox.style.marginLeft = 'auto';
560    bigCheckBox.style.marginRight = 'auto';
561    littleCheckBox.addEventListener('change', (e: unknown) => {
562      midCheckBox.checked = false;
563      bigCheckBox.checked = false;
564      // @ts-ignore
565      cpuStatus.little = e.detail.checked;
566      // @ts-ignore
567      this.canUpdateCheckList(e.detail.checked, little, cpuStatus.cpu);
568      mid = mid.filter((it) => it !== cpuStatus.cpu);
569      big = big.filter((it) => it !== cpuStatus.cpu);
570    });
571    midCheckBox.addEventListener('change', (e: unknown) => {
572      bigCheckBox.checked = false;
573      littleCheckBox.checked = false;
574      // @ts-ignore
575      cpuStatus.medium = e.detail.checked;
576      // @ts-ignore
577      this.canUpdateCheckList(e.detail.checked, mid, cpuStatus.cpu);
578      big = big.filter((it) => it !== cpuStatus.cpu);
579      little = little.filter((it) => it !== cpuStatus.cpu);
580    });
581    bigCheckBox.addEventListener('change', (e: unknown) => {
582      midCheckBox.checked = false;
583      littleCheckBox.checked = false;
584      // @ts-ignore
585      cpuStatus.big = e.detail.checked;
586      // @ts-ignore
587      this.canUpdateCheckList(e.detail.checked, big, cpuStatus.cpu);
588      mid = mid.filter((it) => it !== cpuStatus.cpu);
589      little = little.filter((it) => it !== cpuStatus.cpu);
590    });
591    // @ts-ignore
592    divEl!.append(...[div, littleCheckBox, midCheckBox, bigCheckBox]);
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