Skip to content

Commit 0fa3690

Browse files
committed
[NAE-2051] Implement configurable view in menu items
- rework component resolving because of backend changes - rename preference_item to menu_item
1 parent 4ebdbdb commit 0fa3690

File tree

7 files changed

+93
-82
lines changed

7 files changed

+93
-82
lines changed

projects/netgrif-components-core/src/lib/navigation/breadcrumbs/abstract-breadcrumbs.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export abstract class AbstractBreadcrumbsComponent implements OnDestroy, AfterVi
7070
}
7171
const splitPath = this._uriService.splitNodePath(this._uriService.activeNode);
7272
const fullPath = this.createFullPath(splitPath);
73-
const fullPathQueries = fullPath.map(p => '(processIdentifier:preference_item AND dataSet.nodePath.textValue.keyword:\"' + p + '\")')
73+
const fullPathQueries = fullPath.map(p => '(processIdentifier:menu_item AND dataSet.nodePath.textValue.keyword:\"' + p + '\")')
7474
fullPathQueries.push('(taskMongoIds:\"' + filterId + '\")')
7575

7676
const searchBody: CaseSearchRequestBody = {

projects/netgrif-components-core/src/lib/navigation/model/group-navigation-constants.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ export enum GroupNavigationConstants {
4343
/**
4444
* EnumerationMap field, that contains selected search type for case view
4545
* */
46-
ITEM_FIELD_ID_CASE_VIEW_SEARCH_TYPE = 'case_view_search_type',
46+
ITEM_FIELD_ID_CASE_VIEW_SEARCH_TYPE = 'view_search_type',
4747

4848
/**
4949
* EnumerationMap field, that contains selected search type for task view
5050
* */
51-
ITEM_FIELD_ID_TASK_VIEW_SEARCH_TYPE = 'task_view_search_type',
51+
ITEM_FIELD_ID_TASK_VIEW_SEARCH_TYPE = 'view_search_type',
5252

5353
/**
5454
* Boolean field, that is true if user wants to merge base filter and custom filter
@@ -63,82 +63,82 @@ export enum GroupNavigationConstants {
6363
/**
6464
* Boolean field, that is true if the user wants to see more menu for case item in case view
6565
* */
66-
ITEM_FIELD_ID_CASE_SHOW_MORE_MENU = 'case_show_more_menu',
66+
ITEM_FIELD_ID_CASE_SHOW_MORE_MENU = 'show_more_menu',
6767

6868
/**
6969
* Boolean field, that is true if no input for title in case creation is shown
7070
* */
71-
ITEM_FIELD_ID_CASE_TITLE_IN_CREATION = 'case_require_title_in_creation',
71+
ITEM_FIELD_ID_CASE_TITLE_IN_CREATION = 'require_title_in_creation',
7272

7373
/**
7474
* Text field, that contains banned processes in case creation as a value
7575
* */
76-
ITEM_FIELD_ID_CASE_BANNED_PROCESS_CREATION = 'case_banned_nets_in_creation',
76+
ITEM_FIELD_ID_CASE_BANNED_PROCESS_CREATION = 'banned_nets_in_creation',
7777

7878
/**
7979
* Boolean field, that is true if the user wants to see more menu for task item in task view
8080
* */
81-
ITEM_FIELD_ID_TASK_SHOW_MORE_MENU = 'task_show_more_menu',
81+
ITEM_FIELD_ID_TASK_SHOW_MORE_MENU = 'show_more_menu',
8282

8383
/**
8484
* MultichoiceMap field, that contains selected header modes for case view as a value
8585
* */
86-
ITEM_FIELD_ID_CASE_HEADERS_MODE = 'case_headers_mode',
86+
ITEM_FIELD_ID_CASE_HEADERS_MODE = 'headers_mode',
8787

8888
/**
8989
* Boolean field, that is true if table mode can be applied in case view
9090
* */
91-
ITEM_FIELD_ID_CASE_ALLOW_TABLE_MODE = 'case_allow_header_table_mode',
91+
ITEM_FIELD_ID_CASE_ALLOW_TABLE_MODE = 'allow_header_table_mode',
9292

9393
/**
9494
* EnumerationMap field, that contains selected default header mode for case view as a value
9595
* */
96-
ITEM_FIELD_ID_CASE_DEFAULT_HEADERS_MODE = 'case_headers_default_mode',
96+
ITEM_FIELD_ID_CASE_DEFAULT_HEADERS_MODE = 'headers_default_mode',
9797

9898
/**
9999
* Boolean field, that is true to make mode menu in case view visible
100100
* */
101-
ITEM_FIELD_ID_CASE_HEADERS_CHANGEABLE = 'case_is_header_mode_changeable',
101+
ITEM_FIELD_ID_CASE_HEADERS_CHANGEABLE = 'is_header_mode_changeable',
102102

103103
/**
104104
* MultichoiceMap field, that contains selected header modes for task view as a value
105105
* */
106-
ITEM_FIELD_ID_TASK_HEADERS_MODE = 'task_headers_mode',
106+
ITEM_FIELD_ID_TASK_HEADERS_MODE = 'headers_mode',
107107

108108
/**
109109
* Boolean field, that is true if table mode can be applied in task view
110110
* */
111-
ITEM_FIELD_ID_TASK_ALLOW_TABLE_MODE = 'task_allow_header_table_mode',
111+
ITEM_FIELD_ID_TASK_ALLOW_TABLE_MODE = 'allow_header_table_mode',
112112

113113
/**
114114
* EnumerationMap field, that contains selected default header mode for task view as a value
115115
* */
116-
ITEM_FIELD_ID_TASK_DEFAULT_HEADERS_MODE = 'task_headers_default_mode',
116+
ITEM_FIELD_ID_TASK_DEFAULT_HEADERS_MODE = 'headers_default_mode',
117117

118118
/**
119119
* Boolean field, that is true to make mode menu in task view visible
120120
* */
121-
ITEM_FIELD_ID_TASK_HEADERS_CHANGEABLE = 'task_is_header_mode_changeable',
121+
ITEM_FIELD_ID_TASK_HEADERS_CHANGEABLE = 'is_header_mode_changeable',
122122

123123
/**
124124
* Boolean field, that is true to use default headers configuration for case view
125125
* */
126-
ITEM_FIELD_ID_USE_CASE_DEFAULT_HEADERS = 'use_case_default_headers',
126+
ITEM_FIELD_ID_USE_CASE_DEFAULT_HEADERS = 'use_default_headers',
127127

128128
/**
129129
* Text field, that contains default header metadata separated by comma for case view as a value
130130
* */
131-
ITEM_FIELD_ID_CASE_DEFAULT_HEADERS = 'case_default_headers',
131+
ITEM_FIELD_ID_CASE_DEFAULT_HEADERS = 'default_headers',
132132

133133
/**
134134
* Boolean field, that is true to use default headers configuration for task view
135135
* */
136-
ITEM_FIELD_ID_USE_TASK_DEFAULT_HEADERS = 'use_task_default_headers',
136+
ITEM_FIELD_ID_USE_TASK_DEFAULT_HEADERS = 'use_default_headers',
137137

138138
/**
139139
* Text field, that contains default header metadata separated by comma for task view as a value
140140
* */
141-
ITEM_FIELD_ID_TASK_DEFAULT_HEADERS = 'task_default_headers',
141+
ITEM_FIELD_ID_TASK_DEFAULT_HEADERS = 'default_headers',
142142

143143
/**
144144
* MultichoiceMap field, that contains allowed roles as value

projects/netgrif-components-core/src/lib/navigation/model/navigation-configs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export interface NavigationItem extends View {
1515
}
1616

1717
export const MENU_IDENTIFIERS = [
18-
'preference_item',
18+
'menu_item',
1919
];
2020
export const SETTINGS_TRANSITION_ID = 'item_settings';
2121

projects/netgrif-components-core/src/lib/navigation/service/uri.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export class UriService implements OnDestroy {
184184
data: {
185185
[GroupNavigationConstants.ITEM_FIELD_ID_NODE_PATH] : node.uriPath
186186
},
187-
process: {identifier: "preference_item"}
187+
process: {identifier: "menu_item"}
188188
};
189189

190190
let httpParams = new HttpParams()

projects/netgrif-components-core/src/lib/navigation/utility/navigation-item-task-utility-methods.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,16 @@ export function extractFieldValueFromData<T>(dataSection: Array<DataGroup>, fiel
131131
}
132132
return field.value;
133133
}
134+
135+
/**
136+
* Checks if the data groups contain view
137+
* @returns true if the data contains filter
138+
* @throws Error if filter field is not found
139+
* */
140+
export function hasView(dataSection: Array<DataGroup>): boolean {
141+
const field = getFieldFromDataGroups(dataSection, 'view_configuration_form');
142+
if (field === undefined) {
143+
throw new Error(`Field view_configuration_form could not be resolved`);
144+
}
145+
return field.value !== null && field.value !== undefined && field.value.length > 0;
146+
}

projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/default-tab-view/default-tab-view.component.ts

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {Component, Inject} from '@angular/core';
22
import {
33
DataGroup,
4-
extractFilterFromData,
54
extractIconAndTitle,
65
extractSearchTypeFromData,
76
extractFieldValueFromData,
@@ -15,7 +14,8 @@ import {
1514
TabContent,
1615
ViewIdService,
1716
FilterExtractionService,
18-
GroupNavigationConstants
17+
GroupNavigationConstants,
18+
hasView
1919
} from '@netgrif/components-core';
2020
import {DefaultTabbedCaseViewComponent} from '../default-tabbed-case-view/default-tabbed-case-view.component';
2121
import {DefaultTabbedTaskViewComponent} from '../default-tabbed-task-view/default-tabbed-task-view.component';
@@ -38,30 +38,33 @@ export class DefaultTabViewComponent {
3838
constructor(@Inject(NAE_NAVIGATION_ITEM_TASK_DATA) protected _navigationItemTaskData: Array<DataGroup>,
3939
protected translationService: TranslateService,
4040
protected extractionService: FilterExtractionService) {
41-
const filter = extractFilterFromData(this._navigationItemTaskData);
42-
this.tabs = this.getTabs(filter.type);
41+
this.tabs = this.getTabs();
4342
}
4443

45-
protected getTabs(type: FilterType): TabContent[] {
46-
switch (type) {
47-
case FilterType.CASE:
48-
return this.getCaseTabs();
49-
case FilterType.TASK:
50-
return this.getTaskTabs();
44+
protected getTabs(): TabContent[] {
45+
const menuItemDataGroups: Array<DataGroup> = this._navigationItemTaskData.slice(0, 4)
46+
const viewDataGroups: Array<DataGroup> = this._navigationItemTaskData.slice(4, this._navigationItemTaskData.length);
47+
48+
const viewType: string = extractFieldValueFromData(menuItemDataGroups, "view_configuration_type")
49+
switch (viewType) {
50+
case "tabbed_case_view":
51+
return this.getCaseTabs(menuItemDataGroups, viewDataGroups);
52+
case "tabbed_task_view":
53+
return this.getTaskTabs(menuItemDataGroups, viewDataGroups);
5154
default:
52-
throw new Error(`Cannot resolve tabs for '${type}' filter type`);
55+
throw new Error(`Cannot resolve tabs for '${viewType}' view type`);
5356
}
5457
}
5558

56-
protected getCaseTabs(): TabContent[] {
57-
const labelData = extractIconAndTitle(this._navigationItemTaskData, this.translationService);
59+
protected getCaseTabs(menuItemDataGroups: Array<DataGroup>, viewDataGroups: Array<DataGroup>): TabContent[] {
60+
const labelData = extractIconAndTitle(menuItemDataGroups, this.translationService);
5861

59-
const blockNetsString = extractFieldValueFromData<string>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_BANNED_PROCESS_CREATION);
62+
const blockNetsString = extractFieldValueFromData<string>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_BANNED_PROCESS_CREATION);
6063
const blockNets = blockNetsString === undefined ? [] : blockNetsString.split(',')
61-
const createCaseButtonTitle: string = extractFieldValueFromData<string>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CREATE_CASE_BUTTON_TITLE);
62-
const createCaseButtonIcon: string = extractFieldValueFromData<string>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CREATE_CASE_BUTTON_ICON);
63-
const requireTitle: boolean = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_TITLE_IN_CREATION);
64-
const showCreateCaseButton: boolean = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_SHOW_CREATE_CASE_BUTTON);
64+
const createCaseButtonTitle: string = extractFieldValueFromData<string>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CREATE_CASE_BUTTON_TITLE);
65+
const createCaseButtonIcon: string = extractFieldValueFromData<string>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CREATE_CASE_BUTTON_ICON);
66+
const requireTitle: boolean = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_TITLE_IN_CREATION);
67+
const showCreateCaseButton: boolean = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_SHOW_CREATE_CASE_BUTTON);
6568
const newCaseButtonConfig: NewCaseCreationConfigurationData = {
6669
enableCaseTitle: requireTitle,
6770
isCaseTitleRequired: requireTitle,
@@ -72,32 +75,36 @@ export class DefaultTabViewComponent {
7275
},
7376
blockNets: blockNets
7477
};
75-
const caseSearchType = extractSearchTypeFromData(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_VIEW_SEARCH_TYPE);
78+
const caseSearchType = extractSearchTypeFromData(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_VIEW_SEARCH_TYPE);
7679
const caseSearchTypeConfig: SearchComponentConfiguration = {
7780
showSearchIcon: true,
7881
showSearchToggleButton: caseSearchType === SearchMode.ADVANCED,
7982
initialSearchMode: (caseSearchType === undefined) ? undefined : SearchMode.FULLTEXT,
8083
}
81-
const caseShowMoreMenu = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_SHOW_MORE_MENU);
82-
const caseViewHeadersChangeable = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_HEADERS_CHANGEABLE);
83-
const caseViewHeadersMode = extractFieldValueFromData<string[]>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_HEADERS_MODE);
84-
const caseViewAllowTableMode = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_ALLOW_TABLE_MODE);
85-
const caseViewDefaultHeadersMode = extractFieldValueFromData<string[]>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_CASE_DEFAULT_HEADERS_MODE);
84+
const caseShowMoreMenu = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_SHOW_MORE_MENU);
85+
const caseViewHeadersChangeable = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_HEADERS_CHANGEABLE);
86+
const caseViewHeadersMode = extractFieldValueFromData<string[]>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_HEADERS_MODE);
87+
const caseViewAllowTableMode = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_ALLOW_TABLE_MODE);
88+
const caseViewDefaultHeadersMode = extractFieldValueFromData<string[]>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_CASE_DEFAULT_HEADERS_MODE);
89+
90+
if (!hasView(viewDataGroups)) {
91+
throw new Error(`Case view has missing configuration for task view.`);
92+
}
8693

87-
const taskSearchType = extractSearchTypeFromData(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_VIEW_SEARCH_TYPE);
88-
const taskShowMoreMenu = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_SHOW_MORE_MENU);
94+
const taskSearchType = extractSearchTypeFromData(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_VIEW_SEARCH_TYPE);
95+
const taskShowMoreMenu = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_SHOW_MORE_MENU);
8996
const taskSearchTypeConfig: SearchComponentConfiguration = {
9097
showSearchIcon: true,
9198
showSearchToggleButton: taskSearchType === SearchMode.ADVANCED,
9299
initialSearchMode: (taskSearchType === undefined) ? undefined : SearchMode.FULLTEXT,
93100
}
94-
const taskViewHeadersChangeable = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_CHANGEABLE);
95-
const taskViewHeadersMode = extractFieldValueFromData<string[]>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_MODE);
96-
const taskViewAllowTableMode = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_ALLOW_TABLE_MODE);
97-
const taskViewDefaultHeadersMode = extractFieldValueFromData<string[]>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_DEFAULT_HEADERS_MODE);
98-
const taskViewAdditionalFilter = this.extractionService.extractCompleteAdditionalFilterFromData(this._navigationItemTaskData);
99-
const mergeWithBaseFilter = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_MERGE_FILTERS);
100-
const additionalAllowedNets = this.extractionService.extractAdditionalFilterAllowedNets(this._navigationItemTaskData)?.allowedNetsIdentifiers;
101+
const taskViewHeadersChangeable = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_CHANGEABLE);
102+
const taskViewHeadersMode = extractFieldValueFromData<string[]>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_MODE);
103+
const taskViewAllowTableMode = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_ALLOW_TABLE_MODE);
104+
const taskViewDefaultHeadersMode = extractFieldValueFromData<string[]>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_DEFAULT_HEADERS_MODE);
105+
const taskViewAdditionalFilter = this.extractionService.extractCompleteAdditionalFilterFromData(viewDataGroups);
106+
const mergeWithBaseFilter = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_MERGE_FILTERS);
107+
const additionalAllowedNets = this.extractionService.extractAdditionalFilterAllowedNets(viewDataGroups)?.allowedNetsIdentifiers;
101108

102109
return [
103110
{
@@ -131,22 +138,22 @@ export class DefaultTabViewComponent {
131138
];
132139
}
133140

134-
private getTaskTabs(): TabContent[] {
135-
const labelData = extractIconAndTitle(this._navigationItemTaskData, this.translationService);
136-
const taskSearchType = extractSearchTypeFromData(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_VIEW_SEARCH_TYPE);
137-
const headersChangeable = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_CHANGEABLE);
138-
const headersMode = extractFieldValueFromData<string[]>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_MODE);
139-
const allowTableMode = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_ALLOW_TABLE_MODE);
140-
const defaultHeadersMode = extractFieldValueFromData<string[]>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_DEFAULT_HEADERS_MODE);
141+
private getTaskTabs(menuItemDataGroups: Array<DataGroup>, viewDataGroups: Array<DataGroup>): TabContent[] {
142+
const labelData = extractIconAndTitle(menuItemDataGroups, this.translationService);
143+
const taskSearchType = extractSearchTypeFromData(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_VIEW_SEARCH_TYPE);
144+
const headersChangeable = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_CHANGEABLE);
145+
const headersMode = extractFieldValueFromData<string[]>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_HEADERS_MODE);
146+
const allowTableMode = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_ALLOW_TABLE_MODE);
147+
const defaultHeadersMode = extractFieldValueFromData<string[]>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_DEFAULT_HEADERS_MODE);
141148
const showToggleButton = taskSearchType === SearchMode.ADVANCED
142149
const searchTypeConfig: SearchComponentConfiguration = {
143150
showSearchIcon: true,
144151
showSearchToggleButton: showToggleButton,
145152
initialSearchMode: (taskSearchType === undefined) ? undefined : SearchMode.FULLTEXT,
146153
}
147-
const showMoreMenu = extractFieldValueFromData<boolean>(this._navigationItemTaskData, GroupNavigationConstants.ITEM_FIELD_ID_TASK_SHOW_MORE_MENU);
154+
const showMoreMenu = extractFieldValueFromData<boolean>(viewDataGroups, GroupNavigationConstants.ITEM_FIELD_ID_TASK_SHOW_MORE_MENU);
148155

149-
const filter = this.extractionService.extractCompleteFilterFromData(this._navigationItemTaskData);
156+
const filter = this.extractionService.extractCompleteFilterFromData(viewDataGroups);
150157
return [
151158
{
152159
label: {text: labelData.name, icon: labelData.icon},

0 commit comments

Comments
 (0)