form-trigger.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * @node form-trigger
  3. * @name Form
  4. * @category triggers
  5. * @version 1.0.0
  6. * @description Publishes an HTML form at a shareable URL. Submitting it starts the workflow.
  7. * @trigger
  8. * @icon clipboard-list
  9. */
  10. const configSchema = {
  11. type: 'object',
  12. properties: {
  13. title: {
  14. type: 'string',
  15. title: 'Form Title',
  16. description: 'Shown as the heading of the page',
  17. default: 'Untitled form'
  18. },
  19. description: {
  20. type: 'string',
  21. title: 'Description',
  22. description: 'Shown under the heading. Plain text - it is escaped, not rendered as HTML.',
  23. default: ''
  24. },
  25. fields: {
  26. type: 'array',
  27. title: 'Fields',
  28. description: 'The questions on the form, in order.',
  29. default: [],
  30. items: {
  31. type: 'object',
  32. properties: {
  33. name: { type: 'string', title: 'Name',
  34. description: 'The key the workflow reads, e.g. "image" for $node[\'Form\'].form.image. Letters, digits and underscore, not starting with a digit.' },
  35. label: { type: 'string', title: 'Label', description: 'Shown next to the input' },
  36. type: { type: 'string', title: 'Type',
  37. enum: ['text', 'textarea', 'number', 'select', 'checkbox', 'date', 'file'],
  38. default: 'text' },
  39. required: { type: 'boolean', title: 'Required', default: false },
  40. placeholder: { type: 'string', title: 'Placeholder', default: '' },
  41. options: { type: 'array', title: 'Options', description: 'Choices, for a Select field',
  42. items: { type: 'string' }, default: [] },
  43. accept: { type: 'string', title: 'Accept',
  44. description: 'For a File field, e.g. "image/*". A browser hint only - it is not enforced.',
  45. default: '' },
  46. maxSizeMb: { type: 'number', title: 'Max Size (MB)',
  47. description: 'For a File field. 0 uses the server limit.', default: 0 }
  48. }
  49. }
  50. },
  51. password: {
  52. type: 'string',
  53. title: 'Password',
  54. format: 'password',
  55. description: 'Leave empty for anyone with the link. This is stored readable in the workflow, so treat it as a gate against a forwarded link, not as a secret.',
  56. default: ''
  57. },
  58. responseMode: {
  59. type: 'string',
  60. title: 'After Submit',
  61. enum: ['immediate', 'wait'],
  62. description: 'Immediate returns a thank-you page at once and lets the run continue - needed for anything taking more than about 30 seconds. Wait holds the browser until the workflow finishes, so a Respond to Webhook node can answer.',
  63. default: 'immediate'
  64. },
  65. responseMessage: {
  66. type: 'string',
  67. title: 'Thank-you Message',
  68. default: 'Thanks, your answer was received.',
  69. 'x-if': 'responseMode'
  70. },
  71. path: {
  72. type: 'string',
  73. title: 'Path Filter',
  74. description: 'Optional path suffix. Leave empty to answer at the bare form URL.',
  75. default: ''
  76. }
  77. }
  78. };
  79. const inputSchema = { type: 'object', properties: {} };
  80. const outputSchema = {
  81. type: 'object',
  82. properties: {
  83. form: { type: 'object', description: 'The answers, keyed by field name. A file field holds a binary object.' },
  84. submittedAt: { type: 'number', description: 'Milliseconds since the epoch' },
  85. clientIp: { type: 'string' }
  86. }
  87. };
  88. async function execute(config, input, context) {
  89. // Every value here is built by the webhook controller, which has already
  90. // validated it. Executed directly - from the editor's Run button - there is
  91. // no submission, and an empty form is the honest answer rather than an error.
  92. const triggerData = context.triggerData || {};
  93. return {
  94. form: triggerData.form || {},
  95. submittedAt: triggerData.submittedAt || Date.now(),
  96. clientIp: triggerData.clientIp || ''
  97. };
  98. }
  99. module.exports = { configSchema, inputSchema, outputSchema, execute };