robobyte-front-builder 1.0.0 → 1.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "robobyte-front-builder",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "RoboByte low-code UI builder, Report builder, and navigation extension system",
5
5
  "main": "src/lib/index.js",
6
6
  "files": [
@@ -30,9 +30,16 @@
30
30
  "react": ">=18",
31
31
  "react-dom": ">=18",
32
32
  "next": ">=13",
33
- "@mui/material": ">=6",
34
- "@mui/icons-material": ">=6",
33
+ "@mui/material": ">=7",
34
+ "@mui/icons-material": ">=7",
35
+ "@mui/lab": ">=7",
36
+ "@mui/system": ">=7",
37
+ "@mui/x-data-grid": ">=7",
38
+ "@mui/x-date-pickers": ">=7",
39
+ "@mui/x-tree-view": ">=7",
40
+ "@emotion/cache": ">=11",
35
41
  "@emotion/react": ">=11",
42
+ "@emotion/server": ">=11",
36
43
  "@emotion/styled": ">=11",
37
44
  "axios": ">=1"
38
45
  },
@@ -47,10 +54,6 @@
47
54
  "@dnd-kit/core": "^6.3.1",
48
55
  "@dnd-kit/sortable": "^10.0.0",
49
56
  "@dnd-kit/utilities": "^3.2.2",
50
- "@emotion/cache": "11.11.0",
51
- "@emotion/react": "^11.14.0",
52
- "@emotion/server": "11.11.0",
53
- "@emotion/styled": "^11.14.0",
54
57
  "@fullcalendar/common": "5.11.5",
55
58
  "@fullcalendar/core": "6.1.7",
56
59
  "@fullcalendar/daygrid": "6.1.7",
@@ -59,17 +62,8 @@
59
62
  "@fullcalendar/react": "6.1.7",
60
63
  "@fullcalendar/timegrid": "6.1.7",
61
64
  "@hookform/resolvers": "3.1.0",
62
- "@material-ui/core": "^4.12.4",
63
65
  "@microsoft/signalr": "^8.0.0",
64
66
  "@monaco-editor/react": "^4.7.0",
65
- "@mui/icons-material": "^7.1.0",
66
- "@mui/lab": "^7.0.0-beta.12",
67
- "@mui/material": "^7.1.0",
68
- "@mui/styled-engine-sc": "^6.0.0-alpha.18",
69
- "@mui/system": "^7.1.0",
70
- "@mui/x-data-grid": "^8.5.0",
71
- "@mui/x-date-pickers": "^5.0.0",
72
- "@mui/x-tree-view": "^8.5.0",
73
67
  "@popperjs/core": "2.11.7",
74
68
  "@react-google-maps/api": "^2.19.2",
75
69
  "@reduxjs/toolkit": "1.9.5",
@@ -79,7 +73,6 @@
79
73
  "ag-grid-react": "^33.3.2",
80
74
  "apexcharts-clevision": "3.28.5",
81
75
  "aws-amplify": "^5.3.13",
82
- "axios": "1.4.0",
83
76
  "axios-mock-adapter": "1.21.4",
84
77
  "babel-eslint": "10.1.0",
85
78
  "chart.js": "4.3.0",
@@ -105,21 +98,18 @@
105
98
  "mdi-material-ui": "7.7.0",
106
99
  "moment": "^2.30.1",
107
100
  "moment-timezone": "^0.5.47",
108
- "next": "^15.1.8",
109
101
  "notistack": "^3.0.2",
110
102
  "nprogress": "0.2.0",
111
103
  "numeral": "^2.0.6",
112
104
  "payment": "2.4.6",
113
105
  "prismjs": "1.29.0",
114
106
  "prop-types": "^15.8.1",
115
- "react": "^19.1.0",
116
107
  "react-apexcharts": "1.4.0",
117
108
  "react-beautiful-dnd": "13.1.1",
118
109
  "react-chartjs-2": "5.2.0",
119
110
  "react-colorful": "^5.6.1",
120
111
  "react-credit-cards": "0.8.3",
121
112
  "react-datepicker": "4.11.0",
122
- "react-dom": "^19.1.0",
123
113
  "react-draft-wysiwyg": "1.15.0",
124
114
  "react-dropzone": "14.2.3",
125
115
  "react-hook-form": "7.43.9",
@@ -1,179 +1,21 @@
1
- // ** React Imports
2
- import { createContext, useEffect, useState } from 'react'
1
+ /**
2
+ * AuthContext thin pass-through context for robobyte-front-builder.
3
+ *
4
+ * All authentication logic (login, logout, token refresh) lives in the
5
+ * HOST application. The host passes `user` and `accessToken` into
6
+ * RoboByteFrontBuilderProvider, which feeds them here.
7
+ *
8
+ * Components inside the package (TAGGrid, SGrid, SystemContext, etc.)
9
+ * read from this context the same way they always did — nothing changes
10
+ * for consumers, only the source of truth moved to the host.
11
+ */
12
+ import { createContext } from 'react'
3
13
 
4
- // ** Next Import
5
- import { useRouter } from 'next/router'
6
- import PutRefreshToken from 'services/auth/PutRefreshToken'
7
- // ** Axios
8
- import axios from 'axios'
9
-
10
- // ** Config
11
- import authConfig from 'src/configs/auth'
12
- import { UsersEndpoints } from 'services/Endpoints/UsersEndpoints'
13
- import { ApiURL } from 'services/Endpoints'
14
- import { jwtDecode } from "jwt-decode";
15
- import {ReportBuilderEndpoints} from "services/Endpoints/ReportBuilderEndpoints";
16
-
17
- // ** Defaults
18
14
  const defaultProvider = {
19
15
  user: null,
20
16
  accessToken: null,
21
- loading: true,
22
- setUser: () => null,
23
- setLoading: () => Boolean,
24
- isInitialized: false,
25
- login: () => Promise.resolve(),
26
- logout: () => Promise.resolve(),
27
- setIsInitialized: () => Boolean,
28
- register: () => Promise.resolve()
29
17
  }
30
- const AuthContext = createContext(defaultProvider)
31
- const AuthProvider = ({ children }) => {
32
- // ** States
33
- const [user, setUser] = useState(defaultProvider.user)
34
- const [loading, setLoading] = useState(defaultProvider.loading)
35
- const [isInitialized, setIsInitialized] = useState(defaultProvider.isInitialized)
36
- const [token, setToken] = useState()
37
- // ** Hooks
38
- const router = useRouter()
39
- useEffect(() => {
40
- const initAuth = async () => {
41
- setIsInitialized(true)
42
- const storedToken = window.localStorage.getItem(authConfig.storageTokenKeyName)
43
- const storedRefreshToken = window.localStorage.getItem(authConfig.refreshToken)
44
- if (storedToken) {
45
- await PutRefreshToken()
46
- setLoading(true)
47
- await axios
48
- .post(ApiURL + ReportBuilderEndpoints.Post.GenericGet.URL, {
49
- tFilter : [
50
- {
51
- path :"Id",
52
- method : "Equals",
53
- value : window.localStorage.getItem(authConfig.storageUserId)
54
- }
55
- ]
56
- } ,{
57
- headers: {
58
- Authorization: 'Bearer ' + window.localStorage.getItem(authConfig.storageTokenKeyName),
59
- 'content-type': 'application/json'
60
- },
61
- params: {
62
- sourceModel : 'AuthModule.Domain.AuthModels.ApplicationUser',
63
- getType : 'Single',
64
- page : 1,
65
- pageSize: 1,
66
- userId: window.localStorage.getItem(authConfig.storageUserId)
67
- },
68
- })
69
- .then(async response => {
70
- setLoading(false)
71
- response.data.data = {
72
- ...response.data?.data,
73
- permissions : [],
74
- roles : []
75
- }
76
- setUser({ ...response.data?.data })
77
- })
78
- .catch(async e => {
79
- setLoading(false)
80
- handleLogout()
81
- })
82
- } else {
83
- setLoading(false)
84
- handleLogout()
85
- }
86
- }
87
- initAuth()
88
- }, [])
89
- const handleLogin = (params, errorCallback) => {
90
-
91
- axios
92
- .post(ApiURL + UsersEndpoints.Post.Login.URL, params)
93
- .then(async res => {
94
- window.localStorage.setItem(authConfig.storageTokenKeyName, res.data.accessToken)
95
- window.localStorage.setItem(authConfig.storageUserId, res.data.id)
96
- window.localStorage.setItem(authConfig.refreshToken, res.data.refreshToken)
97
- setToken(res.data.accessToken)
98
- })
99
- .then(() => {
100
- axios
101
- .post(ApiURL + ReportBuilderEndpoints.Post.GenericGet.URL, {
102
- tFilter : [
103
- {
104
- path :"Id",
105
- method : "Equals",
106
- value : window.localStorage.getItem(authConfig.storageUserId)
107
- }
108
- ]
109
- } ,{
110
- headers: {
111
- Authorization: 'Bearer ' + window.localStorage.getItem(authConfig.storageTokenKeyName),
112
- 'content-type': 'application/json'
113
- },
114
- params: {
115
- sourceModel : 'AuthModule.Domain.AuthModels.ApplicationUser',
116
- getType : 'Single',
117
- page : 1,
118
- pageSize: 1,
119
- userId: window.localStorage.getItem(authConfig.storageUserId)
120
- },
121
- })
122
- .then(async response => {
123
- const returnUrl = router.query.returnUrl
124
- response.data.data = {
125
- ...response.data?.data,
126
- permissions : [],
127
- roles : []
128
- }
129
- setUser({ ...response.data?.data })
130
- await window.localStorage.setItem('userData', JSON.stringify(response.data?.data))
131
- const redirectURL = returnUrl && returnUrl !== '/' ? returnUrl : '/mainHome'
132
- router.replace(redirectURL)
133
- })
134
- })
135
- .catch(err => {
136
- if (errorCallback) errorCallback(err)
137
- })
138
- }
139
-
140
- const handleLogout = () => {
141
- setUser(null)
142
- setIsInitialized(false)
143
- window.localStorage.removeItem('userData')
144
- window.localStorage.removeItem(authConfig.storageTokenKeyName)
145
- window.localStorage.removeItem(authConfig.storageUserId)
146
- window.localStorage.removeItem(authConfig.refreshToken)
147
- router.push('/login')
148
- }
149
18
 
150
- const handleRegister = (params, errorCallback) => {
151
- axios
152
- .post(authConfig.registerEndpoint, params)
153
- .then(res => {
154
- if (res.data.error) {
155
- if (errorCallback) errorCallback(res.data.error)
156
- } else {
157
- handleLogin({ email: params.email, password: params.password })
158
- }
159
- })
160
- .catch(err => (errorCallback ? errorCallback(err) : null))
161
- }
162
-
163
- const values = {
164
- user,
165
- accessToken: token,
166
- loading,
167
- setUser,
168
- setLoading,
169
- isInitialized,
170
- setIsInitialized,
171
- login: handleLogin,
172
- logout: handleLogout,
173
- register: handleRegister
174
- }
175
-
176
- return <AuthContext.Provider value={values}>{children}</AuthContext.Provider>
177
- }
19
+ const AuthContext = createContext(defaultProvider)
178
20
 
179
- export { AuthContext, AuthProvider }
21
+ export { AuthContext }
@@ -6,7 +6,8 @@ import axios from 'axios'
6
6
  // ** Axios
7
7
 
8
8
  // ** Config
9
- import {BaseURL, Endpoints, Services} from 'services/Endpoints'
9
+ import {Endpoints, Services} from 'services/Endpoints'
10
+ import {getBaseURL} from 'services/config'
10
11
  import {useJsApiLoader} from '@react-google-maps/api'
11
12
  import {AuthContext} from './AuthContext'
12
13
  import handleChange from 'services/helper/handleChange'
package/src/lib/index.js CHANGED
@@ -40,6 +40,11 @@
40
40
  * ─────────────────────────────────────────────────────────────────────────────
41
41
  */
42
42
 
43
+ // ── Configuration ─────────────────────────────────────────────────────────────
44
+ // configureRoboByte({ baseURL, apiURL, getAccessToken, getUser })
45
+ // Or pass these as props to RoboByteFrontBuilderProvider (preferred).
46
+ export { configureRoboByte, getBaseURL, getApiURL, getAccessToken, getUser } from '../services/config'
47
+
43
48
  // ── Navigation Extension API ──────────────────────────────────────────────────
44
49
  // NavigationExtensionProvider : Wrap your app to enable nav injection
45
50
  // useNavigationExtensionContext: Internal context accessor (used by the nav renderer)
@@ -72,4 +77,7 @@ export { default as ReportBuilderPage } from '../pages/reportModule/reportBuilde
72
77
  // Useful when you need to read or drive builder state from the host app.
73
78
  export { BuilderProvider, useBuilder } from '../context/BuilderContext'
74
79
  export { SystemContext, SystemProvider } from '../context/SystemContext'
75
- export { AuthContext, AuthProvider } from '../context/AuthContext'
80
+ // AuthContext is a read-only pass-through — values come from the host via
81
+ // RoboByteFrontBuilderProvider's user / accessToken props.
82
+ // There is no AuthProvider in this package; use your own host auth provider.
83
+ export { AuthContext } from '../context/AuthContext'
@@ -1,56 +1,88 @@
1
1
  /**
2
2
  * RoboByteFrontBuilderProvider
3
3
  *
4
- * Root provider for the @robobyte/front-builder package.
4
+ * Root provider for the robobyte-front-builder package.
5
5
  * Wrap your host app's _app.js with this component.
6
6
  *
7
- * It currently wires up the NavigationExtensionProvider so that
8
- * nav items you pass via `navExtensions` (or register via useNavExtension)
9
- * are merged into the sidebar automatically.
7
+ * ── Props ─────────────────────────────────────────────────────────────────
10
8
  *
11
- * EXAMPLE (_app.js in the host Next.js app):
9
+ * baseURL Root URL of the API server, e.g. "https://api.yourapp.com/"
10
+ * apiURL /api prefix URL, e.g. "https://api.yourapp.com/api/"
11
+ * user The currently logged-in user object from your auth context.
12
+ * Used by builder components that need the current user's id.
13
+ * accessToken The current Bearer token string from your auth context.
14
+ * All robobyte service calls attach this as Authorization header.
15
+ * navExtensions Static nav items to inject into the sidebar (see below).
12
16
  *
13
- * import { RoboByteFrontBuilderProvider } from '@robobyte/front-builder'
17
+ * ── Example (_app.js in Mazajk / any host Next.js app) ───────────────────
14
18
  *
15
- * export default function App({ Component, pageProps }) {
19
+ * // Inside AuthProvider, read your own auth context and bridge it in:
20
+ *
21
+ * function RoboByteBridge({ children }) {
22
+ * const auth = useContext(AuthContext) // YOUR app's auth context
16
23
  * return (
17
24
  * <RoboByteFrontBuilderProvider
18
- * navExtensions={[
19
- * {
20
- * id: 'host-settings',
21
- * title: 'Settings',
22
- * icon: 'CogOutline', // any mdi-material-ui icon name
23
- * type: 'static',
24
- * path: '/settings',
25
- * insertAt: 'end', // 'start' | 'end' | number | { afterId } | { beforeId }
26
- * },
27
- * {
28
- * id: 'host-analytics',
29
- * title: 'Analytics',
30
- * icon: 'ChartBar',
31
- * type: 'static',
32
- * path: '/analytics',
33
- * insertAt: { afterId: 'host-settings' },
34
- * }
35
- * ]}
25
+ * baseURL="https://api.yourapp.com/"
26
+ * apiURL="https://api.yourapp.com/api/"
27
+ * user={auth.user}
28
+ * accessToken={auth.accessToken}
36
29
  * >
37
- * <Component {...pageProps} />
30
+ * {children}
38
31
  * </RoboByteFrontBuilderProvider>
39
32
  * )
40
33
  * }
34
+ *
35
+ * export default function App({ Component, pageProps }) {
36
+ * return (
37
+ * <AuthProvider>
38
+ * <RoboByteBridge>
39
+ * <Component {...pageProps} />
40
+ * </RoboByteBridge>
41
+ * </AuthProvider>
42
+ * )
43
+ * }
41
44
  */
42
45
 
46
+ import { useMemo } from 'react'
43
47
  import { NavigationExtensionProvider } from '../navigation/NavigationExtensionContext'
48
+ import { configureRoboByte } from '../../services/config'
49
+ import { AuthContext } from '../../context/AuthContext'
44
50
 
45
51
  /**
46
- * @param {Object[]} navExtensions - Static nav items to inject into the sidebar
52
+ * @param {string} [baseURL] Root API server URL (with trailing slash)
53
+ * @param {string} [apiURL] /api prefix URL (with trailing slash)
54
+ * @param {object} [user] Current user from the host auth context
55
+ * @param {string} [accessToken] Current Bearer token from the host auth context
56
+ * @param {Object[]} [navExtensions] Static nav items to inject into the sidebar
47
57
  * @param {ReactNode} children
48
58
  */
49
- const RoboByteFrontBuilderProvider = ({ children, navExtensions = [] }) => {
59
+ const RoboByteFrontBuilderProvider = ({
60
+ children,
61
+ baseURL,
62
+ apiURL,
63
+ user = null,
64
+ accessToken = null,
65
+ navExtensions = [],
66
+ }) => {
67
+ // Apply URL config synchronously before any child renders.
68
+ useMemo(() => {
69
+ if (baseURL || apiURL) {
70
+ configureRoboByte({ baseURL, apiURL })
71
+ }
72
+ }, [baseURL, apiURL])
73
+
74
+ // Auth context value — comes entirely from the host. No logic here.
75
+ const authValue = useMemo(
76
+ () => ({ user, accessToken }),
77
+ [user, accessToken]
78
+ )
79
+
50
80
  return (
51
- <NavigationExtensionProvider items={navExtensions}>
52
- {children}
53
- </NavigationExtensionProvider>
81
+ <AuthContext.Provider value={authValue}>
82
+ <NavigationExtensionProvider items={navExtensions}>
83
+ {children}
84
+ </NavigationExtensionProvider>
85
+ </AuthContext.Provider>
54
86
  )
55
87
  }
56
88
 
@@ -0,0 +1,11 @@
1
+ /**
2
+ * ApiURL — backward-compat shim for auth services that import:
3
+ * import ApiURL from '../ApiURL'
4
+ * const url = ApiURL() + '/api/...'
5
+ *
6
+ * Returns the configured API base URL at call time so that host apps
7
+ * can override it via configureRoboByte() before the first request.
8
+ */
9
+ import { getApiURL } from './config'
10
+
11
+ export default getApiURL
@@ -1,13 +1,10 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { ApiURL } from './Endpoints'
4
- import authConfig from 'src/configs/auth'
3
+ import { getApiURL, getAccessToken } from './config'
5
4
  import toast from 'react-hot-toast'
6
- import PutRefreshToken from './auth/PutRefreshToken'
7
5
 
8
6
  export default async function DeleteService(endpoint, showToast, data, params) {
9
- await PutRefreshToken()
10
- const accessToken = localStorage.getItem(authConfig.storageTokenKeyName)
7
+ const accessToken = getAccessToken()
11
8
  let response = { status: 'Error', message: '' }
12
9
  let result = null
13
10
  let currentParams = {
@@ -16,7 +13,7 @@ export default async function DeleteService(endpoint, showToast, data, params) {
16
13
  }
17
14
 
18
15
  if (!data) return
19
- const url = ApiURL + endpoint.URL
16
+ const url = getApiURL() + endpoint.URL
20
17
 
21
18
  const axiosConfig = {
22
19
  method: 'delete',
@@ -23,10 +23,12 @@ import { ViewEndpoints } from './Endpoints/ViewEndpoints'
23
23
  import { UiBuilderEndpoints } from 'services/Endpoints/UiBuilderEndpoints'
24
24
  import { WidgetEndpoints } from 'services/Endpoints/WidgetEndpoints'
25
25
 
26
- // export const BaseURL = 'http://localhost:7012/'
27
- // export const ApiURL = 'http://localhost:7012/api/'
28
- export const BaseURL = 'http://140.82.34.191:3400/'
29
- export const ApiURL = 'http://140.82.34.191:3400/api/'
26
+ // BaseURL and ApiURL are now sourced from the config singleton so that
27
+ // host apps can override them via configureRoboByte() or the
28
+ // RoboByteFrontBuilderProvider baseURL / apiURL props.
29
+ // Use getBaseURL() / getApiURL() from 'services/config' inside functions
30
+ // rather than caching these at module-load time.
31
+ export { getBaseURL as BaseURL, getApiURL as ApiURL, configureRoboByte } from './config'
30
32
 
31
33
  export const Services = {
32
34
  GetService: GetService,
@@ -1,15 +1,12 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { ApiURL } from './Endpoints'
4
- import authConfig from 'src/configs/auth'
3
+ import { getApiURL, getAccessToken } from './config'
5
4
  import toast from 'react-hot-toast'
6
- import PutRefreshToken from './auth/PutRefreshToken'
7
5
  export default async function GetService(endpoint, showToast, data, params) {
8
- await PutRefreshToken()
9
- const accessToken = localStorage.getItem(authConfig.storageTokenKeyName)
6
+ const accessToken = getAccessToken()
10
7
  let response = { status: 'Error', message: '' }
11
8
  let result = null
12
- const url = ApiURL + endpoint.URL
9
+ const url = getApiURL() + endpoint.URL
13
10
 
14
11
  const axiosConfig = {
15
12
  method: 'post',
@@ -1,13 +1,10 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { ApiURL } from './Endpoints'
4
- import authConfig from 'src/configs/auth'
3
+ import { getApiURL, getAccessToken } from './config'
5
4
  import toast from 'react-hot-toast'
6
- import PutRefreshToken from './auth/PutRefreshToken'
7
5
 
8
6
  export default async function PatchService(endpoint, showToast, data, params) {
9
- await PutRefreshToken()
10
- const accessToken = localStorage.getItem(authConfig.storageTokenKeyName)
7
+ const accessToken = getAccessToken()
11
8
  let response = { status: 'Error', message: '' }
12
9
  let result = null
13
10
  let currentParams = {
@@ -22,7 +19,7 @@ export default async function PatchService(endpoint, showToast, data, params) {
22
19
  ...(endpoint.DataType == DataTypes.Body ? { ...data } : {})
23
20
  }
24
21
  if (!data) return
25
- const url = ApiURL + endpoint.URL
22
+ const url = getApiURL() + endpoint.URL
26
23
 
27
24
  const axiosConfig = {
28
25
  method: 'patch',
@@ -1,13 +1,10 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { ApiURL } from './Endpoints'
4
- import authConfig from 'src/configs/auth'
3
+ import { getApiURL, getAccessToken } from './config'
5
4
  import toast from 'react-hot-toast'
6
- import PutRefreshToken from './auth/PutRefreshToken'
7
5
 
8
6
  export default async function PostService(endpoint, showToast, data, params) {
9
- await PutRefreshToken()
10
- const accessToken = localStorage.getItem(authConfig.storageTokenKeyName)
7
+ const accessToken = getAccessToken()
11
8
 
12
9
 
13
10
  let response = { status: 'Error', message: '' }
@@ -19,7 +16,7 @@ export default async function PostService(endpoint, showToast, data, params) {
19
16
  let currnetData = endpoint.DataType == DataTypes.Form || endpoint.DataType == DataTypes.Body ? data : {}
20
17
 
21
18
  if (!data) return
22
- const url = ApiURL + endpoint.URL
19
+ const url = getApiURL() + endpoint.URL
23
20
 
24
21
  const axiosConfig = {
25
22
  method: 'post',
@@ -1,15 +1,12 @@
1
1
  import Axios from 'axios'
2
- import {ApiURL} from './Endpoints'
3
- import authConfig from 'src/configs/auth'
4
- import PutRefreshToken from './auth/PutRefreshToken'
2
+ import { getApiURL, getAccessToken } from './config'
5
3
  import toast from 'react-hot-toast'
6
4
  import {DataTypes} from "services/ContentTypes";
7
5
 
8
6
  export default async function StreamService(endpoint, showToast, data, params, api, progressCallback) {
9
- await PutRefreshToken()
10
- const accessToken = localStorage.getItem(authConfig.storageTokenKeyName)
7
+ const accessToken = getAccessToken()
11
8
 
12
- const url = api ?? ApiURL + endpoint.URL
9
+ const url = api ?? getApiURL() + endpoint.URL
13
10
 
14
11
  let currentParams = {
15
12
  ...params,
@@ -1,13 +1,10 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { ApiURL } from './Endpoints'
4
- import authConfig from 'src/configs/auth'
3
+ import { getApiURL, getAccessToken } from './config'
5
4
  import toast from 'react-hot-toast'
6
- import PutRefreshToken from './auth/PutRefreshToken'
7
5
 
8
6
  export default async function UpdateService(endpoint, showToast, data, params) {
9
- await PutRefreshToken()
10
- const accessToken = localStorage.getItem(authConfig.storageTokenKeyName)
7
+ const accessToken = getAccessToken()
11
8
  let response = { status: 'Error', message: '' }
12
9
  let result = null
13
10
  let currentParams = {
@@ -21,7 +18,7 @@ export default async function UpdateService(endpoint, showToast, data, params) {
21
18
  ...(endpoint.DataType == DataTypes.Body ? { ...data } : {})
22
19
  }
23
20
  if (!data) return
24
- const url = ApiURL + endpoint.URL
21
+ const url = getApiURL() + endpoint.URL
25
22
 
26
23
  const axiosConfig = {
27
24
  method: 'put',
@@ -1,47 +1,5 @@
1
- import Axios from "axios";
2
- import { ApiUrl } from "services/Endpoints";
3
- const apiURL = ApiUrl;
4
-
5
- export default async function AuthService(User) {
6
- let result = { status: "Error", message: "" };
7
-
8
- if (!User) return;
9
- const url = apiURL + `/api/Auth/Login`;
10
-
11
- const axiosConfig = {
12
- method: "post",
13
- headers: {
14
- "Content-Type": "application/json-patch+json",
15
- },
16
- };
17
-
18
- try {
19
- const resporone = await Axios.post(url, User, axiosConfig)
20
- .then((r) => {
21
- result = r.data;
22
- })
23
- .catch((r) => {
24
-
25
- if (r.response && r.response.status == 400) {
26
- result = {
27
- status: "Error",
28
- message: r.response.data,
29
- };
30
- } else if (r.response && r.response.status == 401) {
31
- result = {
32
- status: "Error",
33
- message: "غير مخول بالدخول",
34
- };
35
- } else {
36
- result = {
37
- status: "Error",
38
- message: "حدث خطأ في الاتصال مع الخادم",
39
- };
40
- }
41
- });
42
- } catch (error) {
43
-
44
- }
45
-
46
- return result;
47
- }
1
+ /**
2
+ * This file has been removed.
3
+ * Authentication is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -1,38 +1,5 @@
1
- import Axios from 'axios';
2
- import ApiURL from '../ApiURL'
3
-
4
- export default async function GetUsersService(User,filter){
5
-
6
- let result =null;
7
- const apiURL = ApiURL() + '/api/Users/GetByUserRole';
8
-
9
- if (!User )
10
- return;
11
- let currentFilter
12
- if(filter){
13
- currentFilter={...filter}
14
- }else{
15
- currentFilter={
16
- page:1,
17
- pageSize:100
18
- }
19
- }
20
- const axiosConfig={
21
- method: 'get',
22
- headers: {
23
- 'Authorization': `Bearer ${User.accessToken}`,
24
- 'Content-Type': 'application/json-patch+json',
25
- },params:{
26
- ...currentFilter
27
- }
28
- };
29
-
30
- const response = await Axios.get(apiURL,axiosConfig);
31
- if (response.status===200)
32
- {
33
- result = response.data;
34
-
35
- }
36
-
37
- return result
38
- }
1
+ /**
2
+ * This file has been removed.
3
+ * Authentication is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -1,29 +1,5 @@
1
- import Axios from 'axios';
2
- import ApiURL from '../ApiURL'
3
-
4
- export default async function PostRegisterUser(User,data){
5
-
6
-
7
- let result =null;
8
- const apiURL = ApiURL() + '/api/Auth/Register';
9
-
10
-
11
- if (!User || !data)
12
- return;
13
- const axiosConfig={
14
- method: 'post',
15
- headers: {
16
- 'Authorization': `Bearer ${User.accessToken}`,
17
- 'Content-Type': 'application/json-patch+json',
18
- },
19
-
20
- };
21
-
22
- const resporone = await Axios.post(apiURL,data,axiosConfig);
23
- if (resporone.status===200)
24
- {
25
- result = resporone.data;
26
-
27
- }
28
- return result
29
- }
1
+ /**
2
+ * This file has been removed.
3
+ * Authentication is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -1,28 +1,5 @@
1
- import Axios from 'axios';
2
- import ApiURL from '../ApiURL'
3
-
4
- export default async function PostResetPasswordService(User,data){
5
-
6
- let result =null;
7
- const apiURL = ApiURL() + '/api/Auth/ResetPassword';
8
-
9
-
10
- if (!User || !data)
11
- return;
12
- const axiosConfig={
13
- method: 'post',
14
- headers: {
15
- 'Authorization': `Bearer ${User.accessToken}`,
16
- 'Content-Type': 'application/json-patch+json',
17
- }
18
- };
19
-
20
- const resporone = await Axios.post(apiURL,data,axiosConfig);
21
-
22
- if (resporone.status===200)
23
- {
24
- result = resporone.data;
25
-
26
- }
27
- return result
28
- }
1
+ /**
2
+ * This file has been removed.
3
+ * Authentication is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -1,29 +1,5 @@
1
- import Axios from "axios";
2
- import ApiURL from "../ApiURL";
3
-
4
- export default async function PutAccountService(User, data) {
5
- let result = null;
6
- if (!User || !data) return;
7
- const apiURL = ApiURL() + `/api/Users/${data.id}`;
8
-
9
- const axiosConfig = {
10
- method: "put",
11
- headers: {
12
- Authorization: `Bearer ${User.accessToken}`,
13
- "Content-Type": "application/json-patch+json",
14
- },
15
- };
16
-
17
- try {
18
- const resporone = await Axios.put(apiURL, data, axiosConfig);
19
-
20
- if (resporone.status === 200) {
21
- result = resporone.data;
22
- }
23
- throw resporone;
24
- } catch (error) {
25
-
26
- }
27
-
28
- return result;
29
- }
1
+ /**
2
+ * This file has been removed.
3
+ * Authentication is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -1,69 +1,5 @@
1
- import Axios from 'axios';
2
- import {ApiURL, BaseURL} from '../Endpoints'
3
- import {jwtDecode} from "jwt-decode";
4
- import {ElevatorPassengerOffOutline} from 'mdi-material-ui';
5
- import {useContext} from 'react';
6
- import authConfig from 'src/configs/auth'
7
- import {Router} from 'next/router';
8
- import {useRouter} from 'next/router';
9
-
10
-
11
- const apiURL = BaseURL
12
-
13
- const handleLogout = () => {
14
- localStorage.removeItem('userData')
15
- localStorage.removeItem('refreshToken')
16
- localStorage.removeItem('userId')
17
- localStorage.removeItem('accessToken')
18
-
19
- window.location.href = '/login'
20
-
21
- }
22
-
23
- export default async function PutRefreshToken() {
24
- let token = localStorage.getItem(authConfig.storageTokenKeyName)
25
- if (token == null || token == '') {
26
- handleLogout()
27
- }
28
- let refreshToken = localStorage.getItem(authConfig.refreshToken)
29
- let response = null;
30
-
31
- function isTokenExpired(token) {
32
- try {
33
- const decodedToken = jwtDecode(token);
34
- const expirationDate = new Date(decodedToken.exp * 1000);
35
- return expirationDate < new Date();
36
- } catch {
37
- handleLogout()
38
- }
39
-
40
- }
41
-
42
- const istokenExpired = isTokenExpired(token)
43
- if (istokenExpired) {
44
- const url = apiURL + `api/Auth/Refresh-Token?refreshToken=${refreshToken}`;
45
- const axiosConfig = {
46
- method: 'put',
47
- headers: {
48
-
49
- 'Content-Type': 'application/json-patch+json',
50
- },
51
- };
52
-
53
- try {
54
- response = await Axios.put(url, axiosConfig);
55
- if (response.status == 200) {
56
- localStorage.setItem(authConfig.storageTokenKeyName, response.data.accessToken)
57
- } else {
58
- handleLogout();
59
- }
60
-
61
- } catch (error) {
62
- handleLogout();
63
- }
64
-
65
- }
66
-
67
-
68
- return
69
- }
1
+ /**
2
+ * This file has been removed.
3
+ * Token refresh is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -0,0 +1,5 @@
1
+ /**
2
+ * This file has been removed.
3
+ * Authentication is handled entirely by the host application.
4
+ * robobyte-front-builder no longer owns any auth logic.
5
+ */
@@ -0,0 +1,103 @@
1
+ /**
2
+ * RoboByte Configuration
3
+ *
4
+ * Single source of truth for API URLs and auth accessors.
5
+ * This module has NO imports from other local service files — it can
6
+ * never participate in a circular dependency.
7
+ *
8
+ * ── Usage in the host app ──────────────────────────────────────────────────
9
+ *
10
+ * // Option A — via RoboByteFrontBuilderProvider props (recommended):
11
+ * <RoboByteFrontBuilderProvider
12
+ * baseURL="https://api.yourapp.com/"
13
+ * apiURL="https://api.yourapp.com/api/"
14
+ * user={authUser}
15
+ * accessToken={authToken}
16
+ * >
17
+ *
18
+ * // Option B — imperative call once before rendering:
19
+ * import { configureRoboByte } from 'robobyte-front-builder'
20
+ * configureRoboByte({
21
+ * baseURL: 'https://api.yourapp.com/',
22
+ * apiURL: 'https://api.yourapp.com/api/',
23
+ * getAccessToken: () => localStorage.getItem('accessToken'),
24
+ * getUser: () => JSON.parse(localStorage.getItem('userData') || 'null'),
25
+ * })
26
+ *
27
+ * ─────────────────────────────────────────────────────────────────────────
28
+ */
29
+
30
+ const _config = {
31
+ baseURL: 'http://140.82.34.191:3400/',
32
+ apiURL: 'http://140.82.34.191:3400/api/',
33
+
34
+ // Default token reader — reads the key Mazajk (and most host apps) use.
35
+ // Override via configureRoboByte({ getAccessToken }) or via the provider prop.
36
+ getAccessToken: () => {
37
+ if (typeof window === 'undefined') return null
38
+ return localStorage.getItem('accessToken') ?? null
39
+ },
40
+
41
+ // Default user reader — parses the JSON object Mazajk stores in localStorage.
42
+ // Override via configureRoboByte({ getUser }) or via the provider prop.
43
+ getUser: () => {
44
+ if (typeof window === 'undefined') return null
45
+ try {
46
+ const raw = localStorage.getItem('userData')
47
+ return raw ? JSON.parse(raw) : null
48
+ } catch {
49
+ return null
50
+ }
51
+ },
52
+ }
53
+
54
+ /**
55
+ * Configure robobyte-front-builder.
56
+ * All fields are optional — only the ones you pass will be updated.
57
+ *
58
+ * @param {Object} [options]
59
+ * @param {string} [options.baseURL] Root URL of the API server (trailing slash)
60
+ * @param {string} [options.apiURL] /api prefix URL (trailing slash)
61
+ * @param {Function} [options.getAccessToken] () => string | null — returns the current Bearer token
62
+ * @param {Function} [options.getUser] () => object | null — returns the current user object
63
+ */
64
+ export function configureRoboByte({ baseURL, apiURL, getAccessToken, getUser } = {}) {
65
+ if (baseURL) {
66
+ _config.baseURL = baseURL.endsWith('/') ? baseURL : baseURL + '/'
67
+ }
68
+ if (apiURL) {
69
+ _config.apiURL = apiURL.endsWith('/') ? apiURL : apiURL + '/'
70
+ }
71
+ if (typeof getAccessToken === 'function') {
72
+ _config.getAccessToken = getAccessToken
73
+ }
74
+ if (typeof getUser === 'function') {
75
+ _config.getUser = getUser
76
+ }
77
+ }
78
+
79
+ /** Returns the current base URL (e.g. "https://api.example.com/") */
80
+ export function getBaseURL() {
81
+ return _config.baseURL
82
+ }
83
+
84
+ /** Returns the current API URL (e.g. "https://api.example.com/api/") */
85
+ export function getApiURL() {
86
+ return _config.apiURL
87
+ }
88
+
89
+ /**
90
+ * Returns the current Bearer access token.
91
+ * Call this inside service functions — never cache the result at module level.
92
+ */
93
+ export function getAccessToken() {
94
+ return _config.getAccessToken()
95
+ }
96
+
97
+ /**
98
+ * Returns the current user object from the host app.
99
+ * Call this inside component render functions.
100
+ */
101
+ export function getUser() {
102
+ return _config.getUser()
103
+ }
@@ -1,10 +1,23 @@
1
1
  import { useRef } from 'react'
2
- import SunEditor from 'suneditor-react'
3
- import 'suneditor/dist/css/suneditor.min.css'
2
+ import dynamic from 'next/dynamic'
4
3
  import { Box, FormHelperText } from '@mui/material'
5
4
  import ViewerComponentWrapper from '../ViewerComponentWrapper'
6
5
  import { resolveProps } from 'services/builderHelper/resolveProps'
7
6
 
7
+ // SunEditor requires the DOM and loads suneditor/src/plugins at require-time,
8
+ // which is raw ESM with bare specifiers. Node.js 22's strict ESM resolver
9
+ // cannot resolve those extensionless imports at SSR, causing a fatal error.
10
+ // Dynamic import with ssr:false keeps the entire module out of the server bundle.
11
+ const SunEditor = dynamic(
12
+ () => {
13
+ // Import the CSS alongside the component so it's only loaded client-side too.
14
+ // Using require() inside the factory avoids a separate async CSS chunk.
15
+ require('suneditor/dist/css/suneditor.min.css')
16
+ return import('suneditor-react')
17
+ },
18
+ { ssr: false }
19
+ )
20
+
8
21
  export default function RichTextRenderer({ node, viewerContext }) {
9
22
  const { data, form, updateFormValue, validationErrors } = viewerContext
10
23
  const main = resolveProps(node, 'main', { form, data })
@@ -52,7 +65,7 @@ export default function RichTextRenderer({ node, viewerContext }) {
52
65
  height: main.height || '300px',
53
66
  placeholder: main.placeholder || 'Enter text here...',
54
67
  disabled: main.disabled,
55
- mode: main.mode || 'classic', // classic, inline, balloon, balloon-always
68
+ mode: main.mode || 'classic',
56
69
  resizingBar: main.resizingBar !== false,
57
70
  showPathLabel: main.showPathLabel !== false,
58
71
  charCounter: main.charCounter !== false,
@@ -1,5 +1,4 @@
1
1
  import { Avatar, IconButton } from "@mui/material";
2
- import { BaseURL } from "services/Endpoints";
3
2
  import { CloudUploadOutline } from "mdi-material-ui";
4
3
  import { Box } from "@mui/system";
5
4
  import { useContext } from "react";
@@ -20,7 +20,7 @@ import Box from '@mui/material/Box'
20
20
  import {Close} from 'mdi-material-ui'
21
21
  import {useEffect, useState} from 'react'
22
22
  import {useForm} from 'react-hook-form'
23
- import {BaseURL, Endpoints, Services} from 'src/services/Endpoints'
23
+ import {Endpoints, Services} from 'src/services/Endpoints'
24
24
 
25
25
  // ** Third Party Imports
26
26