diff --git a/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx index adc0949fd2..0acec64cca 100644 --- a/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx @@ -19,6 +19,7 @@ import { filterRoles, getAclTemplateText } from "../../../../utils/aclUtils"; import { useAppDispatch, useAppSelector } from "../../../../store"; import { fetchSeriesDetailsAcls } from "../../../../slices/seriesDetailsSlice"; import { getSeriesDetailsAcl } from "../../../../selectors/seriesDetailsSelectors"; +import { Tooltip } from "@mui/material"; /** * This component renders the access page for new events and series in the wizards. @@ -120,7 +121,7 @@ const NewAccessPage = ({ {/* Template selection*/}
- +
) @@ -357,14 +363,14 @@ const NewAccessPage = ({ nextPage(formik.values); } }} - tabIndex={100} + tabIndex={0} > {t("WIZARD.NEXT_STEP")} diff --git a/src/components/events/partials/ModalTabsAndPages/NewMetadataPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewMetadataPage.tsx index 9fbb2fd3ef..d4b8c3c271 100644 --- a/src/components/events/partials/ModalTabsAndPages/NewMetadataPage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/NewMetadataPage.tsx @@ -31,7 +31,7 @@ const NewMetadataPage = ({
{t(header)}
{/* Table view containing input fields for metadata */}
-
@@ -135,6 +136,7 @@ const NewAccessPage = ({
{/* dropdown for selecting a policy template */}
@@ -245,6 +248,7 @@ const NewAccessPage = ({ placeholder={t( "EVENTS.SERIES.NEW.ACCESS.ROLES.LABEL" )} + tabIndex={0} disabled={ !hasAccess( editAccessRole, @@ -285,10 +289,12 @@ const NewAccessPage = ({ )} {/*Remove policy*/}
-
+
{/* Render table row for each metadata field depending on type*/} {!!metadataFields.fields && @@ -51,6 +51,8 @@ const NewMetadataPage = ({ name={field.id} fieldInfo={field} component={RenderMultiField} + ariaLabel={t(field.label)} + ariaRequired={field.required} /> ) : ( ({ metadataField={field} isFirstField={key === 0} component={RenderField} + ariaLabel={t(field.label)} + ariaRequired={field.required} /> )} diff --git a/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx index 65d2bb5fa3..0b311dfcaf 100644 --- a/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx @@ -71,6 +71,7 @@ const NewProcessingPage = ({ {workflowDef.length > 0 ? (
({ placeholder={t( "EVENTS.EVENTS.NEW.PROCESSING.SELECT_WORKFLOW" )} + tabIndex={0} />
) : ( diff --git a/src/components/events/partials/ModalTabsAndPages/NewSourcePage.tsx b/src/components/events/partials/ModalTabsAndPages/NewSourcePage.tsx index bc960a158d..88b25325c3 100644 --- a/src/components/events/partials/ModalTabsAndPages/NewSourcePage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/NewSourcePage.tsx @@ -42,6 +42,7 @@ import { Recording, fetchRecordings } from "../../../../slices/recordingSlice"; import { removeNotificationWizardForm } from "../../../../slices/notificationSlice"; import { parseISO } from "date-fns"; import { checkConflicts } from "../../../../slices/eventSlice"; +import { Tooltip } from "@mui/material"; /** * This component renders the source page for new events in the new event wizard. @@ -242,14 +243,12 @@ const NewSourcePage = ({ nextPage(formik.values); } }} - tabIndex={100} > {t("WIZARD.NEXT_STEP")} @@ -283,7 +282,7 @@ const Upload = ({ formik }) => { {t("EVENTS.EVENTS.NEW.SOURCE.UPLOAD.RECORDING_ELEMENTS")}
-
+
{/*File upload button for each upload asset*/} @@ -292,7 +291,7 @@ const Upload = ({ formik }) => { // @ts-expect-error TS(7006): Parameter 'asset' implicitly has an 'any' type. formik.values.uploadAssetsTrack.map((asset, key) => ( - )) @@ -404,7 +406,6 @@ const Schedule = {t(input.value)} @@ -416,7 +417,7 @@ const Schedule =
{t("EVENTS.EVENTS.NEW.SOURCE.DATE_TIME.CAPTION")}
-
+ {translateOverrideFallback(asset, t, "SHORT")} @@ -312,21 +311,24 @@ const Upload = ({ formik }) => { type="file" multiple={asset.multiple} name={`uploadAssetsTrack.${key}.file`} - tabIndex={0} + aria-labelledby={asset.id + '_description'} /> -
+
@@ -430,6 +431,7 @@ const Schedule = { if (formik.values.sourceMode === "SCHEDULE_MULTIPLE") { @@ -446,8 +448,6 @@ const Schedule = @@ -463,6 +463,7 @@ const Schedule = changeEndDateMultiple( value, @@ -470,8 +471,6 @@ const Schedule = @@ -490,7 +489,7 @@ const Schedule = ))} @@ -509,6 +508,7 @@ const Schedule = {/* drop-down for minute @@ -539,6 +540,7 @@ const Schedule = @@ -576,6 +579,7 @@ const Schedule = {/* drop-down for minute @@ -606,6 +611,7 @@ const Schedule = @@ -643,6 +650,7 @@ const Schedule = {/* drop-down for minute @@ -673,6 +682,7 @@ const Schedule = {/* display end date if on different day to start date, only if this is current source mode */} @@ -722,6 +733,7 @@ const Schedule = diff --git a/src/components/shared/DropDown.tsx b/src/components/shared/DropDown.tsx index 12982eaefe..60e5accba7 100644 --- a/src/components/shared/DropDown.tsx +++ b/src/components/shared/DropDown.tsx @@ -47,6 +47,8 @@ const DropDown = ({ autoFocus = false, defaultOpen = false, disabled = false, + ariaLabel, + ariaRequired = false }: { value: T text: string, @@ -59,6 +61,8 @@ const DropDown = ({ autoFocus?: boolean, defaultOpen?: boolean, disabled?: boolean, + ariaLabel?: string + ariaRequired?: boolean }) => { const { t } = useTranslation(); @@ -87,6 +91,8 @@ const DropDown = ({ onInputChange={(value) => setSearch(value)} onChange={(element) => handleChange(element)} isDisabled={disabled} + aria-label={ariaLabel} + aria-required={ariaRequired} /> ); }; diff --git a/src/components/shared/wizard/RenderField.tsx b/src/components/shared/wizard/RenderField.tsx index e3cb3a8edb..ddab602637 100644 --- a/src/components/shared/wizard/RenderField.tsx +++ b/src/components/shared/wizard/RenderField.tsx @@ -22,12 +22,16 @@ const RenderField = ({ form, showCheck = false, isFirstField = false, + ariaLabel, + ariaRequired = false, }: { field: FieldProps["field"] metadataField: MetadataField form: FieldProps["form"] showCheck?: boolean, isFirstField?: boolean, + ariaLabel?: string + ariaRequired?: boolean }) => { const { t } = useTranslation(); @@ -58,6 +62,8 @@ const RenderField = ({ form={form} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} {metadataField.type === "text" && @@ -80,6 +86,8 @@ const RenderField = ({ setEditMode={setEditMode} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} {metadataField.type === "ordered_text" && ( @@ -92,6 +100,8 @@ const RenderField = ({ setEditMode={setEditMode} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} {metadataField.type === "text" && @@ -106,6 +116,8 @@ const RenderField = ({ setEditMode={setEditMode} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} {metadataField.type === "text_long" && ( @@ -117,6 +129,8 @@ const RenderField = ({ setEditMode={setEditMode} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} {metadataField.type === "date" && ( @@ -128,6 +142,8 @@ const RenderField = ({ setEditMode={setEditMode} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} {metadataField.type === "boolean" && ( @@ -136,6 +152,8 @@ const RenderField = ({ form={form} showCheck={showCheck} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> )} @@ -148,15 +166,19 @@ const EditableBooleanValue = ({ handleKeyDown, form: { initialValues }, showCheck, + ariaLabel, + ariaRequired }: { field: FieldProps["field"] handleKeyDown: (event: React.KeyboardEvent, type: string) => void form: FieldProps["form"] showCheck?: boolean, + ariaLabel?: string, + ariaRequired?: boolean, }) => { return (
handleKeyDown(e, "input")} ref={childRef}> - + {showCheck && ( void showCheck?: boolean, + ariaLabel?: string, + ariaRequired?: boolean handleKeyDown: (event: React.KeyboardEvent, type: string) => void }) => editMode ? (
@@ -203,13 +229,17 @@ const EditableDateValue = ({ }, onBlur: (event) => { setEditMode(false) + }, + inputProps: { + "aria-label": ariaLabel, + "aria-required": ariaRequired } } }} />
) : ( -
setEditMode(true)} className="show-edit"> +
-
+ ); // renders editable field for selecting value via dropdown @@ -236,6 +266,8 @@ const EditableSingleSelect = ({ handleKeyDown, form: { setFieldValue, initialValues }, showCheck, + ariaLabel, + ariaRequired }: { field: FieldProps["field"] metadataField: MetadataField @@ -245,6 +277,8 @@ const EditableSingleSelect = ({ handleKeyDown: (event: React.KeyboardEvent, type: string) => void form: FieldProps["form"] showCheck?: boolean, + ariaLabel?: string, + ariaRequired?: boolean, }) => { const { t } = useTranslation(); @@ -264,10 +298,12 @@ const EditableSingleSelect = ({ placeholder={`-- ${t("SELECT_NO_OPTION_SELECTED")} --`} autoFocus={true} defaultOpen={true} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> ) : ( -
setEditMode(true)} className="show-edit"> +
- + ); }; @@ -294,6 +330,8 @@ const EditableSingleValueTextArea = ({ handleKeyDown, form: { initialValues }, showCheck, + ariaLabel, + ariaRequired, }: { field: FieldProps["field"] text: string @@ -302,6 +340,8 @@ const EditableSingleValueTextArea = ({ handleKeyDown: (event: React.KeyboardEvent, type: string) => void form: FieldProps["form"] showCheck?: boolean, + ariaLabel?: string, + ariaRequired?: boolean }) => { return editMode ? (
) : ( -
setEditMode(true)} className="show-edit"> +
+ ); }; @@ -341,6 +383,8 @@ const EditableSingleValue = ({ setEditMode, handleKeyDown, showCheck, + ariaLabel, + ariaRequired, }: { field: FieldProps["field"] form: FieldProps["form"] @@ -349,6 +393,9 @@ const EditableSingleValue = ({ setEditMode: (e: boolean) => void handleKeyDown: (event: React.KeyboardEvent, type: string) => void showCheck?: boolean, + ariaLabel?: string, + ariaRequired?: boolean + }) => { return editMode ? (
handleKeyDown(e, "input")} ref={childRef} > - +
) : ( -
setEditMode(true)} className="show-edit"> +
+ ); }; @@ -384,6 +431,8 @@ const EditableSingleValueTime = ({ setEditMode, showCheck, handleKeyDown, + ariaLabel, + ariaRequired }: { field: FieldProps["field"] text: string @@ -391,7 +440,9 @@ const EditableSingleValueTime = ({ editMode: boolean | undefined setEditMode: (e: boolean) => void showCheck?: boolean, - handleKeyDown: (event: React.KeyboardEvent, type: string) => void + ariaLabel?: string, + ariaRequired?: boolean, + handleKeyDown: (event: React.KeyboardEvent, type: string) => void, }) => { const { t } = useTranslation(); @@ -412,13 +463,18 @@ const EditableSingleValueTime = ({ }, onBlur: () => { setEditMode(false) + }, + inputProps: { + "aria-label": ariaLabel, + "aria-required": ariaRequired } - } + }, + }} /> ) : ( -
setEditMode(true)} className="show-edit"> +
- + ); }; diff --git a/src/components/shared/wizard/RenderMultiField.tsx b/src/components/shared/wizard/RenderMultiField.tsx index 64b57daa83..c3dabfe980 100644 --- a/src/components/shared/wizard/RenderMultiField.tsx +++ b/src/components/shared/wizard/RenderMultiField.tsx @@ -16,12 +16,16 @@ const RenderMultiField = ({ field, form, showCheck = false, + ariaLabel, + ariaRequired = false, }: { fieldInfo: MetadataField onlyCollectionValues?: boolean field: FieldProps["field"] form: FieldProps["form"] showCheck?: boolean, + ariaLabel?: string + ariaRequired?: boolean }) => { // Indicator if currently edit mode is activated const {editMode, setEditMode} = useClickOutsideField(childRef); @@ -37,12 +41,14 @@ const RenderMultiField = ({ }; const handleKeyDown = (event: React.KeyboardEvent) => { - // Check if pressed key is Enter - if (event.keyCode === 13 && inputValue !== "") { + const { key } = event; + if (key === "Enter" && inputValue !== "") { event.preventDefault(); - submitValue(); } + if (key === "Escape") { + setEditMode(false); + } }; const submitValue = (alternativeInput?: string) => { @@ -97,6 +103,8 @@ const RenderMultiField = ({ handleChange={handleChange} handleKeyDown={handleKeyDown} handleBlur={submitValue} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> ) : ( fieldInfo.type === "mixed_text" && ( @@ -108,6 +116,8 @@ const RenderMultiField = ({ removeItem={removeItem} handleChange={handleChange} handleKeyDown={handleKeyDown} + ariaLabel={ariaLabel} + ariaRequired={ariaRequired} /> ) )} @@ -133,6 +143,8 @@ const EditMultiSelect = ({ removeItem, field, fieldValue, + ariaLabel, + ariaRequired }: { collection: { [key: string]: unknown }[] handleKeyDown: (event: React.KeyboardEvent) => void @@ -141,7 +153,9 @@ const EditMultiSelect = ({ inputValue: HTMLInputElement["value"] removeItem: (key: number) => void field: FieldProps["field"] - fieldValue: FieldInputProps["value"] + fieldValue: FieldInputProps["value"], + ariaLabel?: string, + ariaRequired?: boolean, }) => { const { t } = useTranslation(); @@ -169,6 +183,8 @@ const EditMultiSelect = ({ placeholder={t("EDITABLE.MULTI.PLACEHOLDER")} list="data-list" autoFocus={true} + aria-label={ariaLabel} + aria-required={ariaRequired} /> {/* Display possible options for values as some kind of dropdown */} @@ -202,6 +218,8 @@ const EditMultiValue = ({ handleKeyDown, field, fieldValue, + ariaLabel, + ariaRequired, }: { setEditMode: (e: boolean) => void inputValue: HTMLInputElement["value"] @@ -210,6 +228,8 @@ const EditMultiValue = ({ handleKeyDown: (event: React.KeyboardEvent) => void field: FieldProps["field"] fieldValue: FieldInputProps["value"] + ariaLabel?: string + ariaRequired?: boolean }) => { const { t } = useTranslation(); @@ -223,6 +243,8 @@ const EditMultiValue = ({ onChange={(e) => handleChange(e)} value={inputValue} placeholder={t("EDITABLE.MULTI.PLACEHOLDER")} + aria-label={ariaLabel} + aria-required={ariaRequired} /> {fieldValue instanceof Array && @@ -252,7 +274,7 @@ const ShowValue = ({ showCheck: any, }) => { return ( -
setEditMode(true)} className="show-edit"> +
- + ); }; diff --git a/src/configs/modalConfig.ts b/src/configs/modalConfig.ts index 1511a405df..72c9e516df 100644 --- a/src/configs/modalConfig.ts +++ b/src/configs/modalConfig.ts @@ -56,30 +56,37 @@ export const weekdays = [ { name: "MO", label: "EVENTS.EVENTS.NEW.WEEKDAYS.MO", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.MO" }, { name: "TU", label: "EVENTS.EVENTS.NEW.WEEKDAYS.TU", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.TU", }, { name: "WE", label: "EVENTS.EVENTS.NEW.WEEKDAYS.WE", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.WE", }, { name: "TH", label: "EVENTS.EVENTS.NEW.WEEKDAYS.TH", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.TH", }, { name: "FR", label: "EVENTS.EVENTS.NEW.WEEKDAYS.FR", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.FR", }, { name: "SA", label: "EVENTS.EVENTS.NEW.WEEKDAYS.SA", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.SA", }, { name: "SU", label: "EVENTS.EVENTS.NEW.WEEKDAYS.SU", + readableName: "EVENTS.EVENTS.NEW.WEEKDAYSLONG.SU", }, ]; diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index 488dcdb2ec..7cd0952503 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -501,7 +501,8 @@ "SUBTITLES": { "SHORT": "Subtitles", "DETAIL": "A subtitle file in vtt format" - } + }, + "RESET": "Reset file selection" }, "DATE_TIME": { "CAPTION": "Schedule", @@ -1081,6 +1082,7 @@ "READ": "Read", "ADDITIONAL_ACTIONS": "Additional Actions", "ACTION": "Actions", + "DELETE": "Delete", "NEW": "New policy", "DETAILS": "Details" }, diff --git a/src/styles/components/_tables.scss b/src/styles/components/_tables.scss index ccd69a851e..f468652dd1 100644 --- a/src/styles/components/_tables.scss +++ b/src/styles/components/_tables.scss @@ -297,6 +297,13 @@ } } + &.show-edit { + display: flex !important; + justify-content: space-between; + width: 100%; + color: #333;; + } + .notification { position: absolute; top: -3px; diff --git a/src/styles/main.scss b/src/styles/main.scss index 728d63d86c..5fddfa41ed 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -200,8 +200,9 @@ a.disabled, button.disabled, div.disabled { } div.show-edit { - display: flex; + display: flex !important; justify-content: space-between; + width: 100%; } span.editable { @@ -247,6 +248,7 @@ td.editable { .preserve-newlines { white-space: pre-wrap; + line-height: 25px; } .vertical-resize {
{t("EVENTS.EVENTS.NEW.SOURCE.DATE_TIME.TIMEZONE")}