From a7276659ab08906bb0762b027654202b2bc5bbdc Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 15:38:03 +0200
Subject: [PATCH 01/13] 2000: Adjusted scheduling component
---
src/components/util/schedule/schedule-util.js | 13 +-
src/components/util/schedule/schedule.jsx | 113 ++++++++----------
src/translations/da/common.json | 15 ++-
3 files changed, 61 insertions(+), 80 deletions(-)
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index f2a778d7..1a51e354 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -56,7 +56,7 @@ const createNewSchedule = () => {
const newSchedule = {
id: ulid(nowTimestamp),
- duration: 60 * 60 * 24, // Default one day.
+ duration: 60 * 60, // Default 1 hour.
freq: RRule.WEEKLY,
// For evaluation with the RRule library we pretend that "now" 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.
@@ -124,7 +124,7 @@ const createScheduleFromRRule = (id, duration, rruleString) => {
* @param {number | null} count - The max number of occurrences.
* @returns {Array} - The occurrences.
*/
-const getNextOccurrences = (rrule, count = 5) => {
+const getNextOccurrences = (rrule, duration = null, count = 5) => {
const occurrences = [];
const newRrule = new RRule(rrule.origOptions);
@@ -133,6 +133,7 @@ const getNextOccurrences = (rrule, count = 5) => {
occurrences.push({
key: `occurrence${occurrences.length}`,
text: dayjs(d).utc().locale("da").format("LLLL"),
+ end: duration !== null ? dayjs(d).utc().add(duration, 'second').locale("da").format("LLLL") : null,
});
return true;
});
@@ -156,12 +157,8 @@ const getFreqOptions = (t) => {
},
{ title: t("schedule.weekly"), value: RRule.WEEKLY, key: "rrule.weekly" },
{ title: t("schedule.daily"), value: RRule.DAILY, key: "rrule.daily" },
- { title: t("schedule.hourly"), value: RRule.HOURLY, key: "rrule.hourly" },
- {
- title: t("schedule.minutely"),
- value: RRule.MINUTELY,
- key: "rrule.minutely",
- },
+// { title: t("schedule.hourly"), value: RRule.HOURLY, key: "rrule.hourly" },
+// { title: t("schedule.minutely"), value: RRule.MINUTELY, key: "rrule.minutely" },
];
};
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 50e86fe8..fa5e710e 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -188,7 +188,19 @@ function Schedule({ schedules, onChange }) {
localSchedules.map((schedule, index) => (
- {t("schedule.plan")} #{index + 1}
+
+
+ {t("schedule.plan")} #{index + 1}
+
+
+ removeSchedule(schedule.id)}
+ >
+ {t("schedule.remove")}
+
+
+
@@ -198,21 +210,10 @@ 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"
/>
-
- setDateValue(schedule.id, target)}
- type="datetime-local"
- />
-
-
-
-
- setTimeValue(schedule.id, target)}
- value={getTimeValue(schedule.byhour, schedule.byminute)}
- label={t("schedule.bytime")}
- type="time"
- name="bytime"
- />
-
+ onChange={({target}) =>
changeSchedule(schedule.id, target.id, target.value)
}
value={schedule.freq}
@@ -245,6 +237,17 @@ function Schedule({ schedules, onChange }) {
allowNull={false}
/>
+
+ setTimeValue(schedule.id, target)}
+ value={getTimeValue(schedule.byhour, schedule.byminute)}
+ label={t("schedule.bytime")}
+ type="time"
+ name="bytime"
+ />
+
+
+
{t("schedule.byweekday")}
@@ -254,10 +257,10 @@ function Schedule({ schedules, onChange }) {
value={
schedule.byweekday
? schedule.byweekday.map((weekdayNumber) =>
- byWeekdayOptions.find(
- (weekDay) => weekDay.value === weekdayNumber
- )
+ byWeekdayOptions.find(
+ (weekDay) => weekDay.value === weekdayNumber
)
+ )
: []
}
name="byweekday"
@@ -279,9 +282,6 @@ function Schedule({ schedules, onChange }) {
/>
-
-
-
@@ -309,12 +309,15 @@ function Schedule({ schedules, onChange }) {
/>
+
+
+
+ onChange={({target}) =>
changeSchedule(schedule.id, target.id, target.value)
}
name="byweekno"
@@ -323,46 +326,28 @@ function Schedule({ schedules, onChange }) {
max="52"
/>
+
+ setDateValue(schedule.id, target)}
+ type="datetime-local"
+ />
+
-
-
-
setShowRRuleDetails(!showRRuleDetails)}
- >
- {showRRuleDetails
- ? t("schedule.hide-details")
- : t("schedule.show-details")}
-
-
removeSchedule(schedule.id)}
- >
- {t("schedule.remove")}
-
+
+
+
{t("schedule.next-occurrences")}:
+ {getNextOccurrences(schedule.rruleObject, schedule.duration).map(
+ (occurrence) => (
{occurrence.text} {occurrence.end ? ' - ' + occurrence.end : ''}
)
+ )}
- {showRRuleDetails && (
-
-
{t("schedule.rrulestring")}:
-
{schedule.rrule}
-
{t("schedule.rrulestring-z-ignored")}
-
-
{t("schedule.next-occurrences")}:
- {getNextOccurrences(schedule.rruleObject).map(
- (occurrence) => (
-
{occurrence.text}
- )
- )}
-
-
- )}
+
{t("schedule.rrulestring")}: {schedule.rrule}
))}
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index e3b0b5b9..9ed3b392 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -747,7 +747,7 @@
"byweekno": "Ugenummer",
"bymonth": "Valgte måneder",
"byweekday": "Valgte ugedage",
- "freq": "Frekvens",
+ "freq": "Gentag",
"show-details": "Vis detaljer",
"hide-details": "Skjul detaljer",
"jan": "Januar",
@@ -769,16 +769,15 @@
"friday": "Fredag",
"saturday": "Lørdag",
"sunday": "Søndag",
- "yearly": "År",
- "monthly": "Måned",
- "weekly": "Uge",
- "daily": "Dag",
+ "yearly": "Hvert år",
+ "monthly": "Hver måned",
+ "weekly": "Hver uge",
+ "daily": "Hver dag",
"hourly": "Time",
"minutely": "Minut",
"rrulestring": "RRule",
- "rrulestring-z-ignored": "Bemærk at tidszonen (Z) bliver ignoreret i evalueringen af reglen. Tidsangivelserne vil altid blive behandlet i lokal tid.",
- "dtstart": "Startdato",
- "until": "Slutdato",
+ "dtstart": "Starttidspunkt",
+ "until": "Sluttidspunkt",
"next-occurrences": "Næste 5 forekomster",
"all-selected": "Alle er valgt",
"clear-selection": "Ryd valg",
From 7656b302c26aee9f8a92db99c162ac68fb03b9b5 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 15:56:37 +0200
Subject: [PATCH 02/13] 2000: Further adjustments
---
src/components/util/schedule/schedule-util.js | 7 ++++---
src/components/util/schedule/schedule.jsx | 10 +++++++---
src/translations/da/common.json | 4 ++--
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index 1a51e354..4329c295 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -121,10 +121,11 @@ const createScheduleFromRRule = (id, duration, rruleString) => {
* Get array of count occurrences of rrule.
*
* @param {RRule} rrule - The rrule.
- * @param {number | null} count - The max number of occurrences.
+ * @param {number} duration - The duration of an occurrence in seconds.
+ * @param {number} count - The max number of occurrences.
* @returns {Array} - The occurrences.
*/
-const getNextOccurrences = (rrule, duration = null, count = 5) => {
+const getNextOccurrences = (rrule, duration = 0, count = 5) => {
const occurrences = [];
const newRrule = new RRule(rrule.origOptions);
@@ -133,7 +134,7 @@ const getNextOccurrences = (rrule, duration = null, count = 5) => {
occurrences.push({
key: `occurrence${occurrences.length}`,
text: dayjs(d).utc().locale("da").format("LLLL"),
- end: duration !== null ? dayjs(d).utc().add(duration, 'second').locale("da").format("LLLL") : null,
+ 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 fa5e710e..7ea2329d 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -340,14 +340,18 @@ function Schedule({ schedules, onChange }) {
-
+
{t("schedule.next-occurrences")}:
{getNextOccurrences(schedule.rruleObject, schedule.duration).map(
- (occurrence) => (
{occurrence.text} {occurrence.end ? ' - ' + occurrence.end : ''}
)
+ (occurrence) => (
+ {occurrence.text}
+ -
+ {occurrence.end}
+
)
)}
-
{t("schedule.rrulestring")}: {schedule.rrule}
+
{t("schedule.rrulestring")}: {schedule.rrule}
))}
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 9ed3b392..584a01ed 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -776,8 +776,8 @@
"hourly": "Time",
"minutely": "Minut",
"rrulestring": "RRule",
- "dtstart": "Starttidspunkt",
- "until": "Sluttidspunkt",
+ "dtstart": "Reglens starttidspunkt",
+ "until": "Reglens sluttidspunkt",
"next-occurrences": "Næste 5 forekomster",
"all-selected": "Alle er valgt",
"clear-selection": "Ryd valg",
From ceff7e85c545acb23b6a7a0b2a03d8fe418e26af Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 16:39:24 +0200
Subject: [PATCH 03/13] 2000: Changed how duration is set
---
src/components/util/schedule/duration.jsx | 93 -------------------
src/components/util/schedule/schedule-util.js | 4 +-
src/components/util/schedule/schedule.jsx | 34 +++++--
src/translations/da/common.json | 8 +-
4 files changed, 32 insertions(+), 107 deletions(-)
delete mode 100644 src/components/util/schedule/duration.jsx
diff --git a/src/components/util/schedule/duration.jsx b/src/components/util/schedule/duration.jsx
deleted file mode 100644
index 7ec47c00..00000000
--- a/src/components/util/schedule/duration.jsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import { React, useEffect, useState } from "react";
-import PropTypes from "prop-types";
-import { useTranslation } from "react-i18next";
-import { InputGroup } from "react-bootstrap";
-import FormInput from "../forms/form-input";
-
-/**
- * Duration component.
- *
- * @param {object} props - The props.
- * @param {string} props.label - Label.
- * @param {number} props.duration - Input duration
- * @param {Function} props.onChange - OnChange function.
- * @returns {object} - Component.
- */
-function Duration({ label, duration, onChange }) {
- const { t } = useTranslation("common");
- const [minutes, setMinutes] = useState();
- const [hours, setHours] = useState();
-
- const onValueChange = ({ target }) => {
- const targetValue = parseInt(target.value, 10);
-
- if (target.id === "duration_hour") {
- onChange(minutes * 60 + targetValue * 3600);
- } else if (target.id === "duration_minute") {
- onChange(targetValue * 60 + hours * 3600);
- }
- };
-
- useEffect(() => {
- if (duration !== undefined) {
- const seconds = duration % 60;
- const durationWithoutSeconds = duration - seconds;
- const newMinutes = durationWithoutSeconds / 60;
- const minutesLeft = newMinutes % 60;
- const newHours = (durationWithoutSeconds - minutesLeft * 60) / 3600;
-
- setHours(newHours);
- setMinutes(minutesLeft);
- }
- }, [duration]);
-
- return (
-
-
- {label}
-
-
-
- {t("duration.hours")}
-
- }
- />
-
-
-
- {t("duration.minutes")}
-
- }
- />
-
-
- );
-}
-
-Duration.propTypes = {
- label: PropTypes.string.isRequired,
- duration: PropTypes.number.isRequired,
- onChange: PropTypes.func.isRequired,
-};
-
-export default Duration;
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index 4329c295..8668fe6c 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -11,8 +11,6 @@ dayjs.extend(localizedFormat);
/**
* Get rrule string from schedule.
*
- *
- *
* @param {object} schedule - The schedule.
* @returns {string} - RRule string.
*/
@@ -33,6 +31,7 @@ const getRruleString = (schedule) => {
wkst: schedule.wkst ?? RRule.MO,
freq: schedule.freq,
dtstart: schedule.dtstart,
+ count: schedule.count,
until: schedule.until,
byhour: schedule.byhour,
byminute: schedule.byminute,
@@ -58,6 +57,7 @@ const createNewSchedule = () => {
id: ulid(nowTimestamp),
duration: 60 * 60, // Default 1 hour.
freq: RRule.WEEKLY,
+ count: 1,
// For evaluation with the RRule library we pretend that "now" 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
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 7ea2329d..4fda840f 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -17,7 +17,6 @@ import {
getNextOccurrences,
getRruleString,
} from "./schedule-util";
-import Duration from "./duration";
dayjs.extend(utc);
@@ -37,7 +36,7 @@ function Schedule({ schedules, onChange }) {
const byWeekdayOptions = getByWeekdayOptions(t);
const byMonthOptions = getByMonthOptions(t);
const [localSchedules, setLocalSchedules] = useState([]);
- const [showRRuleDetails, setShowRRuleDetails] = useState(false);
+ const [durationError, setDurationError] = useState(false);
useEffect(() => {
const newSchedules = schedules.map((schedule) =>
@@ -173,6 +172,22 @@ function Schedule({ schedules, onChange }) {
changeSchedule(scheduleId, "byminute", parseInt(split[1], 10));
};
+ const setDuration = (scheduleId, schedule, target) => {
+ const value = target.value;
+
+ const start = dayjs(schedule.dtstart).utc().format("YYYY-MM-DDTHH:mm");
+ const end = dayjs(value);
+ const diff = end.diff(start, 'seconds');
+
+ if (diff < 0) {
+ setDurationError(true)
+ } else {
+ setDurationError(false);
+
+ changeSchedule(scheduleId, 'duration', diff);
+ }
+ }
+
return (
- {
- changeSchedule(schedule.id, "duration", newValue);
- }}
- label={t("schedule.duration")}
+ setDuration(schedule.id, schedule, target)}
+ type="datetime-local"
/>
+ {durationError && {t('schedule.duration-error')} }
@@ -342,7 +358,7 @@ function Schedule({ schedules, onChange }) {
{t("schedule.next-occurrences")}:
- {getNextOccurrences(schedule.rruleObject, schedule.duration).map(
+ {getNextOccurrences(schedule.rruleObject, schedule.duration, schedule.count ?? 5).map(
(occurrence) => (
{occurrence.text}
-
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 584a01ed..97ad59aa 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -776,14 +776,16 @@
"hourly": "Time",
"minutely": "Minut",
"rrulestring": "RRule",
- "dtstart": "Reglens starttidspunkt",
- "until": "Reglens sluttidspunkt",
+ "dtstart": "Start",
+ "until": "Gentagelsernes sluttidspunkt",
"next-occurrences": "Næste 5 forekomster",
"all-selected": "Alle er valgt",
"clear-selection": "Ryd valg",
"selected-all": "Vælg alle",
"select-some-options": "Vælg...",
- "bytime": "Tidspunkt på dagen"
+ "bytime": "Tidspunkt på dagen",
+ "duration-error": "Varighed kan ikke være mindre end 0",
+ "end": "Slut"
},
"duration": {
"hours": "t.",
From 9e829a04e5d5e0a5e578adad1675e8cc0587f4d1 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 17:05:43 +0200
Subject: [PATCH 04/13] 2000: Added count and interval
---
src/components/util/schedule/schedule-util.js | 4 ++-
src/components/util/schedule/schedule.jsx | 31 ++++++++++++++++++-
src/translations/da/common.json | 7 +++--
3 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index 8668fe6c..89736429 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -33,6 +33,7 @@ const getRruleString = (schedule) => {
dtstart: schedule.dtstart,
count: schedule.count,
until: schedule.until,
+ interval: schedule.interval,
byhour: schedule.byhour,
byminute: schedule.byminute,
bysecond,
@@ -57,7 +58,8 @@ const createNewSchedule = () => {
id: ulid(nowTimestamp),
duration: 60 * 60, // Default 1 hour.
freq: RRule.WEEKLY,
- count: 1,
+ count: null,
+ interval: null,
// For evaluation with the RRule library we pretend that "now" 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
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 4fda840f..513eeb66 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -188,6 +188,16 @@ function Schedule({ schedules, onChange }) {
}
}
+ const setPositiveNumberOrNull = (scheduleId, target) => {
+ const value = target.value;
+
+ if (isNaN(value) || value <= 0) {
+ changeSchedule(scheduleId, target.id, null);
+ } else {
+ changeSchedule(scheduleId, target.id, value);
+ }
+ }
+
return (
+
+ setPositiveNumberOrNull(schedule.id, target)}
+ value={schedule.count ?? ''}
+ label={t("schedule.count")}
+ placeholder={t('schedule.count-placeholder')}
+ type="search"
+ name="count"
+ />
+
+
+ setPositiveNumberOrNull(schedule.id, target)}
+ value={schedule.interval ?? ''}
+ label={t("schedule.interval")}
+ type="search"
+ name="interval"
+ />
+
setTimeValue(schedule.id, target)}
@@ -358,7 +387,7 @@ function Schedule({ schedules, onChange }) {
{t("schedule.next-occurrences")}:
- {getNextOccurrences(schedule.rruleObject, schedule.duration, schedule.count ?? 5).map(
+ {getNextOccurrences(schedule.rruleObject, schedule.duration, schedule.count ? Math.min(schedule.count, 5) : 5).map(
(occurrence) => (
{occurrence.text}
-
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 97ad59aa..842be6d5 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -784,8 +784,11 @@
"selected-all": "Vælg alle",
"select-some-options": "Vælg...",
"bytime": "Tidspunkt på dagen",
- "duration-error": "Varighed kan ikke være mindre end 0",
- "end": "Slut"
+ "duration-error": "Slut kan ikke være før start",
+ "end": "Slut",
+ "count": "Antal gentagelser",
+ "count-placeholder": "Ubegrænset",
+ "interval": "Interval"
},
"duration": {
"hours": "t.",
From 9da23ccef652921008b93750b1b063c9b648b9e5 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 17:39:46 +0200
Subject: [PATCH 05/13] 2000: Added backwards compatibility for byhour/byminute
---
src/components/util/schedule/schedule.jsx | 36 +++++++++++++++--------
src/translations/da/common.json | 6 ++--
2 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 513eeb66..ab97e492 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -243,15 +243,23 @@ function Schedule({ schedules, onChange }) {
setDuration(schedule.id, schedule, target)}
type="datetime-local"
/>
+
+
+
+
+
{t('schedule.help1')}
+
{t('schedule.help2')}
+
+
{durationError && {t('schedule.duration-error')} }
-
+
changeSchedule(schedule.id, target.id, target.value)
@@ -263,7 +271,7 @@ function Schedule({ schedules, onChange }) {
allowNull={false}
/>
-
+
setPositiveNumberOrNull(schedule.id, target)}
value={schedule.count ?? ''}
@@ -273,7 +281,7 @@ function Schedule({ schedules, onChange }) {
name="count"
/>
-
+
setPositiveNumberOrNull(schedule.id, target)}
value={schedule.interval ?? ''}
@@ -282,15 +290,17 @@ function Schedule({ schedules, onChange }) {
name="interval"
/>
-
- setTimeValue(schedule.id, target)}
- value={getTimeValue(schedule.byhour, schedule.byminute)}
- label={t("schedule.bytime")}
- type="time"
- name="bytime"
- />
-
+ {schedule.byhour && (
+
+ setTimeValue(schedule.id, target)}
+ value={getTimeValue(schedule.byhour, schedule.byminute)}
+ label={t("schedule.bytime")}
+ type="time"
+ name="bytime"
+ />
+
+ )}
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 842be6d5..b93968ad 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -777,7 +777,7 @@
"minutely": "Minut",
"rrulestring": "RRule",
"dtstart": "Start",
- "until": "Gentagelsernes sluttidspunkt",
+ "until": "Planlægningens sluttidspunkt",
"next-occurrences": "Næste 5 forekomster",
"all-selected": "Alle er valgt",
"clear-selection": "Ryd valg",
@@ -788,7 +788,9 @@
"end": "Slut",
"count": "Antal gentagelser",
"count-placeholder": "Ubegrænset",
- "interval": "Interval"
+ "interval": "Interval",
+ "help1": "Start/slut definerer længden, starttidspunkt på dagen og første mulige dato for gentagelserne.",
+ "help2": "Hvis gentagelsesreglerne ikke inkluderer starttidspunktet, kommer det ikke med."
},
"duration": {
"hours": "t.",
From e3a6d5b68e011bda4d3e162967e114defe31e13f Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 17:41:05 +0200
Subject: [PATCH 06/13] 2000: Updated changelog
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3a1a11b..011383a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+- Refactored scheduling to increase user experience.
+- Added interval and count to rrule inputs.
- [#252](https://github.com/os2display/display-admin-client/pull/252)
- Reverted change in https://github.com/os2display/display-admin-client/commit/65762066c708f541305a48fbd6b28264dca593b5 regarding rrule dtstart.
- Added comments about how rrules are handled.
From fde37d275b8cdd64029ddaab4030a5c705808d33 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Sun, 11 Aug 2024 17:56:18 +0200
Subject: [PATCH 07/13] 2000: Added isNaN checks for hiding byhour:byminute
when not defined
---
src/components/util/schedule/schedule.jsx | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index ab97e492..61537680 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -168,8 +168,16 @@ function Schedule({ schedules, onChange }) {
const { value } = target;
const split = value.split(":");
- changeSchedule(scheduleId, "byhour", parseInt(split[0], 10));
- changeSchedule(scheduleId, "byminute", parseInt(split[1], 10));
+ const hour = parseInt(split[0], 10);
+ const minute = parseInt(split[1], 10);
+
+ if (isNaN(hour) || isNaN(minute)) {
+ changeSchedule(scheduleId, "byhour", null);
+ changeSchedule(scheduleId, "byminute", null);
+ } else {
+ changeSchedule(scheduleId, "byhour", hour);
+ changeSchedule(scheduleId, "byminute", minute);
+ }
};
const setDuration = (scheduleId, schedule, target) => {
@@ -259,7 +267,7 @@ function Schedule({ schedules, onChange }) {
-
+
changeSchedule(schedule.id, target.id, target.value)
@@ -290,7 +298,7 @@ function Schedule({ schedules, onChange }) {
name="interval"
/>
- {schedule.byhour && (
+ {!isNaN(schedule.byhour) && (
setTimeValue(schedule.id, target)}
From ea7233a51c79fbea82387b054c38e061d361bf45 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Mon, 12 Aug 2024 10:45:39 +0200
Subject: [PATCH 08/13] 2000: Changed to human readable text for rrule
---
src/components/util/schedule/schedule.jsx | 7 ++++---
src/translations/da/common.json | 6 +++---
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 61537680..33837321 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -259,8 +259,7 @@ function Schedule({ schedules, onChange }) {
-
{t('schedule.help1')}
-
{t('schedule.help2')}
+
{t('schedule.helptext')}
{durationError && {t('schedule.duration-error')} }
@@ -414,7 +413,9 @@ function Schedule({ schedules, onChange }) {
)}
-
{t("schedule.rrulestring")}: {schedule.rrule}
+
+ {t('schedule.repetition')}: {schedule.rruleObject.toText()}
+
))}
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index b93968ad..3e0f986d 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -777,7 +777,7 @@
"minutely": "Minut",
"rrulestring": "RRule",
"dtstart": "Start",
- "until": "Planlægningens sluttidspunkt",
+ "until": "Planlægningen afsluttes",
"next-occurrences": "Næste 5 forekomster",
"all-selected": "Alle er valgt",
"clear-selection": "Ryd valg",
@@ -789,8 +789,8 @@
"count": "Antal gentagelser",
"count-placeholder": "Ubegrænset",
"interval": "Interval",
- "help1": "Start/slut definerer længden, starttidspunkt på dagen og første mulige dato for gentagelserne.",
- "help2": "Hvis gentagelsesreglerne ikke inkluderer starttidspunktet, kommer det ikke med."
+ "helptext": "Start/slut definerer længden, tidspunkt på dagen og første mulige dato for gentagelserne.",
+ "repetition": "RRule"
},
"duration": {
"hours": "t.",
From 201fe4963c80b08f2bbc2b4c2c0a6192598fea99 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Mon, 12 Aug 2024 12:28:53 +0200
Subject: [PATCH 09/13] 2000: Moved repeat into card
---
src/components/util/schedule/schedule-util.js | 4 +-
src/components/util/schedule/schedule.jsx | 299 +++++++++---------
src/translations/da/common.json | 4 +-
3 files changed, 157 insertions(+), 150 deletions(-)
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index 89736429..14e6a10c 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -57,8 +57,8 @@ const createNewSchedule = () => {
const newSchedule = {
id: ulid(nowTimestamp),
duration: 60 * 60, // Default 1 hour.
- freq: RRule.WEEKLY,
- count: null,
+ freq: RRule.DAILY,
+ count: 1,
interval: null,
// For evaluation with the RRule library we pretend that "now" 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.
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 33837321..8e4a12ce 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -254,168 +254,175 @@ function Schedule({ schedules, onChange }) {
name="end"
onChange={({target}) => setDuration(schedule.id, schedule, target)}
type="datetime-local"
+ className={durationError ? 'border-danger' : ''}
/>
-
{t('schedule.helptext')}
+
{t('schedule.helptext')}
{durationError && {t('schedule.duration-error')} }
-
-
-
- changeSchedule(schedule.id, target.id, target.value)
- }
- value={schedule.freq}
- label={t("schedule.freq")}
- name="freq"
- options={freqOptions}
- allowNull={false}
- />
-
-
- setPositiveNumberOrNull(schedule.id, target)}
- value={schedule.count ?? ''}
- label={t("schedule.count")}
- placeholder={t('schedule.count-placeholder')}
- type="search"
- name="count"
- />
-
-
- setPositiveNumberOrNull(schedule.id, target)}
- value={schedule.interval ?? ''}
- label={t("schedule.interval")}
- type="search"
- name="interval"
- />
-
- {!isNaN(schedule.byhour) && (
-
-
setTimeValue(schedule.id, target)}
- value={getTimeValue(schedule.byhour, schedule.byminute)}
- label={t("schedule.bytime")}
- type="time"
- name="bytime"
- />
+
+
+
+
+
+ changeSchedule(schedule.id, target.id, target.value)
+ }
+ value={schedule.freq}
+ label={t("schedule.freq")}
+ name="freq"
+ options={freqOptions}
+ allowNull={false}
+ />
+
+
+ setPositiveNumberOrNull(schedule.id, target)}
+ value={schedule.interval ?? ''}
+ label={t("schedule.interval")}
+ type="search"
+ name="interval"
+ />
+
+
+ setPositiveNumberOrNull(schedule.id, target)}
+ value={schedule.count ?? ''}
+ label={t("schedule.count")}
+ placeholder={t('schedule.count-placeholder')}
+ type="search"
+ name="count"
+ />
+
+ {!isNaN(schedule.byhour) && (
+
+ setTimeValue(schedule.id, target)}
+ value={getTimeValue(schedule.byhour, schedule.byminute)}
+ label={t("schedule.bytime")}
+ type="time"
+ name="bytime"
+ />
+
+ )}
- )}
-
-
-
-
- {t("schedule.byweekday")}
-
- byWeekdayOptions.find(
- (weekDay) => weekDay.value === weekdayNumber
+
+
+
+ {t("schedule.byweekday")}
+
+ byWeekdayOptions.find(
+ (weekDay) => weekDay.value === weekdayNumber
+ )
+ )
+ : []
+ }
+ name="byweekday"
+ disableSearch
+ overrideStrings={{
+ allItemsAreSelected: t("schedule.all-selected"),
+ clearSelected: t("schedule.clear-selection"),
+ selectAll: t("schedule.selected-all"),
+ selectSomeItems: t("schedule.select-some-options"),
+ }}
+ labelledBy="Select"
+ onChange={(value) => {
+ changeSchedule(
+ schedule.id,
+ "byweekday",
+ value.map((v) => v.value)
+ );
+ }}
+ />
+
+
+
+
+
+ {t("schedule.bymonth")}
+
+
+ changeSchedule(
+ schedule.id,
+ "bymonth",
+ values.map((v) => v.value)
)
- )
- : []
- }
- name="byweekday"
- disableSearch
- overrideStrings={{
- allItemsAreSelected: t("schedule.all-selected"),
- clearSelected: t("schedule.clear-selection"),
- selectAll: t("schedule.selected-all"),
- selectSomeItems: t("schedule.select-some-options"),
- }}
- labelledBy="Select"
- onChange={(value) => {
- changeSchedule(
- schedule.id,
- "byweekday",
- value.map((v) => v.value)
- );
- }}
- />
-
-
-
-
-
- {t("schedule.bymonth")}
-
-
- changeSchedule(
- schedule.id,
- "bymonth",
- values.map((v) => v.value)
- )
- }
- />
-
-
-
+ }
+ />
+
+
+
-
-
-
- changeSchedule(schedule.id, target.id, target.value)
- }
- name="byweekno"
- type="number"
- min="0"
- max="52"
- />
-
-
-
setDateValue(schedule.id, target)}
- type="datetime-local"
- />
+
+
+ setDateValue(schedule.id, target)}
+ type="datetime-local"
+ />
+
+ {schedule.freq === RRule.YEARLY && (
+
+
+ changeSchedule(schedule.id, target.id, target.value)
+ }
+ name="byweekno"
+ type="number"
+ min="0"
+ max="52"
+ />
+
+ )}
+
-
-
-
-
-
-
-
{t("schedule.next-occurrences")}:
- {getNextOccurrences(schedule.rruleObject, schedule.duration, schedule.count ? Math.min(schedule.count, 5) : 5).map(
- (occurrence) => (
- {occurrence.text}
- -
- {occurrence.end}
-
)
- )}
+
+
+
+
{t("schedule.next-occurrences")}:
+ {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/translations/da/common.json b/src/translations/da/common.json
index 3e0f986d..b7c63ef4 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -777,8 +777,8 @@
"minutely": "Minut",
"rrulestring": "RRule",
"dtstart": "Start",
- "until": "Planlægningen afsluttes",
- "next-occurrences": "Næste 5 forekomster",
+ "until": "Gentag indtil",
+ "next-occurrences": "Næste forekomster",
"all-selected": "Alle er valgt",
"clear-selection": "Ryd valg",
"selected-all": "Vælg alle",
From 7ac5b560bfef7d8f4ba9e3f1e5f221f60329bd4d Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Tue, 13 Aug 2024 11:57:02 +0200
Subject: [PATCH 10/13] 2000: Added tooltips
---
config-overrides.js | 6 +
package.json | 1 +
src/components/util/forms/form-checkbox.jsx | 1 -
src/components/util/forms/form-input.jsx | 11 +-
src/components/util/forms/select.jsx | 14 +
src/components/util/schedule/schedule.jsx | 369 +++++++++++---------
src/components/util/tooltip.jsx | 19 +
src/translations/da/common.json | 14 +-
yarn.lock | 33 ++
9 files changed, 306 insertions(+), 162 deletions(-)
create mode 100644 src/components/util/tooltip.jsx
diff --git a/config-overrides.js b/config-overrides.js
index b76f3c36..6bfdb90e 100644
--- a/config-overrides.js
+++ b/config-overrides.js
@@ -5,5 +5,11 @@ module.exports = function override(config, env) {
'remote-component.config.js': `${__dirname}/src/remote-component.config.js`,
};
+ config.module.rules.push({
+ test: /\.mjs$/,
+ include: /node_modules/,
+ type: "javascript/auto"
+ });
+
return config;
};
diff --git a/package.json b/package.json
index 6931f5d9..9a30a626 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"react-select": "^5.2.2",
"react-table": "^7.7.0",
"react-toastify": "^8.1.0",
+ "react-tooltip": "^5.28.0",
"rrule": "^2.7.2",
"typescript": "^4.4.2",
"ulid": "^2.3.0"
diff --git a/src/components/util/forms/form-checkbox.jsx b/src/components/util/forms/form-checkbox.jsx
index 5fe03c56..58d92b48 100644
--- a/src/components/util/forms/form-checkbox.jsx
+++ b/src/components/util/forms/form-checkbox.jsx
@@ -12,7 +12,6 @@ import { FormCheck, FormGroup } from "react-bootstrap";
* @param {string} props.value The value of the checkbox
* @param {Function} props.onChange The callback for changes in the checkbox
* @param {string} props.formGroupClasses Classes for the formgroup
- * @param {boolean} props.required Whether the checkbox is required.
* @returns {object} A checkbox.
*/
function FormCheckbox({
diff --git a/src/components/util/forms/form-input.jsx b/src/components/util/forms/form-input.jsx
index 7b62c71b..86ae7bf8 100644
--- a/src/components/util/forms/form-input.jsx
+++ b/src/components/util/forms/form-input.jsx
@@ -2,6 +2,7 @@ import { React } from "react";
import PropTypes from "prop-types";
import { FormControl, FormGroup, FormLabel, InputGroup } from "react-bootstrap";
import { useTranslation } from "react-i18next";
+import Tooltip from "../tooltip";
/**
* An input for forms.
@@ -36,6 +37,7 @@ function FormInput({
inputGroupExtra,
disabled,
required,
+ tooltip = null,
...rest
}) {
const { t } = useTranslation("common");
@@ -43,12 +45,15 @@ function FormInput({
/* eslint-disable react/jsx-props-no-spreading */
return (
- {label && (
+ {label && (<>
{label}
{required && " *"}
- )}
+ {tooltip !== null && (
+
+ )}
+ >)}
+ {tooltip !== null && (
+ <>
+
+
+ >
+ )}
{
const newSchedules = schedules.map((schedule) =>
@@ -206,6 +209,40 @@ function Schedule({ schedules, onChange }) {
}
}
+ const isRepeatingEvent = (schedule) => {
+ return !(schedule.duration === 60 * 60 &&
+ schedule.freq === RRule.DAILY &&
+ schedule.count === 1 &&
+ schedule.until === undefined &&
+ schedule.interval === undefined &&
+ schedule.byhour === undefined &&
+ schedule.byminute === undefined &&
+ schedule.byweekday === undefined &&
+ schedule.bymonth === undefined &&
+ schedule.byweekno === undefined);
+ }
+
+ const toggleRepeat = (schedule) => {
+ if ((isRepeatingEvent(schedule) || repeatActivated)) {
+ // Disable repeating schedule.
+ setRepeatActivated(false);
+ changeSchedule(schedule.id, 'duration', 60 * 60);
+ 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);
+ } else {
+ // Activate repeating schedule.
+ setRepeatActivated(true);
+ changeSchedule(schedule.id, 'count', null);
+ }
+ }
+
return (
setDateValue(schedule.id, target)}
type="datetime-local"
+ tooltip={t('schedule.dtstart-tooltip')}
/>
@@ -255,173 +293,190 @@ function Schedule({ schedules, onChange }) {
onChange={({target}) => setDuration(schedule.id, schedule, target)}
type="datetime-local"
className={durationError ? 'border-danger' : ''}
+ tooltip={t('schedule.end-tooltip')}
/>
+ {durationError && {t('schedule.duration-error')} }
-
-
- {t('schedule.helptext')}
-
-
- {durationError && {t('schedule.duration-error')} }
-
-
-
+
-
-
-
- changeSchedule(schedule.id, target.id, target.value)
- }
- value={schedule.freq}
- label={t("schedule.freq")}
- name="freq"
- options={freqOptions}
- allowNull={false}
- />
-
-
- setPositiveNumberOrNull(schedule.id, target)}
- value={schedule.interval ?? ''}
- label={t("schedule.interval")}
- type="search"
- name="interval"
- />
-
-
- setPositiveNumberOrNull(schedule.id, target)}
- value={schedule.count ?? ''}
- label={t("schedule.count")}
- placeholder={t('schedule.count-placeholder')}
- type="search"
- name="count"
- />
-
- {!isNaN(schedule.byhour) && (
-
-
setTimeValue(schedule.id, target)}
- value={getTimeValue(schedule.byhour, schedule.byminute)}
- label={t("schedule.bytime")}
- type="time"
- name="bytime"
- />
+ toggleRepeat(schedule)}
+ name="enableRepeat"
+ type="checkbox"
+ value={(isRepeatingEvent(schedule) || repeatActivated)}
+ label={t('schedule.enable-repeat')}
+ formGroupClasses="d-inline-block mb-2"
+ />
+
+
+ {(isRepeatingEvent(schedule) || repeatActivated) && (
+ <>
+
+
+
+ changeSchedule(schedule.id, target.id, target.value)
+ }
+ value={schedule.freq}
+ label={t("schedule.freq")}
+ name="freq"
+ options={freqOptions}
+ allowNull={false}
+ tooltip={t('schedule.frequency-tooltip')}
+ />
+
+
+ setPositiveNumberOrNull(schedule.id, target)}
+ value={schedule.interval ?? ''}
+ label={t("schedule.interval")}
+ type="search"
+ name="interval"
+ tooltip={t('schedule.interval-tooltip')}
+ />
+
+
+ setPositiveNumberOrNull(schedule.id, target)}
+ value={schedule.count ?? ''}
+ label={t("schedule.count")}
+ placeholder={t('schedule.count-placeholder')}
+ type="search"
+ name="count"
+ tooltip={t('schedule.count-tooltip')}
+ />
+
+ {!isNaN(schedule.byhour) && (
+
+ setTimeValue(schedule.id, target)}
+ value={getTimeValue(schedule.byhour, schedule.byminute)}
+ label={t("schedule.bytime")}
+ type="time"
+ name="bytime"
+ tooltip={t('schedule.bytime-tooltip')}
+ />
+
+ )}
- )}
-
-
-
-
- {t("schedule.byweekday")}
-
- byWeekdayOptions.find(
- (weekDay) => weekDay.value === weekdayNumber
+
+
+
+ {t("schedule.byweekday")}
+
+
+ byWeekdayOptions.find(
+ (weekDay) => weekDay.value === weekdayNumber
+ )
+ )
+ : []
+ }
+ name="byweekday"
+ disableSearch
+ overrideStrings={{
+ allItemsAreSelected: t("schedule.all-selected"),
+ clearSelected: t("schedule.clear-selection"),
+ selectAll: t("schedule.selected-all"),
+ selectSomeItems: t("schedule.select-some-options"),
+ }}
+ labelledBy="Select"
+ onChange={(value) => {
+ changeSchedule(
+ schedule.id,
+ "byweekday",
+ value.map((v) => v.value)
+ );
+ }}
+ />
+
+
+
+
+
+ {t("schedule.bymonth")}
+
+
+
+ changeSchedule(
+ schedule.id,
+ "bymonth",
+ values.map((v) => v.value)
)
- )
- : []
- }
- name="byweekday"
- disableSearch
- overrideStrings={{
- allItemsAreSelected: t("schedule.all-selected"),
- clearSelected: t("schedule.clear-selection"),
- selectAll: t("schedule.selected-all"),
- selectSomeItems: t("schedule.select-some-options"),
- }}
- labelledBy="Select"
- onChange={(value) => {
- changeSchedule(
- schedule.id,
- "byweekday",
- value.map((v) => v.value)
- );
- }}
- />
-
-
-
-
-
- {t("schedule.bymonth")}
-
-
- changeSchedule(
- schedule.id,
- "bymonth",
- values.map((v) => v.value)
- )
- }
- />
-
-
-
-
-
-
- setDateValue(schedule.id, target)}
- type="datetime-local"
- />
-
- {schedule.freq === RRule.YEARLY && (
-
-
- changeSchedule(schedule.id, target.id, target.value)
- }
- name="byweekno"
- type="number"
- min="0"
- max="52"
- />
+ }
+ />
+
+
- )}
-
+
+
+ setDateValue(schedule.id, target)}
+ type="datetime-local"
+ tooltip={t('schedule.until-tooltip')}
+ />
+
+ {schedule.freq === RRule.YEARLY && (
+
+
+ changeSchedule(schedule.id, target.id, target.value)
+ }
+ name="byweekno"
+ type="number"
+ min="0"
+ max="52"
+ tooltip={t('schedule.byweekno-tooltip')}
+ />
+
+ )}
+
+ >
+ )}
-
-
-
-
{t("schedule.next-occurrences")}:
- {getNextOccurrences(schedule.rruleObject, schedule.duration, schedule.count ? Math.min(schedule.count, 5) : 5).map(
- (occurrence) => (
- {occurrence.text}
- -
- {occurrence.end}
-
)
- )}
+ {(isRepeatingEvent(schedule) || repeatActivated) && (
+
+
+
+
{t("schedule.next-occurrences")}:
+ {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/tooltip.jsx b/src/components/util/tooltip.jsx
new file mode 100644
index 00000000..8c2ecbac
--- /dev/null
+++ b/src/components/util/tooltip.jsx
@@ -0,0 +1,19 @@
+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";
+
+function Tooltip({ id, content }) {
+ return <>
+
+
+
+
+ >;
+}
+
+export default Tooltip;
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index b7c63ef4..28a19043 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -789,8 +789,18 @@
"count": "Antal gentagelser",
"count-placeholder": "Ubegrænset",
"interval": "Interval",
- "helptext": "Start/slut definerer længden, tidspunkt på dagen og første mulige dato for gentagelserne.",
- "repetition": "RRule"
+ "dtstart-tooltip": "Start definerer tidspunkt på dagen og første mulige dato for gentagelserne, hvis dette aktiveres.",
+ "end-tooltip": "Forskellen imellem start og slut definerer længden på en gentagelse.",
+ "repetition": "RRule",
+ "enable-repeat": "Gentag planlægning",
+ "enable-repeat-tooltip": "Når gentagelse aktiveres bestemmer reglerne man vælger, hvornår spillelisten bliver vist.",
+ "frequency-tooptip": "Hvordan planlægningen skal gentages?",
+ "interval-tooltip": "Skal der være spring imellem gentagelse? Afhænger af frekvensen. F.eks. hver 3 dag.",
+ "count-tooltip": "Hvor mange gange skal planlægningen gentages? Tom værdi betyder ubegrænset.",
+ "tooltip-byweekday": "På hvilke dage skal reglen gælde?",
+ "tooltip-bymonth": "I hvilke månender skal reglen gælde?",
+ "tooltip-byweekno": "Hvilket ugenummer skal reglen gælde for?",
+ "until-tooltip": "Hvornår skal gentagelserne afsluttes? Dette tidspunkt påvirker starttidspunktet på en gentagelse, ikke sluttidspunktet."
},
"duration": {
"hours": "t.",
diff --git a/yarn.lock b/yarn.lock
index 0792a1cc..b4095835 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1243,6 +1243,26 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
+"@floating-ui/core@^1.6.0":
+ version "1.6.7"
+ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.7.tgz#7602367795a390ff0662efd1c7ae8ca74e75fb12"
+ integrity sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==
+ dependencies:
+ "@floating-ui/utils" "^0.2.7"
+
+"@floating-ui/dom@^1.6.1":
+ version "1.6.10"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.10.tgz#b74c32f34a50336c86dcf1f1c845cf3a39e26d6f"
+ integrity sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==
+ dependencies:
+ "@floating-ui/core" "^1.6.0"
+ "@floating-ui/utils" "^0.2.7"
+
+"@floating-ui/utils@^0.2.7":
+ version "0.2.7"
+ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.7.tgz#d0ece53ce99ab5a8e37ebdfe5e32452a2bfc073e"
+ integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==
+
"@foliojs-fork/fontkit@^1.9.1":
version "1.9.1"
resolved "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.1.tgz"
@@ -3761,6 +3781,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
+classnames@^2.3.0:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
+ integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
+
classnames@^2.3.1:
version "2.3.1"
resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz"
@@ -11112,6 +11137,14 @@ react-toastify@^8.1.0:
dependencies:
clsx "^1.1.1"
+react-tooltip@^5.28.0:
+ version "5.28.0"
+ resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-5.28.0.tgz#c7b5343ab2d740a428494a3d8315515af1f26f46"
+ integrity sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg==
+ dependencies:
+ "@floating-ui/dom" "^1.6.1"
+ classnames "^2.3.0"
+
react-transition-group@^4.3.0, react-transition-group@^4.4.1:
version "4.4.2"
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz"
From 4d38df73ede23dbbcc5e4c6d7d535a9cc9dee662 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Wed, 14 Aug 2024 09:35:05 +0200
Subject: [PATCH 11/13] 2000: Fixed repeat active checkbox ui flow
---
src/components/util/schedule/schedule.jsx | 17 ++++++++++-------
src/translations/da/common.json | 3 ++-
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 1ac62b3b..22748bcd 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -39,7 +39,6 @@ function Schedule({ schedules, onChange }) {
const byMonthOptions = getByMonthOptions(t);
const [localSchedules, setLocalSchedules] = useState([]);
const [durationError, setDurationError] = useState(false);
- const [repeatActivated, setRepeatActivated] = useState(false);
useEffect(() => {
const newSchedules = schedules.map((schedule) =>
@@ -223,9 +222,9 @@ function Schedule({ schedules, onChange }) {
}
const toggleRepeat = (schedule) => {
- if ((isRepeatingEvent(schedule) || repeatActivated)) {
+ if ((isRepeatingEvent(schedule) || schedule.repeatActivated)) {
// Disable repeating schedule.
- setRepeatActivated(false);
+ changeSchedule(schedule.id, 'repeatActivated', false);
changeSchedule(schedule.id, 'duration', 60 * 60);
changeSchedule(schedule.id, 'freq', RRule.DAILY);
changeSchedule(schedule.id, 'count', 1);
@@ -238,7 +237,7 @@ function Schedule({ schedules, onChange }) {
changeSchedule(schedule.id, 'byweekno', null);
} else {
// Activate repeating schedule.
- setRepeatActivated(true);
+ changeSchedule(schedule.id, 'repeatActivated', true);
changeSchedule(schedule.id, 'count', null);
}
}
@@ -254,6 +253,10 @@ function Schedule({ schedules, onChange }) {
{t("schedule.add-schedule-button-text")}
+
+ {t('schedule.helptext')}
+
+
{localSchedules &&
localSchedules.map((schedule, index) => (
@@ -304,13 +307,13 @@ function Schedule({ schedules, onChange }) {
onChange={() => toggleRepeat(schedule)}
name="enableRepeat"
type="checkbox"
- value={(isRepeatingEvent(schedule) || repeatActivated)}
+ value={(isRepeatingEvent(schedule) || schedule.repeatActivated)}
label={t('schedule.enable-repeat')}
formGroupClasses="d-inline-block mb-2"
/>
- {(isRepeatingEvent(schedule) || repeatActivated) && (
+ {(isRepeatingEvent(schedule) || schedule.repeatActivated) && (
<>
@@ -457,7 +460,7 @@ function Schedule({ schedules, onChange }) {
>
)}
- {(isRepeatingEvent(schedule) || repeatActivated) && (
+ {(isRepeatingEvent(schedule) || schedule.repeatActivated) && (
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 28a19043..a2ca48d0 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -800,7 +800,8 @@
"tooltip-byweekday": "På hvilke dage skal reglen gælde?",
"tooltip-bymonth": "I hvilke månender skal reglen gælde?",
"tooltip-byweekno": "Hvilket ugenummer skal reglen gælde for?",
- "until-tooltip": "Hvornår skal gentagelserne afsluttes? Dette tidspunkt påvirker starttidspunktet på en gentagelse, ikke sluttidspunktet."
+ "until-tooltip": "Hvornår skal gentagelserne afsluttes? Dette tidspunkt påvirker starttidspunktet på en gentagelse, ikke sluttidspunktet.",
+ "helptext": "Når minimum én planlægning er tilføjet, bliver spillelisten kun vist i planlægningsintervallet."
},
"duration": {
"hours": "t.",
From 36f00f456bbd78276a91ff7372a086cc8d343920 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Wed, 14 Aug 2024 10:38:20 +0200
Subject: [PATCH 12/13] 2000: Minor fixes
---
src/components/util/schedule/schedule.jsx | 30 +++++++++++++++--------
src/translations/da/common.json | 13 +++++-----
2 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/src/components/util/schedule/schedule.jsx b/src/components/util/schedule/schedule.jsx
index 22748bcd..7e931d4e 100644
--- a/src/components/util/schedule/schedule.jsx
+++ b/src/components/util/schedule/schedule.jsx
@@ -39,6 +39,7 @@ function Schedule({ schedules, onChange }) {
const byMonthOptions = getByMonthOptions(t);
const [localSchedules, setLocalSchedules] = useState([]);
const [durationError, setDurationError] = useState(false);
+ const [activatedRepeatIds, setActivatedRepeatIds] = useState({});
useEffect(() => {
const newSchedules = schedules.map((schedule) =>
@@ -209,7 +210,7 @@ function Schedule({ schedules, onChange }) {
}
const isRepeatingEvent = (schedule) => {
- return !(schedule.duration === 60 * 60 &&
+ return !(
schedule.freq === RRule.DAILY &&
schedule.count === 1 &&
schedule.until === undefined &&
@@ -221,11 +222,19 @@ function Schedule({ schedules, onChange }) {
schedule.byweekno === undefined);
}
+ const displayRepeat = (schedule) => {
+ return isRepeatingEvent(schedule) || activatedRepeatIds[schedule.id] === true;
+ }
+
+ const updateActivatedRepeats = (id, value) => {
+ const updated = {...activatedRepeatIds};
+ updated[id] = value;
+ setActivatedRepeatIds(updated);
+ }
+
const toggleRepeat = (schedule) => {
- if ((isRepeatingEvent(schedule) || schedule.repeatActivated)) {
+ if (displayRepeat(schedule)) {
// Disable repeating schedule.
- changeSchedule(schedule.id, 'repeatActivated', false);
- changeSchedule(schedule.id, 'duration', 60 * 60);
changeSchedule(schedule.id, 'freq', RRule.DAILY);
changeSchedule(schedule.id, 'count', 1);
changeSchedule(schedule.id, 'interval', null);
@@ -235,10 +244,11 @@ function Schedule({ schedules, onChange }) {
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, 'repeatActivated', true);
changeSchedule(schedule.id, 'count', null);
+ updateActivatedRepeats(schedule.id, true);
}
}
@@ -307,13 +317,13 @@ function Schedule({ schedules, onChange }) {
onChange={() => toggleRepeat(schedule)}
name="enableRepeat"
type="checkbox"
- value={(isRepeatingEvent(schedule) || schedule.repeatActivated)}
+ value={displayRepeat(schedule)}
label={t('schedule.enable-repeat')}
formGroupClasses="d-inline-block mb-2"
/>
- {(isRepeatingEvent(schedule) || schedule.repeatActivated) && (
+ {displayRepeat(schedule) && (
<>
@@ -367,7 +377,7 @@ function Schedule({ schedules, onChange }) {
{t("schedule.byweekday")}
-
+
{t("schedule.bymonth")}
-
+
)}
- {(isRepeatingEvent(schedule) || schedule.repeatActivated) && (
+ {displayRepeat(schedule) && (
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index a2ca48d0..406f1720 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -789,17 +789,18 @@
"count": "Antal gentagelser",
"count-placeholder": "Ubegrænset",
"interval": "Interval",
- "dtstart-tooltip": "Start definerer tidspunkt på dagen og første mulige dato for gentagelserne, hvis dette aktiveres.",
- "end-tooltip": "Forskellen imellem start og slut definerer længden på en gentagelse.",
"repetition": "RRule",
"enable-repeat": "Gentag planlægning",
"enable-repeat-tooltip": "Når gentagelse aktiveres bestemmer reglerne man vælger, hvornår spillelisten bliver vist.",
- "frequency-tooptip": "Hvordan planlægningen skal gentages?",
+ "end-tooltip": "Forskellen imellem start og slut definerer længden på en gentagelse.",
+ "dtstart-tooltip": "Start definerer tidspunkt på dagen og første mulige dato for gentagelserne, hvis dette aktiveres.",
+ "frequency-tooltip": "Hvordan planlægningen skal gentages?",
"interval-tooltip": "Skal der være spring imellem gentagelse? Afhænger af frekvensen. F.eks. hver 3 dag.",
"count-tooltip": "Hvor mange gange skal planlægningen gentages? Tom værdi betyder ubegrænset.",
- "tooltip-byweekday": "På hvilke dage skal reglen gælde?",
- "tooltip-bymonth": "I hvilke månender skal reglen gælde?",
- "tooltip-byweekno": "Hvilket ugenummer skal reglen gælde for?",
+ "bytime-tooltip": "På hvilke dage skal reglen gælde?",
+ "byweekday-tooltip": "På hvilke dage skal reglen gælde?",
+ "bymonth-tooltip": "I hvilke månender skal reglen gælde?",
+ "byweekno-tooltip": "Hvilket ugenummer skal reglen gælde for?",
"until-tooltip": "Hvornår skal gentagelserne afsluttes? Dette tidspunkt påvirker starttidspunktet på en gentagelse, ikke sluttidspunktet.",
"helptext": "Når minimum én planlægning er tilføjet, bliver spillelisten kun vist i planlægningsintervallet."
},
From 149430eaedb2ff1a138336b0dbed84dbe73cddf8 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 15 Aug 2024 13:14:48 +0200
Subject: [PATCH 13/13] 1859: Removed commented out code
---
src/components/util/schedule/schedule-util.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/components/util/schedule/schedule-util.js b/src/components/util/schedule/schedule-util.js
index 14e6a10c..e5f3fadf 100644
--- a/src/components/util/schedule/schedule-util.js
+++ b/src/components/util/schedule/schedule-util.js
@@ -160,8 +160,6 @@ const getFreqOptions = (t) => {
},
{ title: t("schedule.weekly"), value: RRule.WEEKLY, key: "rrule.weekly" },
{ title: t("schedule.daily"), value: RRule.DAILY, key: "rrule.daily" },
-// { title: t("schedule.hourly"), value: RRule.HOURLY, key: "rrule.hourly" },
-// { title: t("schedule.minutely"), value: RRule.MINUTELY, key: "rrule.minutely" },
];
};