diff --git a/src/components/presentation-review-form.js b/src/components/presentation-review-form.js index 213f0f9..a26dfa8 100644 --- a/src/components/presentation-review-form.js +++ b/src/components/presentation-review-form.js @@ -16,7 +16,9 @@ import 'awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css' import SubmitButtons from "./presentation-submit-buttons"; import { RawHTML } from 'openstack-uicore-foundation/lib/components' import T from "i18n-react/dist/i18n-react"; +import Swal from "sweetalert2"; import {getMarketingValue} from "./marketing-setting"; +import { validateSpeakerCount } from './speaker-limits'; class PresentationReviewForm extends React.Component { constructor(props) { @@ -42,6 +44,20 @@ class PresentationReviewForm extends React.Component { handleSubmit(ev) { ev.preventDefault(); + const { entity, selectionPlanSettings } = this.props; + const speakerValidation = validateSpeakerCount(entity); + + if (!speakerValidation.valid) { + const presentation = selectionPlanSettings?.CFP_PRESENTATIONS_SINGULAR_LABEL || T.translate("edit_presentation.presentation").toLowerCase(); + const speaker = (selectionPlanSettings?.CFP_SPEAKERS_SINGULAR_LABEL || T.translate("edit_presentation.speaker")).toLowerCase(); + const speakers = (selectionPlanSettings?.CFP_SPEAKERS_PLURAL_LABEL || T.translate("edit_presentation.speakers")).toLowerCase(); + const { errorField, min, max, excess } = speakerValidation; + const translationParams = { presentation, speaker, speakers, max, min, excess }; + + Swal.fire("Validation error", T.translate(`edit_presentation.errors.${errorField}`, translationParams), "warning"); + return; + } + this.props.onSubmit(this.props.entity); } diff --git a/src/components/presentation-speakers-form.js b/src/components/presentation-speakers-form.js index cbbacec..3f26c98 100644 --- a/src/components/presentation-speakers-form.js +++ b/src/components/presentation-speakers-form.js @@ -18,7 +18,7 @@ import { Exclusive, Dropdown } from 'openstack-uicore-foundation/lib/components' import T from "i18n-react/dist/i18n-react"; import CPFSpeakerInput from './inputs/speaker-input' import Swal from "sweetalert2"; -import {getMarketingValue} from "./marketing-setting"; +import { getSpeakerLimits, validateSpeakerCount } from './speaker-limits'; class PresentationSpeakersForm extends React.Component { constructor(props) { @@ -27,8 +27,8 @@ class PresentationSpeakersForm extends React.Component { this.state = { speaker: {}, speakerInput: null, - entity: {...props.entity}, - currentSpeakerType : null + entity: { ...props.entity }, + currentSpeakerType: null }; this.handleSubmit = this.handleSubmit.bind(this); @@ -40,31 +40,37 @@ class PresentationSpeakersForm extends React.Component { this.handleAddSpeaker = this.handleAddSpeaker.bind(this); } - handleChangeSpeakerType(ev){ - let {value, id} = ev.target; + handleChangeSpeakerType(ev) { + let { value, id } = ev.target; id = id.toString(); - this.setState({...this.state, currentSpeakerType: value, error: null}); + this.setState({ ...this.state, currentSpeakerType: value, error: null }); } handleSubmit(ev) { - - const entity = {...this.props.entity}; - const { selectionPlanSettings } = this.props; ev.preventDefault(); + const { selectionPlanSettings, entity } = this.props; const validModerator = !entity.type.use_moderator || !entity.type.is_moderator_mandatory || entity.moderator; - const validSpeaker = !entity.type.use_speakers || !entity.type.are_speakers_mandatory || entity.speakers.length > 0; + const presentation = selectionPlanSettings?.CFP_PRESENTATIONS_SINGULAR_LABEL || T.translate("edit_presentation.presentation").toLowerCase(); if (!validModerator) { - Swal.fire("Validation error", T.translate("edit_presentation.errors.add_moderator", - { presentation: selectionPlanSettings?.CFP_PRESENTATIONS_SINGULAR_LABEL || T.translate("edit_presentation.presentation").toLowerCase()}), "warning"); - } else if (!validSpeaker) { - Swal.fire("Validation error", T.translate("edit_presentation.errors.add_speaker", - { presentation: selectionPlanSettings?.CFP_PRESENTATIONS_SINGULAR_LABEL || T.translate("edit_presentation.presentation").toLowerCase(), - speaker: selectionPlanSettings?.CFP_SPEAKERS_SINGULAR_LABEL || T.translate("edit_presentation.speaker").toLowerCase()}), "warning"); - } else { - this.props.onSubmit(this.props.entity); + Swal.fire("Validation error", T.translate("edit_presentation.errors.add_moderator", { presentation }), "warning"); + return; } + + const speakerValidation = validateSpeakerCount(entity); + + if (!speakerValidation.valid) { + const speaker = (selectionPlanSettings?.CFP_SPEAKERS_SINGULAR_LABEL || T.translate("edit_presentation.speaker")).toLowerCase(); + const speakers = (selectionPlanSettings?.CFP_SPEAKERS_PLURAL_LABEL || T.translate("edit_presentation.speakers")).toLowerCase(); + const { errorField, min, max, excess } = speakerValidation; + const translationParams = { presentation, speaker, speakers, max, min, excess }; + + Swal.fire("Validation error", T.translate(`edit_presentation.errors.${errorField}`, translationParams), "warning"); + return; + } + + this.props.onSubmit(this.props.entity); } handleBack(ev) { @@ -73,12 +79,12 @@ class PresentationSpeakersForm extends React.Component { } handleChangeSpeaker(ev) { - let {value, id} = ev.target; - this.setState({speaker: value, speakerInput: value}); + let { value, id } = ev.target; + this.setState({ speaker: value, speakerInput: value }); } handleSpeakerClick(speakerId, speakerType, ev) { - let {history, entity, summit} = this.props; + let { history, entity, summit } = this.props; ev.preventDefault(); this.props.onSpeakerEdit(entity.selection_plan_id, entity.id, speakerId, speakerType); } @@ -94,24 +100,25 @@ class PresentationSpeakersForm extends React.Component { } handleEditSpeaker(speakerId, speakerType, ev) { - let {history, entity} = this.props; + let { history, entity } = this.props; ev.preventDefault(); this.props.onSpeakerEdit(entity.selection_plan_id, entity.id, speakerId, speakerType); } handleAddSpeaker(ev) { - const {speaker, currentSpeakerType} = this.state; - const {history, onAddSpeaker, onAddModerator, match} = this.props; + const { speaker, currentSpeakerType } = this.state; + const { history, onAddSpeaker, onAddModerator, match, selectionPlanSettings } = this.props; + const speakerLabel = selectionPlanSettings?.CFP_SPEAKERS_SINGULAR_LABEL || T.translate("edit_presentation.speaker").toLowerCase(); ev.preventDefault(); - if(!speaker){ + if (!speaker) { // speaker not set - this.setState({...this.state, error: T.translate("edit_presentation.errors.missing_speaker")}); + this.setState({ ...this.state, error: T.translate("edit_presentation.errors.missing_speaker", { speaker: speakerLabel }) }); return; } - if(!currentSpeakerType){ - this.setState({...this.state, error: T.translate("edit_presentation.errors.role")}); + if (!currentSpeakerType) { + this.setState({ ...this.state, error: T.translate("edit_presentation.errors.role") }); return; } @@ -122,7 +129,7 @@ class PresentationSpeakersForm extends React.Component { } else { onAddSpeaker(speaker); } - this.setState({...this.state, currentSpeakerType: null, speakerInput: null, error: null}); + this.setState({ ...this.state, currentSpeakerType: null, speakerInput: null, error: null }); return false; } @@ -134,41 +141,43 @@ class PresentationSpeakersForm extends React.Component { } // speaker not set - this.setState({...this.state, error: T.translate("edit_presentation.errors.missing_speaker")}); + this.setState({ ...this.state, error: T.translate("edit_presentation.errors.missing_speaker", { speaker: speakerLabel }) }); return false; } render() { - let {summit, selectionPlanSettings, entity, presentation, step} = this.props; - let {speakerInput, error, speaker} = this.state; - let eventType = summit.event_types.find(t => t.id == entity.type_id); - let canAddSpeakers = (eventType && eventType.max_speakers > entity.speakers.length); + let { summit, selectionPlanSettings, entity, presentation, step } = this.props; + let { speakerInput, error, speaker } = this.state; + let eventType = summit.event_types.find(t => t.id == entity.type_id); + let speakersCount = entity.speakers?.length ?? 0; + let { max: maxSpeakers } = getSpeakerLimits(entity.type); + let canAddSpeakers = (eventType && maxSpeakers > speakersCount); let canAddModerator = (eventType && eventType.max_moderators && !entity.moderator); let speakerTypes = []; - if(canAddSpeakers){ - speakerTypes.push({value:'speaker', label: selectionPlanSettings?.CFP_SPEAKERS_SINGULAR_LABEL || T.translate("edit_presentation.labels.speaker")}); + if (canAddSpeakers) { + speakerTypes.push({ value: 'speaker', label: selectionPlanSettings?.CFP_SPEAKERS_SINGULAR_LABEL || T.translate("edit_presentation.labels.speaker") }); } - if(canAddModerator){ - speakerTypes.push({value:'moderator', label: T.translate("edit_presentation.labels.moderator")}); + if (canAddModerator) { + speakerTypes.push({ value: 'moderator', label: T.translate("edit_presentation.labels.moderator") }); } return (