Browse Source
Refactor: route all iot-hub dialog.open calls through IotHubActionsService; new openInstalledItems/reviewDevice methods; simpler deleteItem/updateItem signatures reading metadata from installedItem. Extract shared code: - iot-hub-utils.ts — filterIotHubItemsBySearch, groupIotHubFilterItems, resolveIotHubItemImageUrl used by browse, search, widget-select, home - _iot-hub-common.scss — mixins for the 40px search/filter input pattern - device-install-dialog — markEntityStepSuccess and saveRuleChainWithMetadata helpers collapse duplicate blocks - update dialog reuses install dialog's SCSS (styles were byte-identical) Cleanup: - Removed 30+ unused methods, fields, and imports across iot-hub components - Removed 14 unused locale keys (iot-hub.* / item.selected / vendor-placeholder) - Deleted unused SCSS selectors (.dlg-close, .dlg-row-1, dlg-info-actions, etc.) - All router.navigate* calls prefixed with void to satisfy ignored-promise hints IDE diagnostics fixed: - 28 a11y errors — added role/tabindex/keyup.enter to interactive divs/spans - Regex redundant escapes and single-char alternations - Bare boolean attrs (stickyEnd, linear, disabled, showFirstLastButtons) converted to [prop]="true" - Merged background/background-image/background-size shorthand - Removed redundant border-bottom overridespull/15508/head
52 changed files with 503 additions and 1471 deletions
@ -0,0 +1,72 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2026 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
// Shared IoT Hub visual building blocks — used across |
||||
|
// iot-hub-browse, iot-hub-search, and dashboard-widget-select |
||||
|
// to keep filter / search controls in sync. |
||||
|
|
||||
|
@mixin tb-iot-hub-search-container { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 8px; |
||||
|
height: 40px; |
||||
|
padding: 8px 12px; |
||||
|
border: 1px solid rgba(0, 0, 0, 0.12); |
||||
|
border-radius: 8px; |
||||
|
background: white; |
||||
|
} |
||||
|
|
||||
|
@mixin tb-iot-hub-search-icon($color: rgba(0, 0, 0, 0.38)) { |
||||
|
font-size: 24px; |
||||
|
width: 24px; |
||||
|
height: 24px; |
||||
|
color: $color; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
@mixin tb-iot-hub-search-input-text($letter-spacing: normal) { |
||||
|
flex: 1; |
||||
|
min-width: 0; |
||||
|
border: none; |
||||
|
outline: none; |
||||
|
padding: 0; |
||||
|
font-family: inherit; |
||||
|
font-size: 14px; |
||||
|
font-weight: 400; |
||||
|
line-height: 20px; |
||||
|
letter-spacing: $letter-spacing; |
||||
|
color: rgba(0, 0, 0, 0.87); |
||||
|
background: transparent; |
||||
|
|
||||
|
&::placeholder { |
||||
|
color: rgba(0, 0, 0, 0.38); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@mixin tb-iot-hub-search-clear { |
||||
|
width: 24px; |
||||
|
height: 24px; |
||||
|
padding: 0; |
||||
|
flex-shrink: 0; |
||||
|
color: rgba(0, 0, 0, 0.38); |
||||
|
--mdc-icon-button-state-layer-size: 24px; |
||||
|
|
||||
|
mat-icon { |
||||
|
font-size: 18px; |
||||
|
width: 18px; |
||||
|
height: 18px; |
||||
|
} |
||||
|
} |
||||
@ -1,58 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2026 The Thingsboard Authors |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
.tb-iot-hub-install-content { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
gap: 20px; |
|
||||
padding: 24px; |
|
||||
} |
|
||||
|
|
||||
.tb-iot-hub-install-title { |
|
||||
font-size: 20px; |
|
||||
font-weight: 600; |
|
||||
line-height: 24px; |
|
||||
letter-spacing: 0.1px; |
|
||||
color: rgba(0, 0, 0, 0.87); |
|
||||
margin: 0; |
|
||||
} |
|
||||
|
|
||||
.tb-iot-hub-install-desc { |
|
||||
color: rgba(0, 0, 0, 0.54); |
|
||||
font-size: 14px; |
|
||||
line-height: 20px; |
|
||||
letter-spacing: 0.2px; |
|
||||
margin: 0; |
|
||||
} |
|
||||
|
|
||||
.tb-iot-hub-inline-spinner { |
|
||||
display: inline-block; |
|
||||
margin-right: 8px; |
|
||||
vertical-align: middle; |
|
||||
} |
|
||||
|
|
||||
.tb-iot-hub-error-details { |
|
||||
max-height: 200px; |
|
||||
overflow-y: auto; |
|
||||
padding: 12px; |
|
||||
background: #f5f5f5; |
|
||||
border-radius: 4px; |
|
||||
font-family: monospace; |
|
||||
font-size: 12px; |
|
||||
color: rgba(0, 0, 0, 0.7); |
|
||||
white-space: pre-wrap; |
|
||||
word-break: break-word; |
|
||||
} |
|
||||
@ -0,0 +1,69 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2026 The Thingsboard Authors
|
||||
|
///
|
||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
/// you may not use this file except in compliance with the License.
|
||||
|
/// You may obtain a copy of the License at
|
||||
|
///
|
||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
///
|
||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
/// See the License for the specific language governing permissions and
|
||||
|
/// limitations under the License.
|
||||
|
///
|
||||
|
|
||||
|
import { FilterParamInfo } from '@shared/models/iot-hub/iot-hub-item.models'; |
||||
|
import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models'; |
||||
|
import { IotHubApiService } from '@core/http/iot-hub-api.service'; |
||||
|
|
||||
|
export const IOT_HUB_FILTER_GROUPING_THRESHOLD = 11; |
||||
|
export const IOT_HUB_FILTER_POPULAR_LIMIT = 10; |
||||
|
|
||||
|
export interface IotHubFilterGroup { |
||||
|
label: string; |
||||
|
items: FilterParamInfo[]; |
||||
|
} |
||||
|
|
||||
|
export function filterIotHubItemsBySearch(items: FilterParamInfo[], search: string): FilterParamInfo[] { |
||||
|
const normalized = (search || '').toLowerCase(); |
||||
|
if (!normalized) { |
||||
|
return items; |
||||
|
} |
||||
|
return items.filter(item => item.key.toLowerCase().includes(normalized)); |
||||
|
} |
||||
|
|
||||
|
export function groupIotHubFilterItems(items: FilterParamInfo[], search: string): IotHubFilterGroup[] { |
||||
|
const filtered = filterIotHubItemsBySearch(items, search); |
||||
|
if (items.length < IOT_HUB_FILTER_GROUPING_THRESHOLD) { |
||||
|
return [{ label: null, items: filtered }]; |
||||
|
} |
||||
|
const topKeys = new Set( |
||||
|
[...items] |
||||
|
.sort((a, b) => b.totalInstallCount - a.totalInstallCount) |
||||
|
.slice(0, IOT_HUB_FILTER_POPULAR_LIMIT) |
||||
|
.map(i => i.key) |
||||
|
); |
||||
|
const popular = filtered.filter(i => topKeys.has(i.key)); |
||||
|
const rest = filtered.filter(i => !topKeys.has(i.key)); |
||||
|
const groups: IotHubFilterGroup[] = []; |
||||
|
if (popular.length) { |
||||
|
groups.push({ label: 'iot-hub.most-popular', items: popular }); |
||||
|
} |
||||
|
if (rest.length) { |
||||
|
groups.push({ label: 'iot-hub.all', items: rest }); |
||||
|
} |
||||
|
return groups; |
||||
|
} |
||||
|
|
||||
|
export function resolveIotHubItemImageUrl(item: MpItemVersionView, api: IotHubApiService): string | null { |
||||
|
if (item.image) { |
||||
|
return api.resolveResourceUrl(item.image); |
||||
|
} |
||||
|
const resource = item.resources?.find(r => r.type === 'SCREENSHOT') || item.resources?.find(r => r.type === 'ICON'); |
||||
|
if (resource) { |
||||
|
return api.resolveResourceUrl(`/api/resources/${resource.id}`); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
Loading…
Reference in new issue