robobyte-front-builder 1.0.5 → 1.0.7

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.5",
3
+ "version": "1.0.7",
4
4
  "description": "RoboByte low-code UI builder, Report builder, and navigation extension system",
5
5
  "main": "src/lib/index.js",
6
6
  "files": [
@@ -54,6 +54,10 @@ import { AuthContext } from '../../context/AuthContext'
54
54
  * @param {object} [user] Current user from the host auth context
55
55
  * @param {string} [accessToken] Current Bearer token from the host auth context
56
56
  * @param {Object[]} [navExtensions] Static nav items to inject into the sidebar
57
+ * @param {Object} [endpoints] Full-URL overrides for each endpoint group+name.
58
+ * Shape: { [group]: { [name]: fullURL } }
59
+ * e.g. { ReportBuilder: { GenericGet: 'https://api.example.com/api/ReportBuilder/GenericGet' } }
60
+ * When provided, the package uses these URLs instead of its own defaults.
57
61
  * @param {ReactNode} children
58
62
  */
59
63
  const RoboByteFrontBuilderProvider = ({
@@ -63,13 +67,14 @@ const RoboByteFrontBuilderProvider = ({
63
67
  user = null,
64
68
  accessToken = null,
65
69
  navExtensions = [],
70
+ endpoints = null,
66
71
  }) => {
67
- // Apply URL config synchronously before any child renders.
72
+ // Apply URL + endpoint config synchronously before any child renders.
68
73
  useMemo(() => {
69
- if (baseURL || apiURL) {
70
- configureRoboByte({ baseURL, apiURL })
74
+ if (baseURL || apiURL || endpoints) {
75
+ configureRoboByte({ baseURL, apiURL, ...(endpoints ? { endpoints } : {}) })
71
76
  }
72
- }, [baseURL, apiURL])
77
+ }, [baseURL, apiURL, endpoints])
73
78
 
74
79
  // Auth context value — comes entirely from the host. No logic here.
75
80
  const authValue = useMemo(
@@ -1,6 +1,6 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { getApiURL, getAccessToken } from './config'
3
+ import { resolveURL, getAccessToken } from './config'
4
4
  import toast from 'react-hot-toast'
5
5
 
6
6
  export default async function DeleteService(endpoint, showToast, data, params) {
@@ -13,7 +13,7 @@ export default async function DeleteService(endpoint, showToast, data, params) {
13
13
  }
14
14
 
15
15
  if (!data) return
16
- const url = getApiURL() + endpoint.URL
16
+ const url = resolveURL(endpoint)
17
17
 
18
18
  const axiosConfig = {
19
19
  method: 'delete',
@@ -3,16 +3,19 @@ import { ContentTypes, DataTypes } from '../ContentTypes'
3
3
  export const FilterEndpoints = {
4
4
  Post: {
5
5
  GetMinDynamics: {
6
+ group: 'Filter', name: 'GetMinDynamics',
6
7
  URL: 'ReportingModule/Filter/GetMinDynamics',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Body
9
10
  },
10
11
  GetFilterObject: {
12
+ group: 'Filter', name: 'GetFilterObject',
11
13
  URL: 'ReportingModule/Filter/GetFilterObject',
12
14
  ContentType: ContentTypes.Json,
13
15
  DataType: DataTypes.Body
14
16
  },
15
17
  GetFormFields: {
18
+ group: 'Filter', name: 'GetFormFields',
16
19
  URL: 'ReportingModule/Filter/GetFormFields',
17
20
  ContentType: ContentTypes.Json,
18
21
  DataType: DataTypes.Params
@@ -22,6 +25,7 @@ export const FilterEndpoints = {
22
25
  Patch: {},
23
26
  Get: {
24
27
  GetEnumValues: {
28
+ group: 'Filter', name: 'GetEnumValues',
25
29
  URL: 'Filter/GetEnumValues',
26
30
  ContentType: ContentTypes.Json,
27
31
  DataType: DataTypes.Params
@@ -3,6 +3,7 @@ import {ContentTypes, DataTypes} from '../ContentTypes'
3
3
  export const NavigatorEndpoints = {
4
4
  Post: {
5
5
  NavigatorSetting: {
6
+ group: 'Navigator', name: 'UpdateNavigator',
6
7
  URL: 'UiBuilderModule/NavigatorSetting/UpdateNavigator',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Params
@@ -12,6 +13,7 @@ export const NavigatorEndpoints = {
12
13
  Patch: {},
13
14
  Get: {
14
15
  NavigatorSetting: {
16
+ group: 'Navigator', name: 'GetNavigator',
15
17
  URL: 'UiBuilderModule/NavigatorSetting/GetNavigator',
16
18
  ContentType: ContentTypes.Json,
17
19
  DataType: DataTypes.Params
@@ -3,36 +3,43 @@ import {ContentTypes, DataTypes} from '../ContentTypes'
3
3
  export const ReportBuilderEndpoints = {
4
4
  Post: {
5
5
  GetModels: {
6
+ group: 'ReportBuilder', name: 'GetModels',
6
7
  URL: 'ReportingModule/ReportBuilder/GetTypes',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Params
9
10
  },
10
11
  GetModelFields: {
12
+ group: 'ReportBuilder', name: 'GetModelFields',
11
13
  URL: 'ReportingModule/ReportBuilder/GetModelFields',
12
14
  ContentType: ContentTypes.Json,
13
15
  DataType: DataTypes.Params
14
16
  },
15
17
  GenericGet: {
18
+ group: 'ReportBuilder', name: 'GenericGet',
16
19
  URL: 'ReportingModule/ReportBuilder/GenericGet',
17
20
  ContentType: ContentTypes.Json,
18
21
  DataType: DataTypes.Body
19
22
  },
20
23
  GetRawColumns: {
24
+ group: 'ReportBuilder', name: 'GetRawColumns',
21
25
  URL: 'ReportingModule/ReportBuilder/GetRawColumns',
22
26
  ContentType: ContentTypes.Json,
23
27
  DataType: DataTypes.Body
24
28
  },
25
29
  GetAllReports: {
30
+ group: 'ReportBuilder', name: 'GetAllReports',
26
31
  URL: 'ReportingModule/ReportBuilder/GetAllReports',
27
32
  ContentType: ContentTypes.Json,
28
33
  DataType: DataTypes.Body
29
34
  },
30
35
  GetReportDetails: {
36
+ group: 'ReportBuilder', name: 'GetReportDetails',
31
37
  URL: 'ReportingModule/ReportBuilder/GetReportDetails',
32
38
  ContentType: ContentTypes.Json,
33
39
  DataType: DataTypes.Body
34
40
  },
35
41
  AddUpdate: {
42
+ group: 'ReportBuilder', name: 'AddUpdate',
36
43
  URL: 'ReportingModule/ReportBuilder/AddUpdate',
37
44
  ContentType: ContentTypes.Json,
38
45
  DataType: DataTypes.Body
@@ -3,11 +3,13 @@ import {ContentTypes, DataTypes} from '../ContentTypes'
3
3
  export const UiBuilderEndpoints = {
4
4
  Post: {
5
5
  AddUpdate: {
6
+ group: 'UiBuilder', name: 'AddUpdate',
6
7
  URL: 'UiBuilderModule/View',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Body
9
10
  },
10
11
  AddUpdateGroup: {
12
+ group: 'UiBuilder', name: 'AddUpdateGroup',
11
13
  URL: 'UiBuilderModule/ViewGroup',
12
14
  ContentType: ContentTypes.Json,
13
15
  DataType: DataTypes.Body
@@ -15,6 +17,7 @@ export const UiBuilderEndpoints = {
15
17
  },
16
18
  Put: {
17
19
  Update: {
20
+ group: 'UiBuilder', name: 'Update',
18
21
  URL: 'UiBuilderModule/View',
19
22
  ContentType: ContentTypes.Json,
20
23
  DataType: DataTypes.Body
@@ -23,11 +26,13 @@ export const UiBuilderEndpoints = {
23
26
  Patch: {},
24
27
  Get: {
25
28
  GetAllViews: {
29
+ group: 'UiBuilder', name: 'GetAllViews',
26
30
  URL: 'UiBuilderModule/View/GetAllViews',
27
31
  ContentType: ContentTypes.Json,
28
32
  DataType: DataTypes.Body
29
33
  },
30
34
  GetViewDetails: {
35
+ group: 'UiBuilder', name: 'GetViewDetails',
31
36
  URL: 'UiBuilderModule/View/GetViewDetails',
32
37
  ContentType: ContentTypes.Json,
33
38
  DataType: DataTypes.Params
@@ -2,19 +2,22 @@ import { ContentTypes, DataTypes } from '../ContentTypes'
2
2
 
3
3
  export const UserTableTemplateEndpoints = {
4
4
  Post: {
5
- AddTemplate : {
5
+ AddTemplate: {
6
+ group: 'UserTemplate', name: 'AddTemplate',
6
7
  URL: 'ReportingModule/UserTemplate',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Body
9
10
  },
10
11
  GetAllPagedByFilter: {
12
+ group: 'UserTemplate', name: 'GetAllPagedByFilter',
11
13
  URL: 'ReportingModule/UserTemplate/GetUserTemplate',
12
14
  ContentType: ContentTypes.Json,
13
15
  DataType: DataTypes.Body
14
16
  },
15
17
  },
16
18
  Put: {
17
- UpdateTemplate : {
19
+ UpdateTemplate: {
20
+ group: 'UserTemplate', name: 'UpdateTemplate',
18
21
  URL: 'ReportingModule/UserTemplate',
19
22
  ContentType: ContentTypes.Json,
20
23
  DataType: DataTypes.Body
@@ -3,6 +3,7 @@ import { ContentTypes, DataTypes } from '../ContentTypes'
3
3
  export const ViewEndpoints = {
4
4
  Post: {
5
5
  Add: {
6
+ group: 'View', name: 'Add',
6
7
  URL: 'UiBuilderModule/View',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Body
@@ -10,6 +11,7 @@ export const ViewEndpoints = {
10
11
  },
11
12
  Put: {
12
13
  Update: {
14
+ group: 'View', name: 'Update',
13
15
  URL: 'UiBuilderModule/View',
14
16
  ContentType: ContentTypes.Json,
15
17
  DataType: DataTypes.Body
@@ -18,6 +20,7 @@ export const ViewEndpoints = {
18
20
  Patch: {},
19
21
  Get: {
20
22
  GetById: {
23
+ group: 'View', name: 'GetById',
21
24
  URL: 'UiBuilderModule/View/GetViewDetails',
22
25
  ContentType: ContentTypes.Json,
23
26
  DataType: DataTypes.Params
@@ -25,4 +28,3 @@ export const ViewEndpoints = {
25
28
  },
26
29
  Delete: {}
27
30
  }
28
-
@@ -3,6 +3,7 @@ import { ContentTypes, DataTypes } from '../ContentTypes'
3
3
  export const WidgetEndpoints = {
4
4
  Post: {
5
5
  Add: {
6
+ group: 'Widget', name: 'Add',
6
7
  URL: 'UiBuilderModule/Widget',
7
8
  ContentType: ContentTypes.Json,
8
9
  DataType: DataTypes.Body
@@ -10,6 +11,7 @@ export const WidgetEndpoints = {
10
11
  },
11
12
  Put: {
12
13
  Update: {
14
+ group: 'Widget', name: 'Update',
13
15
  URL: 'UiBuilderModule/Widget',
14
16
  ContentType: ContentTypes.Json,
15
17
  DataType: DataTypes.Body
@@ -18,6 +20,7 @@ export const WidgetEndpoints = {
18
20
  Patch: {},
19
21
  Get: {
20
22
  GetById: {
23
+ group: 'Widget', name: 'GetById',
21
24
  URL: 'UiBuilderModule/Widget/GetById',
22
25
  ContentType: ContentTypes.Json,
23
26
  DataType: DataTypes.Params
@@ -25,4 +28,3 @@ export const WidgetEndpoints = {
25
28
  },
26
29
  Delete: {}
27
30
  }
28
-
@@ -1,12 +1,12 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { getApiURL, getAccessToken } from './config'
3
+ import { resolveURL, getAccessToken } from './config'
4
4
  import toast from 'react-hot-toast'
5
5
  export default async function GetService(endpoint, showToast, data, params) {
6
6
  const accessToken = getAccessToken()
7
7
  let response = { status: 'Error', message: '' }
8
8
  let result = null
9
- const url = getApiURL() + endpoint.URL
9
+ const url = resolveURL(endpoint)
10
10
 
11
11
  const axiosConfig = {
12
12
  method: 'post',
@@ -1,6 +1,6 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { getApiURL, getAccessToken } from './config'
3
+ import { resolveURL, getAccessToken } from './config'
4
4
  import toast from 'react-hot-toast'
5
5
 
6
6
  export default async function PatchService(endpoint, showToast, data, params) {
@@ -19,7 +19,7 @@ export default async function PatchService(endpoint, showToast, data, params) {
19
19
  ...(endpoint.DataType == DataTypes.Body ? { ...data } : {})
20
20
  }
21
21
  if (!data) return
22
- const url = getApiURL() + endpoint.URL
22
+ const url = resolveURL(endpoint)
23
23
 
24
24
  const axiosConfig = {
25
25
  method: 'patch',
@@ -1,6 +1,6 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { getApiURL, getAccessToken } from './config'
3
+ import { resolveURL, getAccessToken } from './config'
4
4
  import toast from 'react-hot-toast'
5
5
 
6
6
  export default async function PostService(endpoint, showToast, data, params) {
@@ -16,7 +16,7 @@ export default async function PostService(endpoint, showToast, data, params) {
16
16
  let currnetData = endpoint.DataType == DataTypes.Form || endpoint.DataType == DataTypes.Body ? data : {}
17
17
 
18
18
  if (!data) return
19
- const url = getApiURL() + endpoint.URL
19
+ const url = resolveURL(endpoint)
20
20
 
21
21
  const axiosConfig = {
22
22
  method: 'post',
@@ -1,6 +1,6 @@
1
1
  import Axios from 'axios'
2
2
  import { DataTypes } from './ContentTypes'
3
- import { getApiURL, getAccessToken } from './config'
3
+ import { resolveURL, getAccessToken } from './config'
4
4
  import toast from 'react-hot-toast'
5
5
 
6
6
  export default async function UpdateService(endpoint, showToast, data, params) {
@@ -18,7 +18,7 @@ export default async function UpdateService(endpoint, showToast, data, params) {
18
18
  ...(endpoint.DataType == DataTypes.Body ? { ...data } : {})
19
19
  }
20
20
  if (!data) return
21
- const url = getApiURL() + endpoint.URL
21
+ const url = resolveURL(endpoint)
22
22
 
23
23
  const axiosConfig = {
24
24
  method: 'put',
@@ -31,6 +31,12 @@ const _config = {
31
31
  baseURL: 'http://140.82.34.191:3400/',
32
32
  apiURL: 'http://140.82.34.191:3400/api/',
33
33
 
34
+ // Host-supplied endpoint overrides.
35
+ // Shape: { [group: string]: { [name: string]: string } }
36
+ // e.g. { ReportBuilder: { GenericGet: 'https://api.example.com/api/ReportBuilder/GenericGet' } }
37
+ // Any entry here takes precedence over getApiURL() + endpoint.URL for that endpoint.
38
+ endpointOverrides: {},
39
+
34
40
  // Default token reader — reads the key Mazajk (and most host apps) use.
35
41
  // Override via configureRoboByte({ getAccessToken }) or via the provider prop.
36
42
  getAccessToken: () => {
@@ -56,12 +62,15 @@ const _config = {
56
62
  * All fields are optional — only the ones you pass will be updated.
57
63
  *
58
64
  * @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
65
+ * @param {string} [options.baseURL] Root URL of the API server (trailing slash)
66
+ * @param {string} [options.apiURL] /api prefix URL (trailing slash)
67
+ * @param {Function} [options.getAccessToken] () => string | null — returns the current Bearer token
68
+ * @param {Function} [options.getUser] () => object | null — returns the current user object
69
+ * @param {Object} [options.endpoints] Full-URL overrides per endpoint group+name.
70
+ * Shape: { [group]: { [name]: fullURL } }
71
+ * e.g. { ReportBuilder: { GenericGet: 'https://api.example.com/api/ReportBuilder/GenericGet' } }
63
72
  */
64
- export function configureRoboByte({ baseURL, apiURL, getAccessToken, getUser } = {}) {
73
+ export function configureRoboByte({ baseURL, apiURL, getAccessToken, getUser, endpoints } = {}) {
65
74
  if (baseURL) {
66
75
  _config.baseURL = baseURL.endsWith('/') ? baseURL : baseURL + '/'
67
76
  }
@@ -74,6 +83,17 @@ export function configureRoboByte({ baseURL, apiURL, getAccessToken, getUser } =
74
83
  if (typeof getUser === 'function') {
75
84
  _config.getUser = getUser
76
85
  }
86
+ if (endpoints && typeof endpoints === 'object') {
87
+ // Deep-merge so partial overrides don't wipe other groups
88
+ for (const [group, methods] of Object.entries(endpoints)) {
89
+ if (methods && typeof methods === 'object') {
90
+ _config.endpointOverrides[group] = {
91
+ ...(_config.endpointOverrides[group] ?? {}),
92
+ ...methods,
93
+ }
94
+ }
95
+ }
96
+ }
77
97
  }
78
98
 
79
99
  /** Returns the current base URL (e.g. "https://api.example.com/") */
@@ -101,3 +121,23 @@ export function getAccessToken() {
101
121
  export function getUser() {
102
122
  return _config.getUser()
103
123
  }
124
+
125
+ /**
126
+ * Resolves the full URL for an endpoint object.
127
+ *
128
+ * Resolution order:
129
+ * 1. Host-supplied override: _config.endpointOverrides[endpoint.group][endpoint.name]
130
+ * 2. Fallback: getApiURL() + endpoint.URL
131
+ *
132
+ * Endpoint objects should carry `group` and `name` fields (set in each Endpoints/*.js file).
133
+ * If those are absent the function gracefully falls back to the old behaviour.
134
+ *
135
+ * @param {{ group?: string, name?: string, URL: string }} endpoint
136
+ * @returns {string} Absolute URL ready to pass to Axios
137
+ */
138
+ export function resolveURL(endpoint) {
139
+ const override = endpoint?.group && endpoint?.name
140
+ ? _config.endpointOverrides?.[endpoint.group]?.[endpoint.name]
141
+ : undefined
142
+ return override ?? (getApiURL() + endpoint.URL)
143
+ }
@@ -18,15 +18,20 @@ export default function ComponentsTab() {
18
18
  isDataOnly: true,
19
19
  isPagination: false
20
20
  })
21
- if (response) setWidgets(response)
21
+ if (Array.isArray(response)) setWidgets(response)
22
22
  } catch (error) {
23
23
  console.error(error)
24
24
  }
25
25
  }
26
26
 
27
27
  const sections = useMemo(() => {
28
- // 1) Group widgets
29
- const grouped = Object.groupBy(widgets, x => x.widgetCategory?.name ?? 'Widgets')
28
+ // 1) Group widgets (manual groupBy — Object.groupBy requires Chrome 117+ / Node 21+)
29
+ const safeWidgets = Array.isArray(widgets) ? widgets : []
30
+ const grouped = safeWidgets.reduce((acc, x) => {
31
+ const key = x.widgetCategory?.name ?? 'Widgets'
32
+ ;(acc[key] ??= []).push(x)
33
+ return acc
34
+ }, {})
30
35
  // 2) Convert grouped → sections
31
36
  const newSections = Object.entries(grouped).map(([key, items]) => ({
32
37
  key,