swoop-common 2.2.153 → 2.2.155
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/api/generated/core/services/ComponentService.d.ts +8 -0
- package/dist/api/generated/core/services/ComponentService.js +21 -0
- package/dist/api/generated/core/services/CoreService.d.ts +8 -0
- package/dist/api/generated/core/services/CoreService.js +21 -0
- package/dist/lib/config/templateStructure.d.ts +90 -0
- package/dist/lib/config/templateStructure.js +87 -0
- package/dist/rendering/components/ComponentListItem.d.ts +16 -0
- package/dist/rendering/components/ComponentListItem.js +40 -0
- package/dist/rendering/components/ComponentPicker.js +34 -41
- package/dist/rendering/renderers/ComponentPicker.js +14 -2
- package/package.json +1 -1
|
@@ -49,6 +49,14 @@ export declare class ComponentService {
|
|
|
49
49
|
* @throws ApiError
|
|
50
50
|
*/
|
|
51
51
|
static componentBatchGet(requestBody: ComponentBatchRequest): CancelablePromise<ComponentBatchResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* List Component Types
|
|
54
|
+
* Returns a deduplicated list of type strings from componentFields for all components matching the given templateId.
|
|
55
|
+
* @param templateId The template ID to filter components and componentFields by.
|
|
56
|
+
* @returns string A deduplicated list of type strings
|
|
57
|
+
* @throws ApiError
|
|
58
|
+
*/
|
|
59
|
+
static componentListTypes(templateId: string): CancelablePromise<Array<string>>;
|
|
52
60
|
/**
|
|
53
61
|
* Get Component
|
|
54
62
|
* Get Component via ID
|
|
@@ -84,6 +84,27 @@ export class ComponentService {
|
|
|
84
84
|
},
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* List Component Types
|
|
89
|
+
* Returns a deduplicated list of type strings from componentFields for all components matching the given templateId.
|
|
90
|
+
* @param templateId The template ID to filter components and componentFields by.
|
|
91
|
+
* @returns string A deduplicated list of type strings
|
|
92
|
+
* @throws ApiError
|
|
93
|
+
*/
|
|
94
|
+
static componentListTypes(templateId) {
|
|
95
|
+
return __request(OpenAPI, {
|
|
96
|
+
method: 'GET',
|
|
97
|
+
url: '/component/types',
|
|
98
|
+
query: {
|
|
99
|
+
'templateId': templateId,
|
|
100
|
+
},
|
|
101
|
+
errors: {
|
|
102
|
+
400: `If the templateId parameter is missing or malformed`,
|
|
103
|
+
401: `When the client is not authorised`,
|
|
104
|
+
500: `When an unexpected error occurs`,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
87
108
|
/**
|
|
88
109
|
* Get Component
|
|
89
110
|
* Get Component via ID
|
|
@@ -287,6 +287,14 @@ export declare class CoreService {
|
|
|
287
287
|
* @throws ApiError
|
|
288
288
|
*/
|
|
289
289
|
componentBatchGet(requestBody: ComponentBatchRequest): CancelablePromise<ComponentBatchResponse>;
|
|
290
|
+
/**
|
|
291
|
+
* List Component Types
|
|
292
|
+
* Returns a deduplicated list of type strings from componentFields for all components matching the given templateId.
|
|
293
|
+
* @param templateId The template ID to filter components and componentFields by.
|
|
294
|
+
* @returns string A deduplicated list of type strings
|
|
295
|
+
* @throws ApiError
|
|
296
|
+
*/
|
|
297
|
+
componentListTypes(templateId: string): CancelablePromise<Array<string>>;
|
|
290
298
|
/**
|
|
291
299
|
* Get Component
|
|
292
300
|
* Get Component via ID
|
|
@@ -628,6 +628,27 @@ export class CoreService {
|
|
|
628
628
|
},
|
|
629
629
|
});
|
|
630
630
|
}
|
|
631
|
+
/**
|
|
632
|
+
* List Component Types
|
|
633
|
+
* Returns a deduplicated list of type strings from componentFields for all components matching the given templateId.
|
|
634
|
+
* @param templateId The template ID to filter components and componentFields by.
|
|
635
|
+
* @returns string A deduplicated list of type strings
|
|
636
|
+
* @throws ApiError
|
|
637
|
+
*/
|
|
638
|
+
componentListTypes(templateId) {
|
|
639
|
+
return __request(OpenAPI, {
|
|
640
|
+
method: 'GET',
|
|
641
|
+
url: '/component/types',
|
|
642
|
+
query: {
|
|
643
|
+
'templateId': templateId,
|
|
644
|
+
},
|
|
645
|
+
errors: {
|
|
646
|
+
400: `If the templateId parameter is missing or malformed`,
|
|
647
|
+
401: `When the client is not authorised`,
|
|
648
|
+
500: `When an unexpected error occurs`,
|
|
649
|
+
},
|
|
650
|
+
});
|
|
651
|
+
}
|
|
631
652
|
/**
|
|
632
653
|
* Get Component
|
|
633
654
|
* Get Component via ID
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template names as const for type-safe usage
|
|
3
|
+
*/
|
|
4
|
+
export declare const TEMPLATE_NAMES: {
|
|
5
|
+
readonly FLIGHT: "Flight";
|
|
6
|
+
readonly JOURNEYS: "Journeys";
|
|
7
|
+
readonly CRUISE: "Cruise";
|
|
8
|
+
readonly CRUISE_ACTIVITY: "Cruise Activity";
|
|
9
|
+
readonly GROUND_ACCOMMODATION: "Ground Accommodation";
|
|
10
|
+
readonly TRANSFER: "Transfer";
|
|
11
|
+
readonly INDEPENDENT_ARRANGEMENTS: "Independent Arrangements";
|
|
12
|
+
readonly ACCOMMODATION: "Accommodation";
|
|
13
|
+
readonly EXCURSIONS: "Excursions";
|
|
14
|
+
readonly GUIDED_MULTIDAY_ACTIVITY: "GuidedMultidayActivity";
|
|
15
|
+
readonly SHIP_ACCOMMODATION: "Ship Accommodation";
|
|
16
|
+
readonly ALL_INCLUSIVE_HOTEL: "AllInclusiveHotel";
|
|
17
|
+
readonly PACKAGES: "Packages";
|
|
18
|
+
readonly LOCATION: "Location";
|
|
19
|
+
readonly PRIVATE_TOUR: "Private Tour";
|
|
20
|
+
readonly ACTIVITY: "Activity";
|
|
21
|
+
readonly FEE: "Fee";
|
|
22
|
+
readonly PACKAGE: "Package";
|
|
23
|
+
readonly ROOM: "Room";
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Template Name to Template ID mapping
|
|
27
|
+
* This configuration maps template names to their IDs
|
|
28
|
+
*/
|
|
29
|
+
export declare const templateStructure: {
|
|
30
|
+
readonly Package: "template_c3307de1e53640c4b4d1bb8fa99c4c7a";
|
|
31
|
+
readonly Flight: "template_4aec70add8e74467814fe7337f4e41b3";
|
|
32
|
+
readonly Journeys: "template_14cc18c1408a4b73a16d4e1dad2efca9";
|
|
33
|
+
readonly Cruise: "template_63a57a90570c47b89f830d2c7618324f";
|
|
34
|
+
readonly "Ground Accommodation": "template_68c8d409a9f7462aa528a1216cadf2b5";
|
|
35
|
+
readonly Transfer: "template_901d40ac12214820995880915c5b62f5";
|
|
36
|
+
readonly "Independent Arrangements": "template_932b514e6d804e248bf04a9fa1f836de";
|
|
37
|
+
readonly Accommodation: "template_7546d5da287241629b5190f95346840e";
|
|
38
|
+
readonly Excursions: "template_a6a2dbfd478143de994dca40dc07e054";
|
|
39
|
+
readonly GuidedMultidayActivity: "template_a64e161de5824fcb9515274b0f67d698";
|
|
40
|
+
readonly "Ship Accommodation": "template_bb8caab1d3104257a75b7cb7dd958136";
|
|
41
|
+
readonly AllInclusiveHotel: "template_ba7999ff957c4ca3a5e61496df6178ac";
|
|
42
|
+
readonly Location: "template_0c105b25350647b096753b4f863ab06c";
|
|
43
|
+
readonly "Private Tour": "template_d9081bfcc3b7461987a3728e57ca7363";
|
|
44
|
+
readonly Activity: "template_e2f0e9e5343349358037a0564a3366a0";
|
|
45
|
+
readonly Fee: "template_d15cc4ab72034fb8a098d9a9ec791a7d";
|
|
46
|
+
readonly "Cruise Activity": "template_12345678123456781234567812345678";
|
|
47
|
+
readonly Room: "template_bb0b09c544d242c9a9ef38147966979f";
|
|
48
|
+
};
|
|
49
|
+
export declare const packagesTemplateStructure: {
|
|
50
|
+
readonly Cruise: "template_63a57a90570c47b89f830d2c7618324f";
|
|
51
|
+
readonly Excursions: "template_a6a2dbfd478143de994dca40dc07e054";
|
|
52
|
+
readonly GuidedMultidayActivity: "template_a64e161de5824fcb9515274b0f67d698";
|
|
53
|
+
readonly AllInclusiveHotel: "template_ba7999ff957c4ca3a5e61496df6178ac";
|
|
54
|
+
readonly "Private Tour": "template_d9081bfcc3b7461987a3728e57ca7363";
|
|
55
|
+
};
|
|
56
|
+
export declare const topLevelTemplates: {
|
|
57
|
+
readonly Activity: "template_e2f0e9e5343349358037a0564a3366a0";
|
|
58
|
+
readonly Flight: "template_4aec70add8e74467814fe7337f4e41b3";
|
|
59
|
+
readonly "Ground Accommodation": "template_68c8d409a9f7462aa528a1216cadf2b5";
|
|
60
|
+
readonly "Ship Accommodation": "template_bb8caab1d3104257a75b7cb7dd958136";
|
|
61
|
+
readonly Transfer: "template_901d40ac12214820995880915c5b62f5";
|
|
62
|
+
readonly "Independent Arrangements": "template_932b514e6d804e248bf04a9fa1f836de";
|
|
63
|
+
readonly Cruise: "template_63a57a90570c47b89f830d2c7618324f";
|
|
64
|
+
readonly Excursions: "template_a6a2dbfd478143de994dca40dc07e054";
|
|
65
|
+
readonly GuidedMultidayActivity: "template_a64e161de5824fcb9515274b0f67d698";
|
|
66
|
+
readonly AllInclusiveHotel: "template_ba7999ff957c4ca3a5e61496df6178ac";
|
|
67
|
+
readonly "Private Tour": "template_d9081bfcc3b7461987a3728e57ca7363";
|
|
68
|
+
};
|
|
69
|
+
export type TemplateName = keyof typeof templateStructure;
|
|
70
|
+
export type TemplateId = typeof templateStructure[TemplateName];
|
|
71
|
+
/**
|
|
72
|
+
* Get template ID by template name
|
|
73
|
+
*/
|
|
74
|
+
export declare function getTemplateId(templateName: string): string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Get template name by template ID
|
|
77
|
+
*/
|
|
78
|
+
export declare function getTemplateNameById(templateId: string): TemplateName | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Check if a template name exists in the structure
|
|
81
|
+
*/
|
|
82
|
+
export declare function isValidTemplateName(templateName: string): templateName is TemplateName;
|
|
83
|
+
/**
|
|
84
|
+
* Find and return the data object for a given template name within a componentInstanceFields array.
|
|
85
|
+
* Returns undefined if the template name is unknown or no matching entry exists.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getComponentDataByTemplateName(templateName: string, componentInstanceFields: {
|
|
88
|
+
templateId: string;
|
|
89
|
+
data: Record<string, any>;
|
|
90
|
+
}[]): Record<string, any> | undefined;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template names as const for type-safe usage
|
|
3
|
+
*/
|
|
4
|
+
export const TEMPLATE_NAMES = {
|
|
5
|
+
FLIGHT: "Flight",
|
|
6
|
+
JOURNEYS: "Journeys",
|
|
7
|
+
CRUISE: "Cruise",
|
|
8
|
+
CRUISE_ACTIVITY: "Cruise Activity",
|
|
9
|
+
GROUND_ACCOMMODATION: "Ground Accommodation",
|
|
10
|
+
TRANSFER: "Transfer",
|
|
11
|
+
INDEPENDENT_ARRANGEMENTS: "Independent Arrangements",
|
|
12
|
+
ACCOMMODATION: "Accommodation",
|
|
13
|
+
EXCURSIONS: "Excursions",
|
|
14
|
+
GUIDED_MULTIDAY_ACTIVITY: "GuidedMultidayActivity",
|
|
15
|
+
SHIP_ACCOMMODATION: "Ship Accommodation",
|
|
16
|
+
ALL_INCLUSIVE_HOTEL: "AllInclusiveHotel",
|
|
17
|
+
PACKAGES: "Packages",
|
|
18
|
+
LOCATION: "Location",
|
|
19
|
+
PRIVATE_TOUR: "Private Tour",
|
|
20
|
+
ACTIVITY: "Activity",
|
|
21
|
+
FEE: "Fee",
|
|
22
|
+
PACKAGE: "Package",
|
|
23
|
+
ROOM: "Room"
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Template Name to Template ID mapping
|
|
27
|
+
* This configuration maps template names to their IDs
|
|
28
|
+
*/
|
|
29
|
+
export const templateStructure = {
|
|
30
|
+
[TEMPLATE_NAMES.PACKAGE]: "template_c3307de1e53640c4b4d1bb8fa99c4c7a",
|
|
31
|
+
[TEMPLATE_NAMES.FLIGHT]: "template_4aec70add8e74467814fe7337f4e41b3",
|
|
32
|
+
[TEMPLATE_NAMES.JOURNEYS]: "template_14cc18c1408a4b73a16d4e1dad2efca9",
|
|
33
|
+
[TEMPLATE_NAMES.CRUISE]: "template_63a57a90570c47b89f830d2c7618324f",
|
|
34
|
+
[TEMPLATE_NAMES.GROUND_ACCOMMODATION]: "template_68c8d409a9f7462aa528a1216cadf2b5",
|
|
35
|
+
[TEMPLATE_NAMES.TRANSFER]: "template_901d40ac12214820995880915c5b62f5",
|
|
36
|
+
[TEMPLATE_NAMES.INDEPENDENT_ARRANGEMENTS]: "template_932b514e6d804e248bf04a9fa1f836de",
|
|
37
|
+
[TEMPLATE_NAMES.ACCOMMODATION]: "template_7546d5da287241629b5190f95346840e",
|
|
38
|
+
[TEMPLATE_NAMES.EXCURSIONS]: "template_a6a2dbfd478143de994dca40dc07e054",
|
|
39
|
+
[TEMPLATE_NAMES.GUIDED_MULTIDAY_ACTIVITY]: "template_a64e161de5824fcb9515274b0f67d698",
|
|
40
|
+
[TEMPLATE_NAMES.SHIP_ACCOMMODATION]: "template_bb8caab1d3104257a75b7cb7dd958136",
|
|
41
|
+
[TEMPLATE_NAMES.ALL_INCLUSIVE_HOTEL]: "template_ba7999ff957c4ca3a5e61496df6178ac",
|
|
42
|
+
[TEMPLATE_NAMES.LOCATION]: "template_0c105b25350647b096753b4f863ab06c",
|
|
43
|
+
[TEMPLATE_NAMES.PRIVATE_TOUR]: "template_d9081bfcc3b7461987a3728e57ca7363",
|
|
44
|
+
[TEMPLATE_NAMES.ACTIVITY]: "template_e2f0e9e5343349358037a0564a3366a0",
|
|
45
|
+
[TEMPLATE_NAMES.FEE]: "template_d15cc4ab72034fb8a098d9a9ec791a7d",
|
|
46
|
+
[TEMPLATE_NAMES.CRUISE_ACTIVITY]: "template_12345678123456781234567812345678",
|
|
47
|
+
[TEMPLATE_NAMES.ROOM]: "template_bb0b09c544d242c9a9ef38147966979f"
|
|
48
|
+
};
|
|
49
|
+
export const packagesTemplateStructure = {
|
|
50
|
+
[TEMPLATE_NAMES.CRUISE]: templateStructure[TEMPLATE_NAMES.CRUISE],
|
|
51
|
+
[TEMPLATE_NAMES.EXCURSIONS]: templateStructure[TEMPLATE_NAMES.EXCURSIONS],
|
|
52
|
+
[TEMPLATE_NAMES.GUIDED_MULTIDAY_ACTIVITY]: templateStructure[TEMPLATE_NAMES.GUIDED_MULTIDAY_ACTIVITY],
|
|
53
|
+
[TEMPLATE_NAMES.ALL_INCLUSIVE_HOTEL]: templateStructure[TEMPLATE_NAMES.ALL_INCLUSIVE_HOTEL],
|
|
54
|
+
[TEMPLATE_NAMES.PRIVATE_TOUR]: templateStructure[TEMPLATE_NAMES.PRIVATE_TOUR],
|
|
55
|
+
};
|
|
56
|
+
export const topLevelTemplates = Object.assign(Object.assign({}, packagesTemplateStructure), { [TEMPLATE_NAMES.ACTIVITY]: templateStructure[TEMPLATE_NAMES.ACTIVITY], [TEMPLATE_NAMES.FLIGHT]: templateStructure[TEMPLATE_NAMES.FLIGHT], [TEMPLATE_NAMES.GROUND_ACCOMMODATION]: templateStructure[TEMPLATE_NAMES.GROUND_ACCOMMODATION], [TEMPLATE_NAMES.SHIP_ACCOMMODATION]: templateStructure[TEMPLATE_NAMES.SHIP_ACCOMMODATION], [TEMPLATE_NAMES.TRANSFER]: templateStructure[TEMPLATE_NAMES.TRANSFER], [TEMPLATE_NAMES.INDEPENDENT_ARRANGEMENTS]: templateStructure[TEMPLATE_NAMES.INDEPENDENT_ARRANGEMENTS] });
|
|
57
|
+
/**
|
|
58
|
+
* Get template ID by template name
|
|
59
|
+
*/
|
|
60
|
+
export function getTemplateId(templateName) {
|
|
61
|
+
return templateStructure[templateName];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get template name by template ID
|
|
65
|
+
*/
|
|
66
|
+
export function getTemplateNameById(templateId) {
|
|
67
|
+
var _a;
|
|
68
|
+
return (_a = Object.entries(templateStructure)
|
|
69
|
+
.find(([, id]) => id === templateId)) === null || _a === void 0 ? void 0 : _a[0];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if a template name exists in the structure
|
|
73
|
+
*/
|
|
74
|
+
export function isValidTemplateName(templateName) {
|
|
75
|
+
return templateName in templateStructure;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Find and return the data object for a given template name within a componentInstanceFields array.
|
|
79
|
+
* Returns undefined if the template name is unknown or no matching entry exists.
|
|
80
|
+
*/
|
|
81
|
+
export function getComponentDataByTemplateName(templateName, componentInstanceFields) {
|
|
82
|
+
var _a;
|
|
83
|
+
const templateId = getTemplateId(templateName);
|
|
84
|
+
if (!templateId)
|
|
85
|
+
return undefined;
|
|
86
|
+
return (_a = componentInstanceFields.find((f) => f.templateId === templateId)) === null || _a === void 0 ? void 0 : _a.data;
|
|
87
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { DTOComponentRead, DTORegionRead, DTOTemplateRead } from "../../api/generated/core/exports";
|
|
3
|
+
import { PartnerSwoop } from "../../api/generated/swoop/exports";
|
|
4
|
+
export interface ComponentListItemProps {
|
|
5
|
+
component: DTOComponentRead;
|
|
6
|
+
isSelected: boolean;
|
|
7
|
+
details: {
|
|
8
|
+
template: DTOTemplateRead | undefined;
|
|
9
|
+
partners: PartnerSwoop[];
|
|
10
|
+
regions: DTORegionRead[];
|
|
11
|
+
};
|
|
12
|
+
onSelect: (component: DTOComponentRead) => void;
|
|
13
|
+
showDivider: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare const ComponentListItem: React.FC<ComponentListItemProps>;
|
|
16
|
+
export default ComponentListItem;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Chip, Divider, ListItem, ListItemButton, ListItemText, Typography, } from "@mui/material";
|
|
3
|
+
import { PARTNER_REGION_READABLE } from "../consts/region";
|
|
4
|
+
import { getComponentDataByTemplateName, TEMPLATE_NAMES } from "../../lib/config/templateStructure";
|
|
5
|
+
const ComponentListItem = ({ component, isSelected, details, onSelect, showDivider, }) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const activityData = (_a = getComponentDataByTemplateName(TEMPLATE_NAMES.CRUISE_ACTIVITY, component.componentFields)) !== null && _a !== void 0 ? _a : getComponentDataByTemplateName(TEMPLATE_NAMES.ACTIVITY, component.componentFields);
|
|
8
|
+
const displayName = (activityData === null || activityData === void 0 ? void 0 : activityData.type)
|
|
9
|
+
? `${activityData.type} - ${component.name}`
|
|
10
|
+
: component.name;
|
|
11
|
+
return (React.createElement(React.Fragment, null,
|
|
12
|
+
React.createElement(ListItem, { disablePadding: true },
|
|
13
|
+
React.createElement(ListItemButton, { onClick: () => onSelect(component), selected: isSelected, sx: {
|
|
14
|
+
flexDirection: "column",
|
|
15
|
+
alignItems: "flex-start",
|
|
16
|
+
py: 2,
|
|
17
|
+
"&.Mui-selected": {
|
|
18
|
+
backgroundColor: "primary.50",
|
|
19
|
+
borderLeft: "4px solid",
|
|
20
|
+
borderColor: "primary.main",
|
|
21
|
+
},
|
|
22
|
+
} },
|
|
23
|
+
React.createElement(Box, { width: "100%" },
|
|
24
|
+
React.createElement(ListItemText, { primary: React.createElement(Typography, { variant: "subtitle1", fontWeight: "medium" }, displayName), secondary: React.createElement(Box, { mt: 1 },
|
|
25
|
+
details.template && (React.createElement(Typography, { variant: "body2", color: "text.secondary" },
|
|
26
|
+
"Type: ",
|
|
27
|
+
details.template.name)),
|
|
28
|
+
details.regions.length > 0 && (React.createElement(Box, { display: "flex", alignItems: "center", gap: 1, mt: 0.5 },
|
|
29
|
+
React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "Regions:"),
|
|
30
|
+
details.regions.map((region) => (React.createElement(Chip, { key: region.id, label: region.name, size: "small", variant: "outlined" }))))),
|
|
31
|
+
details.partners.length > 0 && (React.createElement(Box, { display: "flex", alignItems: "center", gap: 1, mt: 0.5 },
|
|
32
|
+
React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "Partners:"),
|
|
33
|
+
details.partners.slice(0, 3).map((partner) => (React.createElement(Chip, { key: partner.id, label: `${partner.name} - ${PARTNER_REGION_READABLE[partner.id || "".split("-")[0]]}`, size: "small", variant: "outlined", color: "secondary" }))),
|
|
34
|
+
details.partners.length > 3 && (React.createElement(Typography, { variant: "body2", color: "text.secondary" },
|
|
35
|
+
"+",
|
|
36
|
+
details.partners.length - 3,
|
|
37
|
+
" more"))))) })))),
|
|
38
|
+
showDivider && React.createElement(Divider, null)));
|
|
39
|
+
};
|
|
40
|
+
export default ComponentListItem;
|
|
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import React, { useState, useEffect } from "react";
|
|
11
|
-
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, TextField, MenuItem, Box, List,
|
|
10
|
+
import React, { useState, useEffect, useMemo } from "react";
|
|
11
|
+
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, TextField, MenuItem, Box, List, Typography, InputAdornment, IconButton, CircularProgress, Pagination, Autocomplete, } from "@mui/material";
|
|
12
12
|
import { Search as SearchIcon, Clear as ClearIcon, FilterList as FilterIcon, } from "@mui/icons-material";
|
|
13
|
-
import { PARTNER_REGION_READABLE } from "../consts/region";
|
|
14
13
|
import { fetchComponents, getAllPartners } from "../util/api";
|
|
15
14
|
import { InternalServices } from "../../api/init";
|
|
15
|
+
import ComponentListItem from "./ComponentListItem";
|
|
16
|
+
import { TEMPLATE_NAMES, templateStructure } from "../../lib/config/templateStructure";
|
|
16
17
|
export default function ComponentPickerModal({ open, onClose, onSelect, selectedComponent, parentIdsFilter, }) {
|
|
17
18
|
const [searchTerm, setSearchTerm] = useState("");
|
|
18
19
|
const [selectedRegion, setSelectedRegion] = useState("");
|
|
@@ -28,7 +29,14 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
28
29
|
const [pageSize] = useState(10);
|
|
29
30
|
const [totalCount, setTotalCount] = useState(0);
|
|
30
31
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
|
31
|
-
|
|
32
|
+
const [activityTypes, setActivityTypes] = useState([]);
|
|
33
|
+
const [selectedActivityType, setSelectedActivityType] = useState("");
|
|
34
|
+
const activityTemplateId = useMemo(() => {
|
|
35
|
+
var _a;
|
|
36
|
+
const cruiseActivityId = templateStructure[TEMPLATE_NAMES.CRUISE_ACTIVITY];
|
|
37
|
+
const activityId = templateStructure[TEMPLATE_NAMES.ACTIVITY];
|
|
38
|
+
return (_a = parentIdsFilter === null || parentIdsFilter === void 0 ? void 0 : parentIdsFilter.find((id) => id === cruiseActivityId || id === activityId)) !== null && _a !== void 0 ? _a : null;
|
|
39
|
+
}, [parentIdsFilter]);
|
|
32
40
|
useEffect(() => {
|
|
33
41
|
const timer = setTimeout(() => {
|
|
34
42
|
setDebouncedSearchTerm(searchTerm);
|
|
@@ -40,6 +48,16 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
40
48
|
loadInitialData();
|
|
41
49
|
}
|
|
42
50
|
}, [open]);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (open && activityTemplateId) {
|
|
53
|
+
InternalServices.CoreService.componentListTypes(activityTemplateId)
|
|
54
|
+
.then(setActivityTypes)
|
|
55
|
+
.catch(console.error);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
setActivityTypes([]);
|
|
59
|
+
}
|
|
60
|
+
}, [open, activityTemplateId]);
|
|
43
61
|
useEffect(() => {
|
|
44
62
|
if (open) {
|
|
45
63
|
fetchFilteredComponents();
|
|
@@ -50,19 +68,21 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
50
68
|
selectedRegion,
|
|
51
69
|
selectedPartner,
|
|
52
70
|
selectedTemplate,
|
|
71
|
+
selectedActivityType,
|
|
53
72
|
page,
|
|
54
73
|
]);
|
|
55
74
|
useEffect(() => {
|
|
56
75
|
if (open) {
|
|
57
76
|
setPage(1);
|
|
58
77
|
}
|
|
59
|
-
}, [debouncedSearchTerm, selectedRegion, selectedPartner, selectedTemplate]);
|
|
78
|
+
}, [debouncedSearchTerm, selectedRegion, selectedPartner, selectedTemplate, selectedActivityType]);
|
|
60
79
|
useEffect(() => {
|
|
61
80
|
if (open) {
|
|
62
81
|
setSearchTerm("");
|
|
63
82
|
setSelectedRegion("");
|
|
64
83
|
setSelectedPartner("");
|
|
65
84
|
setSelectedTemplate("");
|
|
85
|
+
setSelectedActivityType("");
|
|
66
86
|
}
|
|
67
87
|
}, [open]);
|
|
68
88
|
const loadInitialData = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -101,6 +121,8 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
101
121
|
query.templateId = selectedTemplate;
|
|
102
122
|
if (query.search)
|
|
103
123
|
query.on = "name";
|
|
124
|
+
if (selectedActivityType)
|
|
125
|
+
query["componentFields.data.type"] = selectedActivityType;
|
|
104
126
|
// Parent ids overwrites templateid filter
|
|
105
127
|
if (parentIdsFilter === null || parentIdsFilter === void 0 ? void 0 : parentIdsFilter.length)
|
|
106
128
|
query.templateId = parentIdsFilter.join(",");
|
|
@@ -124,6 +146,7 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
124
146
|
setSelectedRegion("");
|
|
125
147
|
setSelectedPartner("");
|
|
126
148
|
setSelectedTemplate("");
|
|
149
|
+
setSelectedActivityType("");
|
|
127
150
|
};
|
|
128
151
|
const handleClearSearch = () => setSearchTerm("");
|
|
129
152
|
const handleSelect = (component) => {
|
|
@@ -136,7 +159,7 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
136
159
|
const componentRegions = regions.filter((r) => { var _a; return (_a = component.regions) === null || _a === void 0 ? void 0 : _a.includes(r.id); });
|
|
137
160
|
return { template, partners: componentPartners, regions: componentRegions };
|
|
138
161
|
};
|
|
139
|
-
const hasActiveFilters = selectedRegion || selectedPartner || selectedTemplate;
|
|
162
|
+
const hasActiveFilters = selectedRegion || selectedPartner || selectedTemplate || selectedActivityType;
|
|
140
163
|
if (initialLoading) {
|
|
141
164
|
return (React.createElement(Dialog, { open: open, onClose: onClose, maxWidth: "md", fullWidth: true, PaperProps: { sx: { height: "80vh", maxHeight: "800px" } } },
|
|
142
165
|
React.createElement(DialogContent, null,
|
|
@@ -167,7 +190,10 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
167
190
|
usedTemplates.map((template) => (React.createElement(MenuItem, { key: template.id, value: template.id },
|
|
168
191
|
template.name,
|
|
169
192
|
" v",
|
|
170
|
-
template.revision)))))
|
|
193
|
+
template.revision))))),
|
|
194
|
+
activityTypes.length > 0 && (React.createElement(TextField, { select: true, size: "small", label: "Activity Type", value: selectedActivityType, onChange: (e) => setSelectedActivityType(e.target.value), sx: { minWidth: 160 } },
|
|
195
|
+
React.createElement(MenuItem, { value: "" }, "All Activity Types"),
|
|
196
|
+
activityTypes.map((type) => (React.createElement(MenuItem, { key: type, value: type }, type)))))),
|
|
171
197
|
React.createElement(Box, { display: "flex", alignItems: "center", gap: 2, mb: 1 },
|
|
172
198
|
React.createElement(Typography, { variant: "body2", color: "text.secondary" },
|
|
173
199
|
totalCount,
|
|
@@ -185,40 +211,7 @@ export default function ComponentPickerModal({ open, onClose, onSelect, selected
|
|
|
185
211
|
React.createElement(Typography, { variant: "body1", color: "text.secondary" }, "Loading components..."))) : components.length === 0 ? (React.createElement(Box, { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", py: 4 },
|
|
186
212
|
React.createElement(FilterIcon, { sx: { fontSize: 48, color: "text.secondary", mb: 2 } }),
|
|
187
213
|
React.createElement(Typography, { variant: "body1", color: "text.secondary" }, "No components match your search criteria"),
|
|
188
|
-
React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "Try adjusting your filters or search term"))) : (components.map((component, index) => {
|
|
189
|
-
const details = getComponentDetails(component);
|
|
190
|
-
const isSelected = (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) === component.id;
|
|
191
|
-
return (React.createElement(React.Fragment, { key: component.id },
|
|
192
|
-
React.createElement(ListItem, { disablePadding: true },
|
|
193
|
-
React.createElement(ListItemButton, { onClick: () => handleSelect(component), selected: isSelected, sx: {
|
|
194
|
-
flexDirection: "column",
|
|
195
|
-
alignItems: "flex-start",
|
|
196
|
-
py: 2,
|
|
197
|
-
"&.Mui-selected": {
|
|
198
|
-
backgroundColor: "primary.50",
|
|
199
|
-
borderLeft: "4px solid",
|
|
200
|
-
borderColor: "primary.main",
|
|
201
|
-
},
|
|
202
|
-
} },
|
|
203
|
-
React.createElement(Box, { width: "100%" },
|
|
204
|
-
React.createElement(ListItemText, { primary: React.createElement(Typography, { variant: "subtitle1", fontWeight: "medium" }, component.name), secondary: React.createElement(Box, { mt: 1 },
|
|
205
|
-
details.template && (React.createElement(Typography, { variant: "body2", color: "text.secondary" },
|
|
206
|
-
"Type: ",
|
|
207
|
-
details.template.name)),
|
|
208
|
-
details.regions.length > 0 && (React.createElement(Box, { display: "flex", alignItems: "center", gap: 1, mt: 0.5 },
|
|
209
|
-
React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "Regions:"),
|
|
210
|
-
details.regions.map((region) => (React.createElement(Chip, { key: region.id, label: region.name, size: "small", variant: "outlined" }))))),
|
|
211
|
-
details.partners.length > 0 && (React.createElement(Box, { display: "flex", alignItems: "center", gap: 1, mt: 0.5 },
|
|
212
|
-
React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "Partners:"),
|
|
213
|
-
details.partners
|
|
214
|
-
.slice(0, 3)
|
|
215
|
-
.map((partner) => (React.createElement(Chip, { key: partner.id, label: `${partner.name} - ${PARTNER_REGION_READABLE[partner.id || "".split("-")[0]]}`, size: "small", variant: "outlined", color: "secondary" }))),
|
|
216
|
-
details.partners.length > 3 && (React.createElement(Typography, { variant: "body2", color: "text.secondary" },
|
|
217
|
-
"+",
|
|
218
|
-
details.partners.length - 3,
|
|
219
|
-
" more"))))) })))),
|
|
220
|
-
index < components.length - 1 && React.createElement(Divider, null)));
|
|
221
|
-
}))),
|
|
214
|
+
React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "Try adjusting your filters or search term"))) : (components.map((component, index) => (React.createElement(ComponentListItem, { key: component.id, component: component, isSelected: (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) === component.id, details: getComponentDetails(component), onSelect: handleSelect, showDivider: index < components.length - 1 }))))),
|
|
222
215
|
components.length > 0 && (React.createElement(Box, { display: "flex", justifyContent: "center", mt: 2 },
|
|
223
216
|
React.createElement(Pagination, { count: Math.ceil(totalCount / pageSize), page: page, onChange: (_, newPage) => setPage(newPage), color: "primary" })))),
|
|
224
217
|
React.createElement(DialogActions, null,
|
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import React, { useEffect, useState } from "react";
|
|
10
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
11
11
|
import { Paper, Button, } from "@mui/material";
|
|
12
12
|
import { useLocalErrors } from "../hooks/errors";
|
|
13
13
|
import { ComponentPool } from "../registry/types";
|
|
@@ -15,6 +15,7 @@ import { registerComponent } from "../registry/components";
|
|
|
15
15
|
import { CoreService } from "../../api/generated/core";
|
|
16
16
|
import { useComponentPicker } from "../contexts/ComponentPickerContext";
|
|
17
17
|
import { InternalServices } from "../../api/init";
|
|
18
|
+
import { getComponentDataByTemplateName, TEMPLATE_NAMES } from "../../lib/config/templateStructure";
|
|
18
19
|
export const FormComponentPicker = ({ selectedComponent, onChange, templateIds, getError, label, enabled, }) => {
|
|
19
20
|
const [selected, setSelected] = useState();
|
|
20
21
|
const { get } = useComponentPicker();
|
|
@@ -24,6 +25,17 @@ export const FormComponentPicker = ({ selectedComponent, onChange, templateIds,
|
|
|
24
25
|
else
|
|
25
26
|
setSelected(undefined);
|
|
26
27
|
}, [selectedComponent]);
|
|
28
|
+
const displayLabel = useMemo(() => {
|
|
29
|
+
var _a;
|
|
30
|
+
if (!selectedComponent)
|
|
31
|
+
return "Select " + label + " Component";
|
|
32
|
+
if (!selected)
|
|
33
|
+
return "";
|
|
34
|
+
const activityData = (_a = getComponentDataByTemplateName(TEMPLATE_NAMES.CRUISE_ACTIVITY, selected.componentFields)) !== null && _a !== void 0 ? _a : getComponentDataByTemplateName(TEMPLATE_NAMES.ACTIVITY, selected.componentFields);
|
|
35
|
+
return (activityData === null || activityData === void 0 ? void 0 : activityData.type)
|
|
36
|
+
? `${activityData.type} - ${selected.name}`
|
|
37
|
+
: selected.name;
|
|
38
|
+
}, [selected, selectedComponent, label]);
|
|
27
39
|
return (React.createElement(Paper, { component: "form", sx: { display: "flex", flexDirection: "column", gap: 1, p: 2, mb: 1 }, noValidate: true, autoComplete: "off" },
|
|
28
40
|
React.createElement(Button, { disabled: !enabled, onClick: () => {
|
|
29
41
|
get(templateIds)
|
|
@@ -48,7 +60,7 @@ export const FormComponentPicker = ({ selectedComponent, onChange, templateIds,
|
|
|
48
60
|
? "rgba(211, 47, 47, 0.04)"
|
|
49
61
|
: undefined,
|
|
50
62
|
},
|
|
51
|
-
} },
|
|
63
|
+
} }, displayLabel)));
|
|
52
64
|
};
|
|
53
65
|
const FormRendererComponentPicker = ({ data, handleChange, path, label, enabled, schema, }) => {
|
|
54
66
|
const getError = useLocalErrors(path);
|