• 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  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 show-search default-value="" id="second-select" class="spacing" placeholder="please choose">`;
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">`;
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        SpSystemTrace.isKeyUp = true;
718        // @ts-ignore
719        event.stopPropagation();
720        // @ts-ignore
721        if (event.keyCode === 13) {
722          // @ts-ignore
723          if (event?.target.value === '') {
724            inputs[idx].value = idx === 0 ? '0' : '∞';
725          }
726          if (this.getCallTreeConstraints) {
727            this.getCallTreeConstraints({
728              checked: check!.checked,
729              // @ts-ignore
730              min: idx === 0 ? event?.target.value : inputs[0].value,
731              // @ts-ignore
732              max: idx === 1 ? event?.target.value : inputs[1].value,
733            });
734          }
735        }
736      });
737    });
738  }
739
740  initializeMining(): void {
741    let html = '';
742    this.cutList!.forEach((a: unknown, b: number): void => {
743      // @ts-ignore
744      html += `<div style="display: flex;padding: 4px 7px;" class="mining-checked" ${a.highlight ? 'highlight' : ''}>
745                        <lit-check-box class="lit-check-box" not-close ${
746        // @ts-ignore
747        a.checked ? 'checked' : ''
748        } style="display: flex"></lit-check-box>
749
750                        <div id="title" title="${
751        // @ts-ignore
752        a.name
753        }">${
754        // @ts-ignore
755        a.name
756        }</div></div>`;
757    });
758
759    this.shadowRoot!.querySelector<HTMLDivElement>('#mining-row')!.innerHTML = html;
760
761    let row = this.shadowRoot!.querySelector('#mining-row')!.childNodes;
762    row!.forEach((e: unknown, idx: number): void => {
763      // @ts-ignore
764      e!.querySelector('#title')!.onclick = (ev: unknown): void => {
765        // @ts-ignore
766        if (e.getAttribute('highlight') === '') {
767          // @ts-ignore
768          e.removeAttribute('highlight');
769          // @ts-ignore
770          this.cutList![idx].highlight = false;
771        } else {
772          // @ts-ignore
773          e.setAttribute('highlight', '');
774          // @ts-ignore
775          this.cutList![idx].highlight = true;
776        }
777      };
778      // @ts-ignore
779      e!.querySelector<LitCheckBox>('lit-check-box')!.onchange = (ev): void => {
780        // @ts-ignore
781        this.cutList[idx].checked = e!.querySelector<LitCheckBox>('lit-check-box')!.checked;
782        if (this.getMining) {
783          this.getMining({ type: 'check', item: this.cutList![idx] });
784        }
785      };
786    });
787  }
788
789  initializeLibrary(): void {
790    let html = '';
791    this.libraryList!.forEach((a: unknown, b: number): void => {
792      // @ts-ignore
793      html += `<div style="display: flex;padding: 4px 7px;" class="library-checked" ${a.highlight ? 'highlight' : ''}>
794                        <lit-check-box class="lit-check-box" not-close ${
795        // @ts-ignore
796        a.checked ? 'checked' : ''
797        } style="display: flex"></lit-check-box>
798                        <div id="title" title="${
799        // @ts-ignore
800        a.name
801        }">${
802        // @ts-ignore
803        a.name
804        }</div></div>`;
805    });
806
807    this.shadowRoot!.querySelector<HTMLDivElement>('#library-row')!.innerHTML = html;
808
809    let row = this.shadowRoot!.querySelector('#library-row')!.childNodes;
810    row!.forEach((e: unknown, idx: number): void => {
811      // @ts-ignore
812      e!.querySelector('#title')!.onclick = (ev: unknown): void => {
813        // @ts-ignore
814        if (e.getAttribute('highlight') === '') {
815          // @ts-ignore
816          e.removeAttribute('highlight');
817          // @ts-ignore
818          this.libraryList![idx].highlight = false;
819        } else {
820          // @ts-ignore
821          e.setAttribute('highlight', '');
822          // @ts-ignore
823          this.libraryList![idx].highlight = true;
824        }
825      };
826
827      // @ts-ignore
828      e!.querySelector<LitCheckBox>('lit-check-box')!.onchange = (ev: unknown): void => {
829        // @ts-ignore
830        this.libraryList[idx].checked = e!.querySelector<LitCheckBox>('lit-check-box')!.checked;
831        if (this.getLibrary) {
832          this.getLibrary({
833            type: 'check',
834            item: this.libraryList![idx],
835          });
836        }
837      };
838    });
839  }
840
841  getDataMining(getMining: (v: MiningData) => void): void {
842    this.getMining = getMining;
843  }
844
845  getDataLibrary(getLibrary: (v: MiningData) => void): void {
846    this.getLibrary = getLibrary;
847  }
848
849  addDataMining(data: unknown, type: string): number {
850    let list: Array<unknown> = (type === 'symbol' ? this.cutList : this.libraryList) || [];
851    // @ts-ignore
852    let idx = list!.findIndex((e) => e.name === data.name);
853    if (idx === -1) {
854      list!.push({
855        type: type,
856        // @ts-ignore
857        name: data.name,
858        checked: true,
859        select: '1',
860        data: data,
861        highlight: false,
862      });
863    } else {
864      list![idx] = {
865        type: type,
866        // @ts-ignore
867        name: data.name,
868        checked: true,
869        select: '1',
870        data: data,
871        highlight: false,
872      };
873    }
874    this.initializeMining();
875    this.initializeLibrary();
876    return idx;
877  }
878
879  getFilterTreeData(): {
880    callTree: boolean[];
881    callTreeConstraints: {
882      checked: boolean;
883      inputs: string[];
884    };
885    dataMining: unknown[] | undefined;
886    dataLibrary: unknown[] | undefined;
887  } {
888    let row = this.shadowRoot!.querySelectorAll<LitCheckBox>('.tree-check lit-check-box');
889    let inputs = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.constraints-input');
890    let check = this.shadowRoot!.querySelector<LitCheckBox>('#constraints-check');
891    let data = {
892      callTree: [row[0]!.checked, row[1]!.checked, row[2]!.checked, row[3]!.checked, row[4]!.checked, row[5]!.checked],
893      callTreeConstraints: {
894        checked: check!.checked,
895        inputs: [inputs[0].value === '' ? '0' : inputs[0].value, inputs[1].value === '' ? '∞' : inputs[1].value],
896      },
897      dataMining: this.cutList,
898      dataLibrary: this.libraryList,
899    };
900    return data;
901  }
902
903  async getTransferList(): Promise<void> {
904    let dataCmd: { id: number; cmdStr: string }[] = (await queryTransferList()) as { id: number; cmdStr: string }[];
905    let html = '';
906    dataCmd.forEach((item: { id: number; cmdStr: string }): void => {
907      html += `<div id="cycles-btn" class="tree-radio">
908      <input name="transfer" class="radio" type="radio" value="${item.id}" style="margin-right:8px" />${item.cmdStr}</div>`;
909    });
910    html += `<div id="cycles-btn" class="tree-radio">
911    <input name="transfer" class="radio" type="radio" value="count" style="margin-right:8px" />Count</div>`;
912    this.shadowRoot!.querySelector<HTMLDivElement>('#transfer-list')!.innerHTML = html;
913    this.initializeTreeTransfer();
914  }
915
916  initializeFilterTree(callTree: boolean = true, treeConstraints: boolean = true, mining: boolean = true): void {
917    if (callTree) {
918      let row = this.shadowRoot!.querySelectorAll('.tree-check');
919      row.forEach((e: Element, idx: number): void => {
920        let check = e.querySelector<LitCheckBox>('lit-check-box');
921        check!.checked = false;
922      });
923    }
924    if (treeConstraints) {
925      let inputs = this.shadowRoot!.querySelectorAll<HTMLInputElement>('.constraints-input');
926      if (inputs.length > 0) {
927        inputs[0].value = '0';
928        inputs[1].value = '∞';
929      }
930      let check = this.shadowRoot!.querySelector<LitCheckBox>('#constraints-check');
931      check!.checked = false;
932    }
933    if (mining) {
934      this.cutList = [];
935      this.libraryList = [];
936      this.initializeMining();
937      this.initializeLibrary();
938    }
939  }
940
941  initHtml(): string {
942    return TabPaneFilterHtml(this.inputPlaceholder);
943  }
944}
945