neo-cmp-cli 1.13.17 → 1.13.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index2.js +1 -1
- package/dist/neo/env.js +1 -1
- package/dist/neo/pushCmp.js +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +3 -2
- package/template/asset-manage-template/docs/README.md +1 -232
- package/template/echarts-custom-cmp-template/package.json +1 -1
- package/template/neo-bi-cmps/package.json +1 -1
- package/template/neo-bi-cmps/src/components/targetNumber__c/model.ts +1 -1
- package/template/neo-custom-cmp-template/docs/README.md +0 -231
- package/template/neo-custom-cmp-template/package.json +1 -1
- package/template/neo-h5-cmps/src/components/entityList__c/index.tsx +1 -2
- package/template/neo-h5-cmps/src/components/entityTabs__c/index.tsx +1 -1
- package/template/neo-h5-cmps/src/components/globalSearchInput__c/index.tsx +1 -1
- package/template/neo-h5-cmps/src/components/openChatPageBtn__c/index.tsx +1 -2
- package/template/neo-pipeline-cmps/neo.config.js +11 -0
- package/template/neo-pipeline-cmps/src/assets/css/common.scss +16 -16
- package/template/neo-pipeline-cmps/src/assets/css/mixin.scss +5 -5
- package/template/neo-pipeline-cmps/src/components/filterBar__c/README.md +9 -9
- package/template/neo-pipeline-cmps/src/components/filterBar__c/common.scss +5 -5
- package/template/neo-pipeline-cmps/src/components/filterBar__c/index.tsx +47 -46
- package/template/neo-pipeline-cmps/src/components/filterBar__c/model.ts +13 -11
- package/template/neo-pipeline-cmps/src/components/filterBar__c/style.scss +1 -1
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/README.md +17 -17
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/index.tsx +23 -22
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/model.ts +18 -17
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/index.tsx +33 -26
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/model.ts +9 -9
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/README.md +53 -54
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/common.scss +5 -5
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/index.tsx +70 -68
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/model.ts +41 -41
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/style.scss +2 -3
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/README.md +15 -15
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/index.tsx +35 -33
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/model.ts +16 -15
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/README.md +18 -18
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/index.tsx +20 -20
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/model.ts +21 -18
- package/template/neo-pipeline-cmps/src/utils/common.ts +14 -14
- package/template/neo-pipeline-cmps/src/utils/filter2chartFilter.ts +21 -23
- package/template/neo-pipeline-cmps/src/utils/filterBar.ts +14 -14
- package/template/neo-pipeline-cmps/src/utils/pipelineFunnel.ts +5 -5
- package/template/neo-pipeline-cmps/src/utils/queryByCustomSQL.ts +26 -22
- package/template/neo-pipeline-cmps/src/utils/requestDebounce.ts +3 -3
- package/template/neo-pipeline-cmps/src/utils/simpleTable.tsx +31 -26
- package/template/neo-pipeline-cmps/src/utils/stageSwitch.ts +1 -1
- package/template/neo-pipeline-cmps/src/utils/stageTimeChart.ts +5 -5
- package/template/neo-pipeline-cmps/src/utils/targetNumber.ts +2 -2
- package/template/neo-web-form/package.json +1 -1
- package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +161 -41
- package/template/neo-web-form/src/components/batchAddTable__c/model.ts +4 -2
- package/template/react-custom-cmp-template/package.json +1 -1
- package/template/asset-manage-template/src/utils/axiosFetcher.ts +0 -37
- package/template/asset-manage-template/src/utils/queryObjectData.ts +0 -112
- package/template/asset-manage-template/src/utils/xobjects.ts +0 -162
- package/template/neo-custom-cmp-template/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-custom-cmp-template/src/utils/queryObjectData.ts +0 -112
- package/template/neo-custom-cmp-template/src/utils/xobjects.ts +0 -162
- package/template/neo-h5-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-h5-cmps/src/utils/queryObjectData.ts +0 -112
- package/template/neo-h5-cmps/src/utils/xobjects.ts +0 -167
- package/template/neo-order-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-order-cmps/src/utils/queryObjectData.ts +0 -112
- package/template/neo-order-cmps/src/utils/xobjects.ts +0 -162
- package/template/neo-web-entity-grid/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-web-entity-grid/src/utils/queryObjectData.ts +0 -112
- package/template/neo-web-entity-grid/src/utils/xobjects.ts +0 -167
- package/template/neo-web-form/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-web-form/src/utils/queryObjectData.ts +0 -112
- package/template/neo-web-form/src/utils/xobjects.ts +0 -167
|
@@ -1,72 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file XObject
|
|
3
|
-
* @description
|
|
2
|
+
* @file XObject table component editor descriptor file (simplified version)
|
|
3
|
+
* @description Defines the component configuration for the Neo platform editor
|
|
4
4
|
* @author Neo Custom Widget CLI
|
|
5
5
|
* @version 1.0.0
|
|
6
6
|
*/
|
|
7
7
|
export class SimpleTableModel {
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Component type identifier
|
|
10
|
+
* Used to uniquely identify the component; automatically generated from the current component directory name during build
|
|
11
|
+
* Note: This field is automatically replaced during build and does not need to be set manually
|
|
12
12
|
*/
|
|
13
13
|
// cmpType: string = 'simpleTable';
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
label: string = '
|
|
15
|
+
/** Component name, displayed in the editor's left component panel */
|
|
16
|
+
label: string = 'Opportunity List';
|
|
17
17
|
|
|
18
|
-
/**
|
|
18
|
+
/** Component description, displayed in the editor's left component panel */
|
|
19
19
|
description: string =
|
|
20
|
-
'
|
|
20
|
+
'Data table component based on XObject, supports data display only, does not support CRUD operations';
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
// tags: string[] = ['
|
|
22
|
+
/** Category tags, determines which category the component appears under in the editor's left component panel */
|
|
23
|
+
// tags: string[] = ['Custom Components'];
|
|
24
24
|
|
|
25
|
-
/**
|
|
25
|
+
/** Component icon, displayed in the editor's left component panel */
|
|
26
26
|
iconUrl: string = 'https://custom-widgets.bj.bcebos.com/table.svg';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Sets the page types supported by the component
|
|
30
30
|
*
|
|
31
|
-
*
|
|
32
|
-
* all: 1
|
|
33
|
-
* entityFormPage: 4
|
|
34
|
-
* customPage: 6
|
|
31
|
+
* Page types available in the current NeoCRM platform:
|
|
32
|
+
* all: 1 All pages
|
|
33
|
+
* entityFormPage: 4 Entity form page
|
|
34
|
+
* customPage: 6 Custom page
|
|
35
35
|
*/
|
|
36
36
|
targetPage: string[] = ['all'];
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* Sets the device types supported by the component
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
* web:
|
|
43
|
-
* mobile:
|
|
41
|
+
* Device types available in the current NeoCRM platform:
|
|
42
|
+
* web: Web
|
|
43
|
+
* mobile: Mobile
|
|
44
44
|
*/
|
|
45
45
|
targetDevice: string = 'web';
|
|
46
46
|
|
|
47
|
-
/**
|
|
47
|
+
/** Default property data when first inserted into a page */
|
|
48
48
|
defaultComProps = {
|
|
49
49
|
title: 'Opportunity List',
|
|
50
50
|
activeStage: 'Prospecting',
|
|
51
51
|
description: 'Filtered by Close Date, Opportunity Owner, Business Type',
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
//
|
|
54
|
+
// List of functions supported by the current component (other components can trigger these functions)
|
|
55
55
|
functions = [
|
|
56
56
|
{
|
|
57
57
|
apiKey: 'loadData',
|
|
58
|
-
label: '
|
|
59
|
-
helpTextKey: '
|
|
58
|
+
label: 'Refresh Table',
|
|
59
|
+
helpTextKey: 'Refresh the current table data',
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
apiKey: 'setFilter',
|
|
63
|
-
label: '
|
|
63
|
+
label: 'Set Filter Conditions',
|
|
64
64
|
helpTextKey:
|
|
65
|
-
'
|
|
65
|
+
'Set filter conditions consistent with the chart (closeDate / ownerId / entityType), and re-query the table',
|
|
66
66
|
funcInParams: [
|
|
67
67
|
{
|
|
68
68
|
apiKey: 'filter',
|
|
69
|
-
label: '
|
|
69
|
+
label: 'Filter condition data',
|
|
70
70
|
type: 'Object',
|
|
71
71
|
required: false,
|
|
72
72
|
},
|
|
@@ -74,12 +74,12 @@ export class SimpleTableModel {
|
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
apiKey: 'updateActiveStage',
|
|
77
|
-
label: '
|
|
78
|
-
helpTextKey: '
|
|
77
|
+
label: 'Update Active Stage',
|
|
78
|
+
helpTextKey: 'Set the currently active sales stage',
|
|
79
79
|
funcInParams: [
|
|
80
80
|
{
|
|
81
81
|
apiKey: 'activeStage',
|
|
82
|
-
label: '
|
|
82
|
+
label: 'Current active stage',
|
|
83
83
|
type: 'String',
|
|
84
84
|
required: false,
|
|
85
85
|
},
|
|
@@ -88,33 +88,33 @@ export class SimpleTableModel {
|
|
|
88
88
|
];
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
91
|
+
* Component property configuration schema
|
|
92
|
+
* Supports static configuration: propsSchema, with lower priority than propsSchemaCreator
|
|
93
|
+
* Defines the configurable properties of the component in the editor
|
|
94
94
|
*/
|
|
95
95
|
propsSchema = [
|
|
96
96
|
{
|
|
97
97
|
type: 'panelInput',
|
|
98
98
|
name: 'title',
|
|
99
|
-
label: '
|
|
100
|
-
placeholder: '
|
|
99
|
+
label: 'Table Title',
|
|
100
|
+
placeholder: 'Enter table title',
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
type: 'panelInput',
|
|
104
104
|
name: 'description',
|
|
105
|
-
label: '
|
|
106
|
-
placeholder: '
|
|
105
|
+
label: 'Table Description',
|
|
106
|
+
placeholder: 'Description text displayed below the title',
|
|
107
107
|
},
|
|
108
108
|
/*
|
|
109
109
|
{
|
|
110
|
-
type: 'xObjectDataApi', //
|
|
110
|
+
type: 'xObjectDataApi', // Configuration item for fetching entity business data list
|
|
111
111
|
name: 'xObjectDataApi',
|
|
112
|
-
label: '
|
|
112
|
+
label: 'Entity Data Source',
|
|
113
113
|
value: {
|
|
114
114
|
xObjectApiKey: 'customContact__c',
|
|
115
115
|
fields: ['name', 'phone__c'],
|
|
116
116
|
},
|
|
117
|
-
placeholder: '
|
|
117
|
+
placeholder: 'Select entity data source',
|
|
118
118
|
custom: true,
|
|
119
119
|
},
|
|
120
120
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Table header AI icon: same usage as openChatPageBtn's openChatPageBtn-icon (background image) */
|
|
2
2
|
.simpleTable-th-title-with-ai-icon {
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
align-items: center;
|
|
@@ -157,7 +157,7 @@
|
|
|
157
157
|
color: #fff;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
//
|
|
160
|
+
// Responsive design
|
|
161
161
|
@media (max-width: 768px) {
|
|
162
162
|
.panel-header {
|
|
163
163
|
padding: 12px;
|
|
@@ -190,4 +190,3 @@
|
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
|
-
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# StageSwitch
|
|
1
|
+
# StageSwitch Component
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Stage switch card component that toggles between different sales stage data.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
import StageSwitch from './components/stageSwitch__c';
|
|
@@ -19,18 +19,18 @@ import StageSwitch from './components/stageSwitch__c';
|
|
|
19
19
|
|
|
20
20
|
## Props
|
|
21
21
|
|
|
22
|
-
|
|
|
23
|
-
|
|
24
|
-
| stages |
|
|
25
|
-
| activeStage |
|
|
26
|
-
| onStageChange |
|
|
22
|
+
| Property | Description | Type | Default |
|
|
23
|
+
|----------|-------------|------|---------|
|
|
24
|
+
| stages | Stage data | StageTab[] | [] |
|
|
25
|
+
| activeStage | Current stage | string | First stage |
|
|
26
|
+
| onStageChange | Stage switch callback | (stage: StageTab) => void | - |
|
|
27
27
|
|
|
28
28
|
## StageTab
|
|
29
29
|
|
|
30
|
-
|
|
|
31
|
-
|
|
32
|
-
| key |
|
|
33
|
-
| name |
|
|
34
|
-
| amount |
|
|
35
|
-
| count |
|
|
36
|
-
| changes |
|
|
30
|
+
| Property | Description | Type |
|
|
31
|
+
|----------|-------------|------|
|
|
32
|
+
| key | Unique identifier | string |
|
|
33
|
+
| name | Stage name | string |
|
|
34
|
+
| amount | Amount | string |
|
|
35
|
+
| count | Count | number |
|
|
36
|
+
| changes | Change data | { amount, amountDirection, count, countDirection } |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file
|
|
3
|
-
* @description
|
|
2
|
+
* @file Stage Switch Card Component
|
|
3
|
+
* @description Toggle between different sales stage data; opportunities from xObject.query, stages from stage API
|
|
4
4
|
*/
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { Spin } from 'antd';
|
|
@@ -33,7 +33,7 @@ interface StageTab {
|
|
|
33
33
|
name: string;
|
|
34
34
|
amount: string;
|
|
35
35
|
count: number;
|
|
36
|
-
/**
|
|
36
|
+
/** Can be empty object when no period-over-period data, not rendered */
|
|
37
37
|
changes?: Record<string, unknown>;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -51,11 +51,11 @@ interface StageSwitchProps {
|
|
|
51
51
|
interface StageSwitchState {
|
|
52
52
|
activeStage: string;
|
|
53
53
|
opportunityList: Record<string, unknown>[];
|
|
54
|
-
/**
|
|
54
|
+
/** Display stages generated from API + getOpportunityList */
|
|
55
55
|
stages: StageTab[];
|
|
56
56
|
loading: boolean;
|
|
57
57
|
error: string | null;
|
|
58
|
-
/**
|
|
58
|
+
/** Consistent with FilterBar event payload (closeDateCustomRange / opportunityOwner / businessType, etc.); falls back to defaultFilter when empty object */
|
|
59
59
|
filter: any;
|
|
60
60
|
defaultEntityTypeApiKey: string;
|
|
61
61
|
}
|
|
@@ -93,15 +93,15 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
93
93
|
this.fetchAllData();
|
|
94
94
|
|
|
95
95
|
/*
|
|
96
|
-
//
|
|
96
|
+
// Listen to a broadcast event
|
|
97
97
|
NeoEvent.listen('updateFilterData', (filterData: any) => {
|
|
98
|
-
console.log('StageSwitch
|
|
98
|
+
console.log('StageSwitch received a broadcast event updateFilterData: ', filterData);
|
|
99
99
|
this.setFilter(filterData);
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
//
|
|
102
|
+
// Broadcast event: update the currently active sales stage
|
|
103
103
|
NeoEvent.listen('updateActiveStage', (activeStage: string) => {
|
|
104
|
-
console.log('SimpleTable
|
|
104
|
+
console.log('SimpleTable received a broadcast event updateActiveStage: ', activeStage);
|
|
105
105
|
this.updateActiveStage(activeStage);
|
|
106
106
|
});
|
|
107
107
|
*/
|
|
@@ -117,8 +117,9 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
/**
|
|
120
|
+
/** Convert FilterBar structured filter to xObject.query where string array (SDK concatenates with AND in order) */
|
|
121
121
|
getOpportunityQueryFilter(): string[] {
|
|
122
|
+
const defaultFilter = getDefaultFilterByProps(this.props);
|
|
122
123
|
const raw = this.state.filter;
|
|
123
124
|
const curFilter: Record<string, unknown> =
|
|
124
125
|
raw && typeof raw === 'object' && !Array.isArray(raw)
|
|
@@ -149,8 +150,9 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
149
150
|
return where;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
/**
|
|
153
|
+
/** Generate query conditions for fetching historical opportunity list data */
|
|
153
154
|
getHistoryOpportunityQueryFilter(): string[] {
|
|
155
|
+
const defaultFilter = getDefaultFilterByProps(this.props);
|
|
154
156
|
const raw = this.state.filter;
|
|
155
157
|
const curFilter: Record<string, unknown> =
|
|
156
158
|
raw && typeof raw === 'object' && !Array.isArray(raw)
|
|
@@ -187,7 +189,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
187
189
|
return where;
|
|
188
190
|
}
|
|
189
191
|
|
|
190
|
-
/**
|
|
192
|
+
/** Query up to 1000 opportunities per request */
|
|
191
193
|
async fetchOpportunityList(): Promise<Record<string, unknown>[]> {
|
|
192
194
|
const result = await xObject.query({
|
|
193
195
|
xObjectApiKey: 'opportunity',
|
|
@@ -202,7 +204,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
202
204
|
: [];
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
/**
|
|
207
|
+
/** Query historical opportunity list data */
|
|
206
208
|
async fetchHistoryOpportunityList(): Promise<unknown[]> {
|
|
207
209
|
const result = await queryByCustomSQL({
|
|
208
210
|
xObjectApiKey: 'biCustomModel_397169_20260401104916618',
|
|
@@ -220,16 +222,16 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
/**
|
|
223
|
-
*
|
|
224
|
-
* @returns count —
|
|
225
|
+
* Filter opportunities by stageName: extract the segment after the first `.` in stageName as the stage key, and compare with the stage text on the opportunity row using the same rule.
|
|
226
|
+
* @returns count — number of records; amount — sum of money (or amount field if money is absent)
|
|
225
227
|
*/
|
|
226
228
|
getOpportunityStats(
|
|
227
229
|
stageName: string,
|
|
228
|
-
list: Record<string, unknown>[], //
|
|
230
|
+
list: Record<string, unknown>[], // opportunity list
|
|
229
231
|
): { amount: number; count: number } {
|
|
230
232
|
const key = extractStageKeyFromStageName(stageName);
|
|
231
|
-
let amount = 0; //
|
|
232
|
-
let count = 0; //
|
|
233
|
+
let amount = 0; // total opportunity amount
|
|
234
|
+
let count = 0; // total opportunity count
|
|
233
235
|
|
|
234
236
|
for (const row of list) {
|
|
235
237
|
if (!row || typeof row !== 'object') continue;
|
|
@@ -244,9 +246,9 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
244
246
|
}
|
|
245
247
|
|
|
246
248
|
/**
|
|
247
|
-
*
|
|
248
|
-
* `[opportunityName, saleStageId, money, ...]` —
|
|
249
|
-
* @returns count —
|
|
249
|
+
* Historical opportunity list is a 2D array returned by custom SQL:
|
|
250
|
+
* `[opportunityName, saleStageId, money, ...]` — column 2 is the stage ID (corresponds to stage `key`), column 3 is the sales amount.
|
|
251
|
+
* @returns count — number of records; amount — sum of sales amount
|
|
250
252
|
*/
|
|
251
253
|
getHistoryOpportunityStats(
|
|
252
254
|
stageKey: string,
|
|
@@ -284,9 +286,9 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
buildStagesFromApi(
|
|
287
|
-
rows: any[], //
|
|
288
|
-
opportunityList: Record<string, unknown>[], //
|
|
289
|
-
historyOpportunityList: unknown[], //
|
|
289
|
+
rows: any[], // stage list
|
|
290
|
+
opportunityList: Record<string, unknown>[], // opportunity list
|
|
291
|
+
historyOpportunityList: unknown[], // historical opportunities: SQL 2D array rows
|
|
290
292
|
): StageTab[] {
|
|
291
293
|
console.log(
|
|
292
294
|
'[StageSwitch__c] buildStagesFromApi:',
|
|
@@ -304,7 +306,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
304
306
|
row.id ?? row.apiKey ?? (stageName || `stage-${index}`),
|
|
305
307
|
);
|
|
306
308
|
|
|
307
|
-
//
|
|
309
|
+
// Find the corresponding opportunity from the historical opportunity list by opportunity ID
|
|
308
310
|
const { amount: historyAmount, count: historyCount } =
|
|
309
311
|
this.getHistoryOpportunityStats(key, historyOpportunityList);
|
|
310
312
|
|
|
@@ -357,8 +359,8 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
357
359
|
loading: false,
|
|
358
360
|
});
|
|
359
361
|
} catch (e: unknown) {
|
|
360
|
-
console.error('StageSwitch
|
|
361
|
-
const msg = e instanceof Error ? e.message : '
|
|
362
|
+
console.error('StageSwitch failed to load:', e);
|
|
363
|
+
const msg = e instanceof Error ? e.message : 'Failed to load';
|
|
362
364
|
this.setState({
|
|
363
365
|
loading: false,
|
|
364
366
|
error: msg,
|
|
@@ -368,13 +370,13 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
368
370
|
}
|
|
369
371
|
}
|
|
370
372
|
|
|
371
|
-
//
|
|
373
|
+
// When a stage is clicked, update the currently active sales stage
|
|
372
374
|
handleStageClick(stage: StageTab) {
|
|
373
375
|
const { onStageChange } = this.props;
|
|
374
376
|
if (onStageChange) {
|
|
375
377
|
onStageChange(stage);
|
|
376
378
|
}
|
|
377
|
-
//
|
|
379
|
+
// Broadcast event: update the currently active sales stage
|
|
378
380
|
const activeStage = extractStageKeyFromStageName(stage.name);
|
|
379
381
|
this.setState({ activeStage: activeStage });
|
|
380
382
|
|
|
@@ -382,7 +384,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
382
384
|
activeStage,
|
|
383
385
|
});
|
|
384
386
|
|
|
385
|
-
//
|
|
387
|
+
// Trigger a broadcast event
|
|
386
388
|
// NeoEvent.broadcast('updateActiveStage', activeStage);
|
|
387
389
|
}
|
|
388
390
|
|
|
@@ -392,7 +394,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
392
394
|
}
|
|
393
395
|
|
|
394
396
|
/**
|
|
395
|
-
*
|
|
397
|
+
* Consistent with pipelineFunnel: pass in { relation, filter }, will re-fetch opportunities and merge stage statistics.
|
|
396
398
|
*/
|
|
397
399
|
@NeoEvent.function
|
|
398
400
|
setFilter(filter?: any) {
|
|
@@ -413,7 +415,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
413
415
|
}
|
|
414
416
|
|
|
415
417
|
/**
|
|
416
|
-
*
|
|
418
|
+
* Update the currently active sales stage
|
|
417
419
|
*/
|
|
418
420
|
@NeoEvent.function
|
|
419
421
|
updateActiveStage(activeStage?: string) {
|
|
@@ -435,7 +437,7 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
435
437
|
<div
|
|
436
438
|
className={`stageSwitch__c ${className || ''}`}
|
|
437
439
|
style={style}
|
|
438
|
-
data-time="2026.4.
|
|
440
|
+
data-time="2026.4.17 01"
|
|
439
441
|
>
|
|
440
442
|
<Spin spinning={loading}>
|
|
441
443
|
{error ? (
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
export class StageSwitchModel {
|
|
2
|
-
label: string = '
|
|
3
|
-
description: string =
|
|
2
|
+
label: string = 'Stage Switch Card';
|
|
3
|
+
description: string =
|
|
4
|
+
'Toggle between different sales stage data, including amount, count and change trends';
|
|
4
5
|
iconUrl: string = 'https://custom-widgets.bj.bcebos.com/card.svg';
|
|
5
6
|
targetPage: string[] = ['all'];
|
|
6
7
|
targetDevice: string = 'all';
|
|
7
8
|
|
|
8
9
|
defaultComProps = {
|
|
9
|
-
/**
|
|
10
|
+
/** defaultEntityTypeApiKey passed when requesting the stage list API */
|
|
10
11
|
// defaultEntityTypeApiKey: 'defaultBusiType',
|
|
11
12
|
stages: [] as unknown[],
|
|
12
13
|
activeStage: 'Prospecting',
|
|
@@ -15,23 +16,23 @@ export class StageSwitchModel {
|
|
|
15
16
|
events = [
|
|
16
17
|
{
|
|
17
18
|
apiKey: 'onActiveStageChange',
|
|
18
|
-
label: '
|
|
19
|
+
label: 'After active stage changes',
|
|
19
20
|
helpText:
|
|
20
|
-
'
|
|
21
|
+
'Triggered after the active stage changes; event params include activeStage (current active stage)',
|
|
21
22
|
eventParams:
|
|
22
|
-
'[{"apiKey":"eventParam","children":[{"apiKey":"activeStage","label":"
|
|
23
|
+
'[{"apiKey":"eventParam","children":[{"apiKey":"activeStage","label":"Current active stage","type":"String"}],"label":"Event parameters","type":"Object"}]',
|
|
23
24
|
},
|
|
24
25
|
];
|
|
25
26
|
|
|
26
27
|
functions = [
|
|
27
28
|
{
|
|
28
29
|
apiKey: 'updateActiveStage',
|
|
29
|
-
label: '
|
|
30
|
-
helpTextKey: '
|
|
30
|
+
label: 'Update active stage',
|
|
31
|
+
helpTextKey: 'Set the current active sales stage',
|
|
31
32
|
funcInParams: [
|
|
32
33
|
{
|
|
33
34
|
apiKey: 'activeStage',
|
|
34
|
-
label: '
|
|
35
|
+
label: 'Current active stage',
|
|
35
36
|
type: 'String',
|
|
36
37
|
required: false,
|
|
37
38
|
},
|
|
@@ -39,13 +40,13 @@ export class StageSwitchModel {
|
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
apiKey: 'setFilter',
|
|
42
|
-
label: '
|
|
43
|
+
label: 'Set filter conditions',
|
|
43
44
|
helpTextKey:
|
|
44
|
-
'
|
|
45
|
+
'Set the filter consistent with the chart (closeDate / ownerId / entityType) and re-fetch opportunities',
|
|
45
46
|
funcInParams: [
|
|
46
47
|
{
|
|
47
48
|
apiKey: 'filter',
|
|
48
|
-
label: '
|
|
49
|
+
label: 'Filter conditions (relation + filter array)',
|
|
49
50
|
type: 'Object',
|
|
50
51
|
required: false,
|
|
51
52
|
},
|
|
@@ -53,8 +54,8 @@ export class StageSwitchModel {
|
|
|
53
54
|
},
|
|
54
55
|
{
|
|
55
56
|
apiKey: 'refreshData',
|
|
56
|
-
label: '
|
|
57
|
-
helpTextKey: '
|
|
57
|
+
label: 'Refresh data',
|
|
58
|
+
helpTextKey: 'Re-fetch opportunity list and stage list',
|
|
58
59
|
},
|
|
59
60
|
];
|
|
60
61
|
|
|
@@ -62,7 +63,7 @@ export class StageSwitchModel {
|
|
|
62
63
|
{
|
|
63
64
|
type: 'panelInput',
|
|
64
65
|
name: 'defaultEntityTypeApiKey',
|
|
65
|
-
label: '
|
|
66
|
+
label: 'Business type ApiKey (stage list API)',
|
|
66
67
|
},
|
|
67
68
|
];
|
|
68
69
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# StageTimeChart
|
|
1
|
+
# StageTimeChart Component
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Stage time component that displays the average time spent in each sales stage.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
import StageTimeChart from './components/stageTimeChart__c';
|
|
@@ -10,7 +10,7 @@ import StageTimeChart from './components/stageTimeChart__c';
|
|
|
10
10
|
<StageTimeChart
|
|
11
11
|
title="Avg. Time in Stage"
|
|
12
12
|
items={[
|
|
13
|
-
{ stageName: 'Prospecting', actualTime: '
|
|
13
|
+
{ stageName: 'Prospecting', actualTime: '8d 6h', actualPercent: 28, actualColor: '#22c55e', targetPercent: 33, limitPercent: 50 },
|
|
14
14
|
]}
|
|
15
15
|
onStageClick={(name) => console.log('Clicked:', name)}
|
|
16
16
|
/>
|
|
@@ -18,20 +18,20 @@ import StageTimeChart from './components/stageTimeChart__c';
|
|
|
18
18
|
|
|
19
19
|
## Props
|
|
20
20
|
|
|
21
|
-
|
|
|
22
|
-
|
|
23
|
-
| title |
|
|
24
|
-
| items |
|
|
25
|
-
| showAiButton |
|
|
26
|
-
| onStageClick |
|
|
21
|
+
| Property | Description | Type | Default |
|
|
22
|
+
|----------|-------------|------|---------|
|
|
23
|
+
| title | Title | string | 'Avg. Time in Stage' |
|
|
24
|
+
| items | Stage data | StageTimeItem[] | [] |
|
|
25
|
+
| showAiButton | Show AI button | boolean | true |
|
|
26
|
+
| onStageClick | Stage click callback | (stageName: string) => void | - |
|
|
27
27
|
|
|
28
28
|
## StageTimeItem
|
|
29
29
|
|
|
30
|
-
|
|
|
31
|
-
|
|
32
|
-
| stageName |
|
|
33
|
-
| actualTime |
|
|
34
|
-
| actualPercent |
|
|
35
|
-
| actualColor |
|
|
36
|
-
| targetPercent |
|
|
37
|
-
| limitPercent |
|
|
30
|
+
| Property | Description | Type |
|
|
31
|
+
|----------|-------------|------|
|
|
32
|
+
| stageName | Stage name | string |
|
|
33
|
+
| actualTime | Actual time | string |
|
|
34
|
+
| actualPercent | Actual percentage | number |
|
|
35
|
+
| actualColor | Actual color | string |
|
|
36
|
+
| targetPercent | Target percentage | number |
|
|
37
|
+
| limitPercent | Limit percentage | number |
|