@@ -134,7 +135,7 @@ function DragAndDropTable({
providedSnapshot.isDragging,
providedDraggable.draggableProps.style
)}
- className={data.className ?? ''}
+ className={data.className ?? ""}
>
{t("help-text")}
);
+ /* eslint-enable react/jsx-props-no-spreading */
+ /* eslint-enable jsx-a11y/control-has-associated-label */
}
DragAndDropTable.propTypes = {
data: PropTypes.arrayOf(
- PropTypes.shape({ name: PropTypes.string, id: PropTypes.string, className: PropTypes.string })
+ PropTypes.shape({
+ name: PropTypes.string,
+ id: PropTypes.string,
+ className: PropTypes.string,
+ })
).isRequired,
columns: ColumnProptypes.isRequired,
name: PropTypes.string.isRequired,
diff --git a/src/components/util/forms/checkbox-options.jsx b/src/components/util/forms/checkbox-options.jsx
new file mode 100644
index 00000000..9ad11adb
--- /dev/null
+++ b/src/components/util/forms/checkbox-options.jsx
@@ -0,0 +1,67 @@
+import { React } from "react";
+import PropTypes from "prop-types";
+
+/**
+ * @param {object} props The props.
+ * @param {object} props.formData The form data.
+ * @param {object} props.data The data.
+ * @param {Function} props.onChange On change callback.
+ * @returns {React.JSX} The component.
+ */
+function CheckboxOptions({ formData, data, onChange }) {
+ const values = data[formData.name] ?? [];
+
+ const containsValue = (value) => {
+ return values.includes(value);
+ };
+
+ const onOptionChange = ({ target }) => {
+ const { value } = target;
+
+ const newValues = [...values];
+
+ if (newValues.includes(value)) {
+ newValues.splice(newValues.indexOf(value), 1);
+ } else {
+ newValues.push(value);
+ }
+
+ onChange({
+ target: { id: formData.name, value: newValues },
+ });
+ };
+
+ return (
+
+ {formData.options.map((option) => (
+
+
+ {option.title}
+
+ ))}
+
+ );
+}
+
+CheckboxOptions.propTypes = {
+ formData: PropTypes.shape({
+ name: PropTypes.string,
+ formGroupClasses: PropTypes.string,
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ value: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ })
+ ),
+ }),
+ onChange: PropTypes.func.isRequired,
+ data: PropTypes.shape({}),
+};
+
+export default CheckboxOptions;
diff --git a/src/components/util/forms/form-input-area.jsx b/src/components/util/forms/form-input-area.jsx
index 180b0695..39a66fc2 100644
--- a/src/components/util/forms/form-input-area.jsx
+++ b/src/components/util/forms/form-input-area.jsx
@@ -23,7 +23,7 @@ function FormInputArea({
required = false,
}) {
return (
-
+
{label}
{required && " *"}
@@ -43,6 +43,7 @@ function FormInputArea({
FormInputArea.propTypes = {
name: PropTypes.string.isRequired,
+ formGroupClasses: PropTypes.string,
label: PropTypes.string.isRequired,
placeholder: PropTypes.string,
value: PropTypes.string,
diff --git a/src/components/util/forms/form-input.jsx b/src/components/util/forms/form-input.jsx
index 78eae152..5283ee45 100644
--- a/src/components/util/forms/form-input.jsx
+++ b/src/components/util/forms/form-input.jsx
@@ -46,15 +46,17 @@ function FormInput({
/* eslint-disable react/jsx-props-no-spreading */
return (
- {label && (<>
-
- {label}
- {required && " *"}
-
- {tooltip !== null && (
-
- )}
- >)}
+ {label && (
+ <>
+
+ {label}
+ {required && " *"}
+
+ {tooltip !== null && (
+
+ )}
+ >
+ )}
{tooltip !== null && (
<>
-
-
+
+ {" "}
+
+
+
>
)}
}
);
+ /* eslint-enable jsx-a11y/anchor-is-valid */
}
Select.propTypes = {
@@ -110,6 +115,8 @@ Select.propTypes = {
title: PropTypes.string.isRequired,
})
).isRequired,
+ disabled: PropTypes.bool,
+ tooltip: PropTypes.string,
errors: PropTypes.arrayOf(PropTypes.string),
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
diff --git a/src/components/util/image-uploader/image-uploader.jsx b/src/components/util/image-uploader/image-uploader.jsx
index 948e7203..6f6e7c54 100644
--- a/src/components/util/image-uploader/image-uploader.jsx
+++ b/src/components/util/image-uploader/image-uploader.jsx
@@ -85,6 +85,7 @@ function ImageUploader({
handleImageUpload({ target });
};
+ /* eslint-disable jsx-a11y/control-has-associated-label */
return (
// @TODO: error handling
@@ -186,6 +187,7 @@ function ImageUploader({
)}
);
+ /* eslint-enable jsx-a11y/control-has-associated-label */
}
ImageUploader.propTypes = {
diff --git a/src/components/util/list/list.jsx b/src/components/util/list/list.jsx
index 2b885939..968dd9aa 100644
--- a/src/components/util/list/list.jsx
+++ b/src/components/util/list/list.jsx
@@ -91,7 +91,8 @@ function List({
}
// search
- const localSearch = searchParams || localStorage.getItem(localStorageKeys.SEARCH) || "";
+ const localSearch =
+ searchParams || localStorage.getItem(localStorageKeys.SEARCH) || "";
params.delete("search");
if (localSearch) {
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index e5f3fadf..2e913821 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -136,7 +136,7 @@ const getNextOccurrences = (rrule, duration = 0, count = 5) => {
occurrences.push({
key: `occurrence${occurrences.length}`,
text: dayjs(d).utc().locale("da").format("LLLL"),
- end: dayjs(d).utc().add(duration, 'second').locale("da").format("LLLL"),
+ end: dayjs(d).utc().add(duration, "second").locale("da").format("LLLL"),
});
return true;
});
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 7e931d4e..92736388 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -126,13 +126,19 @@ function Schedule({ schedules, onChange }) {
// For evaluation with the RRule library we pretend that the date is in UTC instead of the local timezone.
// That is 9:00 in Europe/Copenhagen time will be evaluated as if it was 9:00 in UTC.
// @see https://github.com/jkbrzt/rrule#important-use-utc-dates
- changeSchedule(scheduleId, target.id, new Date(Date.UTC(
- date.getFullYear(),
- date.getMonth(),
- date.getDate(),
- date.getHours(),
- date.getMinutes()
- )));
+ changeSchedule(
+ scheduleId,
+ target.id,
+ new Date(
+ Date.UTC(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ date.getHours(),
+ date.getMinutes()
+ )
+ )
+ );
};
/**
@@ -174,7 +180,7 @@ function Schedule({ schedules, onChange }) {
const hour = parseInt(split[0], 10);
const minute = parseInt(split[1], 10);
- if (isNaN(hour) || isNaN(minute)) {
+ if (Number.isNaN(hour) || Number.isNaN(minute)) {
changeSchedule(scheduleId, "byhour", null);
changeSchedule(scheduleId, "byminute", null);
} else {
@@ -184,30 +190,30 @@ function Schedule({ schedules, onChange }) {
};
const setDuration = (scheduleId, schedule, target) => {
- const value = target.value;
+ const { value } = target;
const start = dayjs(schedule.dtstart).utc().format("YYYY-MM-DDTHH:mm");
const end = dayjs(value);
- const diff = end.diff(start, 'seconds');
+ const diff = end.diff(start, "seconds");
if (diff < 0) {
- setDurationError(true)
+ setDurationError(true);
} else {
setDurationError(false);
- changeSchedule(scheduleId, 'duration', diff);
+ changeSchedule(scheduleId, "duration", diff);
}
- }
+ };
const setPositiveNumberOrNull = (scheduleId, target) => {
- const value = target.value;
+ const { value } = target;
- if (isNaN(value) || value <= 0) {
+ if (Number.isNaN(value) || value <= 0) {
changeSchedule(scheduleId, target.id, null);
} else {
changeSchedule(scheduleId, target.id, value);
}
- }
+ };
const isRepeatingEvent = (schedule) => {
return !(
@@ -219,38 +225,41 @@ function Schedule({ schedules, onChange }) {
schedule.byminute === undefined &&
schedule.byweekday === undefined &&
schedule.bymonth === undefined &&
- schedule.byweekno === undefined);
- }
+ schedule.byweekno === undefined
+ );
+ };
const displayRepeat = (schedule) => {
- return isRepeatingEvent(schedule) || activatedRepeatIds[schedule.id] === true;
- }
+ return (
+ isRepeatingEvent(schedule) || activatedRepeatIds[schedule.id] === true
+ );
+ };
const updateActivatedRepeats = (id, value) => {
- const updated = {...activatedRepeatIds};
+ const updated = { ...activatedRepeatIds };
updated[id] = value;
setActivatedRepeatIds(updated);
- }
+ };
const toggleRepeat = (schedule) => {
if (displayRepeat(schedule)) {
// Disable repeating schedule.
- changeSchedule(schedule.id, 'freq', RRule.DAILY);
- changeSchedule(schedule.id, 'count', 1);
- changeSchedule(schedule.id, 'interval', null);
- changeSchedule(schedule.id, 'until', null);
- changeSchedule(schedule.id, 'byhour', null);
- changeSchedule(schedule.id, 'byminute', null);
- changeSchedule(schedule.id, 'byweekday', null);
- changeSchedule(schedule.id, 'bymonth', null);
- changeSchedule(schedule.id, 'byweekno', null);
+ changeSchedule(schedule.id, "freq", RRule.DAILY);
+ changeSchedule(schedule.id, "count", 1);
+ changeSchedule(schedule.id, "interval", null);
+ changeSchedule(schedule.id, "until", null);
+ changeSchedule(schedule.id, "byhour", null);
+ changeSchedule(schedule.id, "byminute", null);
+ changeSchedule(schedule.id, "byweekday", null);
+ changeSchedule(schedule.id, "bymonth", null);
+ changeSchedule(schedule.id, "byweekno", null);
updateActivatedRepeats(schedule.id, false);
} else {
// Activate repeating schedule.
- changeSchedule(schedule.id, 'count', null);
+ changeSchedule(schedule.id, "count", null);
updateActivatedRepeats(schedule.id, true);
}
- }
+ };
return (
@@ -264,7 +273,7 @@ function Schedule({ schedules, onChange }) {
- {t('schedule.helptext')}
+ {t("schedule.helptext")}
{localSchedules &&
@@ -293,22 +302,35 @@ function Schedule({ schedules, onChange }) {
label={t("schedule.dtstart")}
value={getDateValue(schedule.dtstart)}
name="dtstart"
- onChange={({target}) => setDateValue(schedule.id, target)}
+ onChange={({ target }) => setDateValue(schedule.id, target)}
type="datetime-local"
- tooltip={t('schedule.dtstart-tooltip')}
+ tooltip={t("schedule.dtstart-tooltip")}
/>
setDuration(schedule.id, schedule, target)}
+ onChange={({ target }) =>
+ setDuration(schedule.id, schedule, target)
+ }
type="datetime-local"
- className={durationError ? 'border-danger' : ''}
- tooltip={t('schedule.end-tooltip')}
+ className={durationError ? "border-danger" : ""}
+ tooltip={t("schedule.end-tooltip")}
/>
- {durationError && {t('schedule.duration-error')}}
+ {durationError && (
+
+ {t("schedule.duration-error")}
+
+ )}
@@ -318,57 +340,77 @@ function Schedule({ schedules, onChange }) {
name="enableRepeat"
type="checkbox"
value={displayRepeat(schedule)}
- label={t('schedule.enable-repeat')}
+ label={t("schedule.enable-repeat")}
formGroupClasses="d-inline-block mb-2"
/>
-
+
{displayRepeat(schedule) && (
<>
-
+
setPositiveNumberOrNull(schedule.id, target)}
- value={schedule.interval ?? ''}
+ onChange={({ target }) =>
+ setPositiveNumberOrNull(schedule.id, target)
+ }
+ value={schedule.interval ?? ""}
label={t("schedule.interval")}
type="search"
name="interval"
- tooltip={t('schedule.interval-tooltip')}
+ tooltip={t("schedule.interval-tooltip")}
/>
setPositiveNumberOrNull(schedule.id, target)}
- value={schedule.count ?? ''}
+ onChange={({ target }) =>
+ setPositiveNumberOrNull(schedule.id, target)
+ }
+ value={schedule.count ?? ""}
label={t("schedule.count")}
- placeholder={t('schedule.count-placeholder')}
+ placeholder={t("schedule.count-placeholder")}
type="search"
name="count"
- tooltip={t('schedule.count-tooltip')}
+ tooltip={t("schedule.count-tooltip")}
/>
- {!isNaN(schedule.byhour) && (
+ {!Number.isNaN(schedule.byhour) && (
setTimeValue(schedule.id, target)}
- value={getTimeValue(schedule.byhour, schedule.byminute)}
+ onChange={({ target }) =>
+ setTimeValue(schedule.id, target)
+ }
+ value={getTimeValue(
+ schedule.byhour,
+ schedule.byminute
+ )}
label={t("schedule.bytime")}
type="time"
name="bytime"
- tooltip={t('schedule.bytime-tooltip')}
+ tooltip={t("schedule.bytime-tooltip")}
/>
)}
@@ -376,18 +418,24 @@ function Schedule({ schedules, onChange }) {
-
-
+
+
- byWeekdayOptions.find(
- (weekDay) => weekDay.value === weekdayNumber
+ byWeekdayOptions.find(
+ (weekDay) =>
+ weekDay.value === weekdayNumber
+ )
)
- )
: []
}
name="byweekday"
@@ -396,7 +444,9 @@ function Schedule({ schedules, onChange }) {
allItemsAreSelected: t("schedule.all-selected"),
clearSelected: t("schedule.clear-selection"),
selectAll: t("schedule.selected-all"),
- selectSomeItems: t("schedule.select-some-options"),
+ selectSomeItems: t(
+ "schedule.select-some-options"
+ ),
}}
labelledBy="Select"
onChange={(value) => {
@@ -414,7 +464,10 @@ function Schedule({ schedules, onChange }) {
-
+
changeSchedule(
@@ -444,9 +499,11 @@ function Schedule({ schedules, onChange }) {
label={t("schedule.until")}
value={getDateValue(schedule.until)}
name="until"
- onChange={({target}) => setDateValue(schedule.id, target)}
+ onChange={({ target }) =>
+ setDateValue(schedule.id, target)
+ }
type="datetime-local"
- tooltip={t('schedule.until-tooltip')}
+ tooltip={t("schedule.until-tooltip")}
/>
{schedule.freq === RRule.YEARLY && (
@@ -455,14 +512,18 @@ function Schedule({ schedules, onChange }) {
disabled={schedule.freq !== RRule.YEARLY}
label={t("schedule.byweekno")}
value={schedule.byweekno ?? ""}
- onChange={({target}) =>
- changeSchedule(schedule.id, target.id, target.value)
+ onChange={({ target }) =>
+ changeSchedule(
+ schedule.id,
+ target.id,
+ target.value
+ )
}
name="byweekno"
type="number"
min="0"
max="52"
- tooltip={t('schedule.byweekno-tooltip')}
+ tooltip={t("schedule.byweekno-tooltip")}
/>
)}
@@ -475,18 +536,24 @@ function Schedule({ schedules, onChange }) {
{t("schedule.next-occurrences")}:
- {getNextOccurrences(schedule.rruleObject, schedule.duration, schedule.count ? Math.min(schedule.count, 5) : 5).map(
- (occurrence) => (
+ {getNextOccurrences(
+ schedule.rruleObject,
+ schedule.duration,
+ schedule.count ? Math.min(schedule.count, 5) : 5
+ ).map((occurrence) => (
+
{occurrence.text}
-
{occurrence.end}
- )
- )}
+
+ ))}
- {t('schedule.repetition')}: {schedule.rruleObject.toText()}
+ {t("schedule.repetition")}:{" "}
+
+ {schedule.rruleObject.toText()}
+
)}
diff --git a/src/components/util/table/table-header.jsx b/src/components/util/table/table-header.jsx
index 9373cf1b..f0d6a01e 100644
--- a/src/components/util/table/table-header.jsx
+++ b/src/components/util/table/table-header.jsx
@@ -25,7 +25,10 @@ function TableHeader({ columns, draggable = false }) {
)}
{columns.map((column) => (
- {column.label}{column.actions} |
+
+ {column.label}
+ {column.actions}
+ |
))}
diff --git a/src/components/util/tooltip.jsx b/src/components/util/tooltip.jsx
index 8c2ecbac..bd4cdd0b 100644
--- a/src/components/util/tooltip.jsx
+++ b/src/components/util/tooltip.jsx
@@ -1,19 +1,29 @@
-import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
-import {faQuestionCircle} from "@fortawesome/free-solid-svg-icons";
-import {Tooltip as ReactTooltip} from "react-tooltip";
-import {React} from "react";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons";
+import { Tooltip as ReactTooltip } from "react-tooltip";
+import { React } from "react";
+import PropTypes from "prop-types";
+/**
+ * @param {object} props The props.
+ * @param {string} props.id The if of the tooltip.
+ * @param {string} props.content The content to show in the tooltip.
+ * @returns {React.JSX} Tooltip component.
+ */
function Tooltip({ id, content }) {
- return <>
-
-
-
-
- >;
+ return (
+ <>
+
+
+
+
+ >
+ );
}
+Tooltip.propTypes = {
+ id: PropTypes.string.isRequired,
+ content: PropTypes.string.isRequired,
+};
+
export default Tooltip;
diff --git a/src/remote-component.config.js b/src/remote-component.config.js
index a1f37f23..985d17e4 100644
--- a/src/remote-component.config.js
+++ b/src/remote-component.config.js
@@ -1,5 +1,6 @@
import react from "react";
+// eslint-disable-next-line import/prefer-default-export
export const resolve = {
react,
};
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index acc1355f..4bc6340d 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -274,8 +274,9 @@
},
"calendar-api-feed-type": {
"title": "Kalender feed",
- "resources": "Ressourcer",
- "redacted-value-input-placeholder": "Skjult værdi"
+ "locations": "Lokationer",
+ "redacted-value-input-placeholder": "Skjult værdi",
+ "save-before-locations-can-be-set": "Bemærk! Datakilden skal gemmes før der kan tilkobles lokationer. Gem og åbn datakilden igen."
},
"rss-feed-type": {
"title": "RSS feed"
|