Skip to content

Commit 403e5c9

Browse files
committed
release 4.5.3
2 parents 483e3b9 + 8e7c3aa commit 403e5c9

30 files changed

Lines changed: 1087 additions & 1608 deletions

.gitlab-ci.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ after_script:
3030
1_build_test_java:
3131
stage: 2_build_and_install
3232
script:
33-
#- cd backend
3433
- mvn clean
3534
- mvn test
3635

@@ -44,8 +43,6 @@ after_script:
4443
- npm install
4544
- rm -rf www/*.js
4645
- npm run build-dev
47-
#- cd backend
48-
# - ls -al www/
4946
- pwd
5047
- mvn clean deploy -DskipTests
5148
only:
@@ -106,8 +103,6 @@ after_script:
106103
- npm install
107104
- rm -rf www/*.js
108105
- npm run build
109-
#- cd backend
110-
# - ls -al www/
111106
- pwd
112107
- mvn clean deploy -DskipTests
113108
only:
@@ -118,15 +113,13 @@ after_script:
118113
stage: 4_sonarqube
119114
script:
120115
- cd $CI_PROJECT_DIR/
121-
#- cd backend
122116
- mvn sonar:sonar -Dsonar.analysis.mode=preview -Dsonar.projectName=$CI_PROJECT_NAME -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME -Dsonar.gitlab.project_id=$CI_PROJECT_ID
123117
when: manual
124118

125119
2_perun-sonarqube_backend_publish:
126120
stage: 4_sonarqube
127121
script:
128122
- cd $CI_PROJECT_DIR/
129-
#- cd backend
130123
- mvn sonar:sonar -Dsonar.analysis.mode=publish -Dsonar.projectName=$CI_PROJECT_NAME -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME -Dsonar.gitlab.project_id=$CI_PROJECT_ID -Donar.gitlab.user_token access=a18878c7b5beb401ce2f847537c296b46a3902b8
131124
environment:
132125
name: $CI_COMMIT_REF_NAME

frontend/assets/svg/svgHolder.js

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/client.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export {
3838
};
3939

4040
import { Button, DependencyDropdown, Dropdown, InputElement, alertUserV2, alertUserResponse } from './elements'
41+
import { Tooltip } from 'react-tooltip'
4142
import Form from '@rjsf/core';
4243
import validator from '@rjsf/validator-ajv8';
4344
import FormManager from './elements/form/FormManager'
@@ -49,12 +50,10 @@ import GenericGrid from './elements/grid/GenericGrid'
4950
import GridManager from './elements/grid/GridManager'
5051
import { ComponentManager } from './elements/ComponentManager'
5152
import Modal from './components/Modal/Modal.js'
52-
import MenuHolder from './components/MenuBuilder/MenuHolder'
53-
import ContextMenuHolder from './components/Menus/ContextMenu/ContextMenuHolder'
5453

5554
export {
56-
Form, Button, DependencyDropdown, Dropdown, InputElement, FormManager, GenericForm, ContextMenuPopup, CustomGridToolbar,
57-
ExportableGrid, GenericGrid, GridManager, ComponentManager, Modal, MenuHolder, ContextMenuHolder, validator
55+
Form, Tooltip, Button, DependencyDropdown, Dropdown, InputElement, FormManager, GenericForm, ContextMenuPopup, CustomGridToolbar,
56+
ExportableGrid, GenericGrid, GridManager, ComponentManager, Modal, validator
5857
};
5958

6059
/* check for arraybuffer response types */

frontend/components/AdminConsole/AdminConsole.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ import SvarogSystemParams from './SvarogSystemParams'
1212
import GeoLayerTypes from './GeoLayerTypes'
1313
import PerunPluginTable from './PerunPluginTable'
1414
import SvarogMenu from './SvarogMenu'
15+
import PerunMenu from './PerunMenu/PerunMenu'
1516
import BusinessType from './BusinessType'
1617
import CodeListEditor from './CodeListComp/CodeListEditor'
18+
import WorkFlow from './WorkFlow'
19+
import WorkFlowAutomaton from './WorkFlowAutomaton'
1720

1821
const AdminConsole = (_props, context) => {
1922
const [dynamicComponent, setDynamicComponent] = useState('UserManagement')
@@ -57,8 +60,10 @@ const AdminConsole = (_props, context) => {
5760
{dynamicComponent === 'OrganizationalUnit' && <OrganizationalUnit />}
5861
{dynamicComponent === 'PerunPluginTable' && <PerunPluginTable />}
5962
{dynamicComponent === 'SvarogMenu' && <SvarogMenu />}
63+
{dynamicComponent === 'PerunMenu' && <PerunMenu />}
6064
{dynamicComponent === 'BusinessType' && <BusinessType />}
6165
{dynamicComponent === 'CodeListEditor' && <CodeListEditor />}
66+
{dynamicComponent === 'WorkFlowAutomaton' && <WorkFlowAutomaton />}
6267
</div>
6368
</div>
6469
)
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import React, { useRef } from 'react'
2+
import PropTypes from 'prop-types'
3+
import { connect } from 'react-redux'
4+
import { ComponentManager, ExportableGrid, GenericForm, GridManager, axios } from '../../../client'
5+
import { alertUserResponse, alertUserV2, ReactBootstrap } from '../../../elements';
6+
import { Loading } from '../../ComponentsIndex';
7+
import PerunMenuWrapper from './PerunMenuWrapper';
8+
const { useReducer, useEffect } = React;
9+
const { Modal } = ReactBootstrap;
10+
11+
const PerunMenu = (props, context) => {
12+
const initialState = { loading: false, tableName: 'PERUN_MENU', gridId: 'PERUN_MENU_GRID', show: false, objectId: 0 }
13+
const reducer = (currState, update) => ({ ...currState, ...update })
14+
const [{ loading, tableName, gridId, show, objectId }, setState] = useReducer(reducer, initialState)
15+
16+
const uploadInputRef = useRef(null)
17+
18+
useEffect(() => {
19+
return () => {
20+
ComponentManager.cleanComponentReducerState(gridId);
21+
}
22+
}, []);
23+
24+
const reloadGrid = () => {
25+
GridManager.reloadGridData(gridId)
26+
ComponentManager.setStateForComponent(gridId, null, { rowClicked: undefined })
27+
}
28+
29+
const handleRowClick = (_id, _rowIdx, row) => {
30+
setState({ objectId: row[`${tableName}.OBJECT_ID`] || 0, show: true })
31+
};
32+
33+
const generatePerunMenuGrid = () => {
34+
const { svSession } = props;
35+
const buttonsArray = [
36+
{
37+
id: 'import_perun_menu',
38+
name: context.intl.formatMessage({ id: 'perun.admin_console.import_menu', defaultMessage: 'perun.admin_console.import_menu' }),
39+
action: () => uploadInputRef?.current?.click()
40+
},
41+
{
42+
id: 'add_perun_menu',
43+
name: context.intl.formatMessage({ id: 'perun.admin_console.add', defaultMessage: 'perun.admin_console.add' }),
44+
action: () => setState({ show: true, objectId: 0 })
45+
},
46+
]
47+
48+
return (
49+
<ExportableGrid
50+
gridType={'READ_URL'}
51+
key={gridId}
52+
id={gridId}
53+
configTableName={`/ReactElements/getTableFieldList/${svSession}/${tableName}`}
54+
dataTableName={`/ReactElements/getTableData/${props.svSession}/${tableName}/0`}
55+
onRowClickFunct={handleRowClick}
56+
refreshData={true}
57+
buttonsArray={buttonsArray}
58+
heightRatio={0.75}
59+
editContextFunc={handleRowClick}
60+
/>
61+
)
62+
};
63+
64+
const saveRecord = () => {
65+
const { svSession } = props
66+
const url = `${window.server}/Menu/add/${svSession}`
67+
const onConfirm = () => ComponentManager.setStateForComponent(`${tableName}_FORM`, null, { saveExecuted: false })
68+
const formData = ComponentManager.getStateForComponent(`${tableName}_FORM`, 'formTableData');
69+
const data = Object.assign({}, {
70+
...formData,
71+
OBJECT_ID: objectId,
72+
MENU_CONF: formData.MENU_CONF ? JSON.parse(formData.MENU_CONF) : undefined
73+
})
74+
const reqConfig = { method: 'post', data, url, headers: { 'Content-Type': 'application/json' } }
75+
axios(reqConfig).then((res) => {
76+
if (res?.data) {
77+
const resType = res.data?.type?.toLowerCase() || 'info'
78+
alertUserResponse({ type: resType, response: res, onConfirm })
79+
if (resType === 'success') {
80+
reloadGrid()
81+
setState({ show: false })
82+
}
83+
}
84+
}).catch(err => {
85+
console.error(err)
86+
alertUserResponse({ response: err, onConfirm })
87+
});
88+
};
89+
90+
const generatePerunMenuForm = (objectId) => {
91+
const { svSession } = props;
92+
return (
93+
<GenericForm
94+
params={'READ_URL'}
95+
key={`${tableName}_FORM`}
96+
id={`${tableName}_FORM`}
97+
method={`/ReactElements/getTableJSONSchema/${svSession}/${tableName}`}
98+
uiSchemaConfigMethod={`/ReactElements/getTableUISchema/${svSession}/${tableName}`}
99+
tableFormDataMethod={`/ReactElements/getTableFormData/${svSession}/${objectId}/${tableName}`}
100+
addSaveFunction={saveRecord}
101+
hideBtns={objectId === 0 ? 'closeAndDelete' : 'close'}
102+
addDeleteFunction={deleteFunc}
103+
className={'admin-settings-forms'}
104+
inputWrapper={PerunMenuWrapper}
105+
objectId={objectId}
106+
/>
107+
)
108+
};
109+
110+
const deleteFunc = (_id, _action, _session, formData) => {
111+
const { svSession } = props
112+
const onConfirm = () => ComponentManager.setStateForComponent(`${tableName}_FORM`, null, { deleteExecuted: false })
113+
const data = JSON.parse(formData[4]['PARAM_VALUE'])
114+
const menuCode = data.MENU_CODE
115+
const url = `${window.server}/Menu/remove/${svSession}/${menuCode}`
116+
axios.get(url).then(res => {
117+
if (res?.data) {
118+
const resType = res.data?.type?.toLowerCase() || 'info'
119+
alertUserResponse({ response: res, onConfirm })
120+
if (resType === 'success') {
121+
reloadGrid()
122+
setState({ show: false })
123+
}
124+
}
125+
}).catch(err => {
126+
console.error(err)
127+
alertUserResponse({ response: err, onConfirm })
128+
})
129+
}
130+
131+
const uploadFile = (file) => {
132+
setState({ loading: true })
133+
const { svSession } = props
134+
const data = new FormData()
135+
data.append('file', file)
136+
const url = `${window.server}/Menu/upload/${svSession}`
137+
const reqConfig = { method: 'post', data, url, headers: { 'Content-Type': 'multipart/form-data' } }
138+
axios(reqConfig).then(res => {
139+
setState({ loading: false })
140+
if (res?.data) {
141+
alertUserResponse({ response: res })
142+
if (res.data?.type?.toLowerCase() === 'success') {
143+
reloadGrid()
144+
}
145+
}
146+
}).catch(err => {
147+
console.error(err)
148+
setState({ loading: false })
149+
alertUserResponse({ response: err })
150+
})
151+
}
152+
153+
const handleFileSelection = (e) => {
154+
const notJSONLabel = context.intl.formatMessage({ id: 'perun.admin_console.file_is_not_json', defaultMessage: 'perun.admin_console.file_is_not_json' })
155+
const file = e.target.files[0]
156+
// Check if the selected file is valid JSON
157+
const fileReader = new FileReader()
158+
fileReader.onload = (e) => {
159+
try {
160+
JSON.parse(e.target.result)
161+
uploadFile(file)
162+
} catch (error) {
163+
alertUserV2({ type: 'info', title: notJSONLabel })
164+
}
165+
}
166+
fileReader.onerror = () => alertUserV2({ type: 'info', title: notJSONLabel })
167+
fileReader.readAsText(file)
168+
if (uploadInputRef?.current?.value) {
169+
uploadInputRef.current.value = ''
170+
}
171+
}
172+
173+
return (
174+
<>
175+
{loading && <Loading />}
176+
<input type='file' id='upload-perun-menu-input' ref={uploadInputRef} onInput={handleFileSelection} style={{ display: 'none' }} />
177+
<div className='admin-console-grid-container'>
178+
<div className='admin-console-component-header'>
179+
<p>{context.intl.formatMessage({ id: 'perun.admin_console.perun_menu', defaultMessage: 'perun.admin_console.perun_menu' })}</p>
180+
</div>
181+
{generatePerunMenuGrid()}
182+
</div>
183+
{show && (
184+
<Modal className='admin-console-unit-modal' show={show} onHide={() => setState({ show: false })}>
185+
<Modal.Header className='admin-console-unit-modal-header' closeButton>
186+
<Modal.Title>{context.intl.formatMessage({ id: 'perun.admin_console.add', defaultMessage: 'perun.admin_console.add' })}</Modal.Title>
187+
</Modal.Header>
188+
<Modal.Body className='admin-console-unit-modal-body'>
189+
{generatePerunMenuForm(objectId)}
190+
</Modal.Body>
191+
<Modal.Footer className='admin-console-unit-modal-footer'></Modal.Footer>
192+
</Modal>
193+
)}
194+
</>
195+
);
196+
};
197+
198+
const mapStateToProps = (state) => ({
199+
svSession: state.security.svSession,
200+
});
201+
202+
PerunMenu.contextTypes = {
203+
intl: PropTypes.object.isRequired
204+
}
205+
206+
export default connect(mapStateToProps)(PerunMenu);

0 commit comments

Comments
 (0)