@datlv-trustshop/shopify-inapp-components 0.1.9
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/README.md +141 -0
- package/dist/components/AppList.d.ts +13 -0
- package/dist/components/AppList.js +64 -0
- package/dist/components/ArticleList.d.ts +20 -0
- package/dist/components/ArticleList.js +174 -0
- package/dist/components/ArticleSlide.d.ts +14 -0
- package/dist/components/ArticleSlide.js +151 -0
- package/dist/components/FooterBanner.d.ts +10 -0
- package/dist/components/FooterBanner.js +72 -0
- package/dist/components/GrowApps.d.ts +13 -0
- package/dist/components/GrowApps.js +213 -0
- package/dist/components/ImageLoading.d.ts +15 -0
- package/dist/components/ImageLoading.js +66 -0
- package/dist/components/PartnerList.d.ts +9 -0
- package/dist/components/PartnerList.js +102 -0
- package/dist/components/PopupBanner.d.ts +12 -0
- package/dist/components/PopupBanner.js +100 -0
- package/dist/components/TopBanner.d.ts +14 -0
- package/dist/components/TopBanner.js +31 -0
- package/dist/components/WhatsNew.d.ts +14 -0
- package/dist/components/WhatsNew.js +258 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.js +9 -0
- package/dist/components/inlineStyles.d.ts +110 -0
- package/dist/components/inlineStyles.js +114 -0
- package/dist/components/styles.d.ts +152 -0
- package/dist/components/styles.js +158 -0
- package/dist/core/adapter.d.ts +6 -0
- package/dist/core/adapter.js +301 -0
- package/dist/core/engine.d.ts +33 -0
- package/dist/core/engine.js +176 -0
- package/dist/core/fetcher.d.ts +4 -0
- package/dist/core/fetcher.js +72 -0
- package/dist/core/global-manager.d.ts +99 -0
- package/dist/core/global-manager.js +315 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/useApps.d.ts +3 -0
- package/dist/hooks/useApps.js +18 -0
- package/dist/hooks/useArticles.d.ts +11 -0
- package/dist/hooks/useArticles.js +49 -0
- package/dist/hooks/useBanner.d.ts +5 -0
- package/dist/hooks/useBanner.js +22 -0
- package/dist/hooks/useDashboard.d.ts +11 -0
- package/dist/hooks/useDashboard.js +13 -0
- package/dist/hooks/useGrowApps.d.ts +10 -0
- package/dist/hooks/useGrowApps.js +14 -0
- package/dist/hooks/useTranslations.d.ts +3 -0
- package/dist/hooks/useTranslations.js +9 -0
- package/dist/hooks/useWhatsNew.d.ts +11 -0
- package/dist/hooks/useWhatsNew.js +34 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +16 -0
- package/dist/provider/DashboardProvider.d.ts +36 -0
- package/dist/provider/DashboardProvider.js +184 -0
- package/dist/translations/default.d.ts +2 -0
- package/dist/translations/default.js +27 -0
- package/dist/types/app.d.ts +14 -0
- package/dist/types/app.js +1 -0
- package/dist/types/article.d.ts +14 -0
- package/dist/types/article.js +1 -0
- package/dist/types/banner.d.ts +22 -0
- package/dist/types/banner.js +1 -0
- package/dist/types/dashboard.d.ts +42 -0
- package/dist/types/dashboard.js +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +6 -0
- package/dist/types/partner.d.ts +8 -0
- package/dist/types/partner.js +1 -0
- package/dist/types/product-update.d.ts +23 -0
- package/dist/types/product-update.js +1 -0
- package/dist/types/translations.d.ts +28 -0
- package/dist/types/translations.js +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
export declare const sdkStyles: {
|
|
2
|
+
slidesContainer: {
|
|
3
|
+
position: "relative";
|
|
4
|
+
width: string;
|
|
5
|
+
overflow: string;
|
|
6
|
+
margin: number;
|
|
7
|
+
};
|
|
8
|
+
slidesWrapper: {
|
|
9
|
+
display: string;
|
|
10
|
+
transition: string;
|
|
11
|
+
gap: string;
|
|
12
|
+
willChange: string;
|
|
13
|
+
};
|
|
14
|
+
slideBox: {
|
|
15
|
+
flex: string;
|
|
16
|
+
display: string;
|
|
17
|
+
alignItems: string;
|
|
18
|
+
justifyContent: string;
|
|
19
|
+
gap: string;
|
|
20
|
+
border: string;
|
|
21
|
+
padding: string;
|
|
22
|
+
borderRadius: string;
|
|
23
|
+
backgroundColor: string;
|
|
24
|
+
minHeight: string;
|
|
25
|
+
};
|
|
26
|
+
slideContent: {
|
|
27
|
+
flex: number;
|
|
28
|
+
display: string;
|
|
29
|
+
flexDirection: "column";
|
|
30
|
+
gap: string;
|
|
31
|
+
};
|
|
32
|
+
slideImage: {
|
|
33
|
+
flex: number;
|
|
34
|
+
display: string;
|
|
35
|
+
justifyContent: string;
|
|
36
|
+
alignItems: string;
|
|
37
|
+
};
|
|
38
|
+
slideNavigation: {
|
|
39
|
+
position: "relative";
|
|
40
|
+
width: string;
|
|
41
|
+
boxSizing: "content-box";
|
|
42
|
+
padding: string;
|
|
43
|
+
display: string;
|
|
44
|
+
flexDirection: "row";
|
|
45
|
+
flexWrap: "nowrap";
|
|
46
|
+
gap: string;
|
|
47
|
+
borderRadius: string;
|
|
48
|
+
backgroundColor: string;
|
|
49
|
+
};
|
|
50
|
+
slideButton: {
|
|
51
|
+
display: string;
|
|
52
|
+
alignItems: string;
|
|
53
|
+
justifyContent: string;
|
|
54
|
+
width: string;
|
|
55
|
+
height: string;
|
|
56
|
+
padding: number;
|
|
57
|
+
border: string;
|
|
58
|
+
borderRadius: string;
|
|
59
|
+
backgroundColor: string;
|
|
60
|
+
cursor: string;
|
|
61
|
+
transition: string;
|
|
62
|
+
};
|
|
63
|
+
slideButtonDisabled: {
|
|
64
|
+
cursor: string;
|
|
65
|
+
opacity: number;
|
|
66
|
+
};
|
|
67
|
+
slideItem: {
|
|
68
|
+
flex: string;
|
|
69
|
+
width: string;
|
|
70
|
+
};
|
|
71
|
+
slideItemMobile: {
|
|
72
|
+
width: string;
|
|
73
|
+
};
|
|
74
|
+
slideNav: {
|
|
75
|
+
position: "absolute";
|
|
76
|
+
top: string;
|
|
77
|
+
transform: string;
|
|
78
|
+
background: string;
|
|
79
|
+
border: string;
|
|
80
|
+
borderRadius: string;
|
|
81
|
+
width: string;
|
|
82
|
+
height: string;
|
|
83
|
+
display: string;
|
|
84
|
+
alignItems: string;
|
|
85
|
+
justifyContent: string;
|
|
86
|
+
cursor: string;
|
|
87
|
+
zIndex: number;
|
|
88
|
+
transition: string;
|
|
89
|
+
};
|
|
90
|
+
slideNavPrev: {
|
|
91
|
+
left: string;
|
|
92
|
+
};
|
|
93
|
+
slideNavNext: {
|
|
94
|
+
right: string;
|
|
95
|
+
};
|
|
96
|
+
slideNavHover: {
|
|
97
|
+
background: string;
|
|
98
|
+
boxShadow: string;
|
|
99
|
+
};
|
|
100
|
+
slideDots: {
|
|
101
|
+
display: string;
|
|
102
|
+
justifyContent: string;
|
|
103
|
+
gap: string;
|
|
104
|
+
marginTop: string;
|
|
105
|
+
};
|
|
106
|
+
slideDot: {
|
|
107
|
+
width: string;
|
|
108
|
+
height: string;
|
|
109
|
+
borderRadius: string;
|
|
110
|
+
backgroundColor: string;
|
|
111
|
+
cursor: string;
|
|
112
|
+
transition: string;
|
|
113
|
+
};
|
|
114
|
+
slideDotActive: {
|
|
115
|
+
backgroundColor: string;
|
|
116
|
+
};
|
|
117
|
+
dashboardWhatsNew: {
|
|
118
|
+
width: string;
|
|
119
|
+
overflow: string;
|
|
120
|
+
maxWidth: string;
|
|
121
|
+
};
|
|
122
|
+
dashboardGrowApps: {
|
|
123
|
+
width: string;
|
|
124
|
+
};
|
|
125
|
+
dashboardPartnerList: {
|
|
126
|
+
width: string;
|
|
127
|
+
};
|
|
128
|
+
truncateText: {
|
|
129
|
+
display: string;
|
|
130
|
+
WebkitLineClamp: number;
|
|
131
|
+
WebkitBoxOrient: "vertical";
|
|
132
|
+
overflow: string;
|
|
133
|
+
textOverflow: string;
|
|
134
|
+
fontSize: string;
|
|
135
|
+
color: string;
|
|
136
|
+
lineHeight: number;
|
|
137
|
+
};
|
|
138
|
+
mobile: string;
|
|
139
|
+
mobileSlideBox: {
|
|
140
|
+
flexDirection: "column";
|
|
141
|
+
gap: string;
|
|
142
|
+
};
|
|
143
|
+
mobileSlideImage: {
|
|
144
|
+
width: string;
|
|
145
|
+
height: string;
|
|
146
|
+
};
|
|
147
|
+
mobileSlideItem: {
|
|
148
|
+
width: string;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
export declare const mergeStyles: (...styles: Array<React.CSSProperties | undefined>) => React.CSSProperties;
|
|
152
|
+
export declare const useResponsiveStyle: (desktopStyle: React.CSSProperties, _mobileStyle: React.CSSProperties) => import("react").CSSProperties;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
export const sdkStyles = {
|
|
2
|
+
// Container styles
|
|
3
|
+
slidesContainer: {
|
|
4
|
+
position: "relative",
|
|
5
|
+
width: "100%",
|
|
6
|
+
overflow: "hidden",
|
|
7
|
+
margin: 0,
|
|
8
|
+
},
|
|
9
|
+
slidesWrapper: {
|
|
10
|
+
display: "flex",
|
|
11
|
+
transition: "transform 0.5s ease-in-out",
|
|
12
|
+
gap: "20px",
|
|
13
|
+
willChange: "transform",
|
|
14
|
+
},
|
|
15
|
+
slideBox: {
|
|
16
|
+
flex: "0 0 90%",
|
|
17
|
+
display: "flex",
|
|
18
|
+
alignItems: "stretch",
|
|
19
|
+
justifyContent: "space-between",
|
|
20
|
+
gap: "47px",
|
|
21
|
+
border: "1px solid #e3e3e3",
|
|
22
|
+
padding: "16px",
|
|
23
|
+
borderRadius: "8px",
|
|
24
|
+
backgroundColor: "#ffffff",
|
|
25
|
+
minHeight: "280px",
|
|
26
|
+
},
|
|
27
|
+
slideContent: {
|
|
28
|
+
flex: 1,
|
|
29
|
+
display: "flex",
|
|
30
|
+
flexDirection: "column",
|
|
31
|
+
gap: "9px",
|
|
32
|
+
},
|
|
33
|
+
slideImage: {
|
|
34
|
+
flex: 1,
|
|
35
|
+
display: "flex",
|
|
36
|
+
justifyContent: "center",
|
|
37
|
+
alignItems: "center",
|
|
38
|
+
},
|
|
39
|
+
slideNavigation: {
|
|
40
|
+
position: "relative",
|
|
41
|
+
width: "fit-content",
|
|
42
|
+
boxSizing: "content-box",
|
|
43
|
+
padding: "4px 6px",
|
|
44
|
+
display: "flex",
|
|
45
|
+
flexDirection: "row",
|
|
46
|
+
flexWrap: "nowrap",
|
|
47
|
+
gap: "4px",
|
|
48
|
+
borderRadius: "8px",
|
|
49
|
+
backgroundColor: "#e3e3e3",
|
|
50
|
+
},
|
|
51
|
+
slideButton: {
|
|
52
|
+
display: "flex",
|
|
53
|
+
alignItems: "center",
|
|
54
|
+
justifyContent: "center",
|
|
55
|
+
width: "24px",
|
|
56
|
+
height: "24px",
|
|
57
|
+
padding: 0,
|
|
58
|
+
border: "none",
|
|
59
|
+
borderRadius: "4px",
|
|
60
|
+
backgroundColor: "transparent",
|
|
61
|
+
cursor: "pointer",
|
|
62
|
+
transition: "background-color 0.2s ease",
|
|
63
|
+
},
|
|
64
|
+
slideButtonDisabled: {
|
|
65
|
+
cursor: "not-allowed",
|
|
66
|
+
opacity: 0.5,
|
|
67
|
+
},
|
|
68
|
+
slideItem: {
|
|
69
|
+
flex: "0 0 auto",
|
|
70
|
+
width: "270px",
|
|
71
|
+
},
|
|
72
|
+
slideItemMobile: {
|
|
73
|
+
width: "90% !important",
|
|
74
|
+
},
|
|
75
|
+
slideNav: {
|
|
76
|
+
position: "absolute",
|
|
77
|
+
top: "50%",
|
|
78
|
+
transform: "translateY(-50%)",
|
|
79
|
+
background: "rgba(255, 255, 255, 0.9)",
|
|
80
|
+
border: "1px solid #e3e3e3",
|
|
81
|
+
borderRadius: "50%",
|
|
82
|
+
width: "32px",
|
|
83
|
+
height: "32px",
|
|
84
|
+
display: "flex",
|
|
85
|
+
alignItems: "center",
|
|
86
|
+
justifyContent: "center",
|
|
87
|
+
cursor: "pointer",
|
|
88
|
+
zIndex: 10,
|
|
89
|
+
transition: "background-color 0.2s",
|
|
90
|
+
},
|
|
91
|
+
slideNavPrev: {
|
|
92
|
+
left: "10px",
|
|
93
|
+
},
|
|
94
|
+
slideNavNext: {
|
|
95
|
+
right: "10px",
|
|
96
|
+
},
|
|
97
|
+
slideNavHover: {
|
|
98
|
+
background: "#ffffff",
|
|
99
|
+
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
|
|
100
|
+
},
|
|
101
|
+
slideDots: {
|
|
102
|
+
display: "flex",
|
|
103
|
+
justifyContent: "center",
|
|
104
|
+
gap: "8px",
|
|
105
|
+
marginTop: "16px",
|
|
106
|
+
},
|
|
107
|
+
slideDot: {
|
|
108
|
+
width: "8px",
|
|
109
|
+
height: "8px",
|
|
110
|
+
borderRadius: "50%",
|
|
111
|
+
backgroundColor: "#e3e3e3",
|
|
112
|
+
cursor: "pointer",
|
|
113
|
+
transition: "background-color 0.3s",
|
|
114
|
+
},
|
|
115
|
+
slideDotActive: {
|
|
116
|
+
backgroundColor: "#303030",
|
|
117
|
+
},
|
|
118
|
+
// Dashboard specific styles
|
|
119
|
+
dashboardWhatsNew: {
|
|
120
|
+
width: "100%",
|
|
121
|
+
overflow: "hidden",
|
|
122
|
+
maxWidth: "950px",
|
|
123
|
+
},
|
|
124
|
+
dashboardGrowApps: {
|
|
125
|
+
width: "100%",
|
|
126
|
+
},
|
|
127
|
+
dashboardPartnerList: {
|
|
128
|
+
width: "100%",
|
|
129
|
+
},
|
|
130
|
+
truncateText: {
|
|
131
|
+
display: "-webkit-box",
|
|
132
|
+
WebkitLineClamp: 3,
|
|
133
|
+
WebkitBoxOrient: "vertical",
|
|
134
|
+
overflow: "hidden",
|
|
135
|
+
textOverflow: "ellipsis",
|
|
136
|
+
fontSize: "13px",
|
|
137
|
+
color: "#616161",
|
|
138
|
+
lineHeight: 1.4,
|
|
139
|
+
},
|
|
140
|
+
mobile: "@media (max-width: 768px)",
|
|
141
|
+
mobileSlideBox: {
|
|
142
|
+
flexDirection: "column",
|
|
143
|
+
gap: "16px",
|
|
144
|
+
},
|
|
145
|
+
mobileSlideImage: {
|
|
146
|
+
width: "100%",
|
|
147
|
+
height: "auto",
|
|
148
|
+
},
|
|
149
|
+
mobileSlideItem: {
|
|
150
|
+
width: "90%",
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
export const mergeStyles = (...styles) => {
|
|
154
|
+
return Object.assign({}, ...styles.filter(Boolean));
|
|
155
|
+
};
|
|
156
|
+
export const useResponsiveStyle = (desktopStyle, _mobileStyle) => {
|
|
157
|
+
return desktopStyle;
|
|
158
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DashboardData, BannerItem, AppItem, ArticleItem, ProductUpdateItem, AppGroup } from "../types";
|
|
2
|
+
export declare function adaptDashboardData(rawData: any): DashboardData;
|
|
3
|
+
export declare function adaptBanner(apiData: any): BannerItem;
|
|
4
|
+
export declare function adaptApp(apiData: any, defaultGroup?: AppGroup): AppItem;
|
|
5
|
+
export declare function adaptArticle(apiData: any): ArticleItem;
|
|
6
|
+
export declare function adaptProductUpdate(apiData: any): ProductUpdateItem;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
export function adaptDashboardData(rawData) {
|
|
2
|
+
const data = rawData.data || rawData;
|
|
3
|
+
const banners = [];
|
|
4
|
+
if (data.banner) {
|
|
5
|
+
banners.push({
|
|
6
|
+
...data.banner,
|
|
7
|
+
type: "top_banner",
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
const allApps = [
|
|
11
|
+
...(data.partner_list || []),
|
|
12
|
+
...(data.seo_apps || []),
|
|
13
|
+
...(data.integrations || []),
|
|
14
|
+
];
|
|
15
|
+
const articles = data.whats_new?.articles || [];
|
|
16
|
+
const whatsNew = data.whats_new?.product_update || [];
|
|
17
|
+
const growApps = data.grow_apps || [];
|
|
18
|
+
const growAppsDisplayLimit = data.grow_apps_display_limit;
|
|
19
|
+
return {
|
|
20
|
+
banners: adaptBanners(banners),
|
|
21
|
+
apps: adaptApps(allApps),
|
|
22
|
+
articles: adaptArticles(articles),
|
|
23
|
+
whatsNew: adaptProductUpdates(whatsNew),
|
|
24
|
+
grow_apps: growApps,
|
|
25
|
+
grow_apps_display_limit: growAppsDisplayLimit,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function adaptBanners(banners) {
|
|
29
|
+
if (!Array.isArray(banners))
|
|
30
|
+
return [];
|
|
31
|
+
return banners.map((banner) => adaptBanner(banner)).filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
export function adaptBanner(apiData) {
|
|
34
|
+
const type = determineBannerType(apiData);
|
|
35
|
+
return {
|
|
36
|
+
id: apiData.id || generateId(),
|
|
37
|
+
type,
|
|
38
|
+
title: apiData.title || "",
|
|
39
|
+
description: apiData.description || apiData.content || apiData.subtitle || "",
|
|
40
|
+
image: apiData.image || apiData.image_url || apiData.imageUrl,
|
|
41
|
+
icon: apiData.icon || apiData.icon_url || apiData.iconUrl,
|
|
42
|
+
link: apiData.link ||
|
|
43
|
+
apiData.button_url ||
|
|
44
|
+
apiData.buttonUrl ||
|
|
45
|
+
apiData.url ||
|
|
46
|
+
"#",
|
|
47
|
+
linkText: apiData.linkText ||
|
|
48
|
+
apiData.button_text ||
|
|
49
|
+
apiData.buttonText ||
|
|
50
|
+
"Learn More",
|
|
51
|
+
openType: apiData.openType || apiData.open_type || "new_tab",
|
|
52
|
+
style: {
|
|
53
|
+
backgroundColor: apiData.background_color || apiData.backgroundColor || apiData.bgColor,
|
|
54
|
+
textColor: apiData.text_color || apiData.textColor,
|
|
55
|
+
buttonColor: apiData.button_color || apiData.buttonColor,
|
|
56
|
+
buttonTextColor: apiData.button_text_color || apiData.buttonTextColor,
|
|
57
|
+
},
|
|
58
|
+
priority: apiData.priority || apiData.order || 0,
|
|
59
|
+
isActive: apiData.isActive !== undefined
|
|
60
|
+
? apiData.isActive
|
|
61
|
+
: apiData.active !== undefined
|
|
62
|
+
? apiData.active
|
|
63
|
+
: apiData.enabled !== undefined
|
|
64
|
+
? apiData.enabled
|
|
65
|
+
: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function determineBannerType(apiData) {
|
|
69
|
+
if (apiData.type) {
|
|
70
|
+
const typeMap = {
|
|
71
|
+
popup: "popup",
|
|
72
|
+
pop_up: "popup",
|
|
73
|
+
modal: "popup",
|
|
74
|
+
top: "top_banner",
|
|
75
|
+
top_banner: "top_banner",
|
|
76
|
+
header: "top_banner",
|
|
77
|
+
footer: "footer_banner",
|
|
78
|
+
footer_banner: "footer_banner",
|
|
79
|
+
bottom: "footer_banner",
|
|
80
|
+
};
|
|
81
|
+
const normalizedType = apiData.type.toLowerCase().replace(/-/g, "_");
|
|
82
|
+
return typeMap[normalizedType] || "top_banner";
|
|
83
|
+
}
|
|
84
|
+
if (apiData.position) {
|
|
85
|
+
const positionMap = {
|
|
86
|
+
top: "top_banner",
|
|
87
|
+
header: "top_banner",
|
|
88
|
+
bottom: "footer_banner",
|
|
89
|
+
footer: "footer_banner",
|
|
90
|
+
center: "popup",
|
|
91
|
+
modal: "popup",
|
|
92
|
+
};
|
|
93
|
+
const normalizedPosition = apiData.position.toLowerCase();
|
|
94
|
+
return positionMap[normalizedPosition] || "top_banner";
|
|
95
|
+
}
|
|
96
|
+
return "top_banner";
|
|
97
|
+
}
|
|
98
|
+
function adaptApps(apps) {
|
|
99
|
+
const result = {
|
|
100
|
+
grow_faster: [],
|
|
101
|
+
integration: [],
|
|
102
|
+
marketing: [],
|
|
103
|
+
analytics: [],
|
|
104
|
+
other: [],
|
|
105
|
+
};
|
|
106
|
+
if (Array.isArray(apps)) {
|
|
107
|
+
const adaptedApps = apps.map((app) => adaptApp(app)).filter(Boolean);
|
|
108
|
+
adaptedApps.forEach((app) => {
|
|
109
|
+
const group = app.group || "other";
|
|
110
|
+
if (result[group]) {
|
|
111
|
+
result[group].push(app);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else if (typeof apps === "object") {
|
|
116
|
+
Object.entries(apps).forEach(([key, value]) => {
|
|
117
|
+
const group = normalizeAppGroup(key);
|
|
118
|
+
if (Array.isArray(value)) {
|
|
119
|
+
result[group] = value
|
|
120
|
+
.map((app) => adaptApp(app, group))
|
|
121
|
+
.filter(Boolean);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
function normalizeAppGroup(group) {
|
|
128
|
+
const groupMap = {
|
|
129
|
+
grow_faster: "grow_faster",
|
|
130
|
+
growfaster: "grow_faster",
|
|
131
|
+
"grow-faster": "grow_faster",
|
|
132
|
+
integration: "integration",
|
|
133
|
+
integrations: "integration",
|
|
134
|
+
marketing: "marketing",
|
|
135
|
+
analytics: "analytics",
|
|
136
|
+
analysis: "analytics",
|
|
137
|
+
};
|
|
138
|
+
const normalized = group.toLowerCase().replace(/[\s_-]/g, "");
|
|
139
|
+
return groupMap[normalized] || "other";
|
|
140
|
+
}
|
|
141
|
+
export function adaptApp(apiData, defaultGroup) {
|
|
142
|
+
const group = defaultGroup ||
|
|
143
|
+
normalizeAppGroup(apiData.group || apiData.category || "other");
|
|
144
|
+
return {
|
|
145
|
+
id: apiData.id || generateId(),
|
|
146
|
+
key: apiData.key ||
|
|
147
|
+
apiData.slug ||
|
|
148
|
+
apiData.name?.toLowerCase().replace(/\s+/g, "-") ||
|
|
149
|
+
generateKey(),
|
|
150
|
+
title: apiData.title || apiData.name || "",
|
|
151
|
+
description: apiData.description || apiData.subtitle || "",
|
|
152
|
+
icon: apiData.icon || apiData.icon_url || apiData.iconUrl || apiData.logo || "",
|
|
153
|
+
link: apiData.link || apiData.url || apiData.app_url || apiData.appUrl || "#",
|
|
154
|
+
group,
|
|
155
|
+
rating: apiData.rating || apiData.score,
|
|
156
|
+
installs: apiData.installs || apiData.installations || apiData.install_count,
|
|
157
|
+
price: apiData.price || apiData.pricing,
|
|
158
|
+
featured: apiData.featured || apiData.is_featured || false,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function adaptArticles(articles) {
|
|
162
|
+
if (!Array.isArray(articles))
|
|
163
|
+
return [];
|
|
164
|
+
return articles.map((article) => adaptArticle(article)).filter(Boolean);
|
|
165
|
+
}
|
|
166
|
+
export function adaptArticle(apiData) {
|
|
167
|
+
return {
|
|
168
|
+
id: apiData.id || generateId(),
|
|
169
|
+
title: apiData.title || apiData.headline || "",
|
|
170
|
+
description: apiData.description || apiData.summary || apiData.excerpt || "",
|
|
171
|
+
content: apiData.content || apiData.body || apiData.text,
|
|
172
|
+
thumbnail: apiData.thumbnail ||
|
|
173
|
+
apiData.image ||
|
|
174
|
+
apiData.cover_image ||
|
|
175
|
+
apiData.coverImage,
|
|
176
|
+
imageUrl: apiData.imageUrl ||
|
|
177
|
+
apiData.image_url ||
|
|
178
|
+
apiData.image ||
|
|
179
|
+
apiData.thumbnail,
|
|
180
|
+
link: apiData.link ||
|
|
181
|
+
apiData.url ||
|
|
182
|
+
apiData.article_url ||
|
|
183
|
+
apiData.button_url ||
|
|
184
|
+
"#",
|
|
185
|
+
author: apiData.author || apiData.author_name || apiData.authorName,
|
|
186
|
+
publishedDate: apiData.published_date ||
|
|
187
|
+
apiData.publishedDate ||
|
|
188
|
+
apiData.date ||
|
|
189
|
+
apiData.created_at,
|
|
190
|
+
category: apiData.category || apiData.section || apiData.label,
|
|
191
|
+
readTime: apiData.read_time || apiData.readTime || apiData.reading_time,
|
|
192
|
+
tags: apiData.tags || apiData.keywords || [],
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function adaptProductUpdates(updates) {
|
|
196
|
+
if (!Array.isArray(updates))
|
|
197
|
+
return [];
|
|
198
|
+
const mappedUpdates = updates
|
|
199
|
+
.map((update) => adaptProductUpdate(update))
|
|
200
|
+
.filter(Boolean);
|
|
201
|
+
return mappedUpdates.sort((a, b) => {
|
|
202
|
+
const posA = a.position ?? Number.MAX_VALUE;
|
|
203
|
+
const posB = b.position ?? Number.MAX_VALUE;
|
|
204
|
+
return posA - posB;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
export function adaptProductUpdate(apiData) {
|
|
208
|
+
const description = apiData.description ||
|
|
209
|
+
apiData.content?.text ||
|
|
210
|
+
apiData.content ||
|
|
211
|
+
apiData.summary ||
|
|
212
|
+
"";
|
|
213
|
+
const features = apiData.features || apiData.content?.list || apiData.new_features;
|
|
214
|
+
// Handle new nested buttons structure
|
|
215
|
+
const tryButton = apiData.buttons?.try;
|
|
216
|
+
const learnButton = apiData.buttons?.learn;
|
|
217
|
+
// Fallback to old format if new format not available
|
|
218
|
+
const link = tryButton?.url ||
|
|
219
|
+
learnButton?.url ||
|
|
220
|
+
apiData.link ||
|
|
221
|
+
apiData.button_try_url ||
|
|
222
|
+
apiData.button_learn_url ||
|
|
223
|
+
apiData.url ||
|
|
224
|
+
apiData.release_notes_url;
|
|
225
|
+
return {
|
|
226
|
+
id: apiData.id || generateId(),
|
|
227
|
+
title: apiData.title || apiData.name || "",
|
|
228
|
+
description,
|
|
229
|
+
version: apiData.version || apiData.release_version,
|
|
230
|
+
releaseDate: apiData.version || // New: use version field for date display
|
|
231
|
+
apiData.date_time ||
|
|
232
|
+
apiData.release_date ||
|
|
233
|
+
apiData.releaseDate ||
|
|
234
|
+
apiData.date ||
|
|
235
|
+
new Date().toISOString(),
|
|
236
|
+
date_time: apiData.version || apiData.date_time, // New: prioritize version field
|
|
237
|
+
features: adaptStringArray(features),
|
|
238
|
+
improvements: adaptStringArray(apiData.improvements || apiData.enhancements),
|
|
239
|
+
fixes: adaptStringArray(apiData.fixes || apiData.bug_fixes || apiData.bugFixes),
|
|
240
|
+
link,
|
|
241
|
+
imageUrl: apiData.image_url ||
|
|
242
|
+
apiData.imageUrl ||
|
|
243
|
+
apiData.image ||
|
|
244
|
+
apiData.thumbnail,
|
|
245
|
+
image_url: apiData.image_url,
|
|
246
|
+
type: determineUpdateType(apiData),
|
|
247
|
+
position: apiData.position || apiData.order || apiData.priority,
|
|
248
|
+
// Handle new button structure with fallbacks
|
|
249
|
+
button_try_it_now: tryButton?.text || apiData.button_try_it_now || "Try it now",
|
|
250
|
+
button_try_url: tryButton?.url || apiData.button_try_url,
|
|
251
|
+
button_learn_more: learnButton?.text || apiData.button_learn_more || "Learn more",
|
|
252
|
+
button_learn_url: learnButton?.url || apiData.button_learn_url,
|
|
253
|
+
content: apiData.content
|
|
254
|
+
? {
|
|
255
|
+
text: apiData.content.text || apiData.content,
|
|
256
|
+
}
|
|
257
|
+
: undefined,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function determineUpdateType(apiData) {
|
|
261
|
+
if (apiData.type) {
|
|
262
|
+
const type = apiData.type.toLowerCase();
|
|
263
|
+
if (type.includes("major"))
|
|
264
|
+
return "major";
|
|
265
|
+
if (type.includes("minor"))
|
|
266
|
+
return "minor";
|
|
267
|
+
if (type.includes("patch"))
|
|
268
|
+
return "patch";
|
|
269
|
+
}
|
|
270
|
+
if (apiData.version) {
|
|
271
|
+
const version = apiData.version.toString();
|
|
272
|
+
const parts = version.split(".");
|
|
273
|
+
if (parts.length >= 3) {
|
|
274
|
+
const [, minor, patch] = parts;
|
|
275
|
+
if (patch !== "0")
|
|
276
|
+
return "patch";
|
|
277
|
+
if (minor !== "0")
|
|
278
|
+
return "minor";
|
|
279
|
+
return "major";
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return "minor";
|
|
283
|
+
}
|
|
284
|
+
function adaptStringArray(data) {
|
|
285
|
+
if (Array.isArray(data)) {
|
|
286
|
+
return data.filter((item) => typeof item === "string");
|
|
287
|
+
}
|
|
288
|
+
if (typeof data === "string") {
|
|
289
|
+
return data
|
|
290
|
+
.split(/[,;|\n]/)
|
|
291
|
+
.map((s) => s.trim())
|
|
292
|
+
.filter(Boolean);
|
|
293
|
+
}
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
function generateId() {
|
|
297
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
298
|
+
}
|
|
299
|
+
function generateKey() {
|
|
300
|
+
return `item-${Math.random().toString(36).substr(2, 9)}`;
|
|
301
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DashboardData, DashboardConfig, BannerItem, AppItem, AppGroup, ArticleItem, ProductUpdateItem, BannerType } from "../types";
|
|
2
|
+
export declare class DashboardEngine {
|
|
3
|
+
private static instance;
|
|
4
|
+
private data;
|
|
5
|
+
private config;
|
|
6
|
+
private initPromise;
|
|
7
|
+
private lastFetchTime;
|
|
8
|
+
private listeners;
|
|
9
|
+
private fetchInProgress;
|
|
10
|
+
private currentLocale;
|
|
11
|
+
private constructor();
|
|
12
|
+
static getInstance(config?: DashboardConfig): DashboardEngine;
|
|
13
|
+
static resetInstance(): void;
|
|
14
|
+
init(forceRefresh?: boolean): Promise<void>;
|
|
15
|
+
private loadData;
|
|
16
|
+
subscribe(listener: (data: DashboardData | null) => void): () => void;
|
|
17
|
+
private notifyListeners;
|
|
18
|
+
getData(): DashboardData | null;
|
|
19
|
+
getBanners(type?: BannerType): BannerItem[];
|
|
20
|
+
getActiveBanners(type?: BannerType): BannerItem[];
|
|
21
|
+
getApps(group?: AppGroup): AppItem[];
|
|
22
|
+
getAppGroups(): AppGroup[];
|
|
23
|
+
getArticles(limit?: number): ArticleItem[];
|
|
24
|
+
getWhatsNew(limit?: number): ProductUpdateItem[];
|
|
25
|
+
refresh(): Promise<void>;
|
|
26
|
+
isInitialized(): boolean;
|
|
27
|
+
getCacheAge(): number;
|
|
28
|
+
isCacheValid(): boolean;
|
|
29
|
+
updateLocale(locale: string): boolean;
|
|
30
|
+
setLocale(locale: string): Promise<void>;
|
|
31
|
+
updateConfig(newConfig: Partial<DashboardConfig>): void;
|
|
32
|
+
getCurrentLocale(): string;
|
|
33
|
+
}
|