@zohodesk/library-platform 1.2.0 → 1.2.2
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/es/index.js +6 -2
- package/es/platform/client-actions/behaviour/zclient-actions/adapters/presenters/FilterUtils.js +11 -0
- package/es/platform/client-actions/behaviour/zclient-actions/adapters/resources/ClientActionsFetchSDK.js +76 -0
- package/es/platform/client-actions/behaviour/zclient-actions/adapters/resources/__test__/ClientActionsFetchSDK.test.js +183 -0
- package/es/platform/client-actions/behaviour/zclient-actions/applications/interfaces/ClientActionsAPIGatewayParams.js +1 -0
- package/es/platform/client-actions/behaviour/zclient-actions/applications/interfaces/ClientActionsFetchSDKParams.js +10 -0
- package/es/platform/client-actions/behaviour/zclient-actions/applications/interfaces/IClientActionsFetchSDK.js +0 -0
- package/es/platform/client-actions/cc/client-actions-renderer/Properties.js +58 -0
- package/es/platform/client-actions/cc/client-actions-renderer/ViewMetaSchema.js +17 -0
- package/es/platform/client-actions/components/client-actions-renderer/adapters/presenters/ClientActionsRendererTranslator.js +24 -0
- package/es/platform/client-actions/components/client-actions-renderer/domain/entities/ClientActionsRendererDatatype.js +1 -0
- package/es/platform/client-actions/components/client-actions-renderer/domain/entities/ClientActionsRendererViewProps.js +1 -0
- package/es/platform/client-actions/components/client-actions-renderer/domain/entities/Context.js +1 -0
- package/es/platform/client-actions/components/client-actions-renderer/domain/entities/State.js +8 -0
- package/es/platform/client-actions/components/client-actions-renderer/frameworks/ui/client-actions-renderer/ClientActionsRenderer.js +11 -0
- package/es/platform/client-actions/components/client-actions-renderer/frameworks/ui/client-actions-renderer/ClientActionsRenderer.module.css +23 -0
- package/es/platform/client-actions/components/client-actions-renderer/frameworks/ui/client-actions-renderer/ClientActionsRendererView.js +25 -0
- package/es/platform/client-actions/components/client-actions-renderer/frameworks/ui/client-actions-renderer/views/DefaultActionsRendererView.js +66 -0
- package/es/platform/client-actions/components/client-actions-renderer/frameworks/ui/more-actions-renderer/MoreActionsRenderer.js +9 -0
- package/es/platform/client-actions/components/client-actions-renderer/frameworks/ui/more-actions-renderer/MoreActionsRendererView.js +81 -0
- package/es/platform/client-scripts/behaviour/zclient-scripts-fetch/adapters/resources/ClientScriptsFetchSDK.js +43 -0
- package/es/platform/client-scripts/behaviour/zclient-scripts-fetch/adapters/resources/__test__/ClientScriptsFetchSDK.test.js +163 -0
- package/es/platform/client-scripts/behaviour/zclient-scripts-fetch/applications/interfaces/ClientScriptsAPIGatewayParams.js +1 -0
- package/es/platform/client-scripts/behaviour/zclient-scripts-fetch/applications/interfaces/ClientScriptsSDKFetchParams.js +1 -0
- package/es/platform/client-scripts/behaviour/zclient-scripts-fetch/applications/interfaces/IClientScriptsFetchSDK.js +0 -0
- package/es/platform/components/smart-action-band/adapters/presenters/ActionBandTranslator.js +7 -4
- package/es/platform/data-source/http-template/getPageClientActions.js +23 -0
- package/es/platform/zform/adapters/presenter/FormTranslator.js +18 -15
- package/es/platform/zform/adapters/presenter/translators/SectionTranslator.js +1 -1
- package/es/platform/zlist/adapters/presenters/TableTranslator.js +5 -4
- package/es/platform/zlist/adapters/presenters/translators/fields/DateFieldTranslator.js +7 -3
- package/es/platform/zlist/adapters/presenters/translators/fields/DateTimeFieldTranslator.js +7 -3
- package/package.json +4 -4
- package/es/.DS_Store +0 -0
- package/es/platform/.DS_Store +0 -0
package/es/index.js
CHANGED
|
@@ -5,7 +5,9 @@ import ExternalConstants from "./cc/table-connected/constants/ExternalConstants"
|
|
|
5
5
|
import ActionEventMediator from "./platform/client-actions/components/action-event-mediator/frameworks/ui/ActionEventMediator";
|
|
6
6
|
import RowActionsRenderer from "./platform/client-actions/components/row-actions-renderer/frameworks/ui/RowActions/RowActionsRenderer";
|
|
7
7
|
import AdaptiveRowActionsRenderer from "./platform/client-actions/components/row-actions-renderer/frameworks/ui/AdaptiveRowActions/AdaptiveRowActionsRenderer";
|
|
8
|
-
import ClientActionReordererRegistry from "./platform/client-actions/components/action-event-mediator/frameworks/ui/ClientActionReordererRegistry";
|
|
8
|
+
import ClientActionReordererRegistry from "./platform/client-actions/components/action-event-mediator/frameworks/ui/ClientActionReordererRegistry";
|
|
9
|
+
import ClientActionsFetchSDK from "./platform/client-actions/behaviour/zclient-actions/adapters/resources/ClientActionsFetchSDK";
|
|
10
|
+
import ClientScriptsFetchSDK from "./platform/client-scripts/behaviour/zclient-scripts-fetch/adapters/resources/ClientScriptsFetchSDK"; // Rebuild SmartTableConstants without Events
|
|
9
11
|
|
|
10
12
|
const SmartTableConstants = {
|
|
11
13
|
ExternalConstants
|
|
@@ -40,4 +42,6 @@ export const Behaviours = {
|
|
|
40
42
|
FieldSectionEventMappingBehaviourFactory
|
|
41
43
|
};
|
|
42
44
|
export * from "./library/analytics";
|
|
43
|
-
export { ClientActionReordererRegistry };
|
|
45
|
+
export { ClientActionReordererRegistry };
|
|
46
|
+
export { ClientActionsFetchSDK };
|
|
47
|
+
export { ClientScriptsFetchSDK };
|
package/es/platform/client-actions/behaviour/zclient-actions/adapters/presenters/FilterUtils.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function validateClientActionLocation(actualLocation, expectedLocation) {
|
|
2
|
+
return actualLocation === expectedLocation || actualLocation.endsWith(`.${expectedLocation}`);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function validateClientAction(clientAction, location) {
|
|
6
|
+
return clientAction.location && validateClientActionLocation(clientAction.location, location);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function filterClientActionsByLocation(clientActions, location) {
|
|
10
|
+
return clientActions.filter(clientAction => clientAction && validateClientAction(clientAction, location));
|
|
11
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import FetchGateWay from "../../../../../zhttp/adapters/gateway/FetchGateWay";
|
|
2
|
+
import APITemplate from "../../../../../zdata-source/domain/entities/APITemplate";
|
|
3
|
+
import getClientActions from "../../../../../data-source/http-template/getPageClientActions";
|
|
4
|
+
import TemplateHelpers from "../../../../../zdata-source/adapters/gateways/TemplateHelpers";
|
|
5
|
+
|
|
6
|
+
//TODO: Remove this SDK when smart page is ready for production
|
|
7
|
+
// Use this SDK only for fetching client actions at page level in desk_client_app until smart page is ready
|
|
8
|
+
class ClientActionsFetchSDK {
|
|
9
|
+
getClientActionsAPIDetails(args) {
|
|
10
|
+
const apiTemplate = new APITemplate(getClientActions, new TemplateHelpers());
|
|
11
|
+
const apiArgs = { ...args,
|
|
12
|
+
servicePrefix: 'supportapi/zd',
|
|
13
|
+
// @ts-ignore - custom property
|
|
14
|
+
orgName: window.currentOrg.portalName
|
|
15
|
+
};
|
|
16
|
+
const apiDetailsModel = apiTemplate.getApiDetails(apiArgs);
|
|
17
|
+
return { ...apiDetailsModel,
|
|
18
|
+
options: {
|
|
19
|
+
headers: {
|
|
20
|
+
// @ts-ignore - custom property
|
|
21
|
+
orgId: window.currentOrg.id
|
|
22
|
+
},
|
|
23
|
+
method: apiDetailsModel.method
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
mapClientActionsByInstanceLocation(clientActions) {
|
|
29
|
+
const filteredClientActionsMap = new Map();
|
|
30
|
+
|
|
31
|
+
for (const clientAction of clientActions) {
|
|
32
|
+
const {
|
|
33
|
+
location,
|
|
34
|
+
component
|
|
35
|
+
} = clientAction;
|
|
36
|
+
const locationPathArr = location.split('.');
|
|
37
|
+
const instanceName = locationPathArr[1] || component;
|
|
38
|
+
const locationName = locationPathArr[2] || location;
|
|
39
|
+
|
|
40
|
+
if (!instanceName || !locationName) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!filteredClientActionsMap.has(instanceName)) {
|
|
45
|
+
filteredClientActionsMap.set(instanceName, {});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const instanceActions = filteredClientActionsMap.get(instanceName);
|
|
49
|
+
|
|
50
|
+
if (!instanceActions[locationName]) {
|
|
51
|
+
instanceActions[locationName] = [];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
instanceActions[locationName].push(clientAction);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return filteredClientActionsMap;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async fetchClientActions(params) {
|
|
61
|
+
const apiDetails = this.getClientActionsAPIDetails(params);
|
|
62
|
+
const fetchGateway = new FetchGateWay(window.fetch.bind(window));
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
fetchGateway.fetch(apiDetails.url, apiDetails.options).then(response => response.json()).then(clientActions => {
|
|
65
|
+
this.clientActions = clientActions;
|
|
66
|
+
const filteredClientActionsMap = this.mapClientActionsByInstanceLocation(this.clientActions);
|
|
67
|
+
return resolve(filteredClientActionsMap);
|
|
68
|
+
}).catch(err => {
|
|
69
|
+
reject(err);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default ClientActionsFetchSDK;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import ClientActionsFetchSDK from "../ClientActionsFetchSDK";
|
|
2
|
+
const getApiDetailsMock = jest.fn();
|
|
3
|
+
jest.mock("../../../../../../zdata-source/domain/entities/APITemplate", () => ({
|
|
4
|
+
__esModule: true,
|
|
5
|
+
default: jest.fn().mockImplementation(() => ({
|
|
6
|
+
getApiDetails: getApiDetailsMock
|
|
7
|
+
}))
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
const createAction = function () {
|
|
11
|
+
let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
12
|
+
return {
|
|
13
|
+
id: 'action-1',
|
|
14
|
+
name: 'test-action',
|
|
15
|
+
location: 'module.instance.header_actions',
|
|
16
|
+
component: 'smartTable',
|
|
17
|
+
...overrides
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe('ClientActionsFetchSDK', () => {
|
|
22
|
+
let sdk;
|
|
23
|
+
const originalWindow = global.window;
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
getApiDetailsMock.mockReturnValue({
|
|
26
|
+
url: '/supportapi/zd/acme/api/v1/clientActions?from=0&limit=50',
|
|
27
|
+
method: 'GET',
|
|
28
|
+
options: {
|
|
29
|
+
method: 'GET'
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
global.window = {
|
|
33
|
+
currentOrg: {
|
|
34
|
+
portalName: 'acme',
|
|
35
|
+
id: '1001'
|
|
36
|
+
},
|
|
37
|
+
fetch: jest.fn()
|
|
38
|
+
};
|
|
39
|
+
sdk = new ClientActionsFetchSDK();
|
|
40
|
+
});
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
global.window = originalWindow;
|
|
44
|
+
});
|
|
45
|
+
describe('getClientActionsAPIDetails', () => {
|
|
46
|
+
test('builds API details with org context and headers', () => {
|
|
47
|
+
const details = sdk.getClientActionsAPIDetails({
|
|
48
|
+
from: 0,
|
|
49
|
+
limit: 50
|
|
50
|
+
});
|
|
51
|
+
expect(getApiDetailsMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
52
|
+
from: 0,
|
|
53
|
+
limit: 50,
|
|
54
|
+
servicePrefix: 'supportapi/zd',
|
|
55
|
+
orgName: 'acme'
|
|
56
|
+
}));
|
|
57
|
+
expect(details.url).toContain('/supportapi/zd/acme/api/v1/clientActions');
|
|
58
|
+
expect(details.method).toBe('GET');
|
|
59
|
+
expect(details.options.method).toBe('GET');
|
|
60
|
+
expect(details.options.headers.orgId).toBe('1001');
|
|
61
|
+
});
|
|
62
|
+
test('handles boundary pagination values without failing', () => {
|
|
63
|
+
const details = sdk.getClientActionsAPIDetails({
|
|
64
|
+
from: 0,
|
|
65
|
+
limit: 0
|
|
66
|
+
});
|
|
67
|
+
expect(details.url).toContain('/supportapi/zd/acme/api/v1/clientActions');
|
|
68
|
+
expect(details.options.method).toBe(details.method);
|
|
69
|
+
});
|
|
70
|
+
test('throws when currentOrg is missing', () => {
|
|
71
|
+
delete global.window.currentOrg;
|
|
72
|
+
expect(() => sdk.getClientActionsAPIDetails({
|
|
73
|
+
from: 0,
|
|
74
|
+
limit: 50
|
|
75
|
+
})).toThrow();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('mapClientActionsByInstanceLocation', () => {
|
|
79
|
+
test('returns empty map for empty list', () => {
|
|
80
|
+
const result = sdk.mapClientActionsByInstanceLocation([]);
|
|
81
|
+
expect(result.size).toBe(0);
|
|
82
|
+
});
|
|
83
|
+
test('groups actions by instance and location for dotted location path', () => {
|
|
84
|
+
const action = createAction({
|
|
85
|
+
location: 'module.table.header_actions',
|
|
86
|
+
component: 'smartTable'
|
|
87
|
+
});
|
|
88
|
+
const result = sdk.mapClientActionsByInstanceLocation([action]);
|
|
89
|
+
expect(result.has('table')).toBe(true);
|
|
90
|
+
expect(result.get('table')?.header_actions).toEqual([action]);
|
|
91
|
+
});
|
|
92
|
+
test('falls back to component and full location when location has no dot path', () => {
|
|
93
|
+
const action = createAction({
|
|
94
|
+
location: 'row_actions',
|
|
95
|
+
component: 'smartTable'
|
|
96
|
+
});
|
|
97
|
+
const result = sdk.mapClientActionsByInstanceLocation([action]);
|
|
98
|
+
expect(result.has('smartTable')).toBe(true);
|
|
99
|
+
expect(result.get('smartTable')?.row_actions).toEqual([action]);
|
|
100
|
+
});
|
|
101
|
+
test('keeps duplicates under same instance/location', () => {
|
|
102
|
+
const first = createAction({
|
|
103
|
+
id: '1',
|
|
104
|
+
location: 'module.table.row_actions'
|
|
105
|
+
});
|
|
106
|
+
const second = createAction({
|
|
107
|
+
id: '2',
|
|
108
|
+
location: 'module.table.row_actions'
|
|
109
|
+
});
|
|
110
|
+
const result = sdk.mapClientActionsByInstanceLocation([first, second]);
|
|
111
|
+
expect(result.get('table')?.row_actions).toHaveLength(2);
|
|
112
|
+
expect(result.get('table')?.row_actions).toEqual([first, second]);
|
|
113
|
+
});
|
|
114
|
+
test('uses second and third segments for multi-segment location', () => {
|
|
115
|
+
const action = createAction({
|
|
116
|
+
location: 'a.b.c.d',
|
|
117
|
+
component: 'fallbackComponent'
|
|
118
|
+
});
|
|
119
|
+
const result = sdk.mapClientActionsByInstanceLocation([action]);
|
|
120
|
+
expect(result.has('b')).toBe(true);
|
|
121
|
+
expect(result.get('b')?.c).toEqual([action]);
|
|
122
|
+
});
|
|
123
|
+
test('throws for malformed action location', () => {
|
|
124
|
+
const malformed = createAction({
|
|
125
|
+
location: undefined
|
|
126
|
+
});
|
|
127
|
+
expect(() => sdk.mapClientActionsByInstanceLocation([malformed])).toThrow();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe('fetchClientActions', () => {
|
|
131
|
+
const validParams = {
|
|
132
|
+
from: 0,
|
|
133
|
+
limit: 50,
|
|
134
|
+
components: 'smartTable',
|
|
135
|
+
modules: 'tickets',
|
|
136
|
+
page: 'list'
|
|
137
|
+
};
|
|
138
|
+
test('resolves grouped map on successful fetch', async () => {
|
|
139
|
+
const payload = [createAction({
|
|
140
|
+
location: 'module.table.header_actions',
|
|
141
|
+
component: 'smartTable'
|
|
142
|
+
}), createAction({
|
|
143
|
+
id: '2',
|
|
144
|
+
location: 'row_actions',
|
|
145
|
+
component: 'smartTable'
|
|
146
|
+
})];
|
|
147
|
+
global.window.fetch.mockResolvedValue({
|
|
148
|
+
json: jest.fn().mockResolvedValue(payload)
|
|
149
|
+
});
|
|
150
|
+
const result = await sdk.fetchClientActions(validParams);
|
|
151
|
+
expect(global.window.fetch).toHaveBeenCalledTimes(1);
|
|
152
|
+
const [url, options] = global.window.fetch.mock.calls[0];
|
|
153
|
+
expect(url).toContain('/supportapi/zd/acme/api/v1/clientActions');
|
|
154
|
+
expect(options.headers.orgId).toBe('1001');
|
|
155
|
+
expect(result.get('table')?.header_actions).toHaveLength(1);
|
|
156
|
+
expect(result.get('smartTable')?.row_actions).toHaveLength(1);
|
|
157
|
+
});
|
|
158
|
+
test('resolves empty map when response payload is empty list', async () => {
|
|
159
|
+
global.window.fetch.mockResolvedValue({
|
|
160
|
+
json: jest.fn().mockResolvedValue([])
|
|
161
|
+
});
|
|
162
|
+
const result = await sdk.fetchClientActions(validParams);
|
|
163
|
+
expect(result.size).toBe(0);
|
|
164
|
+
});
|
|
165
|
+
test('rejects when fetch fails', async () => {
|
|
166
|
+
const networkError = new Error('Network down');
|
|
167
|
+
global.window.fetch.mockRejectedValue(networkError);
|
|
168
|
+
await expect(sdk.fetchClientActions(validParams)).rejects.toThrow('Network down');
|
|
169
|
+
});
|
|
170
|
+
test('rejects when response json parsing fails', async () => {
|
|
171
|
+
global.window.fetch.mockResolvedValue({
|
|
172
|
+
json: jest.fn().mockRejectedValue(new Error('Invalid JSON'))
|
|
173
|
+
});
|
|
174
|
+
await expect(sdk.fetchClientActions(validParams)).rejects.toThrow('Invalid JSON');
|
|
175
|
+
});
|
|
176
|
+
test('rejects when json payload is non-iterable', async () => {
|
|
177
|
+
global.window.fetch.mockResolvedValue({
|
|
178
|
+
json: jest.fn().mockResolvedValue(null)
|
|
179
|
+
});
|
|
180
|
+
await expect(sdk.fetchClientActions(validParams)).rejects.toThrow();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var ClientActionPage = /*#__PURE__*/function (ClientActionPage) {
|
|
2
|
+
ClientActionPage["LIST"] = "list";
|
|
3
|
+
ClientActionPage["DETAILS"] = "details";
|
|
4
|
+
ClientActionPage["CREATE_PAGE"] = "createPage";
|
|
5
|
+
ClientActionPage["EDIT_PAGE"] = "editPage";
|
|
6
|
+
ClientActionPage["ALL_PAGES"] = "allPages";
|
|
7
|
+
return ClientActionPage;
|
|
8
|
+
}(ClientActionPage || {});
|
|
9
|
+
|
|
10
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { clientScriptsSchema } from "../../../client-scripts/cc/zclient-scripts-execution/clientScriptsSchema";
|
|
2
|
+
import { actionsSchema } from "../action-event-mediator/Properties";
|
|
3
|
+
import viewMetaSchema from "./ViewMetaSchema";
|
|
4
|
+
export default {
|
|
5
|
+
location: {
|
|
6
|
+
required: false,
|
|
7
|
+
typeMetadata: {
|
|
8
|
+
schema: {
|
|
9
|
+
type: 'string'
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
defaultValue: ''
|
|
13
|
+
},
|
|
14
|
+
instanceName: {
|
|
15
|
+
required: false,
|
|
16
|
+
typeMetadata: {
|
|
17
|
+
schema: {
|
|
18
|
+
type: 'string'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
defaultValue: ''
|
|
22
|
+
},
|
|
23
|
+
testId: {
|
|
24
|
+
required: false,
|
|
25
|
+
typeMetadata: {
|
|
26
|
+
schema: {
|
|
27
|
+
type: 'string'
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
defaultValue: ''
|
|
31
|
+
},
|
|
32
|
+
actions: {
|
|
33
|
+
required: true,
|
|
34
|
+
typeMetadata: {
|
|
35
|
+
schema: actionsSchema
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
clientScripts: {
|
|
39
|
+
required: false,
|
|
40
|
+
typeMetadata: {
|
|
41
|
+
schema: clientScriptsSchema
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
context: {
|
|
45
|
+
required: false,
|
|
46
|
+
typeMetadata: {
|
|
47
|
+
schema: {
|
|
48
|
+
type: 'object'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
viewMeta: {
|
|
53
|
+
required: false,
|
|
54
|
+
typeMetadata: {
|
|
55
|
+
schema: viewMetaSchema
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Layout } from "../../components/client-actions-renderer/domain/entities/State";
|
|
2
|
+
import { ActionViewGap } from "../../components/interfaces/ActionViewModel";
|
|
3
|
+
export default {
|
|
4
|
+
type: 'object',
|
|
5
|
+
properties: {
|
|
6
|
+
layout: {
|
|
7
|
+
type: 'string',
|
|
8
|
+
enum: [Layout.HORIZONTAL, Layout.VERTICAL, Layout.HORIZONTAL_WITH_MORE_ACTIONS, Layout.VERTICAL_WITH_MORE_ACTIONS],
|
|
9
|
+
default: Layout.HORIZONTAL
|
|
10
|
+
},
|
|
11
|
+
gap: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
enum: [ActionViewGap.NONE, ActionViewGap.SMALL, ActionViewGap.MEDIUM, ActionViewGap.LARGE, ActionViewGap.XLARGE, ActionViewGap.XMEDIUM],
|
|
14
|
+
default: ActionViewGap.NONE
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import ClientActionsTranslator from "../../../../translators/client-actions-translator";
|
|
2
|
+
export default class ClientActionsRendererTranslator {
|
|
3
|
+
// eslint-disable-next-line complexity -- Need this complexity to transform client actions to action view model which is used for rendering client actions in UI
|
|
4
|
+
static transformState(state) {
|
|
5
|
+
let actions = state.properties.actions;
|
|
6
|
+
const {
|
|
7
|
+
context,
|
|
8
|
+
location,
|
|
9
|
+
instanceName
|
|
10
|
+
} = state.properties;
|
|
11
|
+
|
|
12
|
+
if ((!actions || actions.length === 0) && location && instanceName) {
|
|
13
|
+
actions = []; //TODO: Need to update this logic to use platformBridge SDK to use fetched client actions at page level
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const resolvedActions = ClientActionsTranslator.transform(actions, context.instanceName, context.moduleName, context);
|
|
17
|
+
return { ...state,
|
|
18
|
+
properties: { ...state.properties,
|
|
19
|
+
actions: resolvedActions
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/es/platform/client-actions/components/client-actions-renderer/domain/entities/Context.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/es/platform/client-actions/components/client-actions-renderer/domain/entities/State.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export let Layout = /*#__PURE__*/function (Layout) {
|
|
2
|
+
Layout["HORIZONTAL"] = "horizontal";
|
|
3
|
+
Layout["VERTICAL"] = "vertical";
|
|
4
|
+
Layout["HORIZONTAL_WITH_MORE_ACTIONS"] = "horizontal-with-more-actions";
|
|
5
|
+
Layout["VERTICAL_WITH_MORE_ACTIONS"] = "vertical-with-more-actions";
|
|
6
|
+
return Layout;
|
|
7
|
+
}({});
|
|
8
|
+
;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createCustomComponent } from "../../../../../../../library/custom-component";
|
|
2
|
+
import ClientActionsRendererProperties from "../../../../../cc/client-actions-renderer/Properties";
|
|
3
|
+
import ClientActionsRendererTranslator from "../../../adapters/presenters/ClientActionsRendererTranslator";
|
|
4
|
+
import ClientActionsRendererView from "./ClientActionsRendererView";
|
|
5
|
+
export default createCustomComponent({
|
|
6
|
+
name: 'ClientActionsRenderer',
|
|
7
|
+
properties: ClientActionsRendererProperties,
|
|
8
|
+
transformState: ClientActionsRendererTranslator.transformState,
|
|
9
|
+
eventHandlers: {},
|
|
10
|
+
View: ClientActionsRendererView
|
|
11
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
max-width: 100%
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.gap_small {
|
|
6
|
+
gap: var(--zd_size4)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.gap_xmedium {
|
|
10
|
+
gap: var(--zd_size6)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.gap_medium {
|
|
14
|
+
gap: var(--zd_size8)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.gap_large {
|
|
18
|
+
gap: var(--zd_size10)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.gap_xlarge {
|
|
22
|
+
gap: var(--zd_size12)
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import DefaultActionsRendererView from "./views/DefaultActionsRendererView";
|
|
3
|
+
import ComponentRegistry from "../../../../../../../library/custom-component/frameworks/ui/ComponentRegistry";
|
|
4
|
+
export default function ClientActionsRendererView(_ref, ref) {
|
|
5
|
+
let {
|
|
6
|
+
state
|
|
7
|
+
} = _ref;
|
|
8
|
+
const {
|
|
9
|
+
actions,
|
|
10
|
+
clientScripts,
|
|
11
|
+
viewMeta,
|
|
12
|
+
testId,
|
|
13
|
+
slotName,
|
|
14
|
+
instanceName
|
|
15
|
+
} = state.properties;
|
|
16
|
+
const customView = slotName !== '' && instanceName !== '' ? ComponentRegistry.get(`${instanceName}_${slotName}_renderer`) : null;
|
|
17
|
+
const View = customView ? customView : DefaultActionsRendererView;
|
|
18
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
19
|
+
clientActions: actions,
|
|
20
|
+
clientScripts: clientScripts,
|
|
21
|
+
viewMeta: viewMeta,
|
|
22
|
+
getRef: ref,
|
|
23
|
+
testId: testId
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import ActionEventMediator from "../../../../../action-event-mediator/frameworks/ui/ActionEventMediator";
|
|
2
|
+
import { findMappedClientScripts } from "../../../../../../../client-scripts/behaviour/zclient-scripts-execution/frameworks/ClientScriptsUtils";
|
|
3
|
+
import { ActionViewGap } from "../../../../../interfaces/ActionViewModel"; //@ts-ignore
|
|
4
|
+
|
|
5
|
+
import style from "../ClientActionsRenderer.module.css";
|
|
6
|
+
import MoreActionsRenderer from "../../more-actions-renderer/MoreActionsRenderer";
|
|
7
|
+
import Flex from '@zohodesk/layout/es/Flex/Flex';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { Layout } from "../../../../domain/entities/State";
|
|
10
|
+
const HORIZONTAL_LAYOUTS = [Layout.HORIZONTAL, Layout.HORIZONTAL_WITH_MORE_ACTIONS];
|
|
11
|
+
const MORE_ACTIONS_LAYOUTS = [Layout.VERTICAL_WITH_MORE_ACTIONS, Layout.HORIZONTAL_WITH_MORE_ACTIONS];
|
|
12
|
+
|
|
13
|
+
function renderAction(action, clientScripts) {
|
|
14
|
+
return /*#__PURE__*/React.createElement(ActionEventMediator, {
|
|
15
|
+
key: action.id //@ts-ignore - action property defined using ACA pattern
|
|
16
|
+
,
|
|
17
|
+
action: action,
|
|
18
|
+
clientScripts: findMappedClientScripts(action, clientScripts),
|
|
19
|
+
instanceName: action.instanceName
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getFlexDirection(layout) {
|
|
24
|
+
return HORIZONTAL_LAYOUTS.includes(layout) ? 'row' : 'column';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getGapClassName(gap) {
|
|
28
|
+
return gap !== ActionViewGap.NONE ? style[`gap_${gap}`] : '';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function shouldShowMoreActions(actionsCount, layout) {
|
|
32
|
+
return actionsCount > 3 && MORE_ACTIONS_LAYOUTS.includes(layout);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getVisibleActions(showMore, firstAction, secondAction, allActions) {
|
|
36
|
+
return showMore ? [firstAction, secondAction] : allActions;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default function DefaultActionsRendererView(_ref) {
|
|
40
|
+
let {
|
|
41
|
+
clientActions,
|
|
42
|
+
clientScripts,
|
|
43
|
+
viewMeta,
|
|
44
|
+
getRef,
|
|
45
|
+
testId = ''
|
|
46
|
+
} = _ref;
|
|
47
|
+
const [firstAction, secondAction, ...moreActions] = clientActions;
|
|
48
|
+
const layout = viewMeta?.layout ?? Layout.HORIZONTAL;
|
|
49
|
+
const gap = viewMeta?.gap ?? ActionViewGap.NONE;
|
|
50
|
+
const showMore = shouldShowMoreActions(clientActions.length, layout);
|
|
51
|
+
const actionsList = getVisibleActions(showMore, firstAction, secondAction, clientActions);
|
|
52
|
+
return /*#__PURE__*/React.createElement(Flex, {
|
|
53
|
+
ref: getRef,
|
|
54
|
+
testId: testId,
|
|
55
|
+
$ui_direction: getFlexDirection(layout),
|
|
56
|
+
$ui_className: getGapClassName(gap),
|
|
57
|
+
$ui_displayMode: "inline",
|
|
58
|
+
$ui_alignItems: "center"
|
|
59
|
+
}, actionsList.map(action => renderAction(action, clientScripts)), showMore &&
|
|
60
|
+
/*#__PURE__*/
|
|
61
|
+
//@ts-ignore - action property defined using ACA pattern
|
|
62
|
+
React.createElement(MoreActionsRenderer, {
|
|
63
|
+
actions: moreActions,
|
|
64
|
+
clientScripts: clientScripts
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createCustomComponent } from "../../../../../../../library/custom-component";
|
|
2
|
+
import RowActionsRendererProperties from "../../../../../cc/client-actions-renderer/Properties";
|
|
3
|
+
import MoreActionsRendererView from "./MoreActionsRendererView";
|
|
4
|
+
export default createCustomComponent({
|
|
5
|
+
name: "MoreActionsRenderer",
|
|
6
|
+
eventHandlers: {},
|
|
7
|
+
properties: RowActionsRendererProperties,
|
|
8
|
+
View: MoreActionsRendererView
|
|
9
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ActionEventMediator from "../../../../action-event-mediator/frameworks/ui/ActionEventMediator";
|
|
3
|
+
import CustomDropdown from '@zohodesk-private/desk-components/es/CustomDropdown/CustomDropdown';
|
|
4
|
+
import ListItemConstants from "../../../../../../../cc/list-item/Constants";
|
|
5
|
+
import IconButton from '@zohodesk/dot/es/IconButton/IconButton';
|
|
6
|
+
import { findMappedClientScripts } from "../../../../../../client-scripts/behaviour/zclient-scripts-execution/frameworks/ClientScriptsUtils";
|
|
7
|
+
export function ListItemConvertor(action) {
|
|
8
|
+
// @ts-ignore - properties from ActionViewModel are being used to convert the action to ListItem compatible action, which is then used for rendering the ListItem in MoreActionsRenderer
|
|
9
|
+
const {
|
|
10
|
+
id,
|
|
11
|
+
properties: {
|
|
12
|
+
icon
|
|
13
|
+
},
|
|
14
|
+
eventMappings,
|
|
15
|
+
instanceName
|
|
16
|
+
} = action; // @ts-ignore - properties from ActionViewModel are being used to convert the action to ListItem compatible action, which is then used for rendering the ListItem in MoreActionsRenderer
|
|
17
|
+
|
|
18
|
+
const label = action.properties.label ? action.properties.label : action.properties.text;
|
|
19
|
+
const updatedEventMappings = eventMappings.map(eventMapping => {
|
|
20
|
+
return { ...eventMapping,
|
|
21
|
+
sourceEvent: ListItemConstants.LISTITEM_CLICKED
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
component: 'ListItem',
|
|
26
|
+
properties: {
|
|
27
|
+
text: label,
|
|
28
|
+
tooltip: label,
|
|
29
|
+
icon,
|
|
30
|
+
id
|
|
31
|
+
},
|
|
32
|
+
eventMappings: updatedEventMappings,
|
|
33
|
+
id,
|
|
34
|
+
instanceName
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function renderTargetElement(_ref) {
|
|
39
|
+
let {
|
|
40
|
+
handleTogglePopup,
|
|
41
|
+
isPopupOpen
|
|
42
|
+
} = _ref;
|
|
43
|
+
return /*#__PURE__*/React.createElement(IconButton, {
|
|
44
|
+
iconName: "ZD-GN-more",
|
|
45
|
+
iconSize: "16",
|
|
46
|
+
isActive: isPopupOpen,
|
|
47
|
+
onClick: handleTogglePopup
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function renderAction(action, clientScripts, instanceName) {
|
|
52
|
+
const mappedClientScripts = findMappedClientScripts(action, clientScripts);
|
|
53
|
+
return /*#__PURE__*/React.createElement(ActionEventMediator //@ts-ignore - property defined in ACA component
|
|
54
|
+
, {
|
|
55
|
+
action: action,
|
|
56
|
+
clientScripts: mappedClientScripts,
|
|
57
|
+
instanceName: instanceName
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function MoreActionsRendererView(_ref2, ref) {
|
|
62
|
+
let {
|
|
63
|
+
state
|
|
64
|
+
} = _ref2;
|
|
65
|
+
const {
|
|
66
|
+
actions,
|
|
67
|
+
clientScripts
|
|
68
|
+
} = state.properties;
|
|
69
|
+
const listItemActions = actions.map(action => ListItemConvertor(action));
|
|
70
|
+
return /*#__PURE__*/React.createElement(CustomDropdown, {
|
|
71
|
+
$ui_boxSize: "medium",
|
|
72
|
+
$flag_padding: true,
|
|
73
|
+
$render_targetElement: renderTargetElement,
|
|
74
|
+
$method_getRef: ref,
|
|
75
|
+
$customProps_dropbox: {
|
|
76
|
+
onClick: undefined
|
|
77
|
+
}
|
|
78
|
+
}, listItemActions.map(action => renderAction(action, clientScripts, action.instanceName)));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default MoreActionsRendererView;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import APITemplate from "../../../../../zdata-source/domain/entities/APITemplate";
|
|
2
|
+
import TemplateHelpers from "../../../../../zdata-source/adapters/gateways/TemplateHelpers";
|
|
3
|
+
import FetchGateWay from "../../../../../zhttp/adapters/gateway/FetchGateWay";
|
|
4
|
+
import getClientScripts from "../../../../../data-source/http-template/getClientScripts";
|
|
5
|
+
|
|
6
|
+
//TODO: Remove this SDK when smart page is ready for production
|
|
7
|
+
// Use this SDK only for fetching client actions at page level in desk_client_app until smart page is ready
|
|
8
|
+
class ClientScriptsFetchSDK {
|
|
9
|
+
getClientScriptsAPIDetails(args) {
|
|
10
|
+
const apiTemplate = new APITemplate(getClientScripts, new TemplateHelpers());
|
|
11
|
+
const apiArgs = { ...args,
|
|
12
|
+
servicePrefix: 'supportapi/zd',
|
|
13
|
+
// @ts-ignore - custom property
|
|
14
|
+
orgName: window.currentOrg.portalName
|
|
15
|
+
};
|
|
16
|
+
const apiDetailsModel = apiTemplate.getApiDetails(apiArgs);
|
|
17
|
+
return { ...apiDetailsModel,
|
|
18
|
+
options: {
|
|
19
|
+
headers: {
|
|
20
|
+
// @ts-ignore - custom property
|
|
21
|
+
orgId: window.currentOrg.id
|
|
22
|
+
},
|
|
23
|
+
method: apiDetailsModel.method
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async fetchClientScripts(params) {
|
|
29
|
+
const apiDetails = this.getClientScriptsAPIDetails(params);
|
|
30
|
+
const fetchGateway = new FetchGateWay(window.fetch.bind(window));
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
fetchGateway.fetch(apiDetails.url, apiDetails.options).then(response => response.json()).then(clientScripts => {
|
|
33
|
+
this.clientScripts = clientScripts;
|
|
34
|
+
return resolve(clientScripts);
|
|
35
|
+
}).catch(err => {
|
|
36
|
+
reject(err);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default ClientScriptsFetchSDK;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import ClientScriptsFetchSDK from "../ClientScriptsFetchSDK";
|
|
2
|
+
const getApiDetailsMock = jest.fn();
|
|
3
|
+
jest.mock("../../../../../../zdata-source/domain/entities/APITemplate", () => ({
|
|
4
|
+
__esModule: true,
|
|
5
|
+
default: jest.fn().mockImplementation(() => ({
|
|
6
|
+
getApiDetails: getApiDetailsMock
|
|
7
|
+
}))
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
const createScript = function () {
|
|
11
|
+
let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
12
|
+
return {
|
|
13
|
+
id: 'script-1',
|
|
14
|
+
name: 'sample-script',
|
|
15
|
+
...overrides
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('ClientScriptsFetchSDK', () => {
|
|
20
|
+
let sdk;
|
|
21
|
+
const originalWindow = global.window;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
getApiDetailsMock.mockReturnValue({
|
|
24
|
+
url: '/supportapi/zd/acme/api/v1/clientScripts?from=0&limit=50',
|
|
25
|
+
method: 'GET',
|
|
26
|
+
options: {
|
|
27
|
+
method: 'GET'
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
global.window = {
|
|
31
|
+
currentOrg: {
|
|
32
|
+
portalName: 'acme',
|
|
33
|
+
id: '1001'
|
|
34
|
+
},
|
|
35
|
+
fetch: jest.fn()
|
|
36
|
+
};
|
|
37
|
+
sdk = new ClientScriptsFetchSDK();
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
jest.clearAllMocks();
|
|
41
|
+
global.window = originalWindow;
|
|
42
|
+
});
|
|
43
|
+
describe('getClientScriptsAPIDetails', () => {
|
|
44
|
+
test('builds API details with org context and headers', () => {
|
|
45
|
+
const details = sdk.getClientScriptsAPIDetails({
|
|
46
|
+
from: 0,
|
|
47
|
+
limit: 50
|
|
48
|
+
});
|
|
49
|
+
expect(getApiDetailsMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
50
|
+
from: 0,
|
|
51
|
+
limit: 50,
|
|
52
|
+
servicePrefix: 'supportapi/zd',
|
|
53
|
+
orgName: 'acme'
|
|
54
|
+
}));
|
|
55
|
+
expect(details.url).toContain('/supportapi/zd/acme/api/v1/clientScripts');
|
|
56
|
+
expect(details.method).toBe('GET');
|
|
57
|
+
expect(details.options.method).toBe('GET');
|
|
58
|
+
expect(details.options.headers.orgId).toBe('1001');
|
|
59
|
+
});
|
|
60
|
+
test('handles boundary pagination values without failing', () => {
|
|
61
|
+
const details = sdk.getClientScriptsAPIDetails({
|
|
62
|
+
from: 0,
|
|
63
|
+
limit: 0
|
|
64
|
+
});
|
|
65
|
+
expect(details.url).toContain('/supportapi/zd/acme/api/v1/clientScripts');
|
|
66
|
+
expect(details.options.method).toBe(details.method);
|
|
67
|
+
});
|
|
68
|
+
test('handles large pagination values without failing', () => {
|
|
69
|
+
const details = sdk.getClientScriptsAPIDetails({
|
|
70
|
+
from: 999999,
|
|
71
|
+
limit: 100000
|
|
72
|
+
});
|
|
73
|
+
expect(details.method).toBe('GET');
|
|
74
|
+
expect(details.options.headers.orgId).toBe('1001');
|
|
75
|
+
});
|
|
76
|
+
test('throws when currentOrg is missing', () => {
|
|
77
|
+
delete global.window.currentOrg;
|
|
78
|
+
expect(() => sdk.getClientScriptsAPIDetails({
|
|
79
|
+
from: 0,
|
|
80
|
+
limit: 50
|
|
81
|
+
})).toThrow();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('fetchClientScripts', () => {
|
|
85
|
+
const validParams = {
|
|
86
|
+
from: 0,
|
|
87
|
+
limit: 50,
|
|
88
|
+
components: 'smartTable',
|
|
89
|
+
modules: 'tickets'
|
|
90
|
+
};
|
|
91
|
+
test('resolves scripts array on successful fetch/json', async () => {
|
|
92
|
+
const payload = [createScript(), createScript({
|
|
93
|
+
id: 'script-2'
|
|
94
|
+
})];
|
|
95
|
+
global.window.fetch.mockResolvedValue({
|
|
96
|
+
json: jest.fn().mockResolvedValue(payload)
|
|
97
|
+
});
|
|
98
|
+
const result = await sdk.fetchClientScripts(validParams);
|
|
99
|
+
expect(global.window.fetch).toHaveBeenCalledTimes(1);
|
|
100
|
+
const [url, options] = global.window.fetch.mock.calls[0];
|
|
101
|
+
expect(url).toContain('/supportapi/zd/acme/api/v1/clientScripts');
|
|
102
|
+
expect(options.headers.orgId).toBe('1001');
|
|
103
|
+
expect(result).toEqual(payload);
|
|
104
|
+
});
|
|
105
|
+
test('passes through API details returned by getClientScriptsAPIDetails', async () => {
|
|
106
|
+
const detailsSpy = jest.spyOn(sdk, 'getClientScriptsAPIDetails').mockReturnValue({
|
|
107
|
+
url: '/custom-client-scripts-url',
|
|
108
|
+
method: 'POST',
|
|
109
|
+
options: {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers: {
|
|
112
|
+
orgId: 'custom-org'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
global.window.fetch.mockResolvedValue({
|
|
117
|
+
json: jest.fn().mockResolvedValue([])
|
|
118
|
+
});
|
|
119
|
+
await sdk.fetchClientScripts(validParams);
|
|
120
|
+
expect(detailsSpy).toHaveBeenCalledWith(validParams);
|
|
121
|
+
expect(global.window.fetch).toHaveBeenCalledWith('/custom-client-scripts-url', expect.objectContaining({
|
|
122
|
+
method: 'POST'
|
|
123
|
+
}));
|
|
124
|
+
});
|
|
125
|
+
test('resolves empty array for empty payload', async () => {
|
|
126
|
+
global.window.fetch.mockResolvedValue({
|
|
127
|
+
json: jest.fn().mockResolvedValue([])
|
|
128
|
+
});
|
|
129
|
+
const result = await sdk.fetchClientScripts(validParams);
|
|
130
|
+
expect(result).toEqual([]);
|
|
131
|
+
});
|
|
132
|
+
test('rejects when fetch fails', async () => {
|
|
133
|
+
const error = new Error('Network down');
|
|
134
|
+
global.window.fetch.mockRejectedValue(error);
|
|
135
|
+
await expect(sdk.fetchClientScripts(validParams)).rejects.toThrow('Network down');
|
|
136
|
+
});
|
|
137
|
+
test('rejects when response json parsing fails', async () => {
|
|
138
|
+
global.window.fetch.mockResolvedValue({
|
|
139
|
+
json: jest.fn().mockRejectedValue(new Error('Invalid JSON'))
|
|
140
|
+
});
|
|
141
|
+
await expect(sdk.fetchClientScripts(validParams)).rejects.toThrow('Invalid JSON');
|
|
142
|
+
});
|
|
143
|
+
test('resolves non-array payload as-is (current behavior)', async () => {
|
|
144
|
+
const payload = {
|
|
145
|
+
unsupported: true
|
|
146
|
+
};
|
|
147
|
+
global.window.fetch.mockResolvedValue({
|
|
148
|
+
json: jest.fn().mockResolvedValue(payload)
|
|
149
|
+
});
|
|
150
|
+
const result = await sdk.fetchClientScripts(validParams);
|
|
151
|
+
expect(result).toEqual(payload);
|
|
152
|
+
});
|
|
153
|
+
test('throws when window.fetch is missing', async () => {
|
|
154
|
+
delete global.window.fetch;
|
|
155
|
+
await expect(sdk.fetchClientScripts(validParams)).rejects.toThrow();
|
|
156
|
+
});
|
|
157
|
+
test('rejects when getClientScriptsAPIDetails throws', async () => {
|
|
158
|
+
delete global.window.currentOrg;
|
|
159
|
+
await expect(sdk.fetchClientScripts(validParams)).rejects.toThrow();
|
|
160
|
+
expect(global.window.fetch).not.toHaveBeenCalled();
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
package/es/platform/components/smart-action-band/adapters/presenters/ActionBandTranslator.js
CHANGED
|
@@ -2,6 +2,7 @@ import ClientActionsTranslator from "../../../../client-actions/translators/clie
|
|
|
2
2
|
import DefaultClientActions from "./utils/DefaultClientActions";
|
|
3
3
|
import { ActionBandLocations } from "../../../../../bc/action-band/Constants";
|
|
4
4
|
import { i18NProviderUtils } from '@zohodesk/i18n';
|
|
5
|
+
import { filterClientActionsByLocation } from "../../../../client-actions/behaviour/zclient-actions/adapters/presenters/FilterUtils";
|
|
5
6
|
export default class ActionBandTranslator {
|
|
6
7
|
static transformState(state) {
|
|
7
8
|
const {
|
|
@@ -83,10 +84,12 @@ export default class ActionBandTranslator {
|
|
|
83
84
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
function mapper(clientActions) {
|
|
88
|
+
return {
|
|
89
|
+
actionBandLeftActions: filterClientActionsByLocation(clientActions, ActionBandLocations.LEFT_ACTIONS),
|
|
90
|
+
actionBandRightActions: filterClientActionsByLocation(clientActions, ActionBandLocations.RIGHT_ACTIONS)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
90
93
|
|
|
91
94
|
function getColumnChooserProps(columnChooser) {
|
|
92
95
|
let availableFields = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
let getClientActions = {
|
|
2
|
+
name: 'uiActions',
|
|
3
|
+
api: '/{{servicePrefix}}/{{orgName}}/api/v1/clientActions',
|
|
4
|
+
parameters: `{
|
|
5
|
+
"from":{{from}},
|
|
6
|
+
"limit":{{limit}},
|
|
7
|
+
"modules": "{{modules}}",
|
|
8
|
+
"page": "{{page}}"
|
|
9
|
+
}`,
|
|
10
|
+
type: 'GET',
|
|
11
|
+
transformer: data => data,
|
|
12
|
+
properties: {
|
|
13
|
+
modelName: {
|
|
14
|
+
required: true,
|
|
15
|
+
typeMetadata: {
|
|
16
|
+
schema: {
|
|
17
|
+
type: 'string'
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export default getClientActions;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ClientActionsTranslator from "../../../client-actions/translators/client-actions-translator";
|
|
2
2
|
import SectionTranslator from "./translators/SectionTranslator";
|
|
3
3
|
import DefaultFormClientActions from "./utils/DefaultClientActions";
|
|
4
|
+
import { filterClientActionsByLocation } from "../../../client-actions/behaviour/zclient-actions/adapters/presenters/FilterUtils";
|
|
4
5
|
export default class FormTranslator {
|
|
5
6
|
static transformState(state) {
|
|
6
7
|
const {
|
|
@@ -56,7 +57,7 @@ export default class FormTranslator {
|
|
|
56
57
|
Object.entries(mappedClientActions).forEach(_ref => {
|
|
57
58
|
let [key, value] = _ref;
|
|
58
59
|
|
|
59
|
-
if (isFooterEnabled && (key === '
|
|
60
|
+
if (isFooterEnabled && (key === 'footerLeftActions' || key === 'footerRightActions')) {
|
|
60
61
|
let footerActions = ClientActionsTranslator.transform(value, instanceName, moduleName, actionContext);
|
|
61
62
|
transformedClientActions[key] = footerActions;
|
|
62
63
|
}
|
|
@@ -152,17 +153,19 @@ export default class FormTranslator {
|
|
|
152
153
|
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
const mapper =
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
156
|
+
const mapper = clientActions => {
|
|
157
|
+
return {
|
|
158
|
+
headerLeftActions: filterClientActionsByLocation(clientActions, 'header_left_actions'),
|
|
159
|
+
headerRightActions: filterClientActionsByLocation(clientActions, 'header_right_actions'),
|
|
160
|
+
footerLeftActions: filterClientActionsByLocation(clientActions, 'footer_left_actions'),
|
|
161
|
+
footerRightActions: filterClientActionsByLocation(clientActions, 'footer_right_actions'),
|
|
162
|
+
fieldLabelActions: filterClientActionsByLocation(clientActions, 'field_label_actions'),
|
|
163
|
+
fieldActions: filterClientActionsByLocation(clientActions, 'field_actions'),
|
|
164
|
+
sectionHeaderLeftActions: filterClientActionsByLocation(clientActions, 'section_header_left_actions'),
|
|
165
|
+
sectionHeaderRightActions: filterClientActionsByLocation(clientActions, 'section_header_right_actions'),
|
|
166
|
+
sectionTitleLeftActions: filterClientActionsByLocation(clientActions, 'section_title_left_actions'),
|
|
167
|
+
sectionTitleRightActions: filterClientActionsByLocation(clientActions, 'section_title_right_actions'),
|
|
168
|
+
fieldOptionLeftActions: filterClientActionsByLocation(clientActions, 'field_options_left_actions'),
|
|
169
|
+
fieldOptionRightActions: filterClientActionsByLocation(clientActions, 'field_options_right_actions')
|
|
170
|
+
};
|
|
171
|
+
};
|
|
@@ -109,7 +109,7 @@ function SectionTranslator(_ref) {
|
|
|
109
109
|
fieldPreModified['actions'] = transformedDefaultActions.fieldActions.concat(transformedActions.fieldActions);
|
|
110
110
|
const noPlaceHolderSupport = ['Boolean', 'Date', 'DateTime']; // Placeholder check
|
|
111
111
|
|
|
112
|
-
if (field.toolTip && field.toolTipType === "
|
|
112
|
+
if (field.toolTip && field.toolTipType === "placeHolder" && !noPlaceHolderSupport.includes(field.type)) {
|
|
113
113
|
fieldPreModified["placeholder"] = field.toolTip;
|
|
114
114
|
} // const optionActionAvailArray = ['Picklist', 'Multiselect'];
|
|
115
115
|
// // Option Actions check
|
|
@@ -13,6 +13,7 @@ import DefaultClientActions from "./utils/DefaultClientActions";
|
|
|
13
13
|
import SelectionTranslator from "./SelectionTranslator";
|
|
14
14
|
import { SortModelOrder } from "../../domain/entities/interfaces/Properties";
|
|
15
15
|
import { SortOrder } from "../../../../bc/zlist/Types";
|
|
16
|
+
import { filterClientActionsByLocation } from "../../../client-actions/behaviour/zclient-actions/adapters/presenters/FilterUtils";
|
|
16
17
|
const EMPTY_OBJECT = {};
|
|
17
18
|
const EMPTY_ARRAY = [];
|
|
18
19
|
|
|
@@ -220,9 +221,9 @@ function mapClientActions(clientActions) {
|
|
|
220
221
|
}
|
|
221
222
|
});
|
|
222
223
|
return {
|
|
223
|
-
headerActions: clientActions
|
|
224
|
-
fieldActions: clientActions
|
|
225
|
-
rowActions: clientActions
|
|
226
|
-
noLocation: clientActions
|
|
224
|
+
headerActions: filterClientActionsByLocation(clientActions, 'header_actions'),
|
|
225
|
+
fieldActions: filterClientActionsByLocation(clientActions, 'field_actions'),
|
|
226
|
+
rowActions: filterClientActionsByLocation(clientActions, 'row_actions'),
|
|
227
|
+
noLocation: filterClientActionsByLocation(clientActions, null)
|
|
227
228
|
};
|
|
228
229
|
}
|
|
@@ -15,14 +15,18 @@ const DateFieldTranslator = _ref => {
|
|
|
15
15
|
uiType,
|
|
16
16
|
name
|
|
17
17
|
} = field;
|
|
18
|
+
const defaultDateTimeFormat = {
|
|
19
|
+
dateFormat: 'dd MM yyyy',
|
|
20
|
+
timeFormat: '12-hour',
|
|
21
|
+
delimiter: 'space',
|
|
22
|
+
isShortenDateTimeInfo: false
|
|
23
|
+
};
|
|
18
24
|
const {
|
|
19
25
|
dateFormat,
|
|
20
26
|
timeFormat,
|
|
21
27
|
delimiter,
|
|
22
28
|
isShortenDateTimeInfo
|
|
23
|
-
} = context
|
|
24
|
-
// const { dateFormat, timeFormat, delimiter } = appContext.dateTimeFormat;
|
|
25
|
-
|
|
29
|
+
} = context?.dateTimeFormat || defaultDateTimeFormat;
|
|
26
30
|
const newDateValue = DateAndTimeFormat({
|
|
27
31
|
dateFormatType: dateFormat,
|
|
28
32
|
timeFormatType: timeFormat,
|
|
@@ -15,14 +15,18 @@ const DateTimeFieldTranslator = _ref => {
|
|
|
15
15
|
uiType,
|
|
16
16
|
name
|
|
17
17
|
} = field;
|
|
18
|
+
const defaultDateTimeFormat = {
|
|
19
|
+
dateFormat: 'dd MM yyyy',
|
|
20
|
+
timeFormat: '12-hour',
|
|
21
|
+
delimiter: 'space',
|
|
22
|
+
isShortenDateTimeInfo: false
|
|
23
|
+
};
|
|
18
24
|
const {
|
|
19
25
|
dateFormat,
|
|
20
26
|
timeFormat,
|
|
21
27
|
delimiter,
|
|
22
28
|
isShortenDateTimeInfo
|
|
23
|
-
} = context
|
|
24
|
-
// const { dateFormat, timeFormat, delimiter } = appContext.dateTimeFormat;
|
|
25
|
-
|
|
29
|
+
} = context?.dateTimeFormat || defaultDateTimeFormat;
|
|
26
30
|
const newDateValue = DateAndTimeFormat({
|
|
27
31
|
dateFormatType: dateFormat,
|
|
28
32
|
timeFormatType: timeFormat,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/library-platform",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "es/index.js",
|
|
6
6
|
"files": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@zohodesk-private/dot-registry": "0.0.2",
|
|
47
47
|
"@zohodesk-private/node-plugins": "1.1.9",
|
|
48
48
|
"@zohodesk/a11y": "2.3.8",
|
|
49
|
-
"@zohodesk/codestandard-validator": "1.1
|
|
49
|
+
"@zohodesk/codestandard-validator": "1.3.1",
|
|
50
50
|
"@zohodesk/components": "1.5.8",
|
|
51
51
|
"@zohodesk/dot": "1.8.6",
|
|
52
52
|
"@zohodesk/dotkit": "1.0.7",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"@zohodesk/dot": "1.8.6",
|
|
83
83
|
"@zohodesk/dotkit": "1.0.7",
|
|
84
84
|
"@zohodesk/hooks": "2.0.6",
|
|
85
|
-
"@zohodesk/i18n": "1.0.0-beta.
|
|
85
|
+
"@zohodesk/i18n": "1.0.0-beta.35",
|
|
86
86
|
"@zohodesk/icons": "1.1.5",
|
|
87
87
|
"@zohodesk/layout": "3.1.0",
|
|
88
88
|
"@zohodesk/svg": "1.2.6",
|
|
@@ -95,4 +95,4 @@
|
|
|
95
95
|
"jsep": "0.3.5",
|
|
96
96
|
"object-path-immutable": "4.1.2"
|
|
97
97
|
}
|
|
98
|
-
}
|
|
98
|
+
}
|
package/es/.DS_Store
DELETED
|
Binary file
|
package/es/platform/.DS_Store
DELETED
|
Binary file
|