-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(ZMS-3253 ZMS-3466 ZMS-3415 ZMS-1891): Replicate frontend validation in the backend for the availability opening hours to improve data integrity and frontend validation messaging #825
base: next
Are you sure you want to change the base?
Changes from 198 commits
310f536
bbd32b1
5543f36
03bc86e
ffcdb0a
47565c8
3f8030e
f5e08ed
e4b36ea
e5f123c
9528271
770e847
4a79605
cdd0d8c
8a1aa79
09c10fb
afd6d5d
ce5d795
07f74c8
da65ff3
93b2820
e0d41c4
bde21f3
0cd0ad1
29b7cff
9e11157
c2df444
5faea71
4cd3618
4840338
c8262a0
8281b0a
390aba7
78013ea
8a07621
7892fe0
9522585
d65ccb8
3fa84a1
317d127
c02e4e3
c75e3c4
2b39546
acb62ac
a16b2e4
1bd40cb
4025319
95dcef0
39ef3a6
3eb8912
46c0af9
fdd0c72
f319de3
b8fd6b6
a2691c1
fc26e13
bffc9fa
5784eb4
51e25ca
4f2a125
e8cae55
e0f4fa6
d17ffa2
8a41469
e230b26
5aadb7b
246b4d1
17dcb07
e984774
d5135e2
ca99ef2
d5c6051
5527c58
ad89835
2a7d978
ea55b27
932fe5f
5aa9d6b
fb7efb7
1fd8f65
f8f536f
e4981ff
7916a70
462be60
46db273
490ddce
2ce2363
735c579
97cee9c
a11f7b8
b620a54
e3375c1
e646a4c
8b7a1f6
2a3cbb7
4cbe423
0053e60
cab1b1d
ab51699
227e741
694194b
d53b28e
088356f
484cbb4
e92684e
faa90c0
8d863ce
ff16fc0
4043a66
860abc6
3a3491f
64c884b
36724e4
ea9b087
687af94
d86c998
39759a4
65d6e79
551438b
2f92832
36e81f3
c595cad
b7d7ac8
ce1dc34
1612ee4
b504141
0a49139
7402576
8e0cdc8
b89844d
75dd8ed
26b63cf
b9c938d
29049a6
97e70f1
4deb527
93bde12
4f31871
a52d441
5cf8728
5acfab2
a53f7c7
1e5cd4d
8824b41
308de88
20d6cbf
9dbb73a
d5e4f5b
e88a979
cc2a6c0
a45cbc2
33b5a73
ca2526a
0731d6f
11f7496
8fb3354
72646c3
896b327
3eaaa1b
52fc4cd
3b65923
35dfce4
fb01fac
ee65b9b
5745df3
c89eb94
b1a3d3c
5c82cb3
c6410ad
a943be8
2b0f8eb
c14d277
6419403
0dba8c3
d316efb
c6e2dc0
7f6f94f
cde1a14
68d68fb
61f3823
0151302
244cef3
9a315fe
f6a641a
6f98308
8e1c425
4cb3ded
1f28b01
fcf3a7d
85be2b5
4ebc9cc
393edf5
a6e2d58
27065a1
c4164cb
48e1fba
c4115e5
341674e
35d0ffb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,27 +1,91 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import React from 'react' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import PropTypes from 'prop-types' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import moment from 'moment' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const FooterButtons = (props) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { hasConflicts, stateChanged, data, onNew, onPublish, onAbort, hasSlotCountError } = props | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasConflicts, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasErrors, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stateChanged, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onNew, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onPublish, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onAbort, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasSlotCountError, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
availabilitylist, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectedDate | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} = props; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const hasNewAvailabilities = availabilitylist?.some( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
availability => availability?.tempId?.includes('__temp__') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const hasSplitInProgress = (() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let hasOriginWithId = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let hasExclusion = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let hasFuture = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
availabilitylist?.forEach(availability => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (availability?.kind) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (availability.kind === 'origin' && availability.id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasOriginWithId = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (availability.kind === 'exclusion') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasExclusion = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (availability.kind === 'future') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasFuture = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return hasOriginWithId && (hasExclusion || hasFuture); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
})(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider refactoring for better maintainability and testability. The current implementation has two areas for improvement:
Consider these improvements: - const hasNewAvailabilities = availabilitylist?.some(
- availability => availability?.tempId?.includes('__temp__')
- );
+ const hasNewAvailabilities = availabilitylist?.some(
+ availability => availability?.tempId?.includes('__temp__')
+ ) ?? false;
- const hasSplitInProgress = (() => {
- let hasOriginWithId = false;
- let hasExclusion = false;
- let hasFuture = false;
-
- availabilitylist?.forEach(availability => {
- if (availability?.kind) {
- if (availability.kind === 'origin' && availability.id) {
- hasOriginWithId = true;
- } else if (availability.kind === 'exclusion') {
- hasExclusion = true;
- } else if (availability.kind === 'future') {
- hasFuture = true;
- }
- }
- });
-
- return hasOriginWithId && (hasExclusion || hasFuture);
- })();
+ const checkSplitInProgress = (availabilitylist) => {
+ const kinds = availabilitylist?.reduce((acc, availability) => {
+ if (availability?.kind) {
+ acc[availability.kind] = true;
+ if (availability.kind === 'origin' && availability.id) {
+ acc.hasOriginWithId = true;
+ }
+ }
+ return acc;
+ }, {});
+ return kinds?.hasOriginWithId && (kinds?.exclusion || kinds?.future) ?? false;
+ };
+ const hasSplitInProgress = checkSplitInProgress(availabilitylist); This refactoring:
📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const isPastDate = moment.unix(selectedDate).isBefore(moment(), 'day'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="form-actions" style={{"marginTop":"0", "padding":"0.75em"}}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button title="Neue Öffnungszeit anlegen und bearbeiten" className="button button--diamond button-new" onClick={onNew} disabled={(stateChanged || hasConflicts || data)}>neue Öffnungszeit</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button title="Alle Änderungen werden zurückgesetzt" className="button btn" type="abort" onClick={onAbort} disabled={(!stateChanged && !hasConflicts && !data)}>Abbrechen</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button title="Alle Änderungen werden gespeichert" className="button button--positive button-save" type="save" value="publish" onClick={onPublish} disabled={(!stateChanged || hasSlotCountError)}>Alle Änderungen aktivieren | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="form-actions" style={{ "marginTop": "0", "padding": "0.75em" }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title="Neue Öffnungszeit anlegen und bearbeiten" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="button button--diamond button-new" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick={onNew} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled={data || hasConflicts || hasSplitInProgress || isPastDate} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
neue Öffnungszeit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title="Alle Änderungen werden zurückgesetzt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="button btn" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type="abort" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick={onAbort} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled={(!stateChanged && !hasNewAvailabilities && !hasConflicts && !hasErrors) || isPastDate} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Abbrechen | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title="Alle Änderungen werden gespeichert" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="button button--positive button-save" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type="save" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value="publish" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick={onPublish} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled={(!stateChanged && !hasNewAvailabilities) || hasSlotCountError || hasConflicts || hasErrors || isPastDate} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Alle Änderungen aktivieren | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FooterButtons.propTypes = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data: PropTypes.object, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasConflicts: PropTypes.bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasErrors: PropTypes.bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stateChanged: PropTypes.bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onNew: PropTypes.func, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onPublish: PropTypes.func, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onAbort: PropTypes.func | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onAbort: PropTypes.func, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasSlotCountError: PropTypes.bool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
availabilitylist: PropTypes.array, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectedDate: PropTypes.number.isRequired | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default FooterButtons | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default FooterButtons |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security Risk: Unsafe HTML rendering.
Using
dangerouslySetInnerHTML
with unsanitized content fromitem.message
exposes the application to XSS attacks.Consider these safer alternatives:
📝 Committable suggestion
🧰 Tools
🪛 Biome (1.9.4)
[error] 33-33: Avoid passing content using the dangerouslySetInnerHTML prop.
Setting content using code can expose users to cross-site scripting (XSS) attacks
(lint/security/noDangerouslySetInnerHtml)