1- import React , { useRef , useState } from "react" ;
1+ import React , { useEffect , useRef , useState } from "react" ;
22import { useTranslation } from "react-i18next" ;
33import DatePicker from "react-datepicker" ;
44import cn from "classnames" ;
5- import { getMetadataCollectionFieldName } from "../../../utils/resourceUtils" ;
5+ import { getMetadataCollectionFieldName , transformListProvider } from "../../../utils/resourceUtils" ;
66import { getCurrentLanguageInformation } from "../../../utils/utils" ;
77import DropDown from "../DropDown" ;
88import { parseISO } from "date-fns" ;
@@ -11,6 +11,7 @@ import { MetadataField } from "../../../slices/eventSlice";
1111import { GroupBase , SelectInstance } from "react-select" ;
1212import TextareaAutosize from "react-textarea-autosize" ;
1313import { LuCheck , LuSquarePen } from "react-icons/lu" ;
14+ import axios from "axios" ;
1415
1516/**
1617 * This component renders an editable field for single values depending on the type of the corresponding metadata
@@ -66,7 +67,7 @@ const RenderField = ({
6667 ) }
6768 { metadataField . type === "text" &&
6869 ! ! metadataField . collection &&
69- metadataField . collection . length > 0 && (
70+ (
7071 < EditableSingleSelect
7172 metadataField = { metadataField }
7273 field = { field }
@@ -92,7 +93,7 @@ const RenderField = ({
9293 ) }
9394 { metadataField . type === "text" &&
9495 ! (
95- ! ! metadataField . collection && metadataField . collection . length !== 0
96+ metadataField . collection
9697 ) && (
9798 < EditableSingleValue
9899 field = { field }
@@ -197,16 +198,7 @@ const EditableDateValue = ({
197198} ;
198199
199200// renders editable field for selecting value via dropdown
200- const EditableSingleSelect = ( {
201- field,
202- metadataField,
203- text,
204- form : { setFieldValue } ,
205- isFirstField,
206- focused,
207- setFocused,
208- ref,
209- } : {
201+ type EditableSingleSelectProps = ( {
210202 field : FieldProps [ "field" ]
211203 metadataField : MetadataField
212204 text : string
@@ -215,9 +207,25 @@ const EditableSingleSelect = ({
215207 focused : boolean ,
216208 setFocused : ( open : boolean ) => void
217209 ref : React . RefObject < SelectInstance < any , boolean , GroupBase < any > > >
218- } ) => {
210+ } )
211+ const EditableSingleSelect = ( props : EditableSingleSelectProps ) => {
219212 const { t } = useTranslation ( ) ;
220213
214+ const {
215+ field,
216+ metadataField,
217+ text,
218+ form : { setFieldValue } ,
219+ isFirstField,
220+ focused,
221+ setFocused,
222+ ref,
223+ } = props ;
224+
225+ if ( metadataField . id === "isPartOf" ) {
226+ return < EditableSingleSelectSeries { ...props } /> ;
227+ }
228+
221229 return (
222230 < DropDown
223231 ref = { ref }
@@ -323,4 +331,67 @@ const EditableSingleValueTime = ({
323331 ) ;
324332} ;
325333
334+ /**
335+ * Special case for series. Uses an async selector to fetch options.
336+ *
337+ * Ideally we could generalize this for all metadata fields with listproviders,
338+ * but other listproviders do not offer the required filtering capabilities.
339+ */
340+ const EditableSingleSelectSeries = ( {
341+ field,
342+ metadataField,
343+ text,
344+ form : { setFieldValue } ,
345+ isFirstField,
346+ focused,
347+ setFocused,
348+ ref,
349+ } : EditableSingleSelectProps ) => {
350+ const { t } = useTranslation ( ) ;
351+
352+ const [ label , setLabel ] = useState ( "" ) ;
353+
354+ useEffect ( ( ) => {
355+ // The metadata catalog only contains the field value, so we need to fetch the label ourselves
356+ const fetchLabelById = async ( ) => {
357+ if ( field . value ) {
358+ const res = await axios . get < { [ key : string ] : string } > ( `/admin-ng/resources/SERIES.WRITE_ONLY.json?limit=1&filter=textFilter:${ field . value } ` ) ;
359+ const data = res . data ;
360+ const transformedData = transformListProvider ( data ) ;
361+ if ( transformedData . length > 0 ) {
362+ setLabel ( transformedData [ 0 ] . label ) ;
363+ }
364+ }
365+ } ;
366+ fetchLabelById ( ) ;
367+ } , [ field . value ] ) ;
368+
369+ // Fetch collection
370+ const fetchOptions = async ( inputValue : string ) => {
371+ const res = await axios . get < { [ key : string ] : string } > ( `/admin-ng/resources/SERIES.WRITE_ONLY.json?filter=textFilter:${ inputValue } ` ) ;
372+ const data = res . data ;
373+ return transformListProvider ( data ) ;
374+ } ;
375+
376+ return (
377+ < DropDown
378+ ref = { ref }
379+ value = { field . value as string }
380+ text = { label }
381+ fetchOptions = { fetchOptions }
382+ required = { metadataField . required }
383+ handleChange = { element => element && setFieldValue ( field . name , element . value ) }
384+ placeholder = { focused
385+ ? `-- ${ t ( "SELECT_NO_OPTION_SELECTED" ) } --`
386+ : `${ t ( "SELECT_NO_OPTION_SELECTED" ) } `
387+ }
388+ customCSS = { { isMetadataStyle : focused ? false : true } }
389+ handleMenuIsOpen = { ( open : boolean ) => setFocused ( open ) }
390+ openMenuOnFocus
391+ autoFocus = { isFirstField }
392+ skipTranslate = { ! metadataField . translatable }
393+ />
394+ ) ;
395+ } ;
396+
326397export default RenderField ;
0 commit comments