@dashadmin/dash-admin-state 1.3.25 → 1.3.28
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/dist/DefaultThemeSettings.js +34 -1
- package/dist/defaults/defaultAuth.js +9 -1
- package/dist/defaults/defaultCommon.js +44 -1
- package/dist/defaults/defaultFormState.js +5 -1
- package/dist/defaults/defaultPage.js +9 -1
- package/dist/defaults/defaultSettings.js +51 -1
- package/dist/hooks/DashAdminStateSelectors.js +149 -1
- package/dist/hooks/useLocalStorage.js +69 -1
- package/dist/index.js +41 -691
- package/dist/redux/ReduxStoreAccesor.js +19 -1
- package/dist/redux/actions/ActionTypes.js +84 -1
- package/dist/redux/actions/Auth.js +6 -1
- package/dist/redux/actions/Common.js +51 -1
- package/dist/redux/actions/ComponentData.js +33 -1
- package/dist/redux/actions/Menu.js +5 -1
- package/dist/redux/actions/Page.js +7 -1
- package/dist/redux/actions/Resources.js +21 -1
- package/dist/redux/actions/Setting.js +90 -1
- package/dist/redux/actions/index.js +6 -1
- package/dist/redux/reducers/Auth.js +55 -1
- package/dist/redux/reducers/Common.js +134 -1
- package/dist/redux/reducers/ComponentData.js +59 -1
- package/dist/redux/reducers/FormData.js +32 -1
- package/dist/redux/reducers/Menu.js +22 -1
- package/dist/redux/reducers/Page.js +30 -1
- package/dist/redux/reducers/Resources.js +19 -1
- package/dist/redux/reducers/Settings.js +79 -1
- package/dist/redux/reducers/index.js +25 -1
- package/dist/redux/sagas/index.js +9 -1
- package/dist/redux/store/index.js +35 -1
- package/package.json +75 -57
- package/src/DefaultThemeSettings.tsx +33 -0
- package/src/defaults/defaultAuth.tsx +8 -0
- package/src/defaults/defaultCommon.tsx +55 -0
- package/src/defaults/defaultFormState.tsx +4 -0
- package/src/defaults/defaultPage.tsx +9 -0
- package/src/defaults/defaultSettings.tsx +61 -0
- package/src/hooks/DashAdminStateSelectors.tsx +142 -0
- package/src/hooks/useLocalStorage.tsx +79 -0
- package/src/index.tsx +34 -0
- package/src/redux/ReduxStoreAccesor.tsx +18 -0
- package/src/redux/actions/ActionTypes.tsx +47 -0
- package/src/redux/actions/Auth.tsx +5 -0
- package/src/redux/actions/Common.tsx +51 -0
- package/src/redux/actions/ComponentData.tsx +78 -0
- package/src/redux/actions/Menu.tsx +4 -0
- package/src/redux/actions/Page.tsx +6 -0
- package/src/redux/actions/Resources.tsx +19 -0
- package/src/redux/actions/Setting.tsx +91 -0
- package/src/redux/actions/index.tsx +7 -0
- package/src/redux/interfaces/IAuthState.tsx +7 -0
- package/src/redux/interfaces/ICommonState.tsx +25 -0
- package/src/redux/interfaces/IComponentData.tsx +32 -0
- package/src/redux/interfaces/IDASHAppState.tsx +53 -0
- package/src/redux/interfaces/IDashResourceGroupsIcons.tsx +5 -0
- package/src/redux/interfaces/IFormDataState.tsx +6 -0
- package/src/redux/interfaces/IPage.tsx +27 -0
- package/src/redux/interfaces/IResources.tsx +0 -0
- package/src/redux/interfaces/ISettings.tsx +27 -0
- package/src/redux/reducers/Auth.tsx +38 -0
- package/src/redux/reducers/Common.tsx +144 -0
- package/src/redux/reducers/ComponentData.tsx +52 -0
- package/src/redux/reducers/FormData.tsx +21 -0
- package/src/redux/reducers/Menu.tsx +27 -0
- package/src/redux/reducers/Page.tsx +17 -0
- package/src/redux/reducers/Resources.tsx +19 -0
- package/src/redux/reducers/Settings.tsx +78 -0
- package/src/redux/reducers/index.tsx +25 -0
- package/src/redux/sagas/index.tsx +8 -0
- package/src/redux/store/index.tsx +33 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FETCH_ERROR,
|
|
3
|
+
FETCH_START,
|
|
4
|
+
FETCH_SUCCESS,
|
|
5
|
+
HIDE_MESSAGE,
|
|
6
|
+
SHOW_MESSAGE,
|
|
7
|
+
LOADING,
|
|
8
|
+
CONTENT_WIDTH,
|
|
9
|
+
CONTENT_HEIGHT,
|
|
10
|
+
SET_HEADER_COMPONENTS,
|
|
11
|
+
SET_PANEL_SETTINGS,
|
|
12
|
+
} from '../actions/ActionTypes';
|
|
13
|
+
import { TOGGLE_COLLAPSED_NAV, WINDOW_WIDTH } from '../actions/ActionTypes';
|
|
14
|
+
import ICommonState from '../interfaces/ICommonState';
|
|
15
|
+
import defaultCommon from '../../defaults/defaultCommon'; // Import the default
|
|
16
|
+
import { dashStorage } from 'dash-utils';
|
|
17
|
+
// Helper function to save nav state to localStorage
|
|
18
|
+
const saveNavState = (navExpanded: boolean, navSize: "large" | "small"): void => {
|
|
19
|
+
try {
|
|
20
|
+
dashStorage.setItem('dashNavExpanded', String(navExpanded));
|
|
21
|
+
dashStorage.setItem('dashNavSize', navSize);
|
|
22
|
+
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.error('Failed to save navigation state to localStorage:', e);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const CommonReducer = (
|
|
29
|
+
state: ICommonState = defaultCommon, // Use the imported default instead of inline object
|
|
30
|
+
action,
|
|
31
|
+
) => {
|
|
32
|
+
switch (action.type) {
|
|
33
|
+
case '@@router/LOCATION_CHANGE': {
|
|
34
|
+
return {
|
|
35
|
+
...state,
|
|
36
|
+
pathname: action.payload.location.pathname,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
case 'SET_COMPONENT_STATE':
|
|
41
|
+
return {
|
|
42
|
+
...state,
|
|
43
|
+
componentsState: {
|
|
44
|
+
...state.componentsState,
|
|
45
|
+
[action.componentId]: action.state,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
case 'UNSET_COMPONENT_STATE':
|
|
49
|
+
let componentStates = { ...state.componentsState }; // Create copy instead of mutating
|
|
50
|
+
delete componentStates[action.componentId];
|
|
51
|
+
return {
|
|
52
|
+
...state,
|
|
53
|
+
componentsState: componentStates, // Fixed typo: was componentStates, should be componentsState
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
case SET_HEADER_COMPONENTS:
|
|
57
|
+
return {
|
|
58
|
+
...state,
|
|
59
|
+
headerToolBar: action.headerToolBar,
|
|
60
|
+
headerToolBarReplace: action.headerToolBarReplace ?? state.headerToolBarReplace,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
case SET_PANEL_SETTINGS:
|
|
64
|
+
return {
|
|
65
|
+
...state,
|
|
66
|
+
panelSettings: {...state.panelSettings,...action.panelSettings},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
case CONTENT_WIDTH:
|
|
70
|
+
return {
|
|
71
|
+
...state,
|
|
72
|
+
content_width: parseInt(action.width),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
case CONTENT_HEIGHT:
|
|
76
|
+
return {
|
|
77
|
+
...state,
|
|
78
|
+
content_height: parseInt(action.height),
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
case WINDOW_WIDTH:
|
|
82
|
+
console.log('updating width', action.width, {
|
|
83
|
+
...state,
|
|
84
|
+
width: action.width,
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
...state,
|
|
88
|
+
width: action.width,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
case TOGGLE_COLLAPSED_NAV: {
|
|
92
|
+
const newNavExpanded = action.navExpanded;
|
|
93
|
+
// Save to localStorage when toggling
|
|
94
|
+
saveNavState(newNavExpanded, state.navSize);
|
|
95
|
+
return {
|
|
96
|
+
...state,
|
|
97
|
+
navExpanded: newNavExpanded,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
case 'SET_NAV_EXPANDED': {
|
|
102
|
+
const newNavExpanded = action.payload;
|
|
103
|
+
// Save to localStorage when setting nav expanded
|
|
104
|
+
saveNavState(newNavExpanded, state.navSize);
|
|
105
|
+
return {
|
|
106
|
+
...state,
|
|
107
|
+
navExpanded: newNavExpanded,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
case 'SET_NAV_SIZE': {
|
|
112
|
+
const newNavSize = action.payload;
|
|
113
|
+
// Save to localStorage when setting nav size
|
|
114
|
+
saveNavState(state.navExpanded, newNavSize);
|
|
115
|
+
return {
|
|
116
|
+
...state,
|
|
117
|
+
navSize: newNavSize,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
case FETCH_START: {
|
|
122
|
+
return { ...state, error: '', message: '', loading: true };
|
|
123
|
+
}
|
|
124
|
+
case FETCH_SUCCESS: {
|
|
125
|
+
return { ...state, error: '', message: '', loading: false };
|
|
126
|
+
}
|
|
127
|
+
case SHOW_MESSAGE: {
|
|
128
|
+
return { ...state, error: '', message: action.payload, loading: false };
|
|
129
|
+
}
|
|
130
|
+
case LOADING: {
|
|
131
|
+
return { ...state, loading: action.payload };
|
|
132
|
+
}
|
|
133
|
+
case FETCH_ERROR: {
|
|
134
|
+
return { ...state, loading: false, error: action.payload, message: '' };
|
|
135
|
+
}
|
|
136
|
+
case HIDE_MESSAGE: {
|
|
137
|
+
return { ...state, loading: false, error: '', message: '' };
|
|
138
|
+
}
|
|
139
|
+
default:
|
|
140
|
+
return state;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export default CommonReducer;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import IComponentDataState from '../interfaces/IComponentData';
|
|
2
|
+
import {
|
|
3
|
+
ComponentDataActionTypes,
|
|
4
|
+
SET_COMPONENT_DATA,
|
|
5
|
+
CLEAR_COMPONENT_DATA,
|
|
6
|
+
REMOVE_COMPONENT_DATA_KEY,
|
|
7
|
+
MERGE_COMPONENT_DATA
|
|
8
|
+
} from '../actions/ComponentData';
|
|
9
|
+
|
|
10
|
+
const INITIAL_STATE: IComponentDataState = {};
|
|
11
|
+
|
|
12
|
+
const ComponentDataReducer = (
|
|
13
|
+
state: IComponentDataState = INITIAL_STATE,
|
|
14
|
+
action: ComponentDataActionTypes
|
|
15
|
+
): IComponentDataState => {
|
|
16
|
+
switch (action.type) {
|
|
17
|
+
case SET_COMPONENT_DATA:
|
|
18
|
+
return {
|
|
19
|
+
...state,
|
|
20
|
+
[action.payload.key]: {
|
|
21
|
+
...action.payload.data,
|
|
22
|
+
_timestamp: Date.now(), // Add automatic timestamp
|
|
23
|
+
_version: '1.0' // Add version for cache invalidation
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
case MERGE_COMPONENT_DATA:
|
|
28
|
+
const existingData = state[action.payload.key] || {};
|
|
29
|
+
return {
|
|
30
|
+
...state,
|
|
31
|
+
[action.payload.key]: {
|
|
32
|
+
...existingData,
|
|
33
|
+
...action.payload.data,
|
|
34
|
+
_timestamp: Date.now(),
|
|
35
|
+
_version: existingData._version || '1.0'
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
case REMOVE_COMPONENT_DATA_KEY:
|
|
40
|
+
const newState = { ...state };
|
|
41
|
+
delete newState[action.payload.key];
|
|
42
|
+
return newState;
|
|
43
|
+
|
|
44
|
+
case CLEAR_COMPONENT_DATA:
|
|
45
|
+
return INITIAL_STATE;
|
|
46
|
+
|
|
47
|
+
default:
|
|
48
|
+
return state;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default ComponentDataReducer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import defaultFormState from '../../defaults/defaultFormState';
|
|
2
|
+
import { CLEAR_FORM_DATA, SET_FORM_DATA } from '../actions/ActionTypes';
|
|
3
|
+
import IFormDataState from '../interfaces/IFormDataState';
|
|
4
|
+
const FormDataReducer = (
|
|
5
|
+
state: IFormDataState = defaultFormState,
|
|
6
|
+
action,
|
|
7
|
+
) => {
|
|
8
|
+
switch (action.type) {
|
|
9
|
+
case SET_FORM_DATA:
|
|
10
|
+
return {
|
|
11
|
+
...state,
|
|
12
|
+
...action.payload
|
|
13
|
+
};
|
|
14
|
+
case CLEAR_FORM_DATA:
|
|
15
|
+
return defaultFormState
|
|
16
|
+
default:
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default FormDataReducer;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
2
|
+
|
|
3
|
+
// This reducer is now deprecated - nav functionality moved to Common reducer
|
|
4
|
+
// Keep this file for backward compatibility but redirect to common state
|
|
5
|
+
|
|
6
|
+
export interface IMenuState {
|
|
7
|
+
// Empty - functionality moved to Common reducer
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const initialState: IMenuState = {};
|
|
11
|
+
|
|
12
|
+
const menuSlice = createSlice({
|
|
13
|
+
name: 'menu',
|
|
14
|
+
initialState,
|
|
15
|
+
reducers: {
|
|
16
|
+
// Deprecated - use common reducer actions instead
|
|
17
|
+
setNavExpanded(state, action: PayloadAction<boolean>) {
|
|
18
|
+
console.warn('menu/setNavExpanded is deprecated. Use common reducer actions instead.');
|
|
19
|
+
},
|
|
20
|
+
toggleNavExpanded(state) {
|
|
21
|
+
console.warn('menu/toggleNavExpanded is deprecated. Use common reducer actions instead.');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const { setNavExpanded, toggleNavExpanded } = menuSlice.actions;
|
|
27
|
+
export default menuSlice.reducer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import IPageState from '../interfaces/IPage';
|
|
2
|
+
|
|
3
|
+
export const ACTION_UPDATE_PAGE = 'UPDATE_PAGE';
|
|
4
|
+
|
|
5
|
+
const PageReducer = (state: IPageState = {}, action) => {
|
|
6
|
+
switch (action.type) {
|
|
7
|
+
case ACTION_UPDATE_PAGE:
|
|
8
|
+
return {
|
|
9
|
+
...state,
|
|
10
|
+
...action.payload,
|
|
11
|
+
};
|
|
12
|
+
default:
|
|
13
|
+
return state;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default PageReducer;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { APPEND_RESOURCES, SET_RESOURCES } from '../actions/ActionTypes';
|
|
2
|
+
|
|
3
|
+
// Any must be replaced by IDashAutoAdminResourceConfig[], and the initial state must be initialized with the initial resources.
|
|
4
|
+
const ResourcesReducer = (state: { items: any[] } = { items: [] }, action) => {
|
|
5
|
+
switch (action.type) {
|
|
6
|
+
case SET_RESOURCES:
|
|
7
|
+
return {
|
|
8
|
+
items: [...action.payload],
|
|
9
|
+
};
|
|
10
|
+
case APPEND_RESOURCES:
|
|
11
|
+
return {
|
|
12
|
+
items: [...state.items, ...action.payload],
|
|
13
|
+
};
|
|
14
|
+
default:
|
|
15
|
+
return state;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default ResourcesReducer;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import DefaultThemeSettings from '../../DefaultThemeSettings';
|
|
2
|
+
import {
|
|
3
|
+
UPDATE_THEME_SETTINGS,
|
|
4
|
+
SWITCH_LANGUAGE,
|
|
5
|
+
SET_RESOURCES,
|
|
6
|
+
} from '../actions/ActionTypes';
|
|
7
|
+
|
|
8
|
+
import ISettingsState from '../interfaces/ISettings';
|
|
9
|
+
|
|
10
|
+
const SettingsReducer = (
|
|
11
|
+
state: ISettingsState = {
|
|
12
|
+
loading: false,
|
|
13
|
+
navStyle: undefined,
|
|
14
|
+
layoutType: '',
|
|
15
|
+
themeType: undefined,
|
|
16
|
+
themeColor: '',
|
|
17
|
+
isDirectionRTL: false,
|
|
18
|
+
/* @ts-ignore */
|
|
19
|
+
locale: {
|
|
20
|
+
languageId: '',
|
|
21
|
+
locale: '',
|
|
22
|
+
name: '',
|
|
23
|
+
icon: '',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
action,
|
|
27
|
+
) => {
|
|
28
|
+
switch (action.type) {
|
|
29
|
+
case SET_RESOURCES:
|
|
30
|
+
return {
|
|
31
|
+
...state,
|
|
32
|
+
resources: action.payload,
|
|
33
|
+
};
|
|
34
|
+
case DefaultThemeSettings.THEME_TYPE:
|
|
35
|
+
return {
|
|
36
|
+
...state,
|
|
37
|
+
themeType: action.themeType,
|
|
38
|
+
};
|
|
39
|
+
case DefaultThemeSettings.THEME_COLOR:
|
|
40
|
+
return {
|
|
41
|
+
...state,
|
|
42
|
+
themeColor: action.themeColor,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
case DefaultThemeSettings.UPDATE_RTL_STATUS:
|
|
46
|
+
return {
|
|
47
|
+
...state,
|
|
48
|
+
isDirectionRTL: action.rtlStatus,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
case UPDATE_THEME_SETTINGS:
|
|
52
|
+
return {
|
|
53
|
+
...state,
|
|
54
|
+
...action.payload,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
case DefaultThemeSettings.NAV_STYLE:
|
|
58
|
+
return {
|
|
59
|
+
...state,
|
|
60
|
+
navStyle: action.navStyle,
|
|
61
|
+
};
|
|
62
|
+
case DefaultThemeSettings.LAYOUT_TYPE:
|
|
63
|
+
return {
|
|
64
|
+
...state,
|
|
65
|
+
layoutType: action.layoutType,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
case SWITCH_LANGUAGE:
|
|
69
|
+
return {
|
|
70
|
+
...state,
|
|
71
|
+
locale: action.payload,
|
|
72
|
+
};
|
|
73
|
+
default:
|
|
74
|
+
return state;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default SettingsReducer;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { combineReducers } from 'redux';
|
|
2
|
+
import SettingsReducer from './Settings';
|
|
3
|
+
import AuthReducer from './Auth';
|
|
4
|
+
import CommonReducer from './Common';
|
|
5
|
+
import PageReducer from './Page';
|
|
6
|
+
import ResourcesReducer from './Resources';
|
|
7
|
+
import FormDataReducer from './FormData';
|
|
8
|
+
import MenuReducer from './Menu';
|
|
9
|
+
import ComponentDataReducer from './ComponentData';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export const createRootReducer = (/*history*/) =>
|
|
13
|
+
combineReducers({
|
|
14
|
+
//router: connectRouter(history),
|
|
15
|
+
page: PageReducer,
|
|
16
|
+
settings: SettingsReducer,
|
|
17
|
+
auth: AuthReducer,
|
|
18
|
+
common: CommonReducer,
|
|
19
|
+
resources: ResourcesReducer,
|
|
20
|
+
formData: FormDataReducer,
|
|
21
|
+
menu: MenuReducer,
|
|
22
|
+
componentData: ComponentDataReducer,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default createRootReducer;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import createSagaMiddleware from 'redux-saga';
|
|
2
|
+
import { applyMiddleware, compose } from 'redux';
|
|
3
|
+
import { routerMiddleware } from 'connected-react-router';
|
|
4
|
+
import rootSaga from '../sagas/index';
|
|
5
|
+
import createRootReducer from '../reducers';
|
|
6
|
+
import { createBrowserHistory } from 'history';
|
|
7
|
+
import { legacy_createStore as createStore } from 'redux';
|
|
8
|
+
import { thunk } from 'redux-thunk';
|
|
9
|
+
|
|
10
|
+
export const history = createBrowserHistory();
|
|
11
|
+
const routeMiddleware = routerMiddleware(history);
|
|
12
|
+
const sagaMiddleware = createSagaMiddleware();
|
|
13
|
+
|
|
14
|
+
const middlewares = [thunk, sagaMiddleware, routeMiddleware];
|
|
15
|
+
|
|
16
|
+
export const configureStore = (preloadedState?: {}) => {
|
|
17
|
+
const store = createStore(
|
|
18
|
+
createRootReducer(/*history*/), // root reducer with router state
|
|
19
|
+
preloadedState,
|
|
20
|
+
compose(
|
|
21
|
+
applyMiddleware(
|
|
22
|
+
routerMiddleware(history), // for dispatching history actions
|
|
23
|
+
...middlewares as any[],
|
|
24
|
+
),
|
|
25
|
+
),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
sagaMiddleware.run(rootSaga, {});
|
|
29
|
+
|
|
30
|
+
return store;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default configureStore;
|