@agilant/toga-blox 1.0.236 → 1.0.238
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 +30 -26
- package/dist/api/apiFunctions.d.ts +6 -5
- package/dist/api/apiFunctions.js +3 -2
- package/dist/api/auth.d.ts +3 -0
- package/dist/api/auth.js +42 -0
- package/dist/api/axiosInstance.d.ts +0 -1
- package/dist/api/axiosInstance.js +23 -104
- package/dist/api/checkSsoAuth.d.ts +6 -0
- package/dist/api/checkSsoAuth.js +64 -0
- package/dist/api/events.d.ts +1 -0
- package/dist/api/events.js +1 -0
- package/dist/api/genericApi.d.ts +6 -0
- package/dist/api/genericApi.js +72 -0
- package/dist/api/handleSamlAuth.d.ts +7 -0
- package/dist/api/handleSamlAuth.js +26 -0
- package/dist/api/types.d.ts +13 -0
- package/dist/api/types.js +1 -0
- package/dist/components/BaseButton/BaseButton.d.ts +1 -1
- package/dist/components/BaseButton/BaseButton.js +28 -33
- package/dist/components/BaseButton/BaseButton.stories.js +127 -60
- package/dist/components/BaseButton/BaseButton.types.d.ts +22 -8
- package/dist/components/DropDownIconButton/DropDownIconButton.stories.js +34 -22
- package/dist/components/DynamicSection/DynamicSection.d.ts +3 -0
- package/dist/components/DynamicSection/DynamicSection.js +31 -0
- package/dist/components/DynamicSection/DynamicSection.stories.d.ts +6 -0
- package/dist/components/DynamicSection/DynamicSection.stories.js +144 -0
- package/dist/components/DynamicSection/index.d.ts +2 -0
- package/dist/components/DynamicSection/index.js +2 -0
- package/dist/components/DynamicSection/types.d.ts +85 -0
- package/dist/components/DynamicSection/types.js +1 -0
- package/dist/components/FeatureList/FeatureList.d.ts +4 -0
- package/dist/components/FeatureList/FeatureList.js +10 -0
- package/dist/components/FeatureList/FeatureList.stories.d.ts +7 -0
- package/dist/components/FeatureList/FeatureList.stories.js +115 -0
- package/dist/components/FeatureList/index.d.ts +1 -0
- package/dist/components/FeatureList/index.js +1 -0
- package/dist/components/FeatureList/types.d.ts +27 -0
- package/dist/components/FeatureList/types.js +1 -0
- package/dist/components/GetSupport/GetSupport.js +2 -2
- package/dist/components/GetSupport/GetSupport.stories.js +1 -1
- package/dist/components/GetSupport/GetSupport.test.js +30 -30
- package/dist/components/GetSupport/GetSupport.types.d.ts +1 -2
- package/dist/components/HamburgerButton/Hamburger.stories.d.ts +2 -2
- package/dist/components/HamburgerButton/Hamburger.stories.js +30 -30
- package/dist/components/InfoBanner/InfoBanner.d.ts +4 -0
- package/dist/components/InfoBanner/InfoBanner.js +7 -0
- package/dist/components/InfoBanner/InfoBanner.stories.d.ts +8 -0
- package/dist/components/InfoBanner/InfoBanner.stories.js +65 -0
- package/dist/components/InfoBanner/index.d.ts +2 -0
- package/dist/components/InfoBanner/index.js +2 -0
- package/dist/components/InfoBanner/types.d.ts +19 -0
- package/dist/components/InfoBanner/types.js +1 -0
- package/dist/components/InitialsAvatar/InitialsAvatar.d.ts +4 -0
- package/dist/components/InitialsAvatar/InitialsAvatar.js +8 -0
- package/dist/components/InitialsAvatar/InitialsAvatar.stories.d.ts +8 -0
- package/dist/components/InitialsAvatar/InitialsAvatar.stories.js +61 -0
- package/dist/components/InitialsAvatar/InitialsAvatar.types.d.ts +6 -0
- package/dist/components/InitialsAvatar/InitialsAvatar.types.js +1 -0
- package/dist/components/NotesList/NoteItem.d.ts +4 -0
- package/dist/components/NotesList/NoteItem.js +9 -0
- package/dist/components/NotesList/NotesList.d.ts +4 -0
- package/dist/components/NotesList/NotesList.js +7 -0
- package/dist/components/NotesList/NotesList.stories.d.ts +8 -0
- package/dist/components/NotesList/NotesList.stories.js +129 -0
- package/dist/components/NotesList/types.d.ts +50 -0
- package/dist/components/NotesList/types.js +1 -0
- package/dist/components/SearchInput/BaseSearchInput.d.ts +4 -0
- package/dist/components/SearchInput/BaseSearchInput.js +21 -0
- package/dist/components/SearchInput/SearchInput.types.d.ts +31 -0
- package/dist/components/TabList/TabList.d.ts +3 -0
- package/dist/components/TabList/TabList.js +45 -0
- package/dist/components/TabList/TabList.stories.d.ts +6 -0
- package/dist/components/TabList/TabList.stories.js +95 -0
- package/dist/components/TabList/index.d.ts +1 -0
- package/dist/components/TabList/index.js +1 -0
- package/dist/components/TabList/types.d.ts +16 -0
- package/dist/components/TabList/types.js +1 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.js +0 -1
- package/dist/main.css +1 -0
- package/dist/reactQuery/index.d.ts +0 -0
- package/dist/reactQuery/index.js +0 -0
- package/dist/reactQuery/queryHelpers.d.ts +54 -0
- package/dist/reactQuery/queryHelpers.js +132 -0
- package/dist/reactQuery/useApiMutation.d.ts +2 -0
- package/dist/reactQuery/useApiMutation.js +24 -0
- package/dist/reactQuery/useApiQuery.d.ts +2 -0
- package/dist/reactQuery/useApiQuery.js +10 -0
- package/dist/utils/formatCurrency.d.ts +2 -0
- package/dist/utils/formatCurrency.js +13 -0
- package/dist/utils/formatDate.d.ts +2 -0
- package/dist/utils/formatDate.js +8 -0
- package/dist/utils/formatTimestamp.d.ts +2 -0
- package/dist/utils/formatTimestamp.js +40 -0
- package/dist/utils/index.d.ts +16 -0
- package/dist/utils/index.js +16 -0
- package/dist/utils/roundNumToDecimalPlaces.d.ts +2 -0
- package/dist/utils/roundNumToDecimalPlaces.js +21 -0
- package/dist/utils/validateEmailFormat.d.ts +15 -0
- package/dist/utils/validateEmailFormat.js +21 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -16,25 +16,6 @@ npm install @your-company/toga-blox
|
|
|
16
16
|
🔧 Customization
|
|
17
17
|
Our components are engineered for extensive customization via props. For comprehensive guidance on customizing each component, consult the specific component documentation.
|
|
18
18
|
|
|
19
|
-
🐳 Docker Integration
|
|
20
|
-
Toga-Blox requires Docker to run certain services like Storybook and CSS watcher. Please ensure Docker is installed on your system. Follow these steps to set up and run the services:
|
|
21
|
-
|
|
22
|
-
Install Docker from Docker's official website.
|
|
23
|
-
|
|
24
|
-
Once Docker is installed, use the following commands to manage the Docker containers:
|
|
25
|
-
|
|
26
|
-
build the Docker images: docker-compose build --no-cache
|
|
27
|
-
|
|
28
|
-
install the required packages using the docker: docker-compose run --rm ui npm install
|
|
29
|
-
|
|
30
|
-
To start the services: docker-compose up
|
|
31
|
-
|
|
32
|
-
To stop the services: docker-compose down
|
|
33
|
-
|
|
34
|
-
To run tests: docker-compose run --rm test
|
|
35
|
-
|
|
36
|
-
Running App outside of Docker
|
|
37
|
-
|
|
38
19
|
To run test coverage report: npx vitest run src/components/{COMPONENT NAME HERE} --coverage
|
|
39
20
|
|
|
40
21
|
📚 Dependencies
|
|
@@ -43,7 +24,7 @@ Toga-Blox is built using:
|
|
|
43
24
|
React
|
|
44
25
|
TypeScript
|
|
45
26
|
Tailwind CSS
|
|
46
|
-
|
|
27
|
+
|
|
47
28
|
|
|
48
29
|
🤝 Contributing
|
|
49
30
|
We value contributions to Toga-Blox, whether they involve documentation enhancements, feature developments, or bug rectifications. Please follow our contribution guidelines.
|
|
@@ -54,15 +35,28 @@ Though toga-blox is developed and optimized using Vite, it's designed to be univ
|
|
|
54
35
|
📚 Storybook
|
|
55
36
|
For an interactive exploration of toga-blox components, check out our Storybook. It provides live examples, usage scenarios, and customizable props for each component.
|
|
56
37
|
|
|
57
|
-
## Peer Dependencies
|
|
58
38
|
|
|
59
|
-
|
|
39
|
+
## To Deploy Changes In Blox
|
|
60
40
|
|
|
61
|
-
|
|
41
|
+
1) up the version number in package.json
|
|
42
|
+
2) in terminal, execute 'npm run build'
|
|
43
|
+
3) in terminal, execute 'npm publish'
|
|
44
|
+
4) login to registry.npmjs.org to check that new version number reflects on profile (credentials in One Password)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## To Check Changes Before Deploying New Version
|
|
48
|
+
*Note: you may need to run separate VS code windows/instances (one for both blox and the consuming app)
|
|
49
|
+
|
|
50
|
+
To Link:
|
|
51
|
+
1) in blox: execute 'npm link' in terminal
|
|
52
|
+
2) in consuming application: execute 'npm link @agilant/toga-blox' in terminal
|
|
53
|
+
3) to check that applications are link, execute: 'ls -l node_modules/@agilant' in either repo terminals
|
|
54
|
+
|
|
55
|
+
To Unlink:
|
|
56
|
+
1) in blox: execute 'npm unlink @agilant/toga-blox' in terminal
|
|
57
|
+
2) in consuming application: execute 'npm unlink @agilant/toga-blox' in terminal
|
|
58
|
+
3) to check that applications are link, execute: 'ls -l node_modules/@agilant' (should return empty list) in terminal
|
|
62
59
|
|
|
63
|
-
```bash
|
|
64
|
-
npm install react-router-dom
|
|
65
|
-
```
|
|
66
60
|
|
|
67
61
|
## FontAwesome Icons
|
|
68
62
|
|
|
@@ -73,3 +67,13 @@ For users without a Pro subscription, the free icons will be used. Make sure to
|
|
|
73
67
|
```bash
|
|
74
68
|
npm install @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/react-fontawesome
|
|
75
69
|
```
|
|
70
|
+
|
|
71
|
+
## Peer Dependencies (DEPRECATED)
|
|
72
|
+
|
|
73
|
+
This library requires `react-router-dom` to be installed in your project. Please ensure that you have `react-router-dom` installed to avoid any issues with missing modules.
|
|
74
|
+
|
|
75
|
+
To install `react-router-dom`, run:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm install react-router-dom
|
|
79
|
+
```
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare const
|
|
1
|
+
export declare const apiGet: <TData = unknown>(route: string, options?: Record<string, any>, params?: {}) => Promise<TData>;
|
|
2
|
+
export declare const apiPost: <TData = unknown>(route: string, data: {
|
|
3
|
+
[key: string]: any;
|
|
4
|
+
}, options?: Record<string, any>, params?: {}) => Promise<TData>;
|
|
5
|
+
export declare const apiPut: <TData = unknown>(route: string, data?: {}, options?: Record<string, any>, params?: {}) => Promise<TData>;
|
|
6
|
+
export declare const apiDelete: <TData = unknown>(route: string, data?: {}, options?: Record<string, any>, params?: {}) => Promise<TData>;
|
package/dist/api/apiFunctions.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { assembleOptions } from "../utils/queryHelpers";
|
|
1
|
+
import { assembleOptions } from "../reactQuery/queryHelpers";
|
|
3
2
|
import axiosInstance from "./axiosInstance";
|
|
3
|
+
// Note: The transactionId is now added automatically via the axios interceptor.
|
|
4
4
|
export const apiGet = async (route, options = {}, params = {}) => {
|
|
5
5
|
let url = route;
|
|
6
6
|
const optionsString = assembleOptions(options);
|
|
@@ -41,6 +41,7 @@ export const apiDelete = async (route, data = {}, options = {}, params = {}) =>
|
|
|
41
41
|
const response = await axiosInstance.delete(url, {
|
|
42
42
|
data,
|
|
43
43
|
params,
|
|
44
|
+
validateStatus: (status) => status < 500,
|
|
44
45
|
});
|
|
45
46
|
return response.data;
|
|
46
47
|
};
|
package/dist/api/auth.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
export const performLogout = () => {
|
|
3
|
+
localStorage.removeItem("accessToken");
|
|
4
|
+
localStorage.removeItem("user");
|
|
5
|
+
localStorage.removeItem("refreshToken");
|
|
6
|
+
window.location.href = "/";
|
|
7
|
+
};
|
|
8
|
+
export const fetchPublicToken = async (baseURL) => {
|
|
9
|
+
try {
|
|
10
|
+
const response = await axios.post(`${baseURL}/auth/public`, null, {
|
|
11
|
+
headers: { "Content-Type": "application/json" },
|
|
12
|
+
});
|
|
13
|
+
localStorage.setItem("accessToken", response.data.data.tokens.access);
|
|
14
|
+
localStorage.setItem("refreshToken", response.data.data.tokens.refresh);
|
|
15
|
+
return response.data.data.tokens.access;
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
console.error("Failed to fetch public token:", error);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export const refreshAccessToken = async (baseURL) => {
|
|
23
|
+
const refreshToken = localStorage.getItem("refreshToken");
|
|
24
|
+
if (!refreshToken)
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
const response = await axios.post(`${baseURL}/auth/refresh`, null, {
|
|
28
|
+
headers: {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
Authorization: `Bearer ${refreshToken}`,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
if (response.data?.data?.tokens?.access) {
|
|
34
|
+
localStorage.setItem("accessToken", response.data.data.tokens.access);
|
|
35
|
+
return response.data.data.tokens.access;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error("Failed to refresh token:", error);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
};
|
|
@@ -1,139 +1,58 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// Assemble the base URL based on environment variables
|
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
|
3
|
+
import { performLogout, fetchPublicToken, refreshAccessToken } from "./auth";
|
|
4
|
+
// Build base URL from environment
|
|
6
5
|
const fullHostName = window.location.hostname.toUpperCase();
|
|
7
6
|
const hostName = fullHostName.split(".");
|
|
8
7
|
const host = "VITE_API_" + hostName[0];
|
|
9
8
|
const baseURL = import.meta.env[host] || import.meta.env.VITE_API;
|
|
10
|
-
// Initialize axios instance with base configurations
|
|
11
9
|
const axiosInstance = axios.create({
|
|
12
10
|
baseURL,
|
|
13
|
-
headers: {
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
timeout: 10000, // Optional: Set a timeout for requests
|
|
11
|
+
headers: { "Content-Type": "application/json" },
|
|
12
|
+
timeout: 180000,
|
|
17
13
|
});
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
localStorage.setItem("refreshToken", response.data.data.tokens.refresh);
|
|
26
|
-
return response.data.data.tokens.access;
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
console.error("Failed to fetch public token:", error);
|
|
30
|
-
Sentry.captureMessage("Failed to fetch public token Error", {
|
|
31
|
-
level: "error",
|
|
32
|
-
tags: {
|
|
33
|
-
errorType: "API",
|
|
34
|
-
authentication: "failed",
|
|
35
|
-
},
|
|
36
|
-
extra: {
|
|
37
|
-
message: "Failed to fetch public token",
|
|
38
|
-
details: error instanceof Error ? error.message : error,
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return null;
|
|
43
|
-
};
|
|
44
|
-
// Function to refresh the access token using the refresh token
|
|
45
|
-
const refreshAccessToken = async () => {
|
|
46
|
-
const refreshToken = localStorage.getItem("refreshToken");
|
|
47
|
-
if (refreshToken) {
|
|
48
|
-
try {
|
|
49
|
-
const response = await axios.post(`${baseURL}/auth/refresh`, null, {
|
|
50
|
-
headers: {
|
|
51
|
-
"Content-Type": "application/json",
|
|
52
|
-
Authorization: `Bearer ${refreshToken}`,
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
if (response.data?.data?.tokens?.access) {
|
|
56
|
-
localStorage.setItem("accessToken", response.data.data.tokens.access);
|
|
57
|
-
return response.data.data.tokens.access;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
console.error("Failed to refresh token:", error);
|
|
62
|
-
Sentry.captureMessage("Failed to fetch refresh token Error", {
|
|
63
|
-
level: "error",
|
|
64
|
-
tags: {
|
|
65
|
-
errorType: "API",
|
|
66
|
-
authentication: "failed",
|
|
67
|
-
},
|
|
68
|
-
extra: {
|
|
69
|
-
message: "Failed to fetch refresh token",
|
|
70
|
-
details: error instanceof Error ? error.message : error,
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return null;
|
|
76
|
-
};
|
|
77
|
-
// Request interceptor to add Authorization header
|
|
14
|
+
// Add transactionId to requests
|
|
15
|
+
axiosInstance.interceptors.request.use((config) => {
|
|
16
|
+
config.params = config.params || {};
|
|
17
|
+
config.params.transactionId = uuidv4();
|
|
18
|
+
return config;
|
|
19
|
+
});
|
|
20
|
+
// Add Authorization header
|
|
78
21
|
axiosInstance.interceptors.request.use(async (config) => {
|
|
79
22
|
let token;
|
|
80
23
|
const userString = localStorage.getItem("user");
|
|
81
24
|
if (userString) {
|
|
82
|
-
// If 'user' exists in localStorage, use the 'accessToken'
|
|
83
25
|
token = localStorage.getItem("accessToken");
|
|
84
26
|
}
|
|
85
27
|
else {
|
|
86
|
-
|
|
87
|
-
token = await fetchPublicToken();
|
|
28
|
+
token = await fetchPublicToken(baseURL);
|
|
88
29
|
}
|
|
89
30
|
if (token) {
|
|
90
31
|
config.headers["Authorization"] = `Bearer ${token}`;
|
|
91
32
|
}
|
|
92
33
|
return config;
|
|
93
|
-
}, (error) => {
|
|
94
|
-
Sentry.captureMessage("Axios Instance request error", {
|
|
95
|
-
level: "error",
|
|
96
|
-
tags: {
|
|
97
|
-
errorType: "API",
|
|
98
|
-
authentication: "failed",
|
|
99
|
-
},
|
|
100
|
-
extra: {
|
|
101
|
-
message: "Axios Instance request error",
|
|
102
|
-
details: error instanceof Error ? error.message : error,
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
return Promise.reject(error);
|
|
106
34
|
});
|
|
107
|
-
//
|
|
35
|
+
// Delay (optional)
|
|
36
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
37
|
+
axiosInstance.interceptors.request.use(async (config) => {
|
|
38
|
+
await delay(1);
|
|
39
|
+
return config;
|
|
40
|
+
});
|
|
41
|
+
// Handle 401
|
|
108
42
|
axiosInstance.interceptors.response.use((response) => response, async (error) => {
|
|
109
43
|
const originalRequest = error.config;
|
|
110
|
-
// Handle 401 Unauthorized errors
|
|
111
44
|
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
112
45
|
originalRequest._retry = true;
|
|
113
|
-
|
|
114
|
-
const newToken = await refreshAccessToken();
|
|
46
|
+
const newToken = await refreshAccessToken(baseURL);
|
|
115
47
|
if (newToken) {
|
|
116
|
-
// Set the new token in the headers and retry the request
|
|
117
48
|
originalRequest.headers["Authorization"] = `Bearer ${newToken}`;
|
|
118
49
|
return axiosInstance(originalRequest);
|
|
119
50
|
}
|
|
120
51
|
else {
|
|
121
|
-
|
|
122
|
-
|
|
52
|
+
if (localStorage.getItem("user"))
|
|
53
|
+
performLogout();
|
|
123
54
|
}
|
|
124
55
|
}
|
|
125
|
-
Sentry.captureMessage("Axios Instance response error", {
|
|
126
|
-
level: "error",
|
|
127
|
-
tags: {
|
|
128
|
-
errorType: "API",
|
|
129
|
-
authentication: "failed",
|
|
130
|
-
},
|
|
131
|
-
extra: {
|
|
132
|
-
message: "Axios Instance response error",
|
|
133
|
-
status: error.response?.status,
|
|
134
|
-
details: error instanceof Error ? error.message : error,
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
56
|
return Promise.reject(error);
|
|
138
57
|
});
|
|
139
58
|
export default axiosInstance;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useMutation } from "@tanstack/react-query";
|
|
2
|
+
import { apiGet } from "./apiFunctions";
|
|
3
|
+
const useCheckSsoAuth = () => useMutation({
|
|
4
|
+
mutationFn: async ({ protocol, hostname, environment, }) => {
|
|
5
|
+
const domainName = `${protocol}//${hostname}`;
|
|
6
|
+
environment =
|
|
7
|
+
environment === "development"
|
|
8
|
+
? "DEV"
|
|
9
|
+
: environment.toUpperCase();
|
|
10
|
+
const response = (await apiGet("/domains", {
|
|
11
|
+
fields: [
|
|
12
|
+
"ClientAuthentications.uuid",
|
|
13
|
+
"ClientAuthentications.type",
|
|
14
|
+
"Apps.uuid",
|
|
15
|
+
"uuid",
|
|
16
|
+
],
|
|
17
|
+
join: [
|
|
18
|
+
{
|
|
19
|
+
Environments: {
|
|
20
|
+
"Environments.id": "Domains.environmentId",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
ClientAuthentications: {
|
|
25
|
+
"ClientAuthentications.clientId": "Domains.clientId",
|
|
26
|
+
"ClientAuthentications.environmentId": "Domains.environmentId",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
Apps: {
|
|
31
|
+
"Apps.id": "Domains.appId",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
where: {
|
|
36
|
+
and: [
|
|
37
|
+
{
|
|
38
|
+
"Domains.domain": {
|
|
39
|
+
like: domainName,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"Environments.slug": {
|
|
44
|
+
like: environment,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
if (response?.data?.domains?.length > 0) {
|
|
51
|
+
const clientConfig = response.data.domains[0];
|
|
52
|
+
if (clientConfig.ClientAuthentications?.type === "SSO") {
|
|
53
|
+
// Get SSO URL
|
|
54
|
+
const ssoResponse = (await apiGet("/client-authentications/singleSignOnServiceUrl", {
|
|
55
|
+
uuid: clientConfig.ClientAuthentications.uuid,
|
|
56
|
+
domainUuid: clientConfig.uuid,
|
|
57
|
+
}));
|
|
58
|
+
return ssoResponse;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
export default useCheckSsoAuth;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const UserLoginRequiredEvent: Event;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const UserLoginRequiredEvent = new Event("UserLoginRequired");
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function getData(slug: string, fields?: string[]): Promise<any[]>;
|
|
2
|
+
export declare function saveData(slug: string, payload: Record<string, any>, returnPayloadDepth?: boolean): Promise<unknown>;
|
|
3
|
+
export declare function updateData(slug: string, uuid: string, payload: Record<string, any>, returnPayloadDepth?: boolean): Promise<unknown>;
|
|
4
|
+
export declare function deleteData(slug: string, uuid: string): Promise<unknown>;
|
|
5
|
+
export declare function deleteAddress(uuid: string): Promise<unknown>;
|
|
6
|
+
export declare function fetchCoreParameters(): Promise<any>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { apiGet, apiPost, apiPut, apiDelete } from "./apiFunctions";
|
|
2
|
+
import { toCamelCase } from "../reactQuery/queryHelpers";
|
|
3
|
+
import * as Sentry from "@sentry/react";
|
|
4
|
+
//Generic component to get all the data from Api based on slug and fields requested for
|
|
5
|
+
export async function getData(slug, fields) {
|
|
6
|
+
const output = [];
|
|
7
|
+
const recordsPerPage = 1000;
|
|
8
|
+
let page = 0;
|
|
9
|
+
let hasNextPage = true;
|
|
10
|
+
const camelCaseSlug = toCamelCase(slug);
|
|
11
|
+
const fieldsOptions = typeof fields !== "undefined" && fields.length > 0
|
|
12
|
+
? fields
|
|
13
|
+
: ["uuid", "name"];
|
|
14
|
+
try {
|
|
15
|
+
while (hasNextPage) {
|
|
16
|
+
page++;
|
|
17
|
+
const options = {
|
|
18
|
+
fields: fieldsOptions,
|
|
19
|
+
recordsPerPage: recordsPerPage,
|
|
20
|
+
page: page,
|
|
21
|
+
};
|
|
22
|
+
const response = await apiGet(`/${slug}`, options);
|
|
23
|
+
const { data, meta } = response;
|
|
24
|
+
if (data && data[camelCaseSlug]) {
|
|
25
|
+
output.push(...data[camelCaseSlug]);
|
|
26
|
+
}
|
|
27
|
+
hasNextPage = meta.nextPage;
|
|
28
|
+
}
|
|
29
|
+
return output;
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
Sentry.captureMessage("Error with getData api call", {
|
|
33
|
+
level: "error",
|
|
34
|
+
tags: {
|
|
35
|
+
errorType: "API",
|
|
36
|
+
},
|
|
37
|
+
extra: {
|
|
38
|
+
details: error,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
console.error("Error fetching data:", error);
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//The global function to save all the data based on the payload , slug
|
|
46
|
+
export async function saveData(slug, payload, returnPayloadDepth) {
|
|
47
|
+
const response = await apiPost(`/${slug}${returnPayloadDepth ? "?depth=-1" : ""}`, payload);
|
|
48
|
+
return response;
|
|
49
|
+
}
|
|
50
|
+
//The global function to update all the data based on the payload , slug and uuid
|
|
51
|
+
export async function updateData(slug, uuid, payload, returnPayloadDepth) {
|
|
52
|
+
const response = await apiPut(`/${slug}/${uuid}` + (returnPayloadDepth ? "?depth=-1" : ""), payload);
|
|
53
|
+
return response;
|
|
54
|
+
}
|
|
55
|
+
//The global function to delete all the data based on the payload , slug and uuid
|
|
56
|
+
export async function deleteData(slug, uuid) {
|
|
57
|
+
const response = await apiDelete(`/${slug}/${uuid}`);
|
|
58
|
+
return response;
|
|
59
|
+
}
|
|
60
|
+
export async function deleteAddress(uuid) {
|
|
61
|
+
const response = await apiDelete("/addresses/" + uuid);
|
|
62
|
+
return response;
|
|
63
|
+
}
|
|
64
|
+
//Api call to fetch the core parameters to look for database changes for all Assortments/Bundles
|
|
65
|
+
export async function fetchCoreParameters() {
|
|
66
|
+
const options = {
|
|
67
|
+
fields: ["value"],
|
|
68
|
+
key: "META_LAST_REFRESH_DATETIME",
|
|
69
|
+
};
|
|
70
|
+
const response = (await apiGet("/core-parameters", options));
|
|
71
|
+
return response?.data?.coreParameters;
|
|
72
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Options } from "./types";
|
|
2
|
+
declare const useHandleSamlAuth: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
|
|
3
|
+
samlEncoded: string;
|
|
4
|
+
extraParams?: Record<string, any>;
|
|
5
|
+
options?: Options;
|
|
6
|
+
}, unknown>;
|
|
7
|
+
export default useHandleSamlAuth;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useMutation } from "@tanstack/react-query";
|
|
2
|
+
import { apiPost } from "../api/apiFunctions";
|
|
3
|
+
function decodeBase64ToUtf8(b64) {
|
|
4
|
+
// Browser path
|
|
5
|
+
if (typeof globalThis.atob === "function") {
|
|
6
|
+
const binary = globalThis.atob(b64);
|
|
7
|
+
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
8
|
+
return new TextDecoder().decode(bytes);
|
|
9
|
+
}
|
|
10
|
+
// Node/SSR fallback
|
|
11
|
+
if (typeof Buffer !== "undefined") {
|
|
12
|
+
return Buffer.from(b64, "base64").toString();
|
|
13
|
+
}
|
|
14
|
+
throw new Error("Base64 decoding not supported in this environment");
|
|
15
|
+
}
|
|
16
|
+
const useHandleSamlAuth = () => {
|
|
17
|
+
return useMutation({
|
|
18
|
+
mutationFn: async ({ samlEncoded, extraParams, options, }) => {
|
|
19
|
+
const decodedSaml = decodeBase64ToUtf8(samlEncoded);
|
|
20
|
+
const saml = JSON.parse(decodedSaml);
|
|
21
|
+
const response = (await apiPost(`/auth/${saml.auth}`, { ...saml.payload, ...extraParams }, options ?? {}));
|
|
22
|
+
return response;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
export default useHandleSamlAuth;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { BaseButtonProps } from "./BaseButton.types";
|
|
3
|
-
declare const BaseButton: React.
|
|
3
|
+
declare const BaseButton: React.ForwardRefExoticComponent<BaseButtonProps & React.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
|
|
4
4
|
export default BaseButton;
|
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
? "cursor-not-allowed opacity-50"
|
|
10
|
-
: "cursor-pointer";
|
|
11
|
-
const textStyleClasses = `${fontFamily}`;
|
|
12
|
-
const buttonShapeClasses = shape;
|
|
13
|
-
const buttonClasses = `
|
|
14
|
-
${baseBaseButtonClasses}
|
|
15
|
-
${buttonColorClasses}
|
|
16
|
-
${buttonShapeClasses}
|
|
17
|
-
${textStyleClasses}
|
|
18
|
-
${hoverClasses}
|
|
19
|
-
${cursorClasses}
|
|
20
|
-
${hasShadow ? "shadow-md" : ""}
|
|
21
|
-
${customWidth}
|
|
22
|
-
${customHeight}
|
|
23
|
-
${additionalClasses}
|
|
24
|
-
`.trim();
|
|
2
|
+
import React from "react";
|
|
3
|
+
const BaseButton = React.forwardRef(({ onClick, text, fontFamily, fontColor, fontSize, shape, buttonSize, backgroundColor, borderColor, iconOrder, icon, iconBreakpoint, textBreakpoint, textAdditionalClasses, disabledButtonClasses, additionalClasses = "justify-center", type = "button", href, to, isDisabled = false, as: asProp = "a", hoverBackground, hoverBorderColor, hoverFontColor, iconAriaLabel, iconClasses, ariaSelected, ariaRole, ariaControls, tabIndex, onKeyDown, dataTestId, linkComponent: LinkComponent, ...rest }, ref) => {
|
|
4
|
+
const textClasses = `${fontFamily ?? ""} ${fontSize ?? ""} ${textBreakpoint ?? ""} ${textAdditionalClasses ?? ""}`;
|
|
5
|
+
const buttonClasses = `flex ${textClasses} ${iconOrder === "last" ? "flex-row-reverse" : ""} items-center ${shape ?? ""} ${buttonSize ?? ""} ${additionalClasses} ${isDisabled
|
|
6
|
+
? `cursor-not-allowed ${disabledButtonClasses ?? ""}`
|
|
7
|
+
: `cursor-pointer ${borderColor ?? ""} ${backgroundColor ?? ""} ${hoverBackground ?? ""} ${hoverBorderColor ?? ""} ${fontColor ?? ""} ${hoverFontColor ?? ""}`}`;
|
|
8
|
+
const iconClassNames = `${iconClasses ?? ""} ${iconBreakpoint ?? ""}`;
|
|
25
9
|
const handleClick = (e) => {
|
|
26
10
|
if (isDisabled) {
|
|
27
11
|
e.preventDefault();
|
|
@@ -32,18 +16,29 @@ const BaseButton = ({ onClick, text, fontFamily, backgroundColor, customWidth, c
|
|
|
32
16
|
const baseProps = {
|
|
33
17
|
className: buttonClasses,
|
|
34
18
|
onClick: handleClick,
|
|
35
|
-
"aria-disabled": isDisabled ? "true" :
|
|
19
|
+
"aria-disabled": isDisabled ? "true" : undefined,
|
|
20
|
+
role: ariaRole,
|
|
21
|
+
"aria-selected": ariaSelected,
|
|
22
|
+
"aria-controls": ariaControls,
|
|
23
|
+
tabIndex,
|
|
24
|
+
onKeyDown,
|
|
25
|
+
"aria-label": iconAriaLabel ? `${iconAriaLabel}` : undefined,
|
|
26
|
+
"data-testid": dataTestId,
|
|
27
|
+
ref,
|
|
28
|
+
...rest,
|
|
36
29
|
};
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
let ComponentToRender = asProp;
|
|
31
|
+
let elementProps = { ...baseProps };
|
|
32
|
+
if (asProp === "a" && href) {
|
|
33
|
+
elementProps.href = href;
|
|
40
34
|
}
|
|
41
|
-
else if (
|
|
42
|
-
|
|
35
|
+
else if (asProp === "button") {
|
|
36
|
+
elementProps.type = type;
|
|
43
37
|
}
|
|
44
|
-
else {
|
|
45
|
-
|
|
38
|
+
else if (asProp === "link" && LinkComponent && to) {
|
|
39
|
+
ComponentToRender = LinkComponent;
|
|
40
|
+
elementProps.to = to;
|
|
46
41
|
}
|
|
47
|
-
return (_jsxs(
|
|
48
|
-
};
|
|
42
|
+
return (_jsxs(ComponentToRender, { ...elementProps, children: [icon && _jsx("span", { className: iconClassNames, children: icon }), text] }));
|
|
43
|
+
});
|
|
49
44
|
export default BaseButton;
|