@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.
Files changed (101) hide show
  1. package/README.md +30 -26
  2. package/dist/api/apiFunctions.d.ts +6 -5
  3. package/dist/api/apiFunctions.js +3 -2
  4. package/dist/api/auth.d.ts +3 -0
  5. package/dist/api/auth.js +42 -0
  6. package/dist/api/axiosInstance.d.ts +0 -1
  7. package/dist/api/axiosInstance.js +23 -104
  8. package/dist/api/checkSsoAuth.d.ts +6 -0
  9. package/dist/api/checkSsoAuth.js +64 -0
  10. package/dist/api/events.d.ts +1 -0
  11. package/dist/api/events.js +1 -0
  12. package/dist/api/genericApi.d.ts +6 -0
  13. package/dist/api/genericApi.js +72 -0
  14. package/dist/api/handleSamlAuth.d.ts +7 -0
  15. package/dist/api/handleSamlAuth.js +26 -0
  16. package/dist/api/types.d.ts +13 -0
  17. package/dist/api/types.js +1 -0
  18. package/dist/components/BaseButton/BaseButton.d.ts +1 -1
  19. package/dist/components/BaseButton/BaseButton.js +28 -33
  20. package/dist/components/BaseButton/BaseButton.stories.js +127 -60
  21. package/dist/components/BaseButton/BaseButton.types.d.ts +22 -8
  22. package/dist/components/DropDownIconButton/DropDownIconButton.stories.js +34 -22
  23. package/dist/components/DynamicSection/DynamicSection.d.ts +3 -0
  24. package/dist/components/DynamicSection/DynamicSection.js +31 -0
  25. package/dist/components/DynamicSection/DynamicSection.stories.d.ts +6 -0
  26. package/dist/components/DynamicSection/DynamicSection.stories.js +144 -0
  27. package/dist/components/DynamicSection/index.d.ts +2 -0
  28. package/dist/components/DynamicSection/index.js +2 -0
  29. package/dist/components/DynamicSection/types.d.ts +85 -0
  30. package/dist/components/DynamicSection/types.js +1 -0
  31. package/dist/components/FeatureList/FeatureList.d.ts +4 -0
  32. package/dist/components/FeatureList/FeatureList.js +10 -0
  33. package/dist/components/FeatureList/FeatureList.stories.d.ts +7 -0
  34. package/dist/components/FeatureList/FeatureList.stories.js +115 -0
  35. package/dist/components/FeatureList/index.d.ts +1 -0
  36. package/dist/components/FeatureList/index.js +1 -0
  37. package/dist/components/FeatureList/types.d.ts +27 -0
  38. package/dist/components/FeatureList/types.js +1 -0
  39. package/dist/components/GetSupport/GetSupport.js +2 -2
  40. package/dist/components/GetSupport/GetSupport.stories.js +1 -1
  41. package/dist/components/GetSupport/GetSupport.test.js +30 -30
  42. package/dist/components/GetSupport/GetSupport.types.d.ts +1 -2
  43. package/dist/components/HamburgerButton/Hamburger.stories.d.ts +2 -2
  44. package/dist/components/HamburgerButton/Hamburger.stories.js +30 -30
  45. package/dist/components/InfoBanner/InfoBanner.d.ts +4 -0
  46. package/dist/components/InfoBanner/InfoBanner.js +7 -0
  47. package/dist/components/InfoBanner/InfoBanner.stories.d.ts +8 -0
  48. package/dist/components/InfoBanner/InfoBanner.stories.js +65 -0
  49. package/dist/components/InfoBanner/index.d.ts +2 -0
  50. package/dist/components/InfoBanner/index.js +2 -0
  51. package/dist/components/InfoBanner/types.d.ts +19 -0
  52. package/dist/components/InfoBanner/types.js +1 -0
  53. package/dist/components/InitialsAvatar/InitialsAvatar.d.ts +4 -0
  54. package/dist/components/InitialsAvatar/InitialsAvatar.js +8 -0
  55. package/dist/components/InitialsAvatar/InitialsAvatar.stories.d.ts +8 -0
  56. package/dist/components/InitialsAvatar/InitialsAvatar.stories.js +61 -0
  57. package/dist/components/InitialsAvatar/InitialsAvatar.types.d.ts +6 -0
  58. package/dist/components/InitialsAvatar/InitialsAvatar.types.js +1 -0
  59. package/dist/components/NotesList/NoteItem.d.ts +4 -0
  60. package/dist/components/NotesList/NoteItem.js +9 -0
  61. package/dist/components/NotesList/NotesList.d.ts +4 -0
  62. package/dist/components/NotesList/NotesList.js +7 -0
  63. package/dist/components/NotesList/NotesList.stories.d.ts +8 -0
  64. package/dist/components/NotesList/NotesList.stories.js +129 -0
  65. package/dist/components/NotesList/types.d.ts +50 -0
  66. package/dist/components/NotesList/types.js +1 -0
  67. package/dist/components/SearchInput/BaseSearchInput.d.ts +4 -0
  68. package/dist/components/SearchInput/BaseSearchInput.js +21 -0
  69. package/dist/components/SearchInput/SearchInput.types.d.ts +31 -0
  70. package/dist/components/TabList/TabList.d.ts +3 -0
  71. package/dist/components/TabList/TabList.js +45 -0
  72. package/dist/components/TabList/TabList.stories.d.ts +6 -0
  73. package/dist/components/TabList/TabList.stories.js +95 -0
  74. package/dist/components/TabList/index.d.ts +1 -0
  75. package/dist/components/TabList/index.js +1 -0
  76. package/dist/components/TabList/types.d.ts +16 -0
  77. package/dist/components/TabList/types.js +1 -0
  78. package/dist/hooks/index.d.ts +0 -1
  79. package/dist/hooks/index.js +0 -1
  80. package/dist/main.css +1 -0
  81. package/dist/reactQuery/index.d.ts +0 -0
  82. package/dist/reactQuery/index.js +0 -0
  83. package/dist/reactQuery/queryHelpers.d.ts +54 -0
  84. package/dist/reactQuery/queryHelpers.js +132 -0
  85. package/dist/reactQuery/useApiMutation.d.ts +2 -0
  86. package/dist/reactQuery/useApiMutation.js +24 -0
  87. package/dist/reactQuery/useApiQuery.d.ts +2 -0
  88. package/dist/reactQuery/useApiQuery.js +10 -0
  89. package/dist/utils/formatCurrency.d.ts +2 -0
  90. package/dist/utils/formatCurrency.js +13 -0
  91. package/dist/utils/formatDate.d.ts +2 -0
  92. package/dist/utils/formatDate.js +8 -0
  93. package/dist/utils/formatTimestamp.d.ts +2 -0
  94. package/dist/utils/formatTimestamp.js +40 -0
  95. package/dist/utils/index.d.ts +16 -0
  96. package/dist/utils/index.js +16 -0
  97. package/dist/utils/roundNumToDecimalPlaces.d.ts +2 -0
  98. package/dist/utils/roundNumToDecimalPlaces.js +21 -0
  99. package/dist/utils/validateEmailFormat.d.ts +15 -0
  100. package/dist/utils/validateEmailFormat.js +21 -0
  101. 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
- DaisyUI
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
- 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.
39
+ ## To Deploy Changes In Blox
60
40
 
61
- To install `react-router-dom`, run:
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
- import { Options } from "../utils/queryHelpers";
2
- export declare const apiGet: <TData = unknown>(route: string, options?: Options, params?: Record<string, any>) => Promise<TData>;
3
- export declare const apiPost: <TData = unknown>(route: string, data: Record<string, any>, options?: Options, params?: Record<string, any>) => Promise<TData>;
4
- export declare const apiPut: <TData = unknown>(route: string, data?: Record<string, any>, options?: Options, params?: Record<string, any>) => Promise<TData>;
5
- export declare const apiDelete: <TData = unknown>(route: string, data?: Record<string, any>, options?: Options, params?: Record<string, any>) => Promise<TData>;
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>;
@@ -1,6 +1,6 @@
1
- // src/api/apiFunctions.ts
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
  };
@@ -0,0 +1,3 @@
1
+ export declare const performLogout: () => void;
2
+ export declare const fetchPublicToken: (baseURL: string) => Promise<string | null>;
3
+ export declare const refreshAccessToken: (baseURL: string) => Promise<string | null>;
@@ -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,3 +1,2 @@
1
- export declare const UserLoginRequiredEvent: Event;
2
1
  declare const axiosInstance: import("axios").AxiosInstance;
3
2
  export default axiosInstance;
@@ -1,139 +1,58 @@
1
1
  import axios from "axios";
2
- import * as Sentry from "@sentry/react";
3
- // Event to indicate when user login is required
4
- export const UserLoginRequiredEvent = new Event("UserLoginRequired");
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
- "Content-Type": "application/json",
15
- },
16
- timeout: 10000, // Optional: Set a timeout for requests
11
+ headers: { "Content-Type": "application/json" },
12
+ timeout: 180000,
17
13
  });
18
- // Function to fetch a public access token for unauthenticated requests
19
- const fetchPublicToken = async () => {
20
- try {
21
- const response = await axios.post(`${baseURL}/auth/public`, null, {
22
- headers: { "Content-Type": "application/json" },
23
- });
24
- localStorage.setItem("accessToken", response.data.data.tokens.access);
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
- // If no 'user' exists, fetch the public token
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
- // Response interceptor to handle 401 errors
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
- // Attempt to refresh the access token
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
- // If refresh fails, trigger login required event
122
- window.dispatchEvent(UserLoginRequiredEvent);
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,6 @@
1
+ declare const useCheckSsoAuth: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
2
+ protocol: string;
3
+ hostname: string;
4
+ environment: string;
5
+ }, unknown>;
6
+ export default useCheckSsoAuth;
@@ -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,13 @@
1
+ export interface Options {
2
+ fields?: any;
3
+ where?: any;
4
+ join?: any;
5
+ ojoin?: any;
6
+ sort?: any;
7
+ [key: string]: any;
8
+ }
9
+ export interface SamlData {
10
+ auth: string;
11
+ payload: any;
12
+ options?: Options;
13
+ }
@@ -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.FC<BaseButtonProps>;
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
- const BaseButton = ({ onClick, text, fontFamily, backgroundColor, customWidth, customHeight, shape, borderColor, icon, additionalClasses, type = "button", to, href, isDisabled = false, hasShadow, as: Element = "button", hoverBackground, hoverFontColor, hoverUnderline = false, hoverBorderColor, iconClasses, ...props }) => {
3
- const baseBaseButtonClasses = "flex items-center justify-center";
4
- const hoverClasses = !isDisabled
5
- ? `${hoverBackground} ${hoverFontColor} ${hoverUnderline ? "underline underline-offset-4" : ""} ${hoverBorderColor}`
6
- : "";
7
- const buttonColorClasses = `${backgroundColor} ${borderColor}`;
8
- const cursorClasses = isDisabled
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" : "false",
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 ElementProps = { ...baseProps };
38
- if (Element === "a" && href) {
39
- ElementProps = { ...baseProps, href };
30
+ let ComponentToRender = asProp;
31
+ let elementProps = { ...baseProps };
32
+ if (asProp === "a" && href) {
33
+ elementProps.href = href;
40
34
  }
41
- else if (Element === "button") {
42
- ElementProps = { ...baseProps, type };
35
+ else if (asProp === "button") {
36
+ elementProps.type = type;
43
37
  }
44
- else {
45
- ElementProps = { ...baseProps };
38
+ else if (asProp === "link" && LinkComponent && to) {
39
+ ComponentToRender = LinkComponent;
40
+ elementProps.to = to;
46
41
  }
47
- return (_jsxs(Element, { ...ElementProps, ...props, children: [icon && _jsx("span", { className: iconClasses, children: icon }), text] }));
48
- };
42
+ return (_jsxs(ComponentToRender, { ...elementProps, children: [icon && _jsx("span", { className: iconClassNames, children: icon }), text] }));
43
+ });
49
44
  export default BaseButton;