diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/I18nRichInputField/I18nRichInputField.jsx b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/I18nRichInputField/I18nRichInputField.jsx index 06e7d413..3ca2101b 100644 --- a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/I18nRichInputField/I18nRichInputField.jsx +++ b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/I18nRichInputField/I18nRichInputField.jsx @@ -20,7 +20,6 @@ export const I18nRichInputField = ({ <GroupField fieldPath={fieldPath} optimized> <LanguageSelectField fieldPath={`${fieldPath}.lang`} - placeholder="" required width={lngFieldWidth} usedLanguages={usedLanguages} @@ -31,7 +30,6 @@ export const I18nRichInputField = ({ editorConfig={editorConfig} // TODO: hacky fix for SUI alignment bug for case with // field groups with empty field label on one of inputs - className={`${!label ? "mt-25" : ""}`} fieldPath={`${fieldPath}.value`} label={ diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/LanguageSelectField/LanguageSelectField.jsx b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/LanguageSelectField/LanguageSelectField.jsx index 2d5b7adc..73308b2f 100644 --- a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/LanguageSelectField/LanguageSelectField.jsx +++ b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/LanguageSelectField/LanguageSelectField.jsx @@ -3,7 +3,6 @@ import { FieldLabel } from "react-invenio-forms"; import { LocalVocabularySelectField } from "@js/oarepo_vocabularies"; import { i18next } from "@translations/oarepo_ui/i18next"; import PropTypes from "prop-types"; -import { useFormConfig } from "@js/oarepo_ui"; export const LanguageSelectField = ({ fieldPath, @@ -17,9 +16,6 @@ export const LanguageSelectField = ({ value, ...uiProps }) => { - const { - formConfig: { default_locale }, - } = useFormConfig(); return ( <LocalVocabularySelectField @@ -35,7 +31,6 @@ export const LanguageSelectField = ({ onChange={({ e, data, formikProps }) => { formikProps.form.setFieldValue(fieldPath, data.value); }} - defaultValue={multiple ? [default_locale] : default_locale} {...uiProps} /> ); diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/MultilingualTextInput/MultilingualTextInput.jsx b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/MultilingualTextInput/MultilingualTextInput.jsx index 050ac034..49a22e91 100644 --- a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/MultilingualTextInput/MultilingualTextInput.jsx +++ b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/components/MultilingualTextInput/MultilingualTextInput.jsx @@ -6,8 +6,12 @@ import { I18nTextInputField, I18nRichInputField, ArrayFieldItem, + useDefaultLocale, + useFormFieldValue, } from "@js/oarepo_ui"; import { i18next } from "@translations/oarepo_ui/i18next"; +import { useFormikContext, getIn } from "formik"; +import _get from "lodash/get"; export const MultilingualTextInput = ({ fieldPath, @@ -24,10 +28,21 @@ export const MultilingualTextInput = ({ lngFieldWidth, ...uiProps }) => { + const { defaultLocale } = useDefaultLocale(); + const { values } = useFormikContext(); + const { usedSubValues, defaultNewValue } = useFormFieldValue({ + defaultValue: defaultLocale, + fieldPath, + subValuesPath: "lang", + }); + const value = getIn(values, fieldPath); + const usedLanguages = usedSubValues(value) + const newValue = defaultNewValue(emptyNewInput, usedLanguages); + return ( <ArrayField addButtonLabel={addButtonLabel} - defaultNewValue={emptyNewInput} + defaultNewValue={newValue} fieldPath={fieldPath} label={ <FieldLabel htmlFor={fieldPath} icon={labelIcon ?? ""} label={label} /> @@ -52,7 +67,7 @@ export const MultilingualTextInput = ({ editorConfig={editorConfig} optimized required={required} - usedLanguages={array.map((v) => v.lang)} + usedLanguages={usedLanguages} lngFieldWidth={lngFieldWidth} {...uiProps} /> @@ -62,7 +77,7 @@ export const MultilingualTextInput = ({ label={textFieldLabel} labelIcon={textFieldIcon} required={required} - usedLanguages={array.map((v) => v.lang)} + usedLanguages={usedLanguages} lngFieldWidth={lngFieldWidth} {...uiProps} /> diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/hooks.js b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/hooks.js index c28b373d..ab35fe27 100644 --- a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/hooks.js +++ b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/forms/hooks.js @@ -1,7 +1,9 @@ import * as React from "react"; import { FormConfigContext } from "./contexts"; import { OARepoDepositApiClient, OARepoDepositSerializer } from "../api"; -import { useFormikContext } from "formik"; +import { useFormikContext, getIn } from "formik"; +import _get from "lodash/get" +import _set from "lodash/set" import _omit from "lodash/omit"; import _pick from "lodash/pick"; import _isEmpty from "lodash/isEmpty"; @@ -18,6 +20,14 @@ export const useFormConfig = () => { return context; }; +export const useDefaultLocale = () => { + const { + formConfig: { default_locale }, + } = useFormConfig(); + + return { defaultLocale: default_locale } +} + export const useVocabularyOptions = (vocabularyType) => { const { formConfig: { vocabularies }, @@ -35,6 +45,16 @@ export const useConfirmationModal = () => { return { isModalOpen, handleCloseModal, handleOpenModal }; }; +export const useFormFieldValue = ({ fieldPath, subValuesPath, defaultValue, subValuesUnique = true }) => { + const usedSubValues = (value) => + value && typeof Array.isArray(value) + ? value.map((val) => _get(val, "lang")) || [] + : []; + const defaultNewValue = (initialVal, usedSubValues = []) => _set({...initialVal}, subValuesPath, !usedSubValues?.includes(defaultValue) || !subValuesUnique ? defaultValue : "") + + return { usedSubValues, defaultNewValue } +} + export const useDepositApiClient = ( baseApiClient, serializer, @@ -71,7 +91,7 @@ export const useDepositApiClient = ( ? new baseApiClient(createUrl, recordSerializer) : new OARepoDepositApiClient(createUrl, recordSerializer); - async function save() { + async function save () { let response; setSubmitting(true); @@ -131,7 +151,7 @@ export const useDepositApiClient = ( } } - async function publish() { + async function publish () { // call save and if save returns false, exit const saveResult = await save(); if (!saveResult) return; @@ -176,11 +196,11 @@ export const useDepositApiClient = ( } } - async function read(recordUrl) { + async function read (recordUrl) { return await apiClient.readDraft({ self: recordUrl }); } - async function _delete(redirectUrl) { + async function _delete (redirectUrl) { if (!redirectUrl) throw new Error( "You must provide url where to be redirected after deleting a draft"