1/* 2 * Copyright (C) 2024 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 */ 15import '../base-ui/menu/MainMenu.js'; 16import '../base-ui/icon/LitIcon.js'; 17import '../base-ui/progress-bar/ProgressBar.js'; 18import './component/search/Search.js'; 19import './component/ApWelcome.js'; 20import {applicationHtml,} from './ApApplicationPublicFunc.js'; 21import './component/sheet/TabPaneApSummary.js'; 22import {TabPaneApSummary} from './component/sheet/TabPaneApSummary.js'; 23 24export class ApApplication extends HTMLElement { 25 constructor() { 26 super(); 27 this.attachShadow({mode: 'open'}).innerHTML = this.initHtml(); 28 this.initElements(); 29 } 30 31 set search(search) { 32 if (search) { 33 this.setAttribute('search', ''); 34 } else { 35 this.removeAttribute('search'); 36 } 37 } 38 39 get search() { 40 return this.hasAttribute('search'); 41 } 42 43 initHtml() { 44 return applicationHtml; 45 } 46 47 initElements() { 48 this.rootEL = this.shadowRoot.querySelector('.root'); 49 this.headerDiv = this.shadowRoot.querySelector('.search-vessel'); 50 this.apWelcome = this.shadowRoot.querySelector('#ap-welcome'); 51 this.apTreeTable = this.shadowRoot.querySelector('#tabpane-summary'); 52 this.mainMenu = this.shadowRoot?.querySelector('#main-menu'); 53 this.menu = this.mainMenu.shadowRoot?.querySelector('.menu-button'); 54 this.progressEL = this.shadowRoot?.querySelector('.progress'); 55 this.litSearch = this.shadowRoot?.querySelector('#lit-search'); 56 this.initElementsAttr(); 57 this.initSearchEvents(); 58 this.resetMenus(); 59 this.initGlobalEvents(); 60 this.initSearchChangeEvents(); 61 } 62 63 initElementsAttr() { 64 this.mainMenu.setAttribute('main_menu', '1'); 65 this.childComponent = [ 66 this.apTreeTable, 67 this.apWelcome, 68 ]; 69 } 70 71 openTraceFile(file) { 72 if (file === null) { 73 return; 74 } 75 this.litSearch.style.marginLeft = '0px'; 76 this.openFileInit(); 77 this.parseApFile(file); 78 } 79 80 initGlobalDropEvents() { 81 let body = document.querySelector('body'); 82 body.addEventListener('drop', (event) => { 83 event.preventDefault(); 84 event.stopPropagation(); 85 if (this.rootEL.classList.contains('filedrag')) { 86 this.rootEL.classList.remove('filedrag'); 87 } 88 if (event && event.dataTransfer && event.dataTransfer.items && 89 event.dataTransfer.items.length > 0) { 90 let item = event.dataTransfer.items[0]; 91 const entry = item.webkitGetAsEntry(); 92 if (entry?.isFile) { 93 this.openTraceFile(item.getAsFile()); 94 } else if (entry?.isDirectory) { 95 this.litSearch.setPercent('This File is not supported!', -1); 96 this.progressEL.loading = false; 97 this.freshMenuDisable(false); 98 } 99 } 100 }, false); 101 } 102 103 initGlobalEvents() { 104 let body = document.querySelector('body'); 105 body.addEventListener('dragover', (event) => { 106 event.preventDefault(); 107 event.stopPropagation(); 108 if (event && event.dataTransfer && event.dataTransfer.items.length > 0 && 109 event.dataTransfer.items[0].kind === 'file') { 110 event.dataTransfer.dropEffect = 'copy'; 111 if (!this.rootEL.classList.contains('filedrag')) { 112 this.rootEL.classList.add('filedrag'); 113 } 114 } 115 }, false); 116 body.addEventListener('dragleave', (event) => { 117 event.stopPropagation(); 118 event.preventDefault(); 119 if (this.rootEL.classList.contains('filedrag')) { 120 this.rootEL.classList.remove('filedrag'); 121 } 122 }, false); 123 this.initGlobalDropEvents(); 124 } 125 126 parseApFile(file) { 127 let fileName = file.name; 128 let showFileName = fileName.lastIndexOf('.') === -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.')); 129 this.litSearch.setPercent('', 1); 130 let fileSizeInKB = (file.size / 1024).toFixed(1); 131 document.title = `${showFileName} (${fileSizeInKB}KB)`; 132 if (!fileName.endsWith('.ap')) { 133 this.litSearch.setPercent('This File is not supported!', -1); 134 this.progressEL.loading = false; 135 this.freshMenuDisable(false); 136 } else { 137 try { 138 this.uploadFile(file).then((value) => { 139 this.litSearch.setPercent('', 101); 140 this.litSearch.style.pointerEvents = 'auto'; 141 this.progressEL.loading = false; 142 this.freshMenuDisable(false); 143 this.apTreeTable.data = TabPaneApSummary.TransformJson(value); 144 }); 145 } catch (httpError) { 146 this.litSearch.setPercent('Parse Filed Please Wait', -1); 147 this.progressEL.loading = false; 148 this.freshMenuDisable(false); 149 } 150 } 151 } 152 153 async uploadFile(file) { 154 const formData = new FormData(); 155 formData.append('file', file, file.name); 156 const response = await fetch(`${window.location.origin}/ap/upload`, { 157 method: 'POST', 158 body: formData, 159 }); 160 if (!response.ok) { 161 throw new Error(`file Upload Failed,status:${response.status}`); 162 } 163 return await response.text(); 164 } 165 166 initSearchEvents() { 167 this.litSearch.addEventListener('focus', () => { 168 }); 169 this.litSearch.addEventListener('ap-change', () => { 170 }); 171 this.initSearchChangeEvents(); 172 } 173 174 resetMenus() { 175 this.mainMenu.menus = [ 176 { 177 collapsed: false, 178 title: 'Navigation', 179 second: false, 180 icon: 'caret-down', 181 describe: 'Import ap file', 182 children: [ 183 { 184 title: 'Import ap file', 185 icon: 'folder', 186 fileChoose: true, 187 fileHandler: (ev) => { 188 this.openTraceFile(ev.detail); 189 }, 190 } 191 ], 192 } 193 ]; 194 } 195 196 openFileInit() { 197 this.litSearch.clear(); 198 this.headerDiv.style.pointerEvents = 'none'; 199 this.resetMenus(); 200 this.freshMenuDisable(true); 201 this.showContent(this.apTreeTable); 202 this.progressEL.loading = true; 203 } 204 205 initSearchChangeEvents() { 206 let timer; 207 this.litSearch.valueChangeHandler = (value) => { 208 this.litSearch.list = []; 209 if (timer) { 210 clearTimeout(timer); 211 } 212 timer = setTimeout(() => { 213 this.litSearch.isClearValue = false; 214 if (value.length > 0) { 215 this.apTreeTable.filterData(value.toString().toLowerCase()); 216 } else { 217 this.litSearch.list = []; 218 this.apTreeTable.filterData(''); 219 } 220 this.apTreeTable.expansionAll(); 221 }, 500); 222 }; 223 } 224 225 showContent(showNode) { 226 if (showNode === this.apTreeTable) { 227 this.menu.style.pointerEvents = 'auto'; 228 this.search = true; 229 this.litSearch.style.display = 'block'; 230 } else { 231 this.menu.style.pointerEvents = 'none'; 232 this.search = this.litSearch.isLoading; 233 if (!this.search) { 234 this.litSearch.style.display = 'none'; 235 } 236 } 237 this.childComponent.forEach((node) => { 238 if (node === showNode) { 239 showNode.style.visibility = 'visible'; 240 } else { 241 node.style.visibility = 'hidden'; 242 } 243 }); 244 } 245 246 247 freshMenuDisable(disable) { 248 let menus; 249 this.mainMenu.menus[0].children[0].disabled = disable; 250 if (this.mainMenu.menus.length > 2) { 251 (menus = this.mainMenu.menus) === null || menus === void 0 ? void 0 : menus[1].children.map((it) => (it.disabled = disable)); 252 } 253 } 254} 255 256if (!customElements.get('ap-application')) { 257 customElements.define('ap-application', ApApplication); 258} 259