Files
xadm 786cbc724f
CI / Server (push) Has been cancelled
Linters / Frappe Linter (push) Has been cancelled
Linters / Vulnerable Dependency Check (push) Has been cancelled
UI Tests / Playwright E2E Tests (push) Has been cancelled
Initialize fork and rebrand app to event_manager
2026-05-11 09:56:57 +02:00

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 User role with create: 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 — add additional_fields (Table → Additional Field)
  • event_manager/proposals/doctype/sponsorship_enquiry/sponsorship_enquiry.json — add additional_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_type must be in CUSTOM_FORM_CONFIG dict
  • 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 like status, submitted_by, owner, event), custom_fields (Pohodex Event Manager Custom Fields for this event + applied_to), event details, closed flag
  • 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: event from route, submitted_by from session user (for Talk Proposal)
  • Validate submitted fields against allowed fieldnames
  • Create doc, append additional_fields rows 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:

  1. Fetch form data via createResourceevent_manager.api.get_custom_form_data
  2. If closed, show "submissions closed" message
  3. Render standard fields using CustomFieldInput.vue (normalized to same shape)
  4. Render Pohodex Event Manager Custom Fields via CustomFieldsSection.vue
  5. Submit via event_manager.api.submit_custom_form
  6. On success, show inline success state (no separate page)

Special field type handling (in BaseCustomEventForm, not CustomFieldInput):

  • Text Editor → frappe-ui TextEditor
  • Attach Image → frappe-ui FileUploader (upload first, set URL on doc)
  • LinkAutocomplete with 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 — passes form-type="Event Feedback", default success strings
  • dashboard/src/pages/ProposeTalkForm.vue — passes form-type="Talk Proposal", default success strings
  • dashboard/src/pages/EnquireSponsorshipForm.vue — passes form-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 Rating fieldtype
  • 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 Code type 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

  1. DocType schema changes + bench migrate
  2. API endpoints in event_manager/api.py
  3. BaseCustomEventForm.vue
  4. Three wrapper pages + router routes
  5. 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_to type
  • 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_at to past, verify form shows closed)
  • Test without login → should redirect to login page