9.0 KiB
Custom Forms Feature - Implementation Plan
Context
Currently, Talk Proposals and Sponsorship Enquiries use Frappe Web Forms, and Event Feedback has a minimal DocType with no frontend form. We want to replace these with dashboard-based Vue forms using a shared BaseCustomEventForm.vue that renders doctype fields + Pohodex Event Manager Custom Fields, with a common success state. This removes the dependency on Frappe Web Forms and gives us full control over UX.
Architecture
Routes:
/dashboard/events/:eventRoute/feedback → FeedbackForm.vue
/dashboard/events/:eventRoute/propose-talk → ProposeTalkForm.vue
/dashboard/events/:eventRoute/enquire-sponsorship → EnquireSponsorshipForm.vue
Components:
FeedbackForm.vue ──────────┐
ProposeTalkForm.vue ────────┼──► BaseCustomEventForm.vue
EnquireSponsorshipForm.vue ─┘ │
├── CustomFieldInput.vue (reused)
├── CustomFieldsSection.vue (reused)
└── FormSuccess.vue (new, inline success state)
Phase 1: Backend DocType Schema Updates
1.1 Update Event Feedback DocType
File: event_manager/events/doctype/event_feedback/event_feedback.json
- Add only
additional_fields(Table → Additional Field) — keep the DocType minimal for now - Add permission:
Pohodex Event Manager Userrole withcreate: 1, read: 1(if_owner)
1.2 Add additional_fields to Talk Proposal & Sponsorship Enquiry
Files:
event_manager/proposals/doctype/talk_proposal/talk_proposal.json— addadditional_fields(Table → Additional Field)event_manager/proposals/doctype/sponsorship_enquiry/sponsorship_enquiry.json— addadditional_fields(Table → Additional Field)
Reuses existing Additional Field child table (event_manager/ticketing/doctype/additional_field/).
1.3 Update Pohodex Event Manager Custom Field applied_to options
File: event_manager/event_manager/doctype/buzz_custom_field/buzz_custom_field.json
- Add options:
Event Feedback,Talk Proposal,Sponsorship Enquiry
1.4 Run bench migrate
Phase 2: Backend API Endpoints
File: event_manager/api.py
2.1 get_custom_form_data(event_route, form_type)
- Whitelist check:
form_typemust be inCUSTOM_FORM_CONFIGdict - Resolve event from
event_route - Check deadline (
talk_proposals_close_at,sponsorship_proposals_close_at, none for feedback, show a nice closed message / banner if the form is closed) - Return
form_fields(from doctype meta, excluding internal fields likestatus,submitted_by,owner,event),custom_fields(Pohodex Event Manager Custom Fields for this event +applied_to),eventdetails,closedflag - we should also check if event itself is published or not, if not 404
2.2 submit_custom_form(event_route, form_type, data, custom_fields_data)
- Whitelist check on
form_type - Auto-set:
eventfrom route,submitted_byfrom session user (for Talk Proposal) - Validate submitted fields against allowed fieldnames
- Create doc, append
additional_fieldsrows for custom field values - Return
{name, doctype}
Config dict:
CUSTOM_FORM_CONFIG = {
"Event Feedback": {
"applied_to": "Event Feedback",
"exclude_fields": {"name", "owner", "creation", "modified", "modified_by",
"docstatus", "idx", "additional_fields", "event"},
"auto_set": {"event": "from_route"},
"deadline_field": None,
},
"Talk Proposal": {
"applied_to": "Talk Proposal",
"exclude_fields": {"name", "owner", "creation", "modified", "modified_by",
"docstatus", "idx", "submitted_by", "status",
"additional_fields", "event"},
"auto_set": {"event": "from_route", "submitted_by": "session_user"},
"deadline_field": "talk_proposals_close_at",
},
"Sponsorship Enquiry": {
"applied_to": "Sponsorship Enquiry",
"exclude_fields": {"name", "owner", "creation", "modified", "modified_by",
"docstatus", "idx", "status", "additional_fields", "event"},
"auto_set": {"event": "from_route"},
"deadline_field": "sponsorship_proposals_close_at",
},
}
Phase 3: Frontend
3.1 Add routes in dashboard/src/router.ts
Three new routes with props: true, marked isPublic but depending on weather the event has guest booking enabled or not, it should handle that
3.2 Create BaseCustomEventForm.vue
File: dashboard/src/components/BaseCustomEventForm.vue
Props: eventRoute, formType, title, successTitle, successMessage
Behavior:
- Fetch form data via
createResource→event_manager.api.get_custom_form_data - If
closed, show "submissions closed" message - Render standard fields using
CustomFieldInput.vue(normalized to same shape) - Render Pohodex Event Manager Custom Fields via
CustomFieldsSection.vue - Submit via
event_manager.api.submit_custom_form - On success, show inline success state (no separate page)
Special field type handling (in BaseCustomEventForm, not CustomFieldInput):
Text Editor→ frappe-uiTextEditorAttach Image→ frappe-uiFileUploader(upload first, set URL on doc)Link→Autocompletewith debounced search on linked doctype (check apps/crm on how it renders link field n the CRM frontend, you might also find other types of fields being rendered in the Field.vue of CRM)Table(e.g. speakers) → List view component showing added rows + "Add" button. Clicking "Add" opens a dialog with the child table's fields. On dialog submit, row is appended. No inline editing — edit button to open the dialog again.
3.3 Create wrapper page components
dashboard/src/pages/FeedbackForm.vue— passesform-type="Event Feedback", default success stringsdashboard/src/pages/ProposeTalkForm.vue— passesform-type="Talk Proposal", default success stringsdashboard/src/pages/EnquireSponsorshipForm.vue— passesform-type="Sponsorship Enquiry", default success strings
Each is ~15 lines: just a template with BaseCustomEventForm and defineProps.
Default success strings are fallbacks — event-level configured messages take priority (see 3.5).
3.4 Extend CustomFieldInput.vue (if needed)
File: dashboard/src/components/CustomFieldInput.vue
- May need minor extensions for
Ratingfieldtype - Complex types (Table) handled directly in
BaseCustomEventForm.vue - Text Editor, Attach Image, Link, should be added to custom field input
- in the backend the value column should be changed to
Codetype to support various values like this - The attachments should be attached to the document being created, the custom field should have the path (check File doctype) to the file
3.5 Configurable success messages per event
DocType change: Add 3 markdown fields to Pohodex Event Manager Event DocType:
feedback_success_message(Markdown)proposal_success_message(Markdown)sponsorship_success_message(Markdown)
API: get_custom_form_data returns the relevant success message field for the form type.
Frontend: BaseCustomEventForm.vue uses event-configured message if set, otherwise falls back to wrapper's default props.
Files Summary
New files (6)
| File | Purpose |
|---|---|
dashboard/src/components/BaseCustomEventForm.vue |
Shared form renderer |
dashboard/src/pages/FeedbackForm.vue |
Feedback wrapper |
dashboard/src/pages/ProposeTalkForm.vue |
Talk proposal wrapper |
dashboard/src/pages/EnquireSponsorshipForm.vue |
Sponsorship wrapper |
Modified files (7)
| File | Change |
|---|---|
event_manager/events/doctype/event_feedback/event_feedback.json |
Add additional_fields + permissions |
event_manager/proposals/doctype/talk_proposal/talk_proposal.json |
Add additional_fields table |
event_manager/proposals/doctype/sponsorship_enquiry/sponsorship_enquiry.json |
Add additional_fields table |
event_manager/event_manager/doctype/buzz_custom_field/buzz_custom_field.json |
Add 3 new applied_to options |
event_manager/events/doctype/buzz_event/buzz_event.json |
Add 3 success message markdown fields |
event_manager/api.py |
Add get_custom_form_data + submit_custom_form |
dashboard/src/router.ts |
Add 3 routes |
Implementation Order
- DocType schema changes +
bench migrate - API endpoints in
event_manager/api.py BaseCustomEventForm.vue- Three wrapper pages + router routes
- Test each form end-to-end
Verification
- Create a Pohodex Event Manager Event with a route
- Add Pohodex Event Manager Custom Fields for each
applied_totype - Navigate to each form URL, verify fields render (standard + custom)
- Submit each form, verify doc created with correct data + additional_fields
- Test deadline enforcement (set
talk_proposals_close_atto past, verify form shows closed) - Test without login → should redirect to login page