procode-lowcode-core 1.0.8 → 1.0.10

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolves a relative app path by prepending the homePage prefix
3
+ * extracted from the current URL.
4
+ *
5
+ * e.g. if env.homePage = "/:appCode" and current URL is "/VARSTAGRxxpPq0ECRMBbnHC/workflows",
6
+ * resolveAppPath("/workflows") returns "/VARSTAGRxxpPq0ECRMBbnHC/workflows"
7
+ */
8
+ export declare const resolveAppPath: (pathname: string) => string;
@@ -7,5 +7,6 @@ export type { IViewModelHandler } from './DataModel/IViewModelHandler';
7
7
  export type { IStorage } from './StorageManager/IStorage';
8
8
  export type { default as IValidationFactory } from './Validation/IValidationFactory';
9
9
  export type { ISchemaReaderProvider } from './UIElement/ISchemaReaderProvider';
10
+ export { resolveAppPath } from './Utils/resolveAppPath';
10
11
  export declare const coreStyles = "./Assets/styles/index.scss";
11
12
  export declare const getCoreStylesPath: () => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "procode-lowcode-core",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "ProCode Core Library - React framework for low-code applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -7,11 +7,11 @@ import handleNavigation from "./handleNavigation";
7
7
  import { appActions } from "../../Store/Slices/appSlice";
8
8
 
9
9
  const handleCreateAndNavigate = async (
10
- actionInvokerProps: ActionInvokerProperties
10
+ actionInvokerProps: ActionInvokerProperties,
11
11
  ) => {
12
12
  const eventService = actionInvokerProps.eventService;
13
13
  const dispatch = eventService?.emit(eventServiceType.DISPATCH_STORE);
14
- // const appActions = eventService?.emit(eventServiceType.DATASTATE_ACTION);
14
+ // const appActions = eventService?.emit(eventServiceType.DATASTATE_ACTION);
15
15
  const uiSchema = eventService?.emit(eventServiceType.UISCHEMA);
16
16
 
17
17
  const apiConfig =
@@ -28,14 +28,14 @@ const handleCreateAndNavigate = async (
28
28
  uiSchema.rootScreenElement,
29
29
  true,
30
30
  {},
31
- actionInvokerProps.executeValidation
31
+ actionInvokerProps.executeValidation,
32
32
  );
33
33
  validationResult.isSchemaValid = isSchemaValid;
34
34
  validationResult.schemaInvalidMessages = schemaInvalidMessages;
35
35
  }
36
36
 
37
37
  dispatch?.(
38
- appActions?.loadValidation(validationResult.schemaInvalidMessages)
38
+ appActions?.loadValidation(validationResult.schemaInvalidMessages),
39
39
  );
40
40
 
41
41
  if (validationResult.isSchemaValid) {
@@ -44,7 +44,7 @@ const handleCreateAndNavigate = async (
44
44
  ?.createModel(
45
45
  actionInvokerProps.viewModel.screenData,
46
46
  apiConfig,
47
- eventService
47
+ eventService,
48
48
  );
49
49
 
50
50
  handleNavigation(actionInvokerProps);
@@ -6,7 +6,7 @@ export const validateUiElementSchema = (
6
6
  uiElement: any,
7
7
  isSchemaValid: boolean,
8
8
  schemaInvalidMessages: Record<string, string[]>,
9
- executeValidation: ExecuteValidationFC
9
+ executeValidation: ExecuteValidationFC,
10
10
  ) => {
11
11
  if (
12
12
  uiElement.uiElementType === ScreenUIType.WIDGET &&
@@ -15,21 +15,24 @@ export const validateUiElementSchema = (
15
15
  const { isComponentValid, invalidMessages } = executeValidation({
16
16
  executeMode: ExecuteMode.ONSUBMIT,
17
17
  modifiedViewModel: undefined,
18
- screenDataField:uiElement.screenDataField,
19
- validations:uiElement.validations
18
+ screenDataField: uiElement.screenDataField,
19
+ validations: uiElement.validations,
20
20
  });
21
21
  isSchemaValid = isSchemaValid && isComponentValid;
22
22
  schemaInvalidMessages = {
23
23
  ...schemaInvalidMessages,
24
24
  [uiElement.screenDataField]: invalidMessages,
25
25
  };
26
- } else if (uiElement.uiElementType === ScreenUIType.LAYOUT) {
26
+ } else if (
27
+ uiElement.uiElementType === ScreenUIType.LAYOUT &&
28
+ uiElement.visible !== false
29
+ ) {
27
30
  uiElement.cells.forEach((cell: any) => {
28
31
  const result = validateUiElementSchema(
29
32
  cell,
30
33
  isSchemaValid,
31
34
  schemaInvalidMessages,
32
- executeValidation
35
+ executeValidation,
33
36
  );
34
37
  isSchemaValid = isSchemaValid && result.isSchemaValid;
35
38
  schemaInvalidMessages = {
@@ -37,13 +40,17 @@ export const validateUiElementSchema = (
37
40
  ...result.schemaInvalidMessages,
38
41
  };
39
42
  });
40
- } else if (uiElement.children && uiElement.children.length > 0) {
43
+ } else if (
44
+ uiElement.children &&
45
+ uiElement.children.length > 0 &&
46
+ uiElement.visible !== false
47
+ ) {
41
48
  uiElement.children.forEach((child: any) => {
42
49
  const result = validateUiElementSchema(
43
50
  child,
44
51
  isSchemaValid,
45
52
  schemaInvalidMessages,
46
- executeValidation
53
+ executeValidation,
47
54
  );
48
55
  isSchemaValid = isSchemaValid && result.isSchemaValid;
49
56
  schemaInvalidMessages = {
@@ -8,6 +8,7 @@ import { Provider } from "react-redux";
8
8
  import { commonStore } from "../Store/commonStore";
9
9
  import { loader } from "./helper";
10
10
  import RouterElement from "./Elements/RouterElement";
11
+ import { resolveAppPath } from "../Utils/resolveAppPath";
11
12
 
12
13
  export type CustomRoute = {
13
14
  path: string;
@@ -124,6 +125,25 @@ const AppRouter = (appRouterProps: AppRouterProps): prcElement => {
124
125
  },
125
126
  ]);
126
127
 
128
+ // Middleware: auto-prepend homePage prefix to all navigation paths.
129
+ // This intercepts useNavigate(), <Link>, <Navigate> — everything goes through router.navigate.
130
+ const originalNavigate = router.navigate.bind(router) as typeof router.navigate;
131
+ (router as any).navigate = (to: any, opts?: any) => {
132
+ if (typeof to === "number" || to === null) {
133
+ return originalNavigate(to, opts);
134
+ }
135
+ if (typeof to === "string") {
136
+ return originalNavigate(resolveAppPath(to), opts);
137
+ }
138
+ if (to?.pathname) {
139
+ return originalNavigate(
140
+ { ...to, pathname: resolveAppPath(to.pathname) },
141
+ opts,
142
+ );
143
+ }
144
+ return originalNavigate(to, opts);
145
+ };
146
+
127
147
  return <RouterProvider router={router} />;
128
148
  };
129
149
 
@@ -26,7 +26,7 @@ const Widget: React.FC<WidgetInjectorProps> = ({
26
26
  viewModel,
27
27
  validation,
28
28
  eventService,
29
- navigate
29
+ navigate,
30
30
  );
31
31
 
32
32
  const standardWidgets = AppDependenceyProvider.getInstance()
@@ -54,7 +54,12 @@ const Widget: React.FC<WidgetInjectorProps> = ({
54
54
  );
55
55
  }
56
56
 
57
- return <WidgetComponent {...widgetProps} />;
57
+ return (
58
+ <WidgetComponent
59
+ {...widgetProps}
60
+ availableValidations={schemaElementProps.validations}
61
+ />
62
+ );
58
63
  };
59
64
 
60
65
  export default Widget;
@@ -21,7 +21,7 @@ const Screen = ({
21
21
  useEffect(() => {
22
22
  eventService.subscribe(
23
23
  eventServiceType.UISCHEMA,
24
- () => uiSchemaState?.uiSchema
24
+ () => uiSchemaState?.uiSchema,
25
25
  );
26
26
  });
27
27
 
@@ -17,7 +17,7 @@ export type ReplaceHandler = (
17
17
  url: string,
18
18
  param: Param,
19
19
  eventService: EventService,
20
- routeParams?: any
20
+ routeParams?: any,
21
21
  ) => string;
22
22
 
23
23
  const replaceHandlers: Record<ValueReplacePolicy, ReplaceHandler> = {
@@ -28,14 +28,13 @@ const replaceHandlers: Record<ValueReplacePolicy, ReplaceHandler> = {
28
28
  [ValueReplacePolicy.ENVIROMENT]: enviromentHandler,
29
29
  [ValueReplacePolicy.QUERYPARAMS]: queryParamHandler,
30
30
  [ValueReplacePolicy.ROUTEPARAMS]: routeParamHandler,
31
-
32
31
  };
33
32
 
34
33
  export const replaceRequestParams = (
35
34
  url: string,
36
35
  params: Param[],
37
36
  eventService: EventService,
38
- routeParams?: any
37
+ routeParams?: any,
39
38
  ) => {
40
39
  params.forEach((param) => {
41
40
  let valueReplacePolicy = param.rightOperand.valueReplacePolicy;
@@ -48,7 +47,7 @@ export const replaceRequestParams = (
48
47
  const handler = replaceHandlers[valueReplacePolicy];
49
48
 
50
49
  if (handler) {
51
- url = handler(url, param, eventService,routeParams);
50
+ url = handler(url, param, eventService, routeParams);
52
51
  }
53
52
  });
54
53
  return url;
@@ -0,0 +1,22 @@
1
+ import { env } from "../Constant";
2
+
3
+ /**
4
+ * Resolves a relative app path by prepending the homePage prefix
5
+ * extracted from the current URL.
6
+ *
7
+ * e.g. if env.homePage = "/:appCode" and current URL is "/VARSTAGRxxpPq0ECRMBbnHC/workflows",
8
+ * resolveAppPath("/workflows") returns "/VARSTAGRxxpPq0ECRMBbnHC/workflows"
9
+ */
10
+ export const resolveAppPath = (pathname: string): string => {
11
+ if (!env.homePage || !pathname) return pathname;
12
+ const homePageSegmentCount = env.homePage.split("/").filter(Boolean).length;
13
+ const currentSegments = window.location.pathname
14
+ .split("/")
15
+ .filter(Boolean);
16
+ const prefix = "/" + currentSegments.slice(0, homePageSegmentCount).join("/");
17
+
18
+ // Avoid double-prepending
19
+ if (pathname.startsWith(prefix + "/") || pathname === prefix) return pathname;
20
+
21
+ return prefix + pathname;
22
+ };
package/src/index.ts CHANGED
@@ -26,6 +26,9 @@ export type { default as IValidationFactory } from './Validation/IValidationFact
26
26
  // Schema Reader Interface
27
27
  export type { ISchemaReaderProvider } from './UIElement/ISchemaReaderProvider';
28
28
 
29
+ // Utils
30
+ export { resolveAppPath } from './Utils/resolveAppPath';
31
+
29
32
  // Core Styles Path (for SCSS imports)
30
33
  export const coreStyles = './Assets/styles/index.scss';
31
34