Skip to content
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

Bugfix zms 3253 3466 3415 1891 validation opening hours of the same appointment type must not overlap #810

Closed
Show file tree
Hide file tree
Changes from 122 commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
310f536
fix(ZMS-3253): validate and block adding conflicting openingtimes
Nov 12, 2024
bbd32b1
fix(ZMS-3253): add backend validation for opening hours and improve f…
Nov 14, 2024
5543f36
fix(ZMS-3253): fix zmsentities unit test
Nov 14, 2024
03bc86e
fix(ZMS-3253): fix zmsdb unit test
Nov 14, 2024
ffcdb0a
fix(ZMS-3253): add logging to zmsapi tests
Nov 14, 2024
47565c8
fix(ZMS-3253): fix one zmsapi unit test
Nov 14, 2024
3f8030e
fix(ZMS-3253): try fix one zmsapi unit test
Nov 14, 2024
f5e08ed
fix(ZMS-3253): try fix one zmsapi unit test
Nov 14, 2024
e4b36ea
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
e5f123c
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
9528271
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
770e847
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
4a79605
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
cdd0d8c
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
8a1aa79
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
09c10fb
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
afd6d5d
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
ce5d795
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
07f74c8
Revert "fix(ZMS-3253): try fix some unit tests"
Nov 14, 2024
da65ff3
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
93b2820
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
e0d41c4
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
bde21f3
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
0cd0ad1
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
29b7cff
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
9e11157
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
c2df444
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
5faea71
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
4cd3618
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
4840338
fix(ZMS-3253): try fix some unit tests
Nov 14, 2024
c8262a0
fix(ZMS-3253): backend validation work in AvailabilityAdd
Nov 15, 2024
8281b0a
fix(ZMS-3253): correct backend validation for timeoverlaps
Nov 15, 2024
390aba7
fix(ZMS-3253): fix a validation
Nov 15, 2024
78013ea
fix(ZMS-3253): try fixing a test
Nov 15, 2024
8a07621
fix(ZMS-3253): try fixing a test
Nov 15, 2024
7892fe0
fix(ZMS-3253): try fixing a test
Nov 15, 2024
9522585
fix(ZMS-3253): try fixing a test
Nov 15, 2024
d65ccb8
fix(ZMS-3253): try fixing availability not found test
Nov 15, 2024
3fa84a1
fix(ZMS-3253): try fixing availability mockdata for testRendering
Nov 15, 2024
317d127
fix(ZMS-3253): try fixing availability mockdata for testRendering
Nov 15, 2024
c02e4e3
fix(ZMS-3253): try fixing availability mockdata for testRendering
Nov 15, 2024
c75e3c4
fix(ZMS-3253): try fixing availability mockdata for testRendering
Nov 15, 2024
2b39546
fix(ZMS-3253): try fixing availability mockdata for testRendering
Nov 15, 2024
acb62ac
fix(ZMS-3253): try fix missing scope testRendering
Nov 15, 2024
a16b2e4
fix(ZMS-3253): fix zmsadmin availabilities conflict test
Nov 15, 2024
1bd40cb
fix(ZMS-3253): show availability opening hour conflicts in the future…
Nov 15, 2024
4025319
fix(ZMS-3253): remove error_logs
Nov 15, 2024
95dcef0
fix(ZMS-3253): refactor function logic getDateTimeRangeFromList to on…
Nov 15, 2024
39ef3a6
Merge remote-tracking branch 'origin/next' into bugfix-zms-3253-valid…
Nov 15, 2024
3eb8912
fix(ZMS-3253): renable twig cache
Nov 15, 2024
46c0af9
fix(ZMS-3253): renable twig cache
Nov 15, 2024
fdd0c72
fix(ZMS-3253): fix unit test
ThomasAFink Nov 18, 2024
f319de3
fix(ZMS-3253): fix unit test
ThomasAFink Nov 18, 2024
b8fd6b6
fix(ZMS-3253): fix unit test
ThomasAFink Nov 18, 2024
a2691c1
fix(ZMS-3253): fix unit test
ThomasAFink Nov 18, 2024
fc26e13
fix(ZMS-3253): fix unit test
ThomasAFink Nov 18, 2024
bffc9fa
fix(ZMS-3253): fix unit test
ThomasAFink Nov 18, 2024
5784eb4
fix(ZMS-3253): try fix unit test
ThomasAFink Nov 18, 2024
51e25ca
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
4f2a125
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
e8cae55
fix(ZMS-3253): remove space
ThomasAFink Nov 18, 2024
e0f4fa6
fix(ZMS-3253): remove space
ThomasAFink Nov 18, 2024
d17ffa2
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
8a41469
fix(ZMS-3253): add unit tests for testing validation availability ope…
ThomasAFink Nov 18, 2024
e230b26
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
5aadb7b
fix(ZMS-3253): add unit tests for testing validation availability ope…
ThomasAFink Nov 18, 2024
246b4d1
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
17dcb07
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
e984774
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
d5135e2
fix(ZMS-3253): add unit tests for testing overlapping availability op…
ThomasAFink Nov 18, 2024
ca99ef2
fix(ZMS-3253): add unit tests for testing validation availability ope…
ThomasAFink Nov 18, 2024
d5c6051
fix(ZMS-3253): add unit tests for testing validation availability ope…
ThomasAFink Nov 18, 2024
5527c58
fix(ZMS-3253): refactor object creation
ThomasAFink Nov 18, 2024
ad89835
fix(ZMS-3253): refactor exception messages
ThomasAFink Nov 18, 2024
2a7d978
fix(ZMS-3253): clean up commented code
ThomasAFink Nov 18, 2024
ea55b27
fix(ZMS-3253): fix grammar
ThomasAFink Nov 20, 2024
932fe5f
fix(ZMS-3253): comment error_log
ThomasAFink Nov 20, 2024
5aa9d6b
fix(ZMS-3253): Improve frontend validation for opening hours availabi…
ThomasAFink Nov 20, 2024
fb7efb7
cleanup(ZMS-3415): remove invalid text instruction for graph view ope…
ThomasAFink Nov 21, 2024
1fd8f65
fix(ZMS-1891): Add missing frontend validation for timepicker
Nov 22, 2024
f8f536f
Merge branch 'next' into bugfix-zms-3253-validation-opening-hours-of-…
Nov 22, 2024
e4981ff
fix(ZMS-1891): Improve frontend validation for time formats
Nov 22, 2024
7916a70
fix(ZMS-3253): fix frontend exclusion availability validation
ThomasAFink Dec 3, 2024
462be60
fix(ZMS-3253): fix backend exclusion availability validation
ThomasAFink Dec 4, 2024
46db273
fix(ZMS-3253): allow exclusion availability on current date
ThomasAFink Dec 4, 2024
490ddce
fix(ZMS-3253): improve validation and cleanup code
ThomasAFink Dec 4, 2024
2ce2363
fix(ZMS-3253): move js spinner
ThomasAFink Dec 4, 2024
735c579
Merge remote-tracking branch 'origin/next' into bugfix-zms-3253-valid…
ThomasAFink Dec 4, 2024
97cee9c
clean(ZMS-3253): remove console logs
ThomasAFink Dec 4, 2024
a11f7b8
Merge branch 'next' into bugfix-zms-3253-validation-opening-hours-of-…
Dec 9, 2024
b620a54
fix(ZMS-3466): fix bookable day range validation
Dec 9, 2024
e3375c1
fix(ZMS-3466): fix error accumulation
Dec 9, 2024
e646a4c
fix(ZMS-3466): improve exception handling
Dec 9, 2024
8b7a1f6
fix(ZMS-3466): improve validation prevent divide by zero
Dec 9, 2024
2a3cbb7
fix(ZMS-3466): improve validation prevent divide by zero
Dec 9, 2024
4cbe423
fix(ZMS-3466): improve validation prevent divide by zero
Dec 9, 2024
0053e60
Merge branch 'next' into bugfix-zms-3253-3466-3415-1891-validation-op…
ThomasAFink Jan 20, 2025
cab1b1d
fix(ZMS-3466): Fix to from default values in opening hours availability
ThomasAFink Jan 20, 2025
ab51699
fix(ZMS): error message
Jan 23, 2025
227e741
Merge branch 'next' into bugfix-zms-3253-3466-3415-1891-validation-op…
Jan 23, 2025
694194b
fix(ZMS-3466): fix open from and open to placeholders in form
Jan 27, 2025
d53b28e
Merge branch 'next' into bugfix-zms-3253-3466-3415-1891-validation-op…
Jan 27, 2025
088356f
fix(ZMS-3466): improve default hours
Jan 28, 2025
484cbb4
fix(ZMS-3466): improve hours selection
Jan 28, 2025
e92684e
fix(ZMS-3466): closing new opening hours
Jan 28, 2025
faa90c0
fix(ZMS-3253): add backend validation check for new availabilities ov…
Jan 29, 2025
8d863ce
fix(ZMS-3253): unit test
Jan 29, 2025
ff16fc0
fix(ZMS-3253): unit tests
Jan 29, 2025
4043a66
fix(ZMS-3253): unit tests
Jan 29, 2025
860abc6
fix(ZMS-3253): add frontend validation check for new availabilities o…
Jan 29, 2025
3a3491f
fix(ZMS-3253): new availability conflict error display
Jan 29, 2025
64c884b
fix(ZMS-3253): when footer buttons are disabled
Jan 29, 2025
36724e4
fix(ZMS-3466): disable editing availabilities in the past
Jan 30, 2025
ea9b087
fix(ZMS-3466): improve infobox message format for non errors
Jan 30, 2025
687af94
fix(ZMS-3466): fix white space scroll error
Jan 30, 2025
d86c998
fix(ZMS-3466): disable maintanence daily cronjob hours from opening h…
Jan 30, 2025
39759a4
fix(ZMS-3466): add validation tests
Jan 31, 2025
65d6e79
fix(ZMS-3466): refactor overlapping new availabilities into one function
Jan 31, 2025
551438b
fix(ZMS-3466): add overlap tests in zmsadmin
Jan 31, 2025
2f92832
fix(ZMS-3466): add overlap test in zmsentities
Jan 31, 2025
36e81f3
fix(ZMS-3466): add more tests
Jan 31, 2025
c595cad
fix(ZMS-3466): fix detect conflict in the future with one time openin…
Jan 31, 2025
b7d7ac8
fix(ZMS-3466): Add tests
Jan 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 22 additions & 17 deletions zmsadmin/js/page/availabilityDay/form/conflicts.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,31 @@ const renderConflictList = (conflictList) => {
let conflictDatesByMessage = [];
conflictList.map(collection => {
collection.conflicts.map((conflict) => {
if (! conflictDatesByMessage[conflict.message]) {
Object.assign({}, conflictDatesByMessage[conflict.message] = []);
const existingConflict = conflictDatesByMessage.find(
item => item.message === conflict.message
);

if (existingConflict) {
existingConflict.dates.push(formatDate(collection.date));
} else {
conflictDatesByMessage.push({
message: conflict.message,
dates: [formatDate(collection.date)]
});
}
conflictDatesByMessage[conflict.message].push(formatDate(collection.date))
})
})
});
});

return (
Object.keys(conflictDatesByMessage).map((key, index) => {
return (
<div key={index}>
<div><strong>{ conflictDatesByMessage[key].join(", ") }</strong></div>
<div key={index}>- {key}</div>
</div>
)
})
)


}
conflictDatesByMessage.map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
{/* Convert newlines in the message to <br /> tags */}
<div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
</div>
))
);
Comment on lines +30 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security: Replace dangerouslySetInnerHTML with safer alternative.

Using dangerouslySetInnerHTML for newline conversion poses potential XSS risks, even with server-side messages.

Consider this safer alternative that splits the message into an array and maps over it:

-                <div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
+                <div>
+                    {item.message.split('\n').map((line, i) => (
+                        <React.Fragment key={i}>
+                            {line}
+                            {i < item.message.split('\n').length - 1 && <br />}
+                        </React.Fragment>
+                    ))}
+                </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
conflictDatesByMessage.map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
{/* Convert newlines in the message to <br /> tags */}
<div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
</div>
))
);
conflictDatesByMessage.map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
{/* Convert newlines in the message to <br /> tags */}
<div>
{item.message.split('\n').map((line, i) => (
<React.Fragment key={i}>
{line}
{i < item.message.split('\n').length - 1 && <br />}
</React.Fragment>
))}
</div>
</div>
))
);
🧰 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)

};


const Conflicts = (props) => {
const conflicts = Object.keys(props.conflictList).map(key => {
Expand Down
274 changes: 173 additions & 101 deletions zmsadmin/js/page/availabilityDay/form/content.js

Large diffs are not rendered by default.

110 changes: 79 additions & 31 deletions zmsadmin/js/page/availabilityDay/form/datepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AvailabilityDatePicker extends Component
availabilityList: this.props.attributes.availabilitylist,
minDate: moment.unix(this.props.attributes.availability.startDate).toDate(),
minTime: setHours(setMinutes(new Date(), 1), 0),
maxTime: setHours(setMinutes(new Date(), 59), 23),
maxTime: setHours(setMinutes(new Date(), 59), 22),
datePickerIsOpen: false,
timPickerIsOpen: false
}
Expand Down Expand Up @@ -124,34 +124,72 @@ class AvailabilityDatePicker extends Component
if (this.state.kind === 'exclusion') {
return;
}
var times = []
this.state.availabilityList.map(availability => {
if (availability.id !== this.state.availability.id &&
var times = [];

// Add maintenance window times (22:00-01:00)
const selectedDate = moment(this.state.selectedDate);
for (let minute = 1; minute < 60; minute++) {
times.push(selectedDate.clone().hour(22).minute(minute).toDate());
}
for (let minute = 0; minute < 59; minute++) {
times.push(selectedDate.clone().hour(0).minute(minute).toDate());
}

// Filter and sort availabilities
const availabilities = [...this.state.availabilityList]
.filter(availability =>
availability.id !== this.state.availability.id &&
availability.type == this.state.availability.type &&
this.isWeekDaySelected(this.state.selectedDate, availability)
) {
const startTime = moment(availability.startTime, 'hh:mm')
.add(this.state.availability.slotTimeInMinutes, "m");
const startOnDay = moment(this.state.selectedDate)
.set({"h": startTime.hours(), "m": startTime.minutes()})
.toDate()

const endTime = moment(availability.endTime, 'hh:mm')
.subtract(this.state.availability.slotTimeInMinutes, "m");
const endOnDay = moment(this.state.selectedDate)
.set({"h": endTime.hours(), "m": endTime.minutes()})
.toDate()

var currentTime = new Date(startOnDay)
while (currentTime < endOnDay) {
times = [...times, new Date(currentTime)]
currentTime = moment(currentTime)
.add(this.state.availability.slotTimeInMinutes, "m")
.toDate()
}
times = [...times, endOnDay]
)
.sort((a, b) => {
const timeA = moment(a.startTime, 'HH:mm');
const timeB = moment(b.startTime, 'HH:mm');
return timeA.diff(timeB);
});

// Add regular excluded times
availabilities.forEach(availability => {
const startTime = moment(availability.startTime, 'hh:mm')
.add(this.state.availability.slotTimeInMinutes, "m");
const startOnDay = moment(this.state.selectedDate)
.set({"h": startTime.hours(), "m": startTime.minutes()})
.toDate();

const endTime = moment(availability.endTime, 'hh:mm')
.subtract(this.state.availability.slotTimeInMinutes, "m");
const endOnDay = moment(this.state.selectedDate)
.set({"h": endTime.hours(), "m": endTime.minutes()})
.toDate();

var currentTime = new Date(startOnDay);
while (currentTime < endOnDay) {
times.push(new Date(currentTime));
currentTime = moment(currentTime)
.add(this.state.availability.slotTimeInMinutes, "m")
.toDate();
}
times.push(endOnDay);
});

// Add boundary timestamps between adjacent availabilities
for (let i = 0; i < availabilities.length - 1; i++) {
const current = availabilities[i];
const next = availabilities[i + 1];

const currentEnd = moment(current.endTime, 'HH:mm');
const nextStart = moment(next.startTime, 'HH:mm');

// If they're adjacent (end time of one equals start time of next)
if (currentEnd.format('HH:mm') === nextStart.format('HH:mm')) {
// Add the boundary timestamp to excluded times
const boundaryTime = moment(this.state.selectedDate)
.set({"h": currentEnd.hours(), "m": currentEnd.minutes()})
.toDate();
times.push(boundaryTime);
}
}

this.setState({excludeTimeList: times});
}

Expand Down Expand Up @@ -256,13 +294,23 @@ class AvailabilityDatePicker extends Component
return className;
}

/*
const filterPassedTime = (time) => {
const currentDate = this.state.selectedDate;
const selectedDate = new Date(time);
return currentDate.getTime() < selectedDate.getTime();
};
if (!moment(this.state.selectedDate).isSame(moment.unix(this.props.attributes.today), 'day')) {
return true;
}

const BUFFER_MINUTES = 60; // Minimum minutes needed between current time and next slot
const currentTime = moment();
const timeToCheck = moment(time);

// Calculate minutes difference between times
const minutesDiff = timeToCheck.diff(currentTime, 'minutes');

// Disable if time is in past or too close to current time
return minutesDiff >= BUFFER_MINUTES;
};

/*
const isWeekday = date => {
const day = date.getDay();
return day !== 0 && day !== 6;
Expand Down Expand Up @@ -337,7 +385,7 @@ class AvailabilityDatePicker extends Component
minTime={this.state.minTime}
maxTime={this.state.maxTime}
excludeTimes={this.state.excludeTimeList}
//filterTime={filterPassedTime}
filterTime={filterPassedTime}
disabled={this.props.attributes.disabled}
onInputClick={this.openTimePicker}
onKeyDown={this.tpKeyDownHandler}
Expand Down
31 changes: 18 additions & 13 deletions zmsadmin/js/page/availabilityDay/form/errors.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
import React from 'react';
import PropTypes from 'prop-types';

const renderErrors = errors => Object.keys(errors).map(key => {
return (
const renderErrors = (errors) =>
Object.keys(errors).map(key => (
<div key={errors[key].id}>
{errors[key].itemList.map((item, index) => {
return <div key={index}>{item[0].message}</div>
})}
if (Array.isArray(item)) {
return item.map((nestedItem, nestedIndex) => (
<div key={`${index}-${nestedIndex}`}>{nestedItem.message}</div>
));
} else {
return <div key={index}>{item.message}</div>;
}
})}
</div>
)
})
));

const Errors = (props) => {
return (
Expand All @@ -18,15 +23,15 @@ const Errors = (props) => {
<h3>Folgende Fehler sind bei der Prüfung Ihrer Eingaben aufgetreten:</h3>
{renderErrors(props.errorList)}
</div> : null
)
}
);
};

Errors.defaultProps = {
errorList: []
}
};

Errors.propTypes = {
errorList: PropTypes.object
}
};

export default Errors
export default Errors;
47 changes: 38 additions & 9 deletions zmsadmin/js/page/availabilityDay/form/footerButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,55 @@ import React from 'react'
import PropTypes from 'prop-types'

const FooterButtons = (props) => {
const { hasConflicts, stateChanged, data, onNew, onPublish, onAbort, hasSlotCountError } = props
const { hasConflicts, hasErrors, stateChanged, data, onNew, onPublish, onAbort, hasSlotCountError, availabilitylist } = props;

const hasNewAvailabilities = availabilitylist?.some(
availability => availability?.tempId?.includes('__temp__')
);

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)}
>
neue Öffnungszeit
</button>
<button
title="Alle Änderungen werden zurückgesetzt"
className="button btn"
type="abort"
onClick={onAbort}
disabled={!stateChanged && !hasNewAvailabilities && !hasConflicts && !hasErrors}
>
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}
>
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
}

export default FooterButtons
8 changes: 5 additions & 3 deletions zmsadmin/js/page/availabilityDay/form/formButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react'
import PropTypes from 'prop-types'

const FormButtons = (props) => {
const { data, onCopy, onExclusion, onEditInFuture, onUpdateSingle, onDelete, selectedDate, hasConflicts } = props
const disabled = ((data && (! data.id || data.__modified === true)) || hasConflicts);
const { data, onCopy, onExclusion, onEditInFuture, onUpdateSingle, onDelete, selectedDate, hasConflicts, hasErrors, hasSlotCountError } = props
const disabled = ((data && (! data.id || data.__modified === true)) || hasConflicts || hasErrors || hasSlotCountError);
return (
<div className="body">
<div className="form-actions">
Expand All @@ -21,7 +21,7 @@ const FormButtons = (props) => {
className="button button--diamond" disabled={disabled || data.startDate == selectedDate}>Ab diesem Tag ändern</button>
<button onClick={onUpdateSingle}
title="Öffnungszeit aktualisieren"
className="button button--diamond" disabled={(data && !data.id) || hasConflicts || props.isCreatingExclusion}>Aktualisieren</button>
className="button button--diamond" disabled={disabled || props.isCreatingExclusion}>Aktualisieren</button>
</div>
</div>
)
Expand All @@ -30,6 +30,8 @@ const FormButtons = (props) => {
FormButtons.propTypes = {
data: PropTypes.object,
hasConflicts: PropTypes.bool,
hasErrors: PropTypes.bool,
hasSlotCountError: PropTypes.bool,
onCopy: PropTypes.func,
onExclusion: PropTypes.func,
onEditInFuture: PropTypes.func,
Expand Down
27 changes: 16 additions & 11 deletions zmsadmin/js/page/availabilityDay/form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import FormButtons from './formButtons'
import FormContent from './content'
import { getDataValuesFromForm, cleanupFormData, getFormValuesFromData } from '../helpers'
import { hasSlotCountError } from '../form/validate';

class AvailabilityForm extends Component {
constructor(props) {
Expand Down Expand Up @@ -38,36 +39,40 @@ class AvailabilityForm extends Component {
}

const hasConflicts = ((
this.props.conflictList.itemList &&
Object.keys(this.props.conflictList.itemList).length
) ||
this.props.conflictList.itemList &&
Object.keys(this.props.conflictList.itemList).length
)) ? true : false
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify boolean expressions.

Both hasConflicts and hasErrors use unnecessary ternary operators and can be simplified.

-        const hasConflicts = ((
-            this.props.conflictList.itemList &&
-            Object.keys(this.props.conflictList.itemList).length
-        )) ? true : false
+        const hasConflicts = !!(
+            this.props.conflictList.itemList &&
+            Object.keys(this.props.conflictList.itemList).length
+        )

-        const hasErrors = (
-            (
-                this.props.errorList &&
-                Object.keys(this.props.errorList).length
-            )) ? true : false
+        const hasErrors = !!(
+            this.props.errorList &&
+            Object.keys(this.props.errorList).length
+        )

Also applies to: 46-50

🧰 Tools
🪛 Biome (1.9.4)

[error] 41-44: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


const hasErrors = (
(
this.props.errorList &&
Object.keys(this.props.errorList).length
)) ? true : false
)) ? true : false

return (
<div>
{<FormContent
today = {this.props.today}
{<FormContent
today={this.props.today}
availabilityList={this.props.availabilityList}
setErrorRef={this.props.setErrorRef}
errorList={this.props.errorList}
conflictList={this.props.conflictList}
{... { data, onChange }} />}
{<FormButtons
data = {data}
onCopy={this.props.onCopy}
{<FormButtons
data={data}
onCopy={this.props.onCopy}
onExclusion={this.props.onExclusion}
onEditInFuture={this.props.onEditInFuture}
onEditInFuture={this.props.onEditInFuture}
onDelete={this.props.onDelete}
onUpdateSingle={this.props.onUpdateSingle}
selectedDate={this.props.selectedDate}
hasConflicts={hasConflicts}
hasErrors={hasErrors}
hasSlotCountError={hasSlotCountError(this.props)}
isCreatingExclusion={this.props.isCreatingExclusion}
/>}
</div>
)
)
}
}

Expand Down
Loading
Loading