Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion src/actions/event-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* */

import T from "i18n-react/dist/i18n-react";
import debounce from "lodash/debounce"
import debounce from "lodash/debounce";
import {
getRequest,
putRequest,
Expand Down Expand Up @@ -908,6 +908,50 @@ export const saveEvent = (entity, publish) => async (dispatch, getState) => {
});
};

export const saveEventAsDraft = (entity) => async (dispatch, getState) => {
if (!entity.id) {
console.error("saveEventAsDraft: entity.id is required");
return;
}

const { currentSummitState } = getState();
const accessToken = await getAccessTokenSafely();
const { currentSummit } = currentSummitState;
const { type_id } = entity;
const type = currentSummit.event_types.find((e) => e.id === type_id);

dispatch(startLoading());

const normalizedEntity = normalizeEvent(entity, type, currentSummit);

const params = {
access_token: accessToken,
expand:
"creator,speakers,moderator,sponsors,groups,type,type.allowed_media_upload_types,type.allowed_media_upload_types.type, slides, links, videos, media_uploads, tags, media_uploads.media_upload_type, media_uploads.media_upload_type.type,extra_questions,selection_plan,selection_plan.track_chair_rating_types,selection_plan.track_chair_rating_types.score_types,selection_plan.extra_questions,selection_plan.extra_questions.values,created_by,track_chair_scores_avg.ranking_type,actions,allowed_ticket_types",
fields: "allowed_ticket_types.id,allowed_ticket_types.name"
};

return putRequest(
createAction(UPDATE_EVENT),
createAction(EVENT_UPDATED),
`${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/events/${entity.id}/draft`,
normalizedEntity,
authErrorHandler,
entity
)(params)(dispatch).then(() => {
const success_message = {
title: T.translate("general.done"),
html: T.translate("edit_event.event_saved_as_draft"),
type: "success"
};
dispatch(
showMessage(success_message, () => {
location.reload();
})
);
});
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

export const saveEventFieldWithoutRefresh =
(field) => async (dispatch, getState) => {
const { currentSummitState, currentSummitEventState } = getState();
Expand Down
115 changes: 100 additions & 15 deletions src/components/forms/event-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css";
import Swal from "sweetalert2";
import { Tooltip } from "react-tooltip";
import { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/methods";
import Dropdown from "openstack-uicore-foundation/lib/components/inputs/dropdown"
import GroupedDropdown from "openstack-uicore-foundation/lib/components/inputs/grouped-dropdown"
import DateTimePicker from "openstack-uicore-foundation/lib/components/inputs/datetimepicker"
import TagInput from "openstack-uicore-foundation/lib/components/inputs/tag-input"
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input"
import CompanyInput from "openstack-uicore-foundation/lib/components/inputs/company-input"
import GroupInput from "openstack-uicore-foundation/lib/components/inputs/group-input"
import UploadInput from "openstack-uicore-foundation/lib/components/inputs/upload-input"
import Input from "openstack-uicore-foundation/lib/components/inputs/text-input"
import Panel from "openstack-uicore-foundation/lib/components/sections/panel"
import Table from "openstack-uicore-foundation/lib/components/table"
import MemberInput from "openstack-uicore-foundation/lib/components/inputs/member-input"
import FreeTextSearch from "openstack-uicore-foundation/lib/components/free-text-search"
import TicketTypesInput from "openstack-uicore-foundation/lib/components/inputs/ticket-types-input"
import Dropdown from "openstack-uicore-foundation/lib/components/inputs/dropdown";
import GroupedDropdown from "openstack-uicore-foundation/lib/components/inputs/grouped-dropdown";
import DateTimePicker from "openstack-uicore-foundation/lib/components/inputs/datetimepicker";
import TagInput from "openstack-uicore-foundation/lib/components/inputs/tag-input";
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
import CompanyInput from "openstack-uicore-foundation/lib/components/inputs/company-input";
import GroupInput from "openstack-uicore-foundation/lib/components/inputs/group-input";
import UploadInput from "openstack-uicore-foundation/lib/components/inputs/upload-input";
import Input from "openstack-uicore-foundation/lib/components/inputs/text-input";
import Panel from "openstack-uicore-foundation/lib/components/sections/panel";
import Table from "openstack-uicore-foundation/lib/components/table";
import MemberInput from "openstack-uicore-foundation/lib/components/inputs/member-input";
import FreeTextSearch from "openstack-uicore-foundation/lib/components/free-text-search";
import TicketTypesInput from "openstack-uicore-foundation/lib/components/inputs/ticket-types-input";
import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable";
import TextEditorV3 from "openstack-uicore-foundation/lib/components/inputs/editor-input-v3";
import { Pagination } from "react-bootstrap";
Expand Down Expand Up @@ -125,6 +125,7 @@ class EventForm extends React.Component {
this.handleCloneEvent = this.handleCloneEvent.bind(this);
this.handleEventTypeChange = this.handleEventTypeChange.bind(this);
this.handleRSVPTypeChange = this.handleRSVPTypeChange.bind(this);
this.handleSaveIncomplete = this.handleSaveIncomplete.bind(this);
}

componentDidMount() {
Expand Down Expand Up @@ -721,6 +722,44 @@ class EventForm extends React.Component {
);
}

handleSaveIncomplete(ev) {
ev.preventDefault();
const { onSaveIncomplete } = this.props;
const { entity } = this.state;
onSaveIncomplete({ ...entity });
}

isNew() {
const { entity } = this.state;
return !entity.id;
}

isComplete() {
const { entity } = this.state;
return entity?.status === "Received" && entity?.progress === "COMPLETE";
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

getMissingDraftFields() {
const { entity } = this.state;
const missing = [];

if (!entity.title) missing.push("Title");
if (!entity.type_id) missing.push("Activity Type");
if (!entity.track_id) missing.push("Activity Category");

if (!entity.type_id || this.shouldShowField("allows_publishing_dates")) {
if (!entity.start_date) missing.push("Start Date");
if (!entity.end_date) missing.push("End Date");
if (!entity.duration) missing.push("Duration");
}

if (!entity.type_id || this.isEventType(EVENT_TYPE_PRESENTATION)) {
if (!entity.disclaimer_accepted) missing.push("Disclaimer Accepted");
}

return missing;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

handleEventTypeChange(oldEntity, newEntity) {
const isEventUpgrade =
!this.isEventType(EVENT_TYPE_PRESENTATION, oldEntity) &&
Expand Down Expand Up @@ -1038,9 +1077,47 @@ class EventForm extends React.Component {
{ label: "Submission", value: "Submission" }
];

const missingDraftFields =
this.isNew() || this.isComplete() ? [] : this.getMissingDraftFields();

return (
<div>
<input type="hidden" id="id" value={entity.id} />
{!this.isNew() && !this.isComplete() && (
<div className="alert alert-warning" role="alert">
<div
style={{
display: "flex",
alignItems: "center",
gap: 10,
marginBottom: 8
}}
>
<strong>{T.translate("edit_event.draft_state_label")}</strong>
<span
className="label label-warning"
style={{
fontSize: "0.85em",
padding: "3px 8px",
borderRadius: 3
}}
>
{T.translate("edit_event.draft_state_badge")}
</span>
</div>
{missingDraftFields.length > 0 && (
<p style={{ marginBottom: 6 }}>
<strong>
{T.translate("edit_event.draft_state_missing_fields")}
</strong>{" "}
{missingDraftFields.join(", ")}
</p>
)}
<p style={{ marginBottom: 0 }}>
{T.translate("edit_event.draft_state_note")}
</p>
</div>
)}
<div className="row form-group">
<div className="col-md-8">
<label> {T.translate("edit_event.submitter")} </label> &nbsp;
Expand Down Expand Up @@ -2059,14 +2136,22 @@ class EventForm extends React.Component {
type="button"
onClick={(ev) => this.triggerFormSubmit(ev, false)}
className="btn btn-primary pull-right"
value={T.translate("general.save")}
value={T.translate("edit_event.save_and_mark_complete")}
/>
<input
type="button"
onClick={(ev) => this.triggerFormSubmit(ev, true)}
className="btn btn-success pull-right"
value={T.translate("general.save_and_publish")}
/>
{!this.isNew() && !this.isComplete() && (
<input
type="button"
onClick={this.handleSaveIncomplete}
className="btn btn-warning pull-right"
value={T.translate("edit_event.save_as_incomplete")}
/>
)}
</div>
)}

Expand Down
9 changes: 8 additions & 1 deletion src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,14 @@
"search_comment": "Search by Comment, Creator ID",
"allowed_ticket_types": "Select ticket types",
"select_submission_source": "Select a Submission Source"
}
},
"draft_state_label": "DRAFT STATE: NOT SUBMITTED BY SUBMITTER",
"draft_state_badge": "Pending Complete Details",
"draft_state_missing_fields": "Missing required fields:",
"draft_state_note": "This activity was saved as a draft by the submitter and contains missing required fields. To make partial changes (e.g., re-categorize or assign tags) without filling out missing fields, use the Save as Incomplete button below. This preserves the draft status.",
"save_as_incomplete": "Save as Incomplete",
"save_and_mark_complete": "Save & Mark Complete",
"event_saved_as_draft": "Activity saved as draft successfully."
},
"edit_event_material": {
"material": "Material",
Expand Down
4 changes: 4 additions & 0 deletions src/pages/events/edit-summit-event-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import T from "i18n-react/dist/i18n-react";
import EventForm from "../../components/forms/event-form";
import {
saveEvent,
saveEventAsDraft,
saveEventFieldWithoutRefresh,
attachFile,
getEvents,
Expand Down Expand Up @@ -225,6 +226,7 @@ function EditSummitEventPage(props) {
loading,
history,
saveEvent,
saveEventAsDraft,
saveEventFieldWithoutRefresh,
attachFile,
unPublishEvent,
Expand Down Expand Up @@ -289,6 +291,7 @@ function EditSummitEventPage(props) {
entity={entity}
errors={errors}
onSubmit={saveEvent}
onSaveIncomplete={saveEventAsDraft}
onUpdate={saveEventFieldWithoutRefresh}
onEventUpgrade={upgradeEvent}
onAttach={attachFile}
Expand Down Expand Up @@ -336,6 +339,7 @@ const mapStateToProps = ({

export default connect(mapStateToProps, {
saveEvent,
saveEventAsDraft,
saveEventFieldWithoutRefresh,
attachFile,
unPublishEvent,
Expand Down
Loading