Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
210 changes: 80 additions & 130 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
"i18next-browser-languagedetector": "^8.2.1",
"i18next-http-backend": "^3.0.2",
"lodash": "^4.17.23",
"moment": "^2.30.1",
"moment-timezone": "^0.6.0",
"react": "^19.2.4",
"react-chartjs-2": "^5.3.1",
"react-datepicker": "^8.8.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import SchedulingInputs from "../wizards/scheduling/SchedulingInputs";
import SchedulingConflicts from "../wizards/scheduling/SchedulingConflicts";
import { ParseKeys } from "i18next";
import ModalContentTable from "../../../shared/modals/ModalContentTable";
import i18n from "../../../../i18n/i18n";

export type InitialValues = {
scheduleStartDate: string;
Expand Down Expand Up @@ -104,7 +105,7 @@ const EventDetailsSchedulingTab = ({
}, []);

// Get info about the current language and its date locale
const currentLanguage = getCurrentLanguageInformation();
const currentLanguage = getCurrentLanguageInformation(i18n.language);

// Get timezone offset; Checks should be performed on UTC times
const offset = getTimezoneOffset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import SchedulingInputs from "../wizards/scheduling/SchedulingInputs";
import SchedulingConflicts from "../wizards/scheduling/SchedulingConflicts";
import { ParseKeys } from "i18next";
import { LuCircleX } from "react-icons/lu";
import i18n from "../../../../i18n/i18n";

/**
* This component renders the source page for new events in the new event wizard.
Expand Down Expand Up @@ -369,7 +370,7 @@ const Schedule = <T extends {
inputDevices: Recording[]
}) => {
const { t } = useTranslation();
const currentLanguage = getCurrentLanguageInformation();
const currentLanguage = getCurrentLanguageInformation(i18n.language);
const dispatch = useAppDispatch();

// Parse start-Date strings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { hours, minutes } from "../../../../../configs/modalConfig";
import { formatTimeForDropdown } from "../../../../../utils/dropDownUtils";
import { getCurrentLanguageInformation } from "../../../../../utils/utils";
import { ParseKeys } from "i18next";
import i18n from "../../../../../i18n/i18n";

const SchedulingTime = ({
hour,
Expand All @@ -28,7 +29,7 @@ const SchedulingTime = ({
}) => {
const { t } = useTranslation();
// Get info about the current language and its date locale
const currentLanguage = getCurrentLanguageInformation();
const currentLanguage = getCurrentLanguageInformation(i18n.language);

return (
<tr>
Expand Down
7 changes: 4 additions & 3 deletions src/components/shared/TableFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
import TableFilterProfiles from "./TableFilterProfiles";
import { availableHotkeys } from "../../configs/hotkeysConfig";
import { useHotkeys } from "react-hotkeys-hook";
import moment from "moment";
import { AppThunk, useAppDispatch, useAppSelector } from "../../store";
import { renderValidDate } from "../../utils/dateUtils";
import { getCurrentLanguageInformation } from "../../utils/utils";
Expand All @@ -35,6 +34,8 @@ import SearchContainer from "./SearchContainer";
import { Resource } from "../../slices/tableSlice";
import { HiFunnel } from "react-icons/hi2";
import { LuSettings, LuX } from "react-icons/lu";
import { isValid } from "date-fns";
import i18n from "../../i18n/i18n";

/**
* This component renders the table filters in the upper right corner of the table
Expand Down Expand Up @@ -202,7 +203,7 @@ const TableFilters = ({
};

const submitDateFilter = async (start: Date | undefined | null, end: Date | undefined | null) => {
if (start && end && moment(start).isValid() && moment(end).isValid()) {
if (start && end && isValid(start) && isValid(end)) {
const filter = filterMap.find(({ name }) => name === selectedFilter);
if (filter) {
dispatch(editFilterValue({
Expand Down Expand Up @@ -488,7 +489,7 @@ const FilterSwitch = ({
popperPlacement="bottom"
popperClassName="datepicker-custom"
className="datepicker-custom-input"
locale={getCurrentLanguageInformation()?.dateLocale}
locale={getCurrentLanguageInformation(i18n.language)?.dateLocale}
strictParsing
/>
</div>
Expand Down
53 changes: 28 additions & 25 deletions src/components/shared/TimeSeriesStatistics.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useState } from "react";
import moment from "moment";
import { getCurrentLanguageInformation } from "../../utils/utils";
import DatePicker from "react-datepicker";
import { Formik, FormikErrors } from "formik";
Expand All @@ -11,14 +10,16 @@ import {
statisticDateFormatStrings,
statisticTimeModes,
} from "../../configs/statisticsConfig";
import { localizedMoment } from "../../utils/dateUtils";
import { formatRangeEnd, formatRangeStart } from "../../utils/dateUtils";
import { useTranslation } from "react-i18next";
import type { ChartOptions } from "chart.js";
import { AsyncThunk } from "@reduxjs/toolkit";
import { useAppDispatch } from "../../store";
import { DataResolution, Statistics, TimeMode } from "../../slices/statisticsSlice";
import { ParseKeys } from "i18next";
import { LuChevronLeft, LuChevronRight, LuDownload } from "react-icons/lu";
import { add, format, parseISO, sub } from "date-fns";
import i18n from "../../i18n/i18n";


/**
Expand Down Expand Up @@ -73,12 +74,17 @@ const TimeSeriesStatistics = ({
const formatStrings = statisticDateFormatStrings;

// Get info about the current language and its date locale
const currentLanguage = getCurrentLanguageInformation();
const currentLanguage = getCurrentLanguageInformation(i18n.language);

// Set the date for the react-datepicker
const [startDatepicker, setStartDatepicker] = useState(fromDate ? new Date(fromDate) : null);
const [endDatepicker, setEndDatepicker] = useState(toDate ? new Date(toDate) : null);

const unitMap = {
year: "years",
month: "months",
} as const;

// change formik values and get new statistic values from API
const change = (
setFormikValue: (field: string, value: any) => Promise<void | FormikErrors<any>>,
Expand All @@ -88,8 +94,8 @@ const TimeSeriesStatistics = ({
dataResolution: DataResolution,
) => {
if (timeMode === "year" || timeMode === "month") {
from = moment(from).clone().startOf(timeMode).format("YYYY-MM-DD");
to = moment(from).clone().endOf(timeMode).format("YYYY-MM-DD");
from = formatRangeStart(from, timeMode);
to = formatRangeEnd(from, timeMode);
setStartDatepicker(new Date(from));
setEndDatepicker(new Date(to));
setFormikValue("fromDate", from);
Expand Down Expand Up @@ -129,9 +135,8 @@ const TimeSeriesStatistics = ({
from: string,
timeMode: keyof typeof formatStrings,
) => {
return localizedMoment(from, currentLanguage ? currentLanguage.dateLocale.code : "en").format(
formatStrings[timeMode],
);
const locale = currentLanguage?.dateLocale;
return format(parseISO(from), formatStrings[timeMode], { locale });
};

// change to and from dates in formik to previous timeframe and get new values from API
Expand All @@ -141,10 +146,11 @@ const TimeSeriesStatistics = ({
timeMode: TimeMode,
dataResolution: DataResolution,
) => {
const newFrom = moment(from)
// According to the moment.js docs, string is supported as a second argument here
.subtract(1, timeMode + "s" as moment.unitOfTime.DurationConstructor)
.format("YYYY-MM-DD");
if (timeMode === "custom") { return; }

const date = parseISO(from);
const newFromDate = sub(date, { [unitMap[timeMode]]: 1 });
const newFrom = format(newFromDate, "yyyy-MM-dd");
const to = newFrom;
change(setFormikValue, timeMode, newFrom, to, dataResolution);
};
Expand All @@ -156,10 +162,11 @@ const TimeSeriesStatistics = ({
timeMode: TimeMode,
dataResolution: DataResolution,
) => {
const newFrom = moment(from)
// According to the moment.js docs, string is supported as a second argument here
.add(1, timeMode + "s" as moment.unitOfTime.DurationConstructor)
.format("YYYY-MM-DD");
if (timeMode === "custom") { return; }

const date = parseISO(from);
const newFromDate = add(date, { [unitMap[timeMode]]: 1 });
const newFrom = format(newFromDate, "yyyy-MM-dd");
const to = newFrom;
change(setFormikValue, timeMode, newFrom, to, dataResolution);
};
Expand All @@ -171,12 +178,8 @@ const TimeSeriesStatistics = ({
initialValues={{
timeMode: timeMode,
dataResolution: dataResolution,
// Typescript complains that the method "startOf" cannot take "custom" as a parameter, but in practice
// this does not seem to be a problem
// @ts-expect-error: timeMode should be assignable here
fromDate: moment(fromDate).startOf(timeMode).format("YYYY-MM-DD"),
// @ts-expect-error: timeMode should be assignable here
toDate: moment(toDate).endOf(timeMode).format("YYYY-MM-DD"),
fromDate: formatRangeStart(fromDate, timeMode),
toDate: formatRangeEnd(toDate, timeMode),
}}
onSubmit={() => {}}
>
Expand Down Expand Up @@ -282,8 +285,8 @@ const TimeSeriesStatistics = ({
const [startDate, endDate] = dates;
setStartDatepicker(startDate);
setEndDatepicker(endDate);
const newStartDate = startDate ? moment(startDate).format("YYYY-MM-DD") : formik.values.fromDate;
const newEndDate = endDate ? moment(endDate).format("YYYY-MM-DD") : formik.values.toDate;
const newStartDate = startDate ? format(startDate, "yyyy-MM-dd") : formik.values.fromDate;
const newEndDate = endDate ? format(endDate, "yyyy-MM-dd") : formik.values.toDate;
change(
formik.setFieldValue,
formik.values.timeMode,
Expand All @@ -304,7 +307,7 @@ const TimeSeriesStatistics = ({
popperPlacement="bottom"
popperClassName="datepicker-custom"
className="datepicker-custom-input"
locale={getCurrentLanguageInformation()?.dateLocale}
locale={getCurrentLanguageInformation(i18n.language)?.dateLocale}
strictParsing
/>
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/components/shared/wizard/RenderField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { GroupBase, SelectInstance } from "react-select";
import TextareaAutosize from "react-textarea-autosize";
import { LuCheck, LuSquarePen } from "react-icons/lu";
import axios from "axios";
import i18n from "../../../i18n/i18n";

/**
* This component renders an editable field for single values depending on the type of the corresponding metadata
Expand Down Expand Up @@ -188,7 +189,7 @@ const EditableDateValue = ({
popperClassName="datepicker-custom"
className="datepicker-custom-input"
wrapperClassName="datepicker-custom-wrapper"
locale={getCurrentLanguageInformation()?.dateLocale}
locale={getCurrentLanguageInformation(i18n.language)?.dateLocale}
strictParsing
autoFocus={isFirstField}
/>
Expand Down Expand Up @@ -319,7 +320,7 @@ const EditableSingleValueTime = ({
popperClassName="datepicker-custom"
className="datepicker-custom-input"
wrapperClassName="datepicker-custom-wrapper"
locale={getCurrentLanguageInformation()?.dateLocale}
locale={getCurrentLanguageInformation(i18n.language)?.dateLocale}
strictParsing
autoFocus={isFirstField}
/>
Expand Down
4 changes: 2 additions & 2 deletions src/components/systems/partials/MeanQueueTimeCell.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Service } from "../../../slices/serviceSlice";
import moment from "moment";
import { formatHMS } from "../../../utils/dateUtils";

/**
* This component renders the mean queue time cells of systems in the table view
Expand All @@ -12,7 +12,7 @@ const MeanQueueTimeCell = ({

return (
<span>
{ moment.utc(moment.duration(row.meanQueueTime * 1000).asMilliseconds()).format("HH:mm:ss") }
{formatHMS(row.meanQueueTime)}
</span>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/systems/partials/MeanRunTimeCell.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Service } from "../../../slices/serviceSlice";
import moment from "moment";
import { formatHMS } from "../../../utils/dateUtils";

/**
* This component renders the mean run time cells of systems in the table view
Expand All @@ -12,7 +12,7 @@ const MeanRunTimeCell = ({

return (
<span>
{ moment.utc(moment.duration(row.meanRunTime * 1000).asMilliseconds()).format("HH:mm:ss") }
{formatHMS(row.meanQueueTime)}
</span>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/configs/statisticsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ export const availableCustomStatisticDataResolutions = [

// date format strings
export const statisticDateFormatStrings = {
month: "MMMM YYYY",
year: "YYYY",
month: "MMMM yyyy",
year: "yyyy",
};
11 changes: 7 additions & 4 deletions src/i18n/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import moment from "moment";

import HttpBackend, { HttpBackendOptions } from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
Expand All @@ -23,6 +22,8 @@ import svSETrans from "./org/opencastproject/adminui/languages/lang-sv_SE.json";
import trTRTrans from "./org/opencastproject/adminui/languages/lang-tr_TR.json";
import zhCNTrans from "./org/opencastproject/adminui/languages/lang-zh_CN.json";
import zhTWTrans from "./org/opencastproject/adminui/languages/lang-zh_TW.json";
import { getCurrentLanguageInformation } from "../utils/utils";
import { format } from "date-fns/format";

// Assignment of language code to translation file
// !!! If translation file of a new language is added, please add assignment here, too !!!
Expand Down Expand Up @@ -58,9 +59,11 @@ i18n

interpolation: {
escapeValue: false,
format: function (value, format, _lng) {
if (value instanceof Date) {
return moment(value).format(format);
format: function (value, formatStr, lng) {
if (value instanceof Date && formatStr && lng) {
return format(value, formatStr, {
locale: getCurrentLanguageInformation(lng)?.dateLocale,
});
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
Expand Down
18 changes: 9 additions & 9 deletions src/i18n/org/opencastproject/adminui/languages/lang-am_ET.json
Original file line number Diff line number Diff line change
Expand Up @@ -2147,19 +2147,19 @@
},
"dateFormats": {
"dateTime": {
"short": "{{dateTime, M\/D\/YY h:mm a}}",
"medium": "{{dateTime, MMM D, YYYY h:mm:ss a}}",
"full": "{{dateTime, dddd, MMMM D, yyyy h:mm:ss a z}}"
"short": "{{dateTime, Pp}}",
"medium": "{{dateTime, PPp}}",
"full": "{{dateTime, PPPPp}}"
},
"date": {
"short": "{{date, M\/D\/YY}}",
"medium": "{{date, MMM D, YYYY}}",
"full": "{{date, dddd, MMMM D, YYYY}}"
"short": "{{date, P}}",
"medium": "{{date, PP}}",
"full": "{{date, PPPPP}}"
},
"time": {
"short": "{{time, h:mm a}}",
"medium": "{{time, h:mm:ss a}}",
"full": "{{time, h:mm:ss a z}}"
"short": "{{time, p}}",
"medium": "{{time, pp}}",
"full": "{{time, ppp}}"
}
},
"ABOUT": {
Expand Down
18 changes: 9 additions & 9 deletions src/i18n/org/opencastproject/adminui/languages/lang-cs_CZ.json
Original file line number Diff line number Diff line change
Expand Up @@ -2147,19 +2147,19 @@
},
"dateFormats": {
"dateTime": {
"short": "{{dateTime, M\/D\/YY h:mm a}}",
"medium": "{{dateTime, MMM D, YYYY h:mm:ss a}}",
"full": "{{dateTime, dddd, MMMM D, yyyy h:mm:ss a z}}"
"short": "{{dateTime, Pp}}",
"medium": "{{dateTime, PPp}}",
"full": "{{dateTime, PPPPp}}"
},
"date": {
"short": "{{date, M\/D\/YY}}",
"medium": "{{date, MMM D, YYYY}}",
"full": "{{date, dddd, MMMM D, YYYY}}"
"short": "{{date, P}}",
"medium": "{{date, PP}}",
"full": "{{date, PPPPP}}"
},
"time": {
"short": "{{time, h:mm a}}",
"medium": "{{time, h:mm:ss a}}",
"full": "{{time, h:mm:ss a z}}"
"short": "{{time, p}}",
"medium": "{{time, pp}}",
"full": "{{time, ppp}}"
}
},
"ABOUT": {
Expand Down
Loading