@applica-software-guru/react-admin 1.2.117 → 1.2.119

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": "@applica-software-guru/react-admin",
3
- "version": "1.2.117",
3
+ "version": "1.2.119",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,8 +4,7 @@ import { Card, Collapse, List, ListItem, ListItemProps, ListItemIcon, ListItemTe
4
4
  import { useSetActiveItem, useSyncWithLocation } from './Provider';
5
5
  import { IItem } from './types';
6
6
  import { useCallback, useMemo, useState } from 'react';
7
- import { useNavigate } from 'react-router';
8
- import { useChildren, useIsActive } from './hooks';
7
+ import { useChildren, useIsActive, useNavigateForm } from './hooks';
9
8
  import { ExpandLess, ExpandMore } from '@mui/icons-material';
10
9
  import { getLevel } from './utils';
11
10
  import { useThemeConfig } from '../../../hooks';
@@ -93,7 +92,7 @@ function useNavMenuItem(
93
92
  const { id } = item,
94
93
  isActive = useIsActive(id),
95
94
  level = getLevel(id),
96
- navigate = useNavigate(),
95
+ navigate = useNavigateForm(),
97
96
  syncWithLocation = useSyncWithLocation(),
98
97
  setActiveItem = useSetActiveItem(),
99
98
  items = useChildren(id),
@@ -1,10 +1,11 @@
1
1
  import { createContext, useCallback, useContext, useEffect, useMemo, useReducer } from 'react';
2
2
  import _ from 'lodash';
3
3
  import { IItem } from './types';
4
- import { useLocation } from 'react-router';
4
+ import { matchPath, useLocation } from 'react-router';
5
5
  import { getItemsIds } from './utils';
6
6
 
7
7
  enum ActionType {
8
+ SET_FORM_ROOT_PATH = 'setFormRootPath',
8
9
  SET_SYNC_WITH_LOCATION = 'setSyncWithLocation',
9
10
  SET_ACTIVE_ITEM = 'setActiveItem',
10
11
  ADD_ITEM = 'addItem',
@@ -13,13 +14,19 @@ enum ActionType {
13
14
 
14
15
  type IProviderProps = React.PropsWithChildren<{
15
16
  syncWithLocation?: boolean;
17
+ rootMatchString?: string;
16
18
  }>;
17
19
  type IState = {
20
+ formRootPath?: string;
18
21
  syncWithLocation: boolean;
19
22
  items: Array<IItem>;
20
23
  activeItem?: string;
21
24
  };
22
25
  type IAction =
26
+ | {
27
+ type: ActionType.SET_FORM_ROOT_PATH;
28
+ payload: string;
29
+ }
23
30
  | {
24
31
  type: ActionType.SET_SYNC_WITH_LOCATION;
25
32
  payload: boolean;
@@ -46,6 +53,8 @@ function reducer(state: IState, action: IAction): IState {
46
53
  const newState = _.clone(state),
47
54
  { type, payload } = action;
48
55
  switch (type) {
56
+ case ActionType.SET_FORM_ROOT_PATH:
57
+ return _.extend(newState, { formRootPath: payload });
49
58
  case ActionType.SET_SYNC_WITH_LOCATION:
50
59
  return _.extend(newState, { syncWithLocation: payload });
51
60
  case ActionType.SET_ACTIVE_ITEM:
@@ -85,11 +94,40 @@ const Context = createContext<IContext | undefined>(undefined);
85
94
 
86
95
  function Provider(props: IProviderProps) {
87
96
  const syncWithLocation = Boolean(props.syncWithLocation ?? true),
97
+ { rootMatchString } = props,
88
98
  { pathname } = useLocation(),
89
99
  [state, dispatch] = useReducer(reducer, _.cloneDeep(DefaultState)),
90
- { items } = state,
100
+ { formRootPath, items } = state,
91
101
  value = useMemo(() => ({ state: state, dispatch: dispatch }), [state, dispatch]);
92
102
 
103
+ useEffect(() => {
104
+ // I possibili match sono ordinati per priorità (è fondamentale).
105
+ const matchStrings = [
106
+ 'entities/:resource/create/*',
107
+ ':resource/create/*',
108
+ 'entities/:resource/:id/show',
109
+ ':resource/:id/show',
110
+ 'entities/:resource/:id/*',
111
+ ':resource/:id/*'
112
+ ];
113
+ if (rootMatchString !== undefined) {
114
+ matchStrings.push(rootMatchString);
115
+ }
116
+ const match = _.chain(matchStrings)
117
+ .map((s) => matchPath(s, pathname))
118
+ .reject((m) => m === null)
119
+ .first()
120
+ .value(),
121
+ pathnameBase = match?.pathnameBase;
122
+
123
+ if (pathnameBase !== undefined && pathnameBase !== formRootPath) {
124
+ dispatch({
125
+ type: ActionType.SET_FORM_ROOT_PATH,
126
+ payload: pathnameBase
127
+ });
128
+ }
129
+ }, [pathname, formRootPath, rootMatchString]);
130
+
93
131
  useEffect(() => {
94
132
  dispatch({
95
133
  type: ActionType.SET_SYNC_WITH_LOCATION,
@@ -98,16 +136,14 @@ function Provider(props: IProviderProps) {
98
136
  }, [syncWithLocation, dispatch]);
99
137
 
100
138
  useEffect(() => {
101
- if (syncWithLocation) {
102
- const match = pathname.match(/([^/]+)$/);
103
- if (match && match[0]) {
104
- dispatch({
105
- type: ActionType.SET_ACTIVE_ITEM,
106
- payload: match[0]
107
- });
108
- }
139
+ if (syncWithLocation && formRootPath !== undefined) {
140
+ const locationItem = pathname.replace(`${formRootPath}/`, '');
141
+ dispatch({
142
+ type: ActionType.SET_ACTIVE_ITEM,
143
+ payload: locationItem
144
+ });
109
145
  }
110
- }, [dispatch, pathname, syncWithLocation, items]);
146
+ }, [dispatch, formRootPath, pathname, items]);
111
147
 
112
148
  return <Context.Provider value={value}>{props.children}</Context.Provider>;
113
149
  }
@@ -132,6 +168,11 @@ function useFormDispatch(): IDispatch {
132
168
  return context.dispatch;
133
169
  }
134
170
 
171
+ function useFormRootPath(): string | undefined {
172
+ const state = useFormState();
173
+ return state.formRootPath;
174
+ }
175
+
135
176
  function useActiveItem(): string | undefined {
136
177
  const state = useFormState();
137
178
  return state.activeItem;
@@ -192,5 +233,5 @@ function useRemoveItem(): (item: string | IItem) => void {
192
233
  return removeItem;
193
234
  }
194
235
 
195
- export { Provider, useItems, useSyncWithLocation, useActiveItem, useSetActiveItem, useAddItem, useRemoveItem };
236
+ export { Provider, useItems, useSyncWithLocation, useFormRootPath, useActiveItem, useSetActiveItem, useAddItem, useRemoveItem };
196
237
  export type { IProviderProps };
@@ -1,8 +1,9 @@
1
1
  import _ from 'lodash';
2
- import { useMemo } from 'react';
3
- import { useActiveItem, useItems } from './Provider';
2
+ import { useCallback, useMemo } from 'react';
3
+ import { useActiveItem, useFormRootPath, useItems } from './Provider';
4
4
  import { IItem } from './types';
5
5
  import { getLevel, isChild } from './utils';
6
+ import { useNavigate } from 'react-router';
6
7
 
7
8
  function useIsActive(id: string): boolean {
8
9
  const activeItem = useActiveItem();
@@ -22,4 +23,17 @@ function useChildren(id?: string): Array<IItem> {
22
23
  return children;
23
24
  }
24
25
 
25
- export { useChildren, useIsActive };
26
+ function useNavigateForm(): (id: string) => void {
27
+ const formRootPath = useFormRootPath(),
28
+ navigate = useNavigate(),
29
+ navigateSection = useCallback(
30
+ (id: string) => {
31
+ navigate(`${formRootPath}/${id}`);
32
+ },
33
+ [formRootPath, navigate]
34
+ );
35
+
36
+ return navigateSection;
37
+ }
38
+
39
+ export { useChildren, useIsActive, useNavigateForm };
@@ -1,7 +1,16 @@
1
1
  import { Form } from './Form';
2
2
  import { BaseForm } from './BaseForm';
3
3
  import { Content } from './Content';
4
- import { Provider, useActiveItem, useItems, useSyncWithLocation, useSetActiveItem, useAddItem, useRemoveItem } from './Provider';
4
+ import {
5
+ Provider,
6
+ useActiveItem,
7
+ useItems,
8
+ useSyncWithLocation,
9
+ useSetActiveItem,
10
+ useAddItem,
11
+ useRemoveItem,
12
+ useFormRootPath
13
+ } from './Provider';
5
14
  import { Sidebar, SidebarSection, SidebarSectionPosition, useSidebarChildren } from './Sidebar';
6
15
  import { NavMenu, NavMenuItem, useNavMenuItem } from './NavMenu';
7
16
  import { Tab, Group, useBaseItemChildren } from './Tab';
@@ -12,6 +21,7 @@ type IForm = typeof Form & {
12
21
  Provider: typeof Provider;
13
22
  useItems: typeof useItems;
14
23
  useSyncWithLocation: typeof useSyncWithLocation;
24
+ useFormRootPath: typeof useFormRootPath;
15
25
  useActiveItem: typeof useActiveItem;
16
26
  useSetActiveItem: typeof useSetActiveItem;
17
27
  useAddItem: typeof useAddItem;
@@ -34,6 +44,7 @@ DefaultForm.Content = Content;
34
44
  DefaultForm.Provider = Provider;
35
45
  DefaultForm.useItems = useItems;
36
46
  DefaultForm.useSyncWithLocation = useSyncWithLocation;
47
+ DefaultForm.useFormRootPath = useFormRootPath;
37
48
  DefaultForm.useActiveItem = useActiveItem;
38
49
  DefaultForm.useSetActiveItem = useSetActiveItem;
39
50
  DefaultForm.useAddItem = useAddItem;