From ed89455eed770882bb72b251ccdab2dbae7a4262 Mon Sep 17 00:00:00 2001 From: tulakann Date: Mon, 4 Oct 2021 20:32:11 +0700 Subject: [PATCH 1/6] refactor(RegisterForm): completely extract mind-matching --- frontend/src/components/RegisterForm/index.js | 99 +++----------- frontend/src/modules/mind-matching/index.js | 128 +++++++++++++++--- 2 files changed, 126 insertions(+), 101 deletions(-) diff --git a/frontend/src/components/RegisterForm/index.js b/frontend/src/components/RegisterForm/index.js index 57bee63..f57667d 100644 --- a/frontend/src/components/RegisterForm/index.js +++ b/frontend/src/components/RegisterForm/index.js @@ -5,7 +5,9 @@ import { Controller, ErrorMessage, useForm } from "react-hook-form" import useAPI from "../../hooks/useAPI" import useEventTime from "../../hooks/useEventTime" import useFirebaseWrapper from "../../hooks/useFirebaseWrapper" -import MindMatchingModule from "../../modules/mind-matching" +import MindMatchingModule, { + defaultOptionalFields, +} from "../../modules/mind-matching" import { common, confirmPromise, @@ -52,42 +54,14 @@ const genderChoices = [ "Female", "Non-Binary", "Gender non conforming", - "Transgender male", - "Transgender female", "Prefer not to say", ] -const defaultOptionalFields = { - google_scholar: "", - personal_page: "", - collaboration_score: "0.5", - computational_score: "0.5", - meeting_platform: [], - abstracts: [], - coi: "", - participate_mind_match: false, - participate_grouped_mind: false, -} - -const defaultOptionalCheckers = { - google_scholar: "", - personal_page: "", - collaboration_score: "0.5", - computational_score: "0.5", - meetingPlatformSelect: [], - // a bit hacky here as there is no way to have default text as none - abstracts: [""], - coi: "", -} - const RegisterForm = ({ prevUserData, origin }) => { // get user info const { currentUserInfo: user } = useFirebaseWrapper() // state - const [isOptedOut, setIsOptedOut] = useState(false) const [isPublic, setIsPublic] = useState(false) - // warning is true only when there is some data in the optional fields - const [optOutWarning, setOptOutWarning] = useState(false) const [isSending, setIsSending] = useState(false) // api const { register: registerAPI, getAffiliation } = useAPI() @@ -95,6 +69,8 @@ const RegisterForm = ({ prevUserData, origin }) => { const { defaultAvailableTime } = useEventTime() // ref const toastControl = useRef(null) + // module states + const [isOptedOutMindMatching, setIsOptedOutMindMatching] = useState(false) const { register, @@ -107,54 +83,10 @@ const RegisterForm = ({ prevUserData, origin }) => { setError, } = useForm() - const watchOptIns = watch([ - "participate_mind_match", - // 'participate_grouped_mind', - ]) - - // side effect to track opt-in checkbox - useEffect(() => { - // isOptedOut is determined by 2 checkboxes - setIsOptedOut(Object.entries(watchOptIns).every(([_, v]) => v === false)) - - const optionalFields = getValues({ nest: true }) - - // check if any optional field is filled - const someIsFilled = Object.entries(defaultOptionalCheckers).some( - ([k, v]) => JSON.stringify(optionalFields[k]) !== JSON.stringify(v) - ) - - if (someIsFilled) { - setOptOutWarning(true) - } else { - setOptOutWarning(false) - } - }, [getValues, watchOptIns]) - useEffect(() => { let isActive = true if (prevUserData && isActive) { - // check if any of the prev optional field has value, if found even one - // do not disable optional fields - Object.entries(prevUserData).some(([key, val]) => { - // check only those optional fields - if (Object.keys(defaultOptionalFields).includes(key)) { - // in case of string - if (!Array.isArray(val) && defaultOptionalFields[key] !== val) { - setIsOptedOut(false) - return true - } - // in case of array - if (Array.isArray(val) && val.length > 0) { - setIsOptedOut(false) - return true - } - } - - return false - }) - const selectFields = { institution: "institutionSelect", gender_status: "genderStatusSelect", @@ -231,7 +163,7 @@ const RegisterForm = ({ prevUserData, origin }) => { setError( "availableDatetimePicker", "isRequired", - `Available Watching Time is required at least ${numberOfSlots} slots.` + `Available attending time is required at least ${numberOfSlots} slots.` ) setIsSending(false) @@ -264,7 +196,7 @@ const RegisterForm = ({ prevUserData, origin }) => { const readyData = { id: user.uid, - payload: !isOptedOut + payload: !isOptedOutMindMatching ? preparedPayload : { ...preparedPayload, @@ -484,8 +416,7 @@ const RegisterForm = ({ prevUserData, origin }) => { Please tell us below time slots that work best for you to - watch talks. We will use it to optimize schedule that best fit - for everyone. + attend the meeting. We collect them for overall statistics. {
setIsOptedOutMindMatching(x)} + formControl={{ + register, + control, + setValue, + errors, + getValues, + watch, + }} /> )} diff --git a/frontend/src/modules/mind-matching/index.js b/frontend/src/modules/mind-matching/index.js index e03062a..a981fcc 100644 --- a/frontend/src/modules/mind-matching/index.js +++ b/frontend/src/modules/mind-matching/index.js @@ -30,32 +30,115 @@ const meetingPlatformChoices = [ "Go To Meeting", ] +export const defaultOptionalFields = { + google_scholar: "", + personal_page: "", + collaboration_score: "0.5", + computational_score: "0.5", + meeting_platform: [], + abstracts: [], + coi: "", + participate_mind_match: false, + participate_grouped_mind: false, +} + +const defaultOptionalCheckers = { + google_scholar: "", + personal_page: "", + collaboration_score: "0.5", + computational_score: "0.5", + meetingPlatformSelect: [], + // a bit hacky here as there is no way to have default text as none + abstracts: [""], + coi: "", +} + // -- FUNCTIONS const createArrayWithNumbers = length => Array.from({ length }, (_, k) => k + 1) // -- MAIN const MindMatchingModule = ({ - abstracts, - formControl: { register, control, setValue, errors }, - isOptedOut, - optOutWarning, + prevUserData, + onOptedOutChange, + formControl: { register, control, setValue, errors, watch, getValues }, }) => { + // warning is true only when there is some data in the optional fields + const [isOptedOut, setIsOptedOut] = useState(false) + const [optOutWarning, setOptOutWarning] = useState(false) const [numberOfAbstract, setNumberOfAbstract] = useState(1) + const watchOptIns = watch([ + "participate_mind_match", + // 'participate_grouped_mind', + ]) + + // side effect to track opt-in checkbox useEffect(() => { - if (abstracts?.length > 0) { - setNumberOfAbstract(abstracts.length) + // isOptedOut is determined by 2 checkboxes + const currentOptedOutStatus = Object.entries(watchOptIns).every( + ([_, v]) => v === false + ) + setIsOptedOut(currentOptedOutStatus) + onOptedOutChange(currentOptedOutStatus) + + const optionalFields = getValues({ nest: true }) + + // check if any optional field is filled + const someIsFilled = Object.entries(defaultOptionalCheckers).some( + ([k, v]) => JSON.stringify(optionalFields[k]) !== JSON.stringify(v) + ) + + if (someIsFilled) { + setOptOutWarning(true) + } else { + setOptOutWarning(false) } - }, [abstracts]) + }, [getValues, onOptedOutChange, watchOptIns]) + + useEffect(() => { + let isActive = true + + if (prevUserData && isActive) { + // check if any of the prev optional field has value, if found even one + // do not disable optional fields + Object.entries(prevUserData).some(([key, val]) => { + // check only those optional fields + if (Object.keys(defaultOptionalFields).includes(key)) { + // in case of string + if (!Array.isArray(val) && defaultOptionalFields[key] !== val) { + setIsOptedOut(false) + return true + } + // in case of array + if (Array.isArray(val) && val.length > 0) { + setIsOptedOut(false) + return true + } + } + + return false + }) + } + + return () => { + isActive = false + } + }, [prevUserData]) + + useEffect(() => { + if (prevUserData?.abstracts?.length > 0) { + setNumberOfAbstract(prevUserData.abstracts.length) + } + }, [prevUserData.abstracts]) // set abstracts and cois when they are rerendered useEffect(() => { - if (abstracts) { - abstracts.forEach((x, ind) => { + if (prevUserData?.abstracts) { + prevUserData.abstracts.forEach((x, ind) => { setValue(`abstracts[${ind}]`, x) }) } - }, [abstracts, setValue, numberOfAbstract]) + }, [prevUserData.abstracts, setValue, numberOfAbstract]) return ( <> @@ -241,9 +324,7 @@ const MindMatchingModule = ({ the un-conference. We will try best not to match you with person you already know. - - Please separate each name with ; - + Please separate each name with ; Date: Mon, 4 Oct 2021 20:34:47 +0700 Subject: [PATCH 2/6] refactor(RegisterForm): remove mind-matching --- frontend/src/components/RegisterForm/index.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/RegisterForm/index.js b/frontend/src/components/RegisterForm/index.js index f57667d..90e4e7b 100644 --- a/frontend/src/components/RegisterForm/index.js +++ b/frontend/src/components/RegisterForm/index.js @@ -5,9 +5,9 @@ import { Controller, ErrorMessage, useForm } from "react-hook-form" import useAPI from "../../hooks/useAPI" import useEventTime from "../../hooks/useEventTime" import useFirebaseWrapper from "../../hooks/useFirebaseWrapper" -import MindMatchingModule, { - defaultOptionalFields, -} from "../../modules/mind-matching" +// import MindMatchingModule, { +// defaultOptionalFields, +// } from "../../modules/mind-matching" import { common, confirmPromise, @@ -70,7 +70,7 @@ const RegisterForm = ({ prevUserData, origin }) => { // ref const toastControl = useRef(null) // module states - const [isOptedOutMindMatching, setIsOptedOutMindMatching] = useState(false) + // const [isOptedOutMindMatching, setIsOptedOutMindMatching] = useState(false) const { register, @@ -78,8 +78,8 @@ const RegisterForm = ({ prevUserData, origin }) => { errors, setValue, control, - watch, - getValues, + // watch, + // getValues, setError, } = useForm() @@ -196,12 +196,13 @@ const RegisterForm = ({ prevUserData, origin }) => { const readyData = { id: user.uid, - payload: !isOptedOutMindMatching - ? preparedPayload - : { - ...preparedPayload, - ...defaultOptionalFields, - }, + payload: preparedPayload, + // payload: !isOptedOutMindMatching + // ? preparedPayload + // : { + // ...preparedPayload, + // ...defaultOptionalFields, + // }, } console.log("readyData:", readyData) @@ -432,8 +433,7 @@ const RegisterForm = ({ prevUserData, origin }) => { as={} /> -
- setIsOptedOutMindMatching(x)} formControl={{ @@ -444,7 +444,7 @@ const RegisterForm = ({ prevUserData, origin }) => { getValues, watch, }} - /> + /> */} )} From a327dbb16280902d32d9c1473afc02fcc79429e5 Mon Sep 17 00:00:00 2001 From: tulakann Date: Mon, 4 Oct 2021 20:40:07 +0700 Subject: [PATCH 3/6] refactor(footer): update content --- frontend/src/components/Footer/index.js | 40 +++++++++++-------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/Footer/index.js b/frontend/src/components/Footer/index.js index bd5d142..2cbc624 100644 --- a/frontend/src/components/Footer/index.js +++ b/frontend/src/components/Footer/index.js @@ -1,12 +1,13 @@ -import { Link } from 'gatsby'; -import React from 'react'; -import styled from 'styled-components'; -import { media } from '../../styles'; -import { color } from '../../utils'; +import { Link } from "gatsby" +import React from "react" +import styled from "styled-components" +import { media } from "../../styles" +import { color } from "../../utils" const StyledFooter = styled.div` height: 5.5em; - background-color: ${p => color.scale(p.theme.colors.primary, p.theme.colors.factor * 7)}; + background-color: ${p => + color.scale(p.theme.colors.primary, p.theme.colors.factor * 7)}; display: flex; align-items: center; @@ -16,21 +17,21 @@ const StyledFooter = styled.div` ${media.extraSmall` height: 6.5em; `} -`; +` const StyledFooterText = styled.div` font-size: 0.75em; text-align: center; color: ${p => p.theme.colors.secondary}; line-height: 1.6em; -`; +` const StyledLink = styled.a.attrs({ - target: '_blank', - rel: 'noopener noreferrer', + target: "_blank", + rel: "noopener noreferrer", })` color: ${p => p.theme.colors.accent}; -`; +` // const StyledInternalLink = styled(Link)` // color: ${p => p.theme.colors.accent}; @@ -38,28 +39,21 @@ const StyledLink = styled.a.attrs({ const Red = styled.span` color: ${p => p.theme.colors.danger}; -`; +` const Footer = () => ( Made with  ❤  - at -
- - Kording lab (University of Pennsylvania) - -  and  - - Neural Reckoning Lab (Imperial College) - + {"by "} + NMC organizers
Terms of Use | Code of Conduct
-); +) -export default Footer; +export default Footer From 7ef978e26a8d3c8284ebf04ada412e4bbad95d96 Mon Sep 17 00:00:00 2001 From: tulakann Date: Mon, 4 Oct 2021 20:42:05 +0700 Subject: [PATCH 4/6] refactor: change wording on agenda and submission --- frontend/src/pages/agenda.js | 16 ++++++---------- frontend/src/pages/submission.js | 14 ++++++-------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/frontend/src/pages/agenda.js b/frontend/src/pages/agenda.js index 3383c0a..60da88f 100644 --- a/frontend/src/pages/agenda.js +++ b/frontend/src/pages/agenda.js @@ -272,17 +272,13 @@ export default () => { />

- Join our conference via Crowdcast. If you sign up and opt-in to the mind matching, - you will be automatically matched with 6 other scientists working in related areas - for one-to-one communication. You can find them in your matches tab under - your profile before the conference. + Join Neuromatch Conference via Crowdcast.

Main Conference

The main conference will be happening on{" "} - {mainConfDateText} (starts at midnight GMT) - followed by mind-matching session if you opt-in to participate. The - main talks will happen in parallel on Zoom Webinar. The sessions will + {mainConfDateText} (starts at midnight GMT). The + main talks will happen in parallel on Crowdcast. The sessions will always be on and function as a lobby during short talks.

    @@ -294,9 +290,9 @@ export default () => { according to your chosen location. You can click each event to access event details and {" to add to Google calendar. "} - When you expand, you will also see links to Zoom ( + When you expand, you will also see links to Crowdcast ( - ). There are one stage and 9 rooms.{" "} + ). There are one stage and parallel rooms.{" "} If you change the timezone, please change the date to refresh this calendar view. @@ -308,7 +304,7 @@ export default () => { We also provide search engine, personal schedule, and recommendation engine on our{" "} - Abstract Browser page + Abstract Browser page.
diff --git a/frontend/src/pages/submission.js b/frontend/src/pages/submission.js index 6f9c42f..002468a 100644 --- a/frontend/src/pages/submission.js +++ b/frontend/src/pages/submission.js @@ -19,7 +19,7 @@ import { SubLabel, WarningMessage, } from "../components/FormComponents" -import { ControlSelect } from "../components/FormComponents/SelectWrapper" +// import { ControlSelect } from "../components/FormComponents/SelectWrapper" import Layout from "../components/layout" import TimezonePicker from "../components/TimezonePicker" import useSiteMetadata from "../hooks/useSiteMetadata" @@ -29,7 +29,7 @@ import useValidateRegistration from "../hooks/useValidateRegistration" import { common, Fa, reactSelectHelpers, timePickerHelpers } from "../utils" // -- CONSTANTS -const talkFormatOptions = ["Traditional talk", "Flash talk"] +// const talkFormatOptions = ["Traditional talk", "Flash talk"] // -- COMPONENTS const TopicHeading = ({ children }) => {`${children} · `} @@ -373,7 +373,7 @@ export default () => { ref={register()} /> - + {/* + */} @@ -424,10 +424,8 @@ export default () => { - Please select as many slots as you can. The more slots you - select, the larger your audience is likely to be. In extreme - cases, we may not be able to fit your talk into the schedule if - you only select a very small number of slots. + Please select as many slots as you can. We can allocate + presentation slots that are good for everyone. Date: Mon, 4 Oct 2021 20:42:29 +0700 Subject: [PATCH 5/6] docs: update instructions --- sitedata/markdown/how-to-register.md | 33 +++------------------------- sitedata/markdown/how-to-submit.md | 2 +- 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/sitedata/markdown/how-to-register.md b/sitedata/markdown/how-to-register.md index 573ba6c..af35486 100644 --- a/sitedata/markdown/how-to-register.md +++ b/sitedata/markdown/how-to-register.md @@ -9,12 +9,10 @@ slug: "/instructions/how-to-register" ![Profile](../../frontend/static/markdown-images/instructions/profile.png) -- If you previously signed up for Neuromatch conferences, you still have to [edit your profile](/edit-profile) under your log-in profile to register for the Neuromatch conference 4 (NMC4). -- After signing up, provide basic information about you, including your abstracts if you want to participate in the **mind-matching** (1-on-1 matching) part of the conference. +- If you previously signed up for Neuromatch conferences, you still have to [register](/edit-profile) under your log-in profile to register for the Neuromatch conference 4 (NMC4). +- After signing up, provide basic information about you. - You can always come back to edit your profile anytime before the registration ends. -- Make sure to choose if you want to participate in the matching component. That is where the fun is. But make sure you do it before the registration ends. -- After the registration ends, we will perform a matching algorithm. You will have an access to your matches under your profile to see your partners. -- We also add local meetups features (coming soon) where you can host or attend local meetups near you at NMC4. +- We will local meetups features (coming soon) where you can host or attend local meetups near you at NMC4. ---- @@ -24,31 +22,6 @@ Registration is required to attend the conference, including to have an abstract ![Payment](../../frontend/static/markdown-images/instructions/payment.png) ----- - -### Mind-matching Instructions (1-on-1 meeting) - -We use machine learning algorithm to match conference attendees together for one-on-one meeting, so called "mind-matching". To sign up, opt-in to the matching part to matching part in your registration profile and provide us your representative abstract. - -![Mind-matching Registration](../../frontend/static/markdown-images/instructions/mind-match-reg.png) - -#### Preparation - -- Preparation - - If you signed up for mind-match, we will send your match partners on your matches page a few days after the registration ends. You will get who your partners are and suggestions on how to e-meet them before, during, or after the main conference. - - You can exchange emails with your match partners to organize a time and meeting platforms (Skype/Zoom/etc.) beforehand. Please don't forget to include your timezone! - - You and your match are responsible for setting up the conversation, we just arrange the matches. -- Before the meeting with your match - - Have a quick look at your partner’s webpage or list of publications (a link will be included in the email we send you), but there is no expectation that you will read their papers. - - Think about how to quickly describe your research interests bearing in mind your partner’s background. This is particularly important for interdisciplinary meetings. -- Recommendation during the meeting - - Start by each of you talking for 1 - 2 minutes about your general interests and approach. - - If you immediately see a point of connection, go for it and talk about that. - - Feel free to use screen-sharing and your slides if you think they help. - - If not, try each of you describing briefly one or two projects that you think would be relevant or interesting to the other one, and see if that sparks an interesting discussion. - - Keep in mind, the idea is to give yourselves the best chance of finding an unexpected and useful connection, so think broadly and try to get across a range of ideas until you find something that gets you both excited that you can talk about in more detail. - - Please be kind and respectful during your meeting (see more on our code of conduct page). - - Don’t worry if you don’t find something, our algorithms aren’t perfect and you’re not being judged on how well you do - have fun! ---- diff --git a/sitedata/markdown/how-to-submit.md b/sitedata/markdown/how-to-submit.md index f6d15dd..bdbd8fa 100644 --- a/sitedata/markdown/how-to-submit.md +++ b/sitedata/markdown/how-to-submit.md @@ -25,7 +25,7 @@ Flash talks will be a *5 minute pre-recorded "flash talk"* featuring a dedicated ### Preprint linking -You can provide any preprints or article(s) during submission. You can also opt-in to have your recorded talk (either Traditional Talk or Flash Talk) to be linked to their preprint. If you provide a preprint link, we will reach out to you via email about linking it to your talk. +You can provide any preprints or article(s) during submission. If you provide a preprint link, we will reach out to you via email about linking it to your talk. ---- From 3d925dfad53c68370e0fd0fd6c076eb12758a4b8 Mon Sep 17 00:00:00 2001 From: tulakann Date: Mon, 4 Oct 2021 21:00:57 +0700 Subject: [PATCH 6/6] fix: remove unused fields --- frontend/src/components/RegisterForm/index.js | 22 +++++++-------- frontend/src/pages/submission.js | 27 ++++++++++++------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/frontend/src/components/RegisterForm/index.js b/frontend/src/components/RegisterForm/index.js index 90e4e7b..d4690c2 100644 --- a/frontend/src/components/RegisterForm/index.js +++ b/frontend/src/components/RegisterForm/index.js @@ -91,7 +91,7 @@ const RegisterForm = ({ prevUserData, origin }) => { institution: "institutionSelect", gender_status: "genderStatusSelect", academic_status: "academicStatusSelect", - meeting_platform: "meetingPlatformSelect", + // meeting_platform: "meetingPlatformSelect", } const datetimeFields = { @@ -143,9 +143,9 @@ const RegisterForm = ({ prevUserData, origin }) => { institutionSelect, genderStatusSelect, academicStatusSelect, - meetingPlatformSelect, - abstracts, availableDatetimePicker, + // meetingPlatformSelect, + // abstracts, ...rest } = data @@ -181,17 +181,17 @@ const RegisterForm = ({ prevUserData, origin }) => { academic_status: !isPublic ? reactSelectHelpers.optionsToSaveFormat(academicStatusSelect) : "", - meeting_platform: !isPublic - ? reactSelectHelpers.optionsToSaveFormat(meetingPlatformSelect) - : [], - abstracts: !isPublic - ? abstracts.every(x => x === "") - ? [] - : abstracts - : [], available_dt: !isPublic ? timePickerHelpers.serializeSelectedDatetime(availableDatetimePicker) : "", + // meeting_platform: !isPublic + // ? reactSelectHelpers.optionsToSaveFormat(meetingPlatformSelect) + // : [], + // abstracts: !isPublic + // ? abstracts.every(x => x === "") + // ? [] + // : abstracts + // : [], } const readyData = { diff --git a/frontend/src/pages/submission.js b/frontend/src/pages/submission.js index 002468a..fc78445 100644 --- a/frontend/src/pages/submission.js +++ b/frontend/src/pages/submission.js @@ -26,7 +26,12 @@ import useSiteMetadata from "../hooks/useSiteMetadata" import useAPI from "../hooks/useAPI" import useFirebaseWrapper from "../hooks/useFirebaseWrapper" import useValidateRegistration from "../hooks/useValidateRegistration" -import { common, Fa, reactSelectHelpers, timePickerHelpers } from "../utils" +import { + common, + Fa, + timePickerHelpers, + // reactSelectHelpers, +} from "../utils" // -- CONSTANTS // const talkFormatOptions = ["Traditional talk", "Flash talk"] @@ -166,11 +171,11 @@ export default () => { useEffect(() => { if (currentSubmission && !isLoadingCurrentData) { setValue([ - { - talkFormatSelect: reactSelectHelpers.saveFormatToOptions( - currentSubmission?.talk_format - ), - }, + // { + // talkFormatSelect: reactSelectHelpers.saveFormatToOptions( + // currentSubmission?.talk_format + // ), + // }, { availableDatetimePicker: timePickerHelpers.deserializeSelectedDatetime( currentSubmission?.available_dt @@ -187,7 +192,11 @@ export default () => { const onSubmit = data => { setIsSending(true) - const { talkFormatSelect, availableDatetimePicker, ...restData } = data + const { + // talkFormatSelect, + availableDatetimePicker, + ...restData + } = data const numberOfSlots = 5 const pickNotEnoughAvailableTime = @@ -199,7 +208,7 @@ export default () => { setError( "availableDatetimePicker", "isRequired", - `Available Watching Time is required at least ${numberOfSlots} slots.` + `Available Presentation Time is required at least ${numberOfSlots} slots.` ) setIsSending(false) return @@ -209,7 +218,7 @@ export default () => { fullname: prevUserData.fullname, email: prevUserData.email, institution: prevUserData.institution, - talk_format: reactSelectHelpers.optionsToSaveFormat(talkFormatSelect), + // talk_format: reactSelectHelpers.optionsToSaveFormat(talkFormatSelect), available_dt: timePickerHelpers.serializeSelectedDatetime( availableDatetimePicker ),