@graph8/sdk 0.370.0 → 0.374.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (646) hide show
  1. package/README.md +22 -3
  2. package/blocks/_foundation/README.md +61 -0
  3. package/blocks/_foundation/block.json +57 -0
  4. package/blocks/_foundation/components/auth-gate.tsx +363 -0
  5. package/blocks/_foundation/components/confirm-spend-dialog.tsx +15 -8
  6. package/blocks/_foundation/components/empty-state.tsx +5 -2
  7. package/blocks/_foundation/components/list-select.tsx +112 -0
  8. package/blocks/_foundation/components/paging-notices.tsx +55 -0
  9. package/blocks/_foundation/components/screen/detail-panel.tsx +2 -1
  10. package/blocks/_foundation/components/screen/filter-controls.tsx +92 -0
  11. package/blocks/_foundation/components/screen/index.ts +1 -0
  12. package/blocks/_foundation/components/screen/split-view.tsx +1 -1
  13. package/blocks/_foundation/hooks/use-all-pages.ts +54 -0
  14. package/blocks/_foundation/hooks/use-load-more-list.ts +61 -0
  15. package/blocks/_foundation/hooks/use-url-filters.ts +93 -0
  16. package/blocks/_foundation/lib/paging.ts +57 -0
  17. package/blocks/_foundation/lib/use-debounced-value.ts +13 -0
  18. package/blocks/_foundation/server/auth.ts +815 -0
  19. package/blocks/agents/README.md +81 -4
  20. package/blocks/agents/block.json +311 -2
  21. package/blocks/agents/components/agent-activity.tsx +112 -0
  22. package/blocks/agents/components/agent-approvals.tsx +135 -0
  23. package/blocks/agents/components/agent-builder.tsx +17 -3
  24. package/blocks/agents/components/agent-conversations.tsx +143 -0
  25. package/blocks/agents/components/agent-knowledge-panel.tsx +2 -2
  26. package/blocks/agents/components/agent-operators.tsx +164 -0
  27. package/blocks/agents/components/agent-run-detail.tsx +20 -3
  28. package/blocks/agents/components/agent-runs.tsx +3 -3
  29. package/blocks/agents/components/agent-skills-panel.tsx +7 -7
  30. package/blocks/agents/components/agent-test-history.tsx +121 -0
  31. package/blocks/agents/components/agents-screen.tsx +53 -11
  32. package/blocks/agents/components/assistant-sessions.tsx +150 -0
  33. package/blocks/agents/components/duplicate-agent-button.tsx +42 -0
  34. package/blocks/agents/components/from-template-button.tsx +65 -0
  35. package/blocks/agents/components/knowledge-browser.tsx +107 -0
  36. package/blocks/agents/components/knowledge-detail.tsx +156 -0
  37. package/blocks/agents/components/knowledge-form.tsx +69 -0
  38. package/blocks/agents/components/name-dialog.tsx +32 -0
  39. package/blocks/agents/components/receptionist-button.tsx +46 -0
  40. package/blocks/agents/components/save-as-template-button.tsx +32 -0
  41. package/blocks/agents/components/skill-editor.tsx +147 -0
  42. package/blocks/agents/components/skill-library.tsx +111 -0
  43. package/blocks/agents/lib/agent-types.ts +7 -1
  44. package/blocks/agents/lib/facts.tsx +13 -0
  45. package/blocks/agents/lib/knowledge-utils.ts +49 -0
  46. package/blocks/agents/lib/load-more.tsx +141 -0
  47. package/blocks/agents/lib/skill-utils.ts +91 -0
  48. package/blocks/agents/recipes/create-agent-and-attach-skill.ts +1 -1
  49. package/blocks/analytics/components/analytics-screen.tsx +16 -3
  50. package/blocks/analytics/components/kpi-tiles.tsx +1 -1
  51. package/blocks/analytics/components/report-builder.tsx +15 -2
  52. package/blocks/appointments/README.md +6 -0
  53. package/blocks/appointments/block.json +27 -0
  54. package/blocks/appointments/components/booking-page.tsx +2 -2
  55. package/blocks/appointments/components/meeting-contact-links.tsx +49 -0
  56. package/blocks/appointments/components/meeting-detail.tsx +2 -2
  57. package/blocks/appointments/components/meeting-list.tsx +29 -13
  58. package/blocks/appointments/components/record-meetings-tab.tsx +92 -0
  59. package/blocks/campaigns/README.md +1 -1
  60. package/blocks/campaigns/block.json +34 -1
  61. package/blocks/campaigns/components/campaign-assets.tsx +1 -1
  62. package/blocks/campaigns/components/campaign-launch-step.tsx +16 -11
  63. package/blocks/campaigns/components/campaign-links.tsx +180 -0
  64. package/blocks/campaigns/components/campaign-metrics.tsx +1 -1
  65. package/blocks/campaigns/components/campaign-wizard.tsx +10 -5
  66. package/blocks/campaigns/components/icp-detail.tsx +11 -2
  67. package/blocks/campaigns/components/icp-editor.tsx +8 -3
  68. package/blocks/campaigns/components/persona-detail.tsx +11 -2
  69. package/blocks/campaigns/components/persona-editor.tsx +6 -1
  70. package/blocks/campaigns/lib/campaigns-utils.ts +4 -4
  71. package/blocks/coach/components/call-scorecard.tsx +7 -7
  72. package/blocks/company-intelligence/README.md +132 -0
  73. package/blocks/company-intelligence/block.json +318 -0
  74. package/blocks/company-intelligence/components/company-intelligence-screen.tsx +114 -0
  75. package/blocks/company-intelligence/components/company-intelligence-tab.tsx +88 -0
  76. package/blocks/company-intelligence/components/company-profile.tsx +68 -0
  77. package/blocks/company-intelligence/components/intelligence-sources.tsx +63 -0
  78. package/blocks/company-intelligence/components/report-detail.tsx +189 -0
  79. package/blocks/company-intelligence/components/research-reports.tsx +136 -0
  80. package/blocks/company-intelligence/components/research-run.tsx +165 -0
  81. package/blocks/company-intelligence/components/source-detail.tsx +117 -0
  82. package/blocks/company-intelligence/components/source-view.tsx +274 -0
  83. package/blocks/company-intelligence/components/wiki-document-detail.tsx +116 -0
  84. package/blocks/company-intelligence/components/wiki-documents.tsx +66 -0
  85. package/blocks/company-intelligence/hooks/use-intelligence.ts +173 -0
  86. package/blocks/company-intelligence/lib/intelligence-types.ts +230 -0
  87. package/blocks/company-intelligence/lib/safe-markdown.tsx +150 -0
  88. package/blocks/company-intelligence/recipes/read-competitors-and-news.ts +33 -0
  89. package/blocks/company-intelligence/recipes/research-your-website.ts +43 -0
  90. package/blocks/company-intelligence/recipes/write-the-research-reports.ts +54 -0
  91. package/blocks/copilot/components/copilot-memory.tsx +6 -2
  92. package/blocks/copilot/components/copilot-panel.tsx +1 -1
  93. package/blocks/copilot/components/copilot-team-chat.tsx +6 -1
  94. package/blocks/crm/README.md +25 -0
  95. package/blocks/crm/block.json +257 -9
  96. package/blocks/crm/components/bulk-update.tsx +119 -0
  97. package/blocks/crm/components/companies-screen.tsx +23 -9
  98. package/blocks/crm/components/company-detail.tsx +2 -2
  99. package/blocks/crm/components/contact-detail.tsx +4 -4
  100. package/blocks/crm/components/contact-documents-tab.tsx +144 -0
  101. package/blocks/crm/components/contact-insights-tab.tsx +118 -0
  102. package/blocks/crm/components/contact-lookup-link.tsx +85 -0
  103. package/blocks/crm/components/contact-row-actions.tsx +43 -0
  104. package/blocks/crm/components/contact-tag-chips.tsx +113 -0
  105. package/blocks/crm/components/contacts-screen.tsx +77 -18
  106. package/blocks/crm/components/dedupe-review.tsx +6 -1
  107. package/blocks/crm/components/import-wizard.tsx +3 -7
  108. package/blocks/crm/components/list-select.tsx +20 -0
  109. package/blocks/crm/components/owner-assign.tsx +132 -0
  110. package/blocks/crm/components/record-engagement-tab.tsx +103 -0
  111. package/blocks/crm/components/record-form.tsx +1 -1
  112. package/blocks/crm/components/record-open-links.tsx +79 -0
  113. package/blocks/crm/components/tag-assign.tsx +112 -0
  114. package/blocks/crm/components/tag-manager.tsx +178 -0
  115. package/blocks/crm/components/tasks-screen.tsx +35 -15
  116. package/blocks/crm/components/unlock-info-button.tsx +82 -0
  117. package/blocks/crm/components/verify-email-button.tsx +93 -0
  118. package/blocks/crm/hooks/use-all-lists.ts +18 -0
  119. package/blocks/crm/hooks/use-contact-tags.ts +29 -0
  120. package/blocks/crm/hooks/use-page-query.ts +3 -1
  121. package/blocks/crm/lib/crm-types.ts +14 -0
  122. package/blocks/crm/lib/read-lists.ts +16 -0
  123. package/blocks/crm/lib/record-actions.ts +102 -0
  124. package/blocks/deals/README.md +25 -6
  125. package/blocks/deals/block.json +168 -2
  126. package/blocks/deals/components/close-deal-dialog.tsx +169 -0
  127. package/blocks/deals/components/create-deal-button.tsx +109 -0
  128. package/blocks/deals/components/deal-contacts-editor.tsx +134 -0
  129. package/blocks/deals/components/deal-detail.tsx +7 -5
  130. package/blocks/deals/components/deal-filters.tsx +65 -0
  131. package/blocks/deals/components/deal-line-items.tsx +120 -0
  132. package/blocks/deals/components/deal-notes-tab.tsx +97 -0
  133. package/blocks/deals/components/deal-related.tsx +30 -9
  134. package/blocks/deals/components/deal-tasks-tab.tsx +88 -0
  135. package/blocks/deals/components/deals-screen.tsx +57 -22
  136. package/blocks/deals/components/forecast-view.tsx +4 -4
  137. package/blocks/deals/components/pipeline-board.tsx +8 -6
  138. package/blocks/deals/components/pipeline-editor.tsx +132 -0
  139. package/blocks/deals/components/record-deals-tab.tsx +62 -0
  140. package/blocks/deals/components/stage-editor.tsx +1 -1
  141. package/blocks/deals/hooks/use-pipeline-deals.ts +17 -4
  142. package/blocks/deals/lib/deal-extras.ts +156 -0
  143. package/blocks/dialer/README.md +14 -5
  144. package/blocks/dialer/block.json +17 -2
  145. package/blocks/dialer/components/call-contact-button.tsx +26 -9
  146. package/blocks/dialer/components/call-log-screen.tsx +10 -2
  147. package/blocks/dialer/components/call-log.tsx +16 -4
  148. package/blocks/dialer/components/call-queue.tsx +3 -3
  149. package/blocks/dialer/components/dialer-screen.tsx +69 -27
  150. package/blocks/dialer/components/disposition-panel.tsx +1 -1
  151. package/blocks/dialer/components/record-calls-tab.tsx +101 -0
  152. package/blocks/dialer/components/session-start-form.tsx +58 -11
  153. package/blocks/dialer/components/softphone.tsx +1 -1
  154. package/blocks/documents/README.md +86 -0
  155. package/blocks/documents/block.json +378 -0
  156. package/blocks/documents/components/account-bar.tsx +48 -0
  157. package/blocks/documents/components/correspondence-form.tsx +95 -0
  158. package/blocks/documents/components/correspondence-import.tsx +106 -0
  159. package/blocks/documents/components/correspondence-panel.tsx +191 -0
  160. package/blocks/documents/components/documents-screen.tsx +76 -0
  161. package/blocks/documents/components/library-document-detail.tsx +175 -0
  162. package/blocks/documents/components/library-document-form.tsx +105 -0
  163. package/blocks/documents/components/library-folder-form.tsx +74 -0
  164. package/blocks/documents/components/library-panel.tsx +235 -0
  165. package/blocks/documents/components/library-upload.tsx +160 -0
  166. package/blocks/documents/components/question-row.tsx +130 -0
  167. package/blocks/documents/components/questionnaire-detail.tsx +197 -0
  168. package/blocks/documents/components/questionnaires-panel.tsx +173 -0
  169. package/blocks/documents/components/record-documents-tab.tsx +109 -0
  170. package/blocks/documents/lib/documents-types.ts +252 -0
  171. package/blocks/documents/lib/download.ts +64 -0
  172. package/blocks/documents/recipes/follow-a-questionnaire.ts +26 -0
  173. package/blocks/documents/recipes/log-account-correspondence.ts +27 -0
  174. package/blocks/documents/recipes/organize-the-library.ts +25 -0
  175. package/blocks/email-signatures/README.md +123 -0
  176. package/blocks/email-signatures/block.json +341 -0
  177. package/blocks/email-signatures/components/email-signatures-screen.tsx +166 -0
  178. package/blocks/email-signatures/components/signature-assign-template.tsx +119 -0
  179. package/blocks/email-signatures/components/signature-block-editor.tsx +87 -0
  180. package/blocks/email-signatures/components/signature-campaign-form.tsx +165 -0
  181. package/blocks/email-signatures/components/signature-campaigns.tsx +75 -0
  182. package/blocks/email-signatures/components/signature-identity-form.tsx +131 -0
  183. package/blocks/email-signatures/components/signature-mailboxes.tsx +195 -0
  184. package/blocks/email-signatures/components/signature-policy.tsx +130 -0
  185. package/blocks/email-signatures/components/signature-preview.tsx +119 -0
  186. package/blocks/email-signatures/components/signature-report.tsx +77 -0
  187. package/blocks/email-signatures/components/signature-template-details.tsx +112 -0
  188. package/blocks/email-signatures/components/signature-template-form.tsx +109 -0
  189. package/blocks/email-signatures/hooks/use-signatures-data.ts +93 -0
  190. package/blocks/email-signatures/lib/signatures-types.ts +392 -0
  191. package/blocks/email-signatures/recipes/assign-a-signature-to-a-new-hire.ts +32 -0
  192. package/blocks/email-signatures/recipes/create-a-template-and-make-it-default.ts +35 -0
  193. package/blocks/email-signatures/recipes/signature-engagement-report.ts +16 -0
  194. package/blocks/enrichment/README.md +38 -10
  195. package/blocks/enrichment/block.json +164 -12
  196. package/blocks/enrichment/components/auto-enrichment-configs.tsx +134 -0
  197. package/blocks/enrichment/components/auto-enrichment-settings.tsx +82 -0
  198. package/blocks/enrichment/components/bulk-enrich-panel.tsx +79 -30
  199. package/blocks/enrichment/components/email-verify-badge.tsx +3 -3
  200. package/blocks/enrichment/components/enrich-button.tsx +1 -1
  201. package/blocks/enrichment/components/enrichment-activity.tsx +93 -0
  202. package/blocks/enrichment/components/enrichment-job-detail.tsx +18 -0
  203. package/blocks/enrichment/components/enrichment-screen.tsx +103 -19
  204. package/blocks/enrichment/components/list-pipelines.tsx +97 -0
  205. package/blocks/enrichment/components/pipeline-detail.tsx +214 -0
  206. package/blocks/enrichment/components/pipeline-editor.tsx +144 -0
  207. package/blocks/enrichment/components/pipeline-templates.tsx +90 -0
  208. package/blocks/enrichment/components/waterfall-config.tsx +27 -7
  209. package/blocks/enrichment/lib/enrichment-types.ts +51 -0
  210. package/blocks/enrichment/lib/pipeline-types.ts +234 -0
  211. package/blocks/enrichment/recipes/bulk-enrich-and-poll.ts +15 -4
  212. package/blocks/forms/README.md +10 -0
  213. package/blocks/forms/block.json +107 -0
  214. package/blocks/forms/components/form-activity.tsx +71 -0
  215. package/blocks/forms/components/form-backfill.tsx +108 -0
  216. package/blocks/forms/components/form-builder.tsx +1 -1
  217. package/blocks/forms/components/form-embed.tsx +1 -1
  218. package/blocks/forms/components/form-groups.tsx +151 -0
  219. package/blocks/forms/components/form-mapping-editor.tsx +6 -9
  220. package/blocks/forms/components/form-route-history.tsx +72 -0
  221. package/blocks/forms/components/form-saved-views.tsx +81 -0
  222. package/blocks/forms/components/forms-screen.tsx +57 -20
  223. package/blocks/forms/components/more-rows.tsx +30 -0
  224. package/blocks/forms/components/submissions-export.tsx +67 -0
  225. package/blocks/forms/components/submissions-table.tsx +15 -6
  226. package/blocks/forms/lib/forms-extra.ts +67 -0
  227. package/blocks/inbox/README.md +45 -4
  228. package/blocks/inbox/block.json +145 -8
  229. package/blocks/inbox/components/blocked-senders.tsx +103 -0
  230. package/blocks/inbox/components/compose-message.tsx +193 -0
  231. package/blocks/inbox/components/inbox-screen.tsx +54 -6
  232. package/blocks/inbox/components/inbox-search.tsx +106 -0
  233. package/blocks/inbox/components/record-conversations-tab.tsx +154 -0
  234. package/blocks/inbox/components/tag-manager.tsx +136 -0
  235. package/blocks/inbox/components/thread-actions.tsx +133 -0
  236. package/blocks/inbox/components/thread-badge.tsx +2 -2
  237. package/blocks/inbox/components/thread-view.tsx +3 -1
  238. package/blocks/inbox/hooks/use-inbox-mailboxes.ts +31 -0
  239. package/blocks/inbox/lib/inbox-manage.ts +227 -0
  240. package/blocks/integrations/README.md +54 -1
  241. package/blocks/integrations/block.json +189 -15
  242. package/blocks/integrations/components/ad-accounts.tsx +82 -0
  243. package/blocks/integrations/components/connection-health.tsx +59 -0
  244. package/blocks/integrations/components/crm-detail.tsx +20 -1
  245. package/blocks/integrations/components/crm-records.tsx +103 -0
  246. package/blocks/integrations/components/field-mappings.tsx +61 -0
  247. package/blocks/integrations/components/integration-list.tsx +4 -4
  248. package/blocks/integrations/components/integrations-screen.tsx +20 -3
  249. package/blocks/integrations/components/migration-panel.tsx +133 -0
  250. package/blocks/integrations/components/sugarcrm-connect.tsx +95 -0
  251. package/blocks/integrations/components/sync-status.tsx +6 -6
  252. package/blocks/integrations/components/sync-triggers.tsx +134 -0
  253. package/blocks/integrations/components/webhook-detail.tsx +26 -7
  254. package/blocks/integrations/components/webhook-manager.tsx +30 -17
  255. package/blocks/integrations/components/workspace-tools.tsx +127 -0
  256. package/blocks/integrations/lib/crm-utils.ts +39 -0
  257. package/blocks/integrations/lib/facts.tsx +13 -0
  258. package/blocks/integrations/lib/integrations-utils.ts +5 -0
  259. package/blocks/integrations/lib/load-more.tsx +141 -0
  260. package/blocks/intent/components/account-intent-score.tsx +5 -5
  261. package/blocks/intent/components/intent-feed.tsx +8 -8
  262. package/blocks/intent/components/intent-keyword-manager.tsx +8 -8
  263. package/blocks/intent/lib/intent-utils.ts +4 -4
  264. package/blocks/lifecycle/components/account-related.tsx +8 -1
  265. package/blocks/lifecycle/components/churn-list.tsx +5 -2
  266. package/blocks/lifecycle/components/customer-table.tsx +1 -1
  267. package/blocks/lists/README.md +7 -1
  268. package/blocks/lists/block.json +31 -3
  269. package/blocks/lists/components/add-company-people-to-list-button.tsx +73 -0
  270. package/blocks/lists/components/add-to-list-button.tsx +17 -7
  271. package/blocks/lists/components/list-picker.tsx +13 -3
  272. package/blocks/lists/components/list-table.tsx +1 -1
  273. package/blocks/lists/components/lists-screen.tsx +4 -2
  274. package/blocks/lists/components/record-lists-tab.tsx +99 -0
  275. package/blocks/lists/components/suppression-manager.tsx +27 -6
  276. package/blocks/lists/components/suppressions-screen.tsx +21 -12
  277. package/blocks/mailboxes/block.json +4 -0
  278. package/blocks/mailboxes/components/connect-mailbox.tsx +9 -8
  279. package/blocks/mailboxes/components/domain-detail.tsx +10 -4
  280. package/blocks/mailboxes/components/domain-purchase.tsx +14 -11
  281. package/blocks/mailboxes/components/mailbox-detail.tsx +3 -2
  282. package/blocks/mailboxes/components/mailbox-list.tsx +8 -3
  283. package/blocks/mailboxes/components/mailboxes-screen.tsx +8 -3
  284. package/blocks/mailboxes/components/warmup-health.tsx +20 -20
  285. package/blocks/mailboxes/lib/mailboxes-utils.ts +4 -4
  286. package/blocks/mailboxes/lib/use-provider-domains.ts +23 -0
  287. package/blocks/newsletter/README.md +12 -0
  288. package/blocks/newsletter/block.json +117 -0
  289. package/blocks/newsletter/components/issue-scheduler.tsx +2 -2
  290. package/blocks/newsletter/components/issue-versions.tsx +93 -0
  291. package/blocks/newsletter/components/more-rows.tsx +30 -0
  292. package/blocks/newsletter/components/newsletter-editor.tsx +1 -1
  293. package/blocks/newsletter/components/newsletter-list-syncs.tsx +121 -0
  294. package/blocks/newsletter/components/newsletter-screen.tsx +38 -13
  295. package/blocks/newsletter/components/newsletter-settings.tsx +211 -0
  296. package/blocks/newsletter/components/newsletter-stats.tsx +2 -2
  297. package/blocks/newsletter/components/newsletter-templates.tsx +133 -0
  298. package/blocks/newsletter/components/subscriber-table.tsx +5 -7
  299. package/blocks/newsletter/components/subscriber-timeline.tsx +65 -0
  300. package/blocks/newsletter/lib/newsletter-extra.ts +60 -0
  301. package/blocks/nurture/components/nurture-builder.tsx +10 -2
  302. package/blocks/nurture/components/nurture-enroll.tsx +6 -7
  303. package/blocks/nurture/components/nurture-form.tsx +5 -8
  304. package/blocks/nurture/components/nurture-screen.tsx +16 -5
  305. package/blocks/nurture/components/nurture-stats.tsx +5 -4
  306. package/blocks/objects/README.md +1 -1
  307. package/blocks/objects/block.json +13 -5
  308. package/blocks/objects/components/attribute-field-input.tsx +14 -1
  309. package/blocks/objects/components/object-record-detail.tsx +8 -1
  310. package/blocks/objects/components/object-schema-editor.tsx +1 -1
  311. package/blocks/objects/components/record-roles-panel.tsx +15 -5
  312. package/blocks/pages/README.md +14 -0
  313. package/blocks/pages/block.json +123 -2
  314. package/blocks/pages/components/more-rows.tsx +30 -0
  315. package/blocks/pages/components/page-ai-tools.tsx +196 -0
  316. package/blocks/pages/components/page-analytics.tsx +176 -0
  317. package/blocks/pages/components/page-clone.tsx +99 -0
  318. package/blocks/pages/components/page-domains.tsx +167 -0
  319. package/blocks/pages/components/page-editor.tsx +1 -1
  320. package/blocks/pages/components/page-generation-status.tsx +48 -0
  321. package/blocks/pages/components/page-tracking.tsx +137 -0
  322. package/blocks/pages/components/pages-screen.tsx +57 -16
  323. package/blocks/pages/components/seo-report.tsx +6 -1
  324. package/blocks/pages/hooks/use-landing-page-paths.ts +60 -0
  325. package/blocks/pages/lib/studio.ts +7 -0
  326. package/blocks/phone-numbers/README.md +74 -0
  327. package/blocks/phone-numbers/block.json +262 -0
  328. package/blocks/phone-numbers/components/a2p-registration.tsx +230 -0
  329. package/blocks/phone-numbers/components/assign-number.tsx +104 -0
  330. package/blocks/phone-numbers/components/number-search.tsx +239 -0
  331. package/blocks/phone-numbers/components/number-settings.tsx +134 -0
  332. package/blocks/phone-numbers/components/number-usage.tsx +97 -0
  333. package/blocks/phone-numbers/components/phone-number-detail.tsx +84 -0
  334. package/blocks/phone-numbers/components/phone-number-list.tsx +110 -0
  335. package/blocks/phone-numbers/components/phone-numbers-screen.tsx +201 -0
  336. package/blocks/phone-numbers/components/register-owned-number.tsx +98 -0
  337. package/blocks/phone-numbers/components/release-number.tsx +126 -0
  338. package/blocks/phone-numbers/hooks/use-phone-numbers.ts +58 -0
  339. package/blocks/phone-numbers/lib/phone-numbers-utils.ts +202 -0
  340. package/blocks/phone-numbers/recipes/01-search-and-buy-number.ts +49 -0
  341. package/blocks/phone-numbers/recipes/02-assign-number-to-rep.ts +25 -0
  342. package/blocks/phone-numbers/recipes/03-audit-numbers.ts +36 -0
  343. package/blocks/phone-numbers/recipes/04-register-text-messaging.ts +39 -0
  344. package/blocks/pickers/README.md +23 -0
  345. package/blocks/pickers/block.json +103 -0
  346. package/blocks/pickers/components/company-picker.tsx +90 -0
  347. package/blocks/pickers/components/contact-picker.tsx +131 -0
  348. package/blocks/pickers/components/member-picker.tsx +99 -0
  349. package/blocks/pickers/components/search-picker.tsx +98 -0
  350. package/blocks/pickers/hooks/use-current-member.ts +104 -0
  351. package/blocks/pickers/hooks/use-picker-pages.ts +73 -0
  352. package/blocks/pickers/lib/use-debounced.ts +13 -0
  353. package/blocks/programmatic-pages/README.md +82 -0
  354. package/blocks/programmatic-pages/block.json +292 -0
  355. package/blocks/programmatic-pages/components/programmatic-campaign-form.tsx +136 -0
  356. package/blocks/programmatic-pages/components/programmatic-generate.tsx +112 -0
  357. package/blocks/programmatic-pages/components/programmatic-generated-pages.tsx +210 -0
  358. package/blocks/programmatic-pages/components/programmatic-overview.tsx +84 -0
  359. package/blocks/programmatic-pages/components/programmatic-pages-screen.tsx +221 -0
  360. package/blocks/programmatic-pages/components/programmatic-preview.tsx +66 -0
  361. package/blocks/programmatic-pages/components/programmatic-publish.tsx +102 -0
  362. package/blocks/programmatic-pages/components/programmatic-settings.tsx +96 -0
  363. package/blocks/programmatic-pages/components/programmatic-source-fields.tsx +75 -0
  364. package/blocks/programmatic-pages/components/programmatic-source.tsx +106 -0
  365. package/blocks/programmatic-pages/components/programmatic-variables.tsx +84 -0
  366. package/blocks/programmatic-pages/hooks/use-programmatic-workspace.ts +19 -0
  367. package/blocks/programmatic-pages/lib/programmatic-types.ts +330 -0
  368. package/blocks/programmatic-pages/recipes/create-a-programmatic-campaign.ts +23 -0
  369. package/blocks/programmatic-pages/recipes/render-and-follow.ts +21 -0
  370. package/blocks/programmatic-pages/recipes/review-then-publish.ts +17 -0
  371. package/blocks/quotes/README.md +38 -1
  372. package/blocks/quotes/block.json +170 -6
  373. package/blocks/quotes/components/create-quote-from-deal.tsx +48 -0
  374. package/blocks/quotes/components/manual-products.tsx +144 -0
  375. package/blocks/quotes/components/quote-batch-actions.tsx +86 -0
  376. package/blocks/quotes/components/quote-builder.tsx +1 -1
  377. package/blocks/quotes/components/quote-documents.tsx +94 -0
  378. package/blocks/quotes/components/quote-evidence.tsx +95 -0
  379. package/blocks/quotes/components/quote-lifecycle-actions.tsx +146 -0
  380. package/blocks/quotes/components/quote-list.tsx +28 -8
  381. package/blocks/quotes/components/quote-related.tsx +3 -2
  382. package/blocks/quotes/components/quote-settings.tsx +184 -0
  383. package/blocks/quotes/components/quote-templates.tsx +189 -0
  384. package/blocks/quotes/components/quote-viewer.tsx +23 -5
  385. package/blocks/quotes/components/quotes-screen.tsx +15 -5
  386. package/blocks/quotes/components/record-quotes-tab.tsx +90 -0
  387. package/blocks/quotes/lib/quote-admin.ts +264 -0
  388. package/blocks/radar/components/competitor-battle-card.tsx +1 -1
  389. package/blocks/radar/components/radar-overview.tsx +4 -4
  390. package/blocks/radar/components/radar-screen.tsx +2 -2
  391. package/blocks/sequencer/README.md +61 -0
  392. package/blocks/sequencer/block.json +200 -6
  393. package/blocks/sequencer/components/add-to-sequence-button.tsx +82 -0
  394. package/blocks/sequencer/components/enroll-dialog.tsx +2 -2
  395. package/blocks/sequencer/components/enrollment-withdraw.tsx +71 -0
  396. package/blocks/sequencer/components/record-sequences-tab.tsx +126 -0
  397. package/blocks/sequencer/components/sequence-builder.tsx +32 -23
  398. package/blocks/sequencer/components/sequence-campaign-link.tsx +78 -0
  399. package/blocks/sequencer/components/sequence-detail.tsx +10 -2
  400. package/blocks/sequencer/components/sequence-edit-form.tsx +111 -0
  401. package/blocks/sequencer/components/sequence-enrollments.tsx +5 -2
  402. package/blocks/sequencer/components/sequence-list.tsx +1 -1
  403. package/blocks/sequencer/components/sequence-manage-actions.tsx +119 -0
  404. package/blocks/sequencer/components/sequence-senders-panel.tsx +84 -0
  405. package/blocks/sequencer/components/sequence-stats.tsx +8 -8
  406. package/blocks/sequencer/components/sequence-templates.tsx +160 -0
  407. package/blocks/sequencer/components/sequences-screen.tsx +39 -6
  408. package/blocks/sequencer/components/step-ai-assist.tsx +196 -0
  409. package/blocks/sequencer/components/step-editor.tsx +21 -12
  410. package/blocks/sequencer/components/step-templates.tsx +224 -0
  411. package/blocks/sequencer/lib/sequencer-manage.ts +235 -0
  412. package/blocks/sequencer/lib/sequencer-utils.ts +9 -5
  413. package/blocks/signals/README.md +39 -0
  414. package/blocks/signals/block.json +287 -0
  415. package/blocks/signals/components/auto-seed-panel.tsx +111 -0
  416. package/blocks/signals/components/listener-form.tsx +184 -0
  417. package/blocks/signals/components/matched-posts.tsx +195 -0
  418. package/blocks/signals/components/post-engagements.tsx +114 -0
  419. package/blocks/signals/components/record-social-tab.tsx +49 -0
  420. package/blocks/signals/components/social-listeners-screen.tsx +250 -0
  421. package/blocks/signals/components/social-settings.tsx +128 -0
  422. package/blocks/signals/components/source-lists.tsx +83 -0
  423. package/blocks/signals/components/top-engagers.tsx +68 -0
  424. package/blocks/signals/components/x-integration.tsx +129 -0
  425. package/blocks/signals/lib/signals-types.ts +228 -0
  426. package/blocks/signals/recipes/preview-and-create-a-listener.ts +16 -0
  427. package/blocks/signals/recipes/spend-against-caps.ts +14 -0
  428. package/blocks/signals/recipes/triage-matched-posts.ts +18 -0
  429. package/blocks/social-ads/README.md +8 -0
  430. package/blocks/social-ads/block.json +137 -4
  431. package/blocks/social-ads/components/audience-sync-detail.tsx +9 -3
  432. package/blocks/social-ads/components/audience-sync.tsx +6 -2
  433. package/blocks/social-ads/components/campaign-ads.tsx +166 -0
  434. package/blocks/social-ads/components/campaign-detail.tsx +6 -1
  435. package/blocks/social-ads/components/campaign-editor.tsx +134 -0
  436. package/blocks/social-ads/components/creative-concepts.tsx +74 -0
  437. package/blocks/social-ads/components/creative-detail.tsx +6 -1
  438. package/blocks/social-ads/components/creative-gallery.tsx +20 -2
  439. package/blocks/social-ads/components/creative-revisions.tsx +57 -0
  440. package/blocks/social-ads/components/creative-tools.tsx +176 -0
  441. package/blocks/social-ads/components/post-composer.tsx +4 -2
  442. package/blocks/social-ads/components/post-detail.tsx +3 -0
  443. package/blocks/social-ads/components/social-ideas.tsx +64 -0
  444. package/blocks/social-ads/components/social-performance.tsx +80 -0
  445. package/blocks/social-ads/components/social-screen.tsx +33 -6
  446. package/blocks/social-ads/lib/ads-extra.ts +67 -0
  447. package/blocks/surveys/README.md +91 -0
  448. package/blocks/surveys/block.json +299 -0
  449. package/blocks/surveys/components/account-nps.tsx +69 -0
  450. package/blocks/surveys/components/contact-survey-history.tsx +52 -0
  451. package/blocks/surveys/components/org-summary.tsx +82 -0
  452. package/blocks/surveys/components/sending-domains.tsx +113 -0
  453. package/blocks/surveys/components/survey-form.tsx +126 -0
  454. package/blocks/surveys/components/survey-responses.tsx +145 -0
  455. package/blocks/surveys/components/survey-results.tsx +72 -0
  456. package/blocks/surveys/components/survey-send-history.tsx +58 -0
  457. package/blocks/surveys/components/survey-send.tsx +162 -0
  458. package/blocks/surveys/components/survey-triggers.tsx +166 -0
  459. package/blocks/surveys/components/surveys-screen.tsx +234 -0
  460. package/blocks/surveys/lib/surveys-types.ts +228 -0
  461. package/blocks/surveys/recipes/create-an-nps-survey.ts +22 -0
  462. package/blocks/surveys/recipes/send-a-survey-and-follow-it.ts +27 -0
  463. package/blocks/surveys/recipes/survey-score-report.ts +27 -0
  464. package/blocks/visitors/components/snippet-install.tsx +18 -9
  465. package/blocks/visitors/components/traffic-chart.tsx +7 -6
  466. package/blocks/visitors/components/visitor-company-card.tsx +24 -14
  467. package/blocks/visitors/components/visitor-feed.tsx +5 -5
  468. package/blocks/web-analytics/README.md +102 -0
  469. package/blocks/web-analytics/block.json +292 -0
  470. package/blocks/web-analytics/components/acquisition-tab.tsx +154 -0
  471. package/blocks/web-analytics/components/analytics-filters.tsx +161 -0
  472. package/blocks/web-analytics/components/audience-tab.tsx +135 -0
  473. package/blocks/web-analytics/components/conversions-tab.tsx +128 -0
  474. package/blocks/web-analytics/components/engagement-tab.tsx +123 -0
  475. package/blocks/web-analytics/components/overview-tab.tsx +102 -0
  476. package/blocks/web-analytics/components/pages-tab.tsx +148 -0
  477. package/blocks/web-analytics/components/ranked-table.tsx +103 -0
  478. package/blocks/web-analytics/components/realtime-tab.tsx +103 -0
  479. package/blocks/web-analytics/components/report-card.tsx +71 -0
  480. package/blocks/web-analytics/components/web-analytics-screen.tsx +90 -0
  481. package/blocks/web-analytics/hooks/use-report.ts +48 -0
  482. package/blocks/web-analytics/lib/analytics-scope.ts +155 -0
  483. package/blocks/web-analytics/lib/page-path.ts +14 -0
  484. package/blocks/web-analytics/lib/web-analytics-types.ts +187 -0
  485. package/blocks/web-analytics/recipes/best-landing-pages.ts +26 -0
  486. package/blocks/web-analytics/recipes/form-conversion-check.ts +19 -0
  487. package/blocks/web-analytics/recipes/weekly-traffic-report.ts +37 -0
  488. package/blocks/webchat/components/chat-widget-config.tsx +1 -1
  489. package/blocks/webchat/components/conversation-list.tsx +1 -1
  490. package/blocks/workbench/README.md +54 -2
  491. package/blocks/workbench/block.json +234 -5
  492. package/blocks/workbench/components/column-recipe-editor.tsx +1 -1
  493. package/blocks/workbench/components/run-progress.tsx +1 -1
  494. package/blocks/workbench/components/workbench-auto-enrich.tsx +88 -0
  495. package/blocks/workbench/components/workbench-automation.tsx +36 -0
  496. package/blocks/workbench/components/workbench-connections.tsx +136 -0
  497. package/blocks/workbench/components/workbench-crm-import.tsx +91 -0
  498. package/blocks/workbench/components/workbench-datafile-import.tsx +154 -0
  499. package/blocks/workbench/components/workbench-grid.tsx +71 -8
  500. package/blocks/workbench/components/workbench-pipelines.tsx +173 -0
  501. package/blocks/workbench/components/workbench-row-actions.tsx +8 -1
  502. package/blocks/workbench/components/workbench-schedule.tsx +191 -0
  503. package/blocks/workbench/components/workbench-screen.tsx +65 -22
  504. package/blocks/workbench/components/workbench-send-to-sequence.tsx +116 -0
  505. package/blocks/workbench/components/workbench-table-list.tsx +14 -2
  506. package/blocks/workbench/components/workbench-table-settings.tsx +53 -0
  507. package/blocks/workbench/components/workbench-triggers.tsx +178 -0
  508. package/blocks/workbench/hooks/use-connected-crms.ts +29 -0
  509. package/blocks/workbench/lib/api-status.ts +8 -0
  510. package/blocks/workbench/lib/automation-types.ts +257 -0
  511. package/blocks/workflows/components/workflow-editor.tsx +1 -1
  512. package/dist/cli.js +744 -394
  513. package/dist/index.browser.js +1 -1
  514. package/dist/index.browser.js.map +1 -1
  515. package/dist/index.browser.mjs +1 -1
  516. package/dist/index.browser.mjs.map +1 -1
  517. package/dist/index.d.mts +2 -2
  518. package/dist/index.d.ts +2 -2
  519. package/dist/index.js +1 -1
  520. package/dist/index.js.map +1 -1
  521. package/dist/index.mjs +1 -1
  522. package/dist/index.mjs.map +1 -1
  523. package/dist/react.browser.js +1 -1
  524. package/dist/react.browser.js.map +1 -1
  525. package/dist/react.browser.mjs +1 -1
  526. package/dist/react.browser.mjs.map +1 -1
  527. package/dist/react.d.mts +2 -2
  528. package/dist/react.d.ts +2 -2
  529. package/dist/react.js +1 -1
  530. package/dist/react.js.map +1 -1
  531. package/dist/react.mjs +1 -1
  532. package/dist/react.mjs.map +1 -1
  533. package/dist/types/blocks/auth.d.ts +45 -0
  534. package/dist/types/blocks/brand.d.ts +11 -2
  535. package/dist/types/blocks/create.d.ts +11 -4
  536. package/dist/types/blocks/doctor.d.ts +1 -0
  537. package/dist/types/blocks/flows.d.ts +7 -1
  538. package/dist/types/blocks/orgBrand.d.ts +34 -0
  539. package/dist/types/cli.d.ts +3 -0
  540. package/dist/types/version.d.ts +2 -2
  541. package/docs/api/desk.d.ts +2 -2
  542. package/docs/api/desk.md +3 -3
  543. package/docs/api/forms.md +1 -1
  544. package/package.json +1 -1
  545. package/stacks/6sense/pages/companies.tsx.tmpl +21 -0
  546. package/stacks/6sense/pages/contacts.tsx.tmpl +21 -0
  547. package/stacks/6sense/pages/tasks.tsx.tmpl +19 -0
  548. package/stacks/6sense.json +37 -4
  549. package/stacks/apollo/pages/calls.tsx.tmpl +23 -0
  550. package/stacks/apollo/pages/campaigns.tsx.tmpl +27 -0
  551. package/stacks/apollo/pages/companies.tsx.tmpl +19 -36
  552. package/stacks/apollo/pages/contacts.tsx.tmpl +35 -95
  553. package/stacks/apollo/pages/deals.tsx.tmpl +17 -0
  554. package/stacks/apollo/pages/inbox-contact.tsx.tmpl +13 -0
  555. package/stacks/apollo/pages/lists.tsx.tmpl +24 -0
  556. package/stacks/apollo/pages/meetings.tsx.tmpl +13 -0
  557. package/stacks/apollo/pages/sequences.tsx.tmpl +18 -0
  558. package/stacks/apollo/pages/tasks.tsx.tmpl +20 -0
  559. package/stacks/apollo.json +68 -9
  560. package/stacks/calendly/pages/companies.tsx.tmpl +19 -0
  561. package/stacks/calendly/pages/contacts.tsx.tmpl +21 -0
  562. package/stacks/calendly/pages/meetings.tsx.tmpl +13 -0
  563. package/stacks/calendly/pages/tasks.tsx.tmpl +19 -0
  564. package/stacks/calendly.json +8 -4
  565. package/stacks/clay/pages/companies.tsx.tmpl +17 -1
  566. package/stacks/clay/pages/contacts.tsx.tmpl +14 -0
  567. package/stacks/clay/pages/lists.tsx.tmpl +24 -0
  568. package/stacks/clay/pages/tasks.tsx.tmpl +19 -0
  569. package/stacks/clay.json +16 -3
  570. package/stacks/gong/pages/calls.tsx.tmpl +23 -0
  571. package/stacks/gong/pages/companies.tsx.tmpl +22 -0
  572. package/stacks/gong/pages/contacts.tsx.tmpl +34 -0
  573. package/stacks/gong/pages/lists.tsx.tmpl +12 -0
  574. package/stacks/gong/pages/meetings.tsx.tmpl +13 -0
  575. package/stacks/gong/pages/tasks.tsx.tmpl +19 -0
  576. package/stacks/gong.json +23 -6
  577. package/stacks/hootsuite/pages/companies.tsx.tmpl +22 -0
  578. package/stacks/hootsuite/pages/contacts.tsx.tmpl +30 -0
  579. package/stacks/hootsuite/pages/lists.tsx.tmpl +12 -0
  580. package/stacks/hootsuite/pages/tasks.tsx.tmpl +19 -0
  581. package/stacks/hootsuite.json +19 -4
  582. package/stacks/hubspot/pages/campaigns.tsx.tmpl +30 -0
  583. package/stacks/hubspot/pages/companies.tsx.tmpl +16 -35
  584. package/stacks/hubspot/pages/contacts.tsx.tmpl +35 -95
  585. package/stacks/hubspot/pages/deals.tsx.tmpl +14 -1
  586. package/stacks/hubspot/pages/forms.tsx.tmpl +36 -0
  587. package/stacks/hubspot/pages/inbox.tsx.tmpl +12 -1
  588. package/stacks/hubspot/pages/lifecycle.tsx.tmpl +23 -0
  589. package/stacks/hubspot/pages/lists.tsx.tmpl +12 -0
  590. package/stacks/hubspot/pages/meetings.tsx.tmpl +13 -0
  591. package/stacks/hubspot/pages/sequences.tsx.tmpl +18 -0
  592. package/stacks/hubspot/pages/tasks.tsx.tmpl +20 -0
  593. package/stacks/hubspot/pages/web-analytics.tsx.tmpl +14 -0
  594. package/stacks/hubspot.json +66 -7
  595. package/stacks/intercom/pages/companies.tsx.tmpl +19 -0
  596. package/stacks/intercom/pages/contacts.tsx.tmpl +21 -0
  597. package/stacks/intercom/pages/inbox-contact.tsx.tmpl +13 -0
  598. package/stacks/intercom/pages/tasks.tsx.tmpl +19 -0
  599. package/stacks/intercom.json +18 -4
  600. package/stacks/mailchimp/pages/companies.tsx.tmpl +22 -0
  601. package/stacks/mailchimp/pages/contacts.tsx.tmpl +30 -0
  602. package/stacks/mailchimp/pages/forms.tsx.tmpl +36 -0
  603. package/stacks/mailchimp/pages/lists.tsx.tmpl +12 -0
  604. package/stacks/mailchimp/pages/tasks.tsx.tmpl +19 -0
  605. package/stacks/mailchimp.json +22 -6
  606. package/stacks/outreach/pages/calls.tsx.tmpl +23 -0
  607. package/stacks/outreach/pages/campaigns.tsx.tmpl +27 -0
  608. package/stacks/outreach/pages/companies.tsx.tmpl +22 -0
  609. package/stacks/outreach/pages/contacts.tsx.tmpl +29 -66
  610. package/stacks/outreach/pages/inbox-contact.tsx.tmpl +13 -0
  611. package/stacks/outreach/pages/lists.tsx.tmpl +12 -0
  612. package/stacks/outreach/pages/meetings.tsx.tmpl +13 -0
  613. package/stacks/outreach/pages/sequences.tsx.tmpl +18 -0
  614. package/stacks/outreach/pages/tasks.tsx.tmpl +19 -0
  615. package/stacks/outreach.json +38 -9
  616. package/stacks/pipedrive/pages/companies.tsx.tmpl +11 -35
  617. package/stacks/pipedrive/pages/contacts.tsx.tmpl +17 -35
  618. package/stacks/pipedrive/pages/deals.tsx.tmpl +10 -1
  619. package/stacks/pipedrive/pages/inbox.tsx.tmpl +12 -1
  620. package/stacks/pipedrive/pages/meetings.tsx.tmpl +13 -0
  621. package/stacks/pipedrive/pages/tasks.tsx.tmpl +20 -0
  622. package/stacks/pipedrive.json +14 -2
  623. package/stacks/salesforce/pages/companies.tsx.tmpl +16 -35
  624. package/stacks/salesforce/pages/contacts.tsx.tmpl +26 -35
  625. package/stacks/salesforce/pages/deals.tsx.tmpl +14 -1
  626. package/stacks/salesforce/pages/lifecycle.tsx.tmpl +23 -0
  627. package/stacks/salesforce/pages/lists.tsx.tmpl +12 -0
  628. package/stacks/salesforce/pages/tasks.tsx.tmpl +20 -0
  629. package/stacks/salesforce.json +17 -3
  630. package/stacks/zoominfo/pages/companies.tsx.tmpl +17 -1
  631. package/stacks/zoominfo/pages/contacts.tsx.tmpl +16 -0
  632. package/stacks/zoominfo/pages/lists.tsx.tmpl +24 -0
  633. package/stacks/zoominfo/pages/tasks.tsx.tmpl +19 -0
  634. package/stacks/zoominfo.json +36 -3
  635. package/styles/styles.css +1 -1
  636. package/templates/auth/auth-route.ts.tmpl +16 -0
  637. package/templates/auth/g8.auth.anonymous.ts.tmpl +15 -0
  638. package/templates/auth/g8.auth.basic.ts.tmpl +17 -0
  639. package/templates/auth/g8.auth.jwt.ts.tmpl +23 -0
  640. package/templates/auth/g8.auth.password.ts.tmpl +18 -0
  641. package/templates/auth/g8.auth.session.ts.tmpl +23 -0
  642. package/templates/auth/middleware.ts.tmpl +14 -0
  643. package/templates/next-app/README.md.tmpl +5 -0
  644. package/templates/next-app/app/globals.css.tmpl +349 -64
  645. package/templates/next-app/components/app-shell.tsx.tmpl +6 -0
  646. package/templates/next-app/components/shell/quick-jump.tsx.tmpl +4 -0
@@ -0,0 +1,86 @@
1
+ # documents
2
+
3
+ The paperwork around selling, in one block: the organization's **document Library** (folders, files, text), **security
4
+ questionnaires** a buyer sends (graph8 answers them from your Library, a person reviews every answer, the filled workbook
5
+ comes back out) and the **correspondence** recorded against an account. 35 operations of the `documents` namespace; every one
6
+ is reachable from `DocumentsScreen`.
7
+
8
+ ## Screens
9
+
10
+ `DocumentsScreen` (`components/documents-screen.tsx`) is the finished page.
11
+
12
+ ```tsx
13
+ import { DocumentsScreen } from "@/g8/documents/components/documents-screen";
14
+ export default function Page() { return <DocumentsScreen />; }
15
+ ```
16
+
17
+ Tabs (`?tab=`): **Library**, **Security questionnaires**, **Correspondence**. The two account tabs share one account (`?account=<company id>`), so a link opens straight to a company's paperwork.
18
+
19
+ - **Library**: folders on one side, documents on the other (search; filter by type and source; Show removed). Open a document (`?id=`) to read its text and facts, download the **original** file, edit it (title, folder, text), read a PDF or Word file's text again, refresh a scraped page, restore a removed one, or delete it (confirmed, permanent). Make, rename and delete folders (an empty folder only). Write a text document. Upload one or many files (checked against the Library's file types and the size limit first; a batch reports each file and keeps the failures selected for a retry). Read the text of every PDF and Word file again, or of one folder (confirmed, counted from the files it will touch).
20
+ - **Security questionnaires**: an account's questionnaires (status filter, Load more). Upload an XLSX or PDF (**confirmed; answering uses credits**), follow its progress, review every question (edit the answer, approve, escalate with notes, mark not applicable, mark wrong, save to the answer library), download the filled workbook, rename or delete it (confirmed).
21
+ - **Correspondence**: what has been said to an account (filter by channel and person, Load more). Record a message, import a JSON batch or one text file, delete (confirmed).
22
+
23
+ Optional props: `renderRowActions`, `renderDetailActions`, `extraDetailTabs` (Library documents), `toolbarActions`, `maxBytes`.
24
+
25
+ Parts you can mount alone: `LibraryPanel`, `LibraryDocumentDetail`, `LibraryDocumentForm`, `LibraryFolderForm`, `LibraryUpload`, `QuestionnairesPanel`, `QuestionnaireDetail`, `QuestionRow`, `CorrespondencePanel`, `CorrespondenceForm`, `CorrespondenceImport`, `AccountBar`.
26
+
27
+ ### On a company, contact or deal page
28
+
29
+ `RecordDocumentsTab` shows the newest messages and questionnaires for the account behind a record, read only, with a link into `DocumentsScreen` that has the account chosen. Mount it through the `extraDetailTabs` slot:
30
+
31
+ ```tsx
32
+ <CompaniesScreen extraDetailTabs={[{ id: "documents", label: "Documents", render: (c) => <RecordDocumentsTab companyId={c.id} onOpenDocuments={(href) => router.push(href)} /> }]} />
33
+ <ContactsScreen extraDetailTabs={[{ id: "documents", label: "Documents", render: (c) => <RecordDocumentsTab contactId={c.id} /> }]} />
34
+ <DealsScreen extraDetailTabs={[{ id: "documents", label: "Documents", render: (d) => <RecordDocumentsTab contactId={d.primary_contact?.id} scope="account" /> }]} />
35
+ ```
36
+
37
+ A contact shows their **company's** paperwork with the messages involving them. A deal has no company on the record the deals block reads, so it goes through its primary contact to find the company (`scope="account"` shows all the company's messages, not only that contact's); a deal with no contact shows an empty state.
38
+
39
+ ## Install
40
+
41
+ ```
42
+ npx @graph8/sdk add documents
43
+ ```
44
+
45
+ Installs `foundation` and `pickers` first if missing. Everything lands under `g8/documents/`.
46
+
47
+ ## Prerequisites (the human must do these)
48
+
49
+ | Where | What | How to verify |
50
+ |---|---|---|
51
+ | graph8 key | `knowledge:read`, `knowledge:write`, `knowledge:delete` (Library); `companies:read`, `companies:write`, `companies:delete` (questionnaires, correspondence); `knowledge:run` to upload a questionnaire (billable, separate from `knowledge:write`); `contacts:read` for the person picker. | `g8.api.me.describeCurrentKey()` |
52
+ | Your app | `allowedPrefixes` must include `library`, `accounts`, `companies`, `contacts`. The endpoints live under `/library` and `/accounts`, not `/documents`. | The route file lists them. |
53
+ | Your app | The proxy caps the WHOLE request body at **5 MiB** by default; the Library takes files up to 50 MB. The screen keeps every file (and every request, for a multi-file upload, which is split into several requests) under that cap. To allow more, raise `maxBodyBytes` in `app/api/g8/[...path]/route.ts` and pass the same number as `maxBytes`. | An upload near the limit succeeds. |
54
+ | The business | Your **Library** holds the security policies and past answers before the first questionnaire is uploaded; answering draws on them. A person decides to spend credits on each upload. | The Library has the documents the buyer's questions draw on. |
55
+
56
+ ## The flow, in order (IDs passed between steps)
57
+
58
+ 1. `getLibraryTree` first (the API creates the preset folders `Security` and `Case Studies` when the tree is read), then `listLibraryFolders` (`full_path` is what documents are filed under) and `listLibraryDocuments` (`items`, each with `id`, `folder_path`, `file_type`, `has_file_data`).
59
+ 2. `createLibraryFolder` ({ name, parent_path }) then `uploadLibraryDocument` / `uploadLibraryDocuments` (multipart `folder_path` + file/files) or `createLibraryDocument` ({ folder_path, file_name, display_name, content }). The folder must exist.
60
+ 3. `getLibraryDocument` (`id`) for the text; `updateLibraryDocument` sends only changed fields; `downloadLibraryDocument` returns the original bytes; `deleteLibraryDocument` is permanent; `restoreLibraryDocument` undoes only a soft delete (find those with `include_deleted=true`).
61
+ 4. Questionnaires: `uploadSecurityQuestionnaire` (account id = a company id; multipart `file`, xlsx or pdf) returns the questionnaire `id`; poll `getSecurityQuestionnaireStatus`; read `getSecurityQuestionnaire` for the questions; act with `updateQuestionnaireAnswer`, `approveQuestionnaireAnswer`, `escalateQuestionnaireQuestion`, `skipQuestionnaireQuestion`, `flagQuestionnaireAnswer`, `saveQuestionnaireAnswerToLibrary`; `downloadSecurityQuestionnaire` once `completed` or `needs_review`.
62
+ 5. Correspondence: `createAccountCorrespondence`, `importAccountCorrespondence` (send `external_id` to make a re-run skip duplicates), `uploadAccountCorrespondence` (a text file; dated now), `listAccountCorrespondence` (`channel`, `stakeholder_id`, `limit`, `offset`), `deleteAccountCorrespondence`.
63
+
64
+ ## Defaults the block chose (so the agent need not ask)
65
+
66
+ | Decision | Default | Ask the human? |
67
+ |---|---|---|
68
+ | Which library | The organization's (global) Library. The campaign and account libraries are not offered (see gaps) | no |
69
+ | Where an upload lands | The open folder, else the Library root; changeable | no |
70
+ | File size limit | 5 MiB (the proxy default) | no |
71
+ | Uploading a questionnaire | Never without a person confirming | yes |
72
+ | Approving an answer | A person reads it and approves; nothing is automatic | yes |
73
+ | Channel and direction of a message | None: the person chooses | yes |
74
+ | Deleting | Always confirmed; cannot be brought back | no |
75
+
76
+ ## Known API gaps (from reading the backend; the block works around them and says so on screen)
77
+
78
+ - **No price for questionnaire answering.** It is billable (`knowledge:run`) but there is no read for the cost, so the confirmation says it uses credits and shows no number.
79
+ - **`refreshLibraryDocument` is not implemented upstream**: for a scraped page it answers `status: "info"` with a message that refresh is not available yet. The screen shows that message as it is and never says the page was refreshed.
80
+ - **`deleteLibraryDocument` is a hard delete** (row and bytes), and only the owner or an admin may do it (403 otherwise). `restoreLibraryDocument` only applies to documents soft-deleted elsewhere (`include_deleted=true`).
81
+ - **Account and campaign libraries read and write with different ids**: `GET /library/documents` and `GET /library/folders` filter on the raw `account_id`/`campaign_id`, while `GET /library/tree` resolves a company id to its overlay id. A document filed under an account can be listed by one and missing from the other, so the block offers the global Library only.
82
+ - **`reextractAllLibraryDocuments` matches the folder by path prefix** (`folder_path LIKE 'x%'`), so `Library/Cases` also matches `Library/Cases 2`. The confirmation counts with the same prefix rule.
83
+ - **`GET /library/tree` leaves out folders deeper than one level and includes soft-deleted documents**, so the block counts from the flat lists.
84
+ - **Batch upload** returns `success` / `failed` (and no `items`), at most 20 files, and the first extension or size problem fails only that file.
85
+ - **Uploaded correspondence is dated now** (no date field on the upload) and read as UTF-8 or Latin-1 text.
86
+ - **Open response bodies**: every documents response is a free-form object in the contract, so the block reads fields defensively and shows a dash for anything missing.
@@ -0,0 +1,378 @@
1
+ {
2
+ "$schema": "../block.schema.json",
3
+ "id": "documents",
4
+ "title": "Documents",
5
+ "summary": "The document Library (folders, files, text), buyers' security questionnaires answered and reviewed per account, and account correspondence: browse, upload, edit, review, download.",
6
+ "features": [
7
+ "Library: folders, search and filters, text and original-file download, edit, upload one or many files, write a text document, restore a removed one, delete with confirmation",
8
+ "re-read the text of PDF and Word files, one or a whole folder, counted and confirmed",
9
+ "security questionnaires per account: upload (confirmed, uses credits), live progress, review every answer, download the filled workbook",
10
+ "review actions per question: edit the answer, approve, escalate with notes, mark not applicable, mark wrong, save to the answer library",
11
+ "account correspondence: record a message, import a JSON batch or a text file, filter by channel and person, delete with confirmation",
12
+ "RecordDocumentsTab: the latest messages and questionnaires on a company, contact or deal page"
13
+ ],
14
+ "dependsOn": [
15
+ "pickers"
16
+ ],
17
+ "operations": [
18
+ "approve_questionnaire_answer_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__approve_post",
19
+ "create_account_correspondence_accounts__account_id__correspondence_post",
20
+ "create_library_document_library_documents_post",
21
+ "create_library_folder_library_folders_post",
22
+ "delete_account_correspondence_accounts__account_id__correspondence__correspondence_id__delete",
23
+ "delete_library_document_library_documents__doc_id__delete",
24
+ "delete_library_document_library_documents__document_id__delete",
25
+ "delete_library_folder_library_folders__folder_id__delete",
26
+ "delete_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__delete",
27
+ "download_library_document_library_documents__document_id__download_get",
28
+ "download_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__download_get",
29
+ "escalate_questionnaire_question_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__escalate_post",
30
+ "flag_questionnaire_answer_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__mark_wrong_post",
31
+ "get_company_companies__company_id__get",
32
+ "get_contact_contacts__contact_id__get",
33
+ "get_library_document_library_documents__doc_id__get",
34
+ "get_library_document_library_documents__document_id__get",
35
+ "get_library_tree_library_tree_get",
36
+ "get_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__get",
37
+ "get_security_questionnaire_status_accounts__account_id__security_questionnaires__questionnaire_id__status_get",
38
+ "import_account_correspondence_accounts__account_id__correspondence_import_post",
39
+ "list_account_correspondence_accounts__account_id__correspondence_get",
40
+ "list_companies_companies_get",
41
+ "list_contacts_contacts_get",
42
+ "list_library_documents_library_documents_get",
43
+ "list_library_folders_library_folders_get",
44
+ "list_security_questionnaires_accounts__account_id__security_questionnaires_get",
45
+ "reextract_all_library_documents_library_documents_reextract_all_post",
46
+ "reextract_library_document_library_documents__doc_id__reextract_post",
47
+ "reextract_library_document_library_documents__document_id__reextract_post",
48
+ "refresh_library_document_library_documents__doc_id__refresh_post",
49
+ "refresh_library_document_library_documents__document_id__refresh_post",
50
+ "rename_library_folder_library_folders__folder_id__put",
51
+ "restore_library_document_library_documents__doc_id__restore_post",
52
+ "restore_library_document_library_documents__document_id__restore_post",
53
+ "save_questionnaire_answer_to_library_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__save_to_library_post",
54
+ "skip_questionnaire_question_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__mark_skip_post",
55
+ "update_library_document_library_documents__doc_id__put",
56
+ "update_library_document_library_documents__document_id__put",
57
+ "update_questionnaire_answer_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__patch",
58
+ "update_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__patch",
59
+ "upload_account_correspondence_accounts__account_id__correspondence_upload_post",
60
+ "upload_library_document_library_documents_upload_post",
61
+ "upload_library_documents_library_documents_upload_batch_post",
62
+ "upload_security_questionnaire_accounts__account_id__security_questionnaires_post"
63
+ ],
64
+ "components": [
65
+ {
66
+ "name": "DocumentsScreen",
67
+ "file": "components/documents-screen.tsx",
68
+ "purpose": "Finished documents workspace: the organization's document Library, an account's security questionnaires with the review loop, and an account's correspondence; composes the parts below.",
69
+ "operations": [],
70
+ "tiers": []
71
+ },
72
+ {
73
+ "name": "LibraryPanel",
74
+ "file": "components/library-panel.tsx",
75
+ "purpose": "The Library page: folder rail, searchable document list with filters and stats, the selected document, new folder, new document, upload; deletes an empty folder and re-reads the text of PDF and Word files, both behind a confirmation counted from what is sent.",
76
+ "operations": [
77
+ "delete_library_folder_library_folders__folder_id__delete",
78
+ "get_library_tree_library_tree_get",
79
+ "list_library_documents_library_documents_get",
80
+ "list_library_folders_library_folders_get",
81
+ "reextract_all_library_documents_library_documents_reextract_all_post"
82
+ ],
83
+ "tiers": [
84
+ "read",
85
+ "write",
86
+ "destructive"
87
+ ]
88
+ },
89
+ {
90
+ "name": "LibraryDocumentDetail",
91
+ "file": "components/library-document-detail.tsx",
92
+ "purpose": "One Library document: its text, its facts, download of the original, edit, read the text again, refresh a scraped page, restore, and permanent delete behind a confirmation.",
93
+ "operations": [
94
+ "delete_library_document_library_documents__doc_id__delete",
95
+ "delete_library_document_library_documents__document_id__delete",
96
+ "download_library_document_library_documents__document_id__download_get",
97
+ "get_library_document_library_documents__doc_id__get",
98
+ "get_library_document_library_documents__document_id__get",
99
+ "reextract_library_document_library_documents__doc_id__reextract_post",
100
+ "reextract_library_document_library_documents__document_id__reextract_post",
101
+ "refresh_library_document_library_documents__doc_id__refresh_post",
102
+ "refresh_library_document_library_documents__document_id__refresh_post",
103
+ "restore_library_document_library_documents__doc_id__restore_post",
104
+ "restore_library_document_library_documents__document_id__restore_post"
105
+ ],
106
+ "tiers": [
107
+ "read",
108
+ "write",
109
+ "destructive"
110
+ ]
111
+ },
112
+ {
113
+ "name": "LibraryDocumentForm",
114
+ "file": "components/library-document-form.tsx",
115
+ "purpose": "Write a text document into the Library, or edit one; edit reads the full record first and sends only changed fields.",
116
+ "operations": [
117
+ "create_library_document_library_documents_post",
118
+ "get_library_document_library_documents__doc_id__get",
119
+ "get_library_document_library_documents__document_id__get",
120
+ "update_library_document_library_documents__doc_id__put",
121
+ "update_library_document_library_documents__document_id__put"
122
+ ],
123
+ "tiers": [
124
+ "read",
125
+ "write"
126
+ ]
127
+ },
128
+ {
129
+ "name": "LibraryFolderForm",
130
+ "file": "components/library-folder-form.tsx",
131
+ "purpose": "Create a Library folder or rename one, with the API's name and depth rules checked first.",
132
+ "operations": [
133
+ "create_library_folder_library_folders_post",
134
+ "rename_library_folder_library_folders__folder_id__put"
135
+ ],
136
+ "tiers": [
137
+ "write"
138
+ ]
139
+ },
140
+ {
141
+ "name": "LibraryUpload",
142
+ "file": "components/library-upload.tsx",
143
+ "purpose": "Add one or many files to a Library folder, checked against the Library's types and the proxy's size limit; a batch reports each file and keeps the failures selected for a retry.",
144
+ "operations": [
145
+ "upload_library_document_library_documents_upload_post",
146
+ "upload_library_documents_library_documents_upload_batch_post"
147
+ ],
148
+ "tiers": [
149
+ "write"
150
+ ]
151
+ },
152
+ {
153
+ "name": "QuestionnairesPanel",
154
+ "file": "components/questionnaires-panel.tsx",
155
+ "purpose": "An account's security questionnaires: list with status filter and Load more, upload a new one (billable, confirmed), and the selected questionnaire's review.",
156
+ "operations": [
157
+ "list_security_questionnaires_accounts__account_id__security_questionnaires_get",
158
+ "upload_security_questionnaire_accounts__account_id__security_questionnaires_post"
159
+ ],
160
+ "tiers": [
161
+ "read",
162
+ "billable"
163
+ ]
164
+ },
165
+ {
166
+ "name": "QuestionnaireDetail",
167
+ "file": "components/questionnaire-detail.tsx",
168
+ "purpose": "One security questionnaire: live progress while it is answered, every question with filters, download of the filled workbook, rename, and delete behind a confirmation.",
169
+ "operations": [
170
+ "delete_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__delete",
171
+ "download_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__download_get",
172
+ "get_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__get",
173
+ "get_security_questionnaire_status_accounts__account_id__security_questionnaires__questionnaire_id__status_get",
174
+ "update_security_questionnaire_accounts__account_id__security_questionnaires__questionnaire_id__patch"
175
+ ],
176
+ "tiers": [
177
+ "read",
178
+ "write",
179
+ "destructive"
180
+ ]
181
+ },
182
+ {
183
+ "name": "QuestionRow",
184
+ "file": "components/question-row.tsx",
185
+ "purpose": "One questionnaire question with the AI's answer and the review actions: edit the answer, approve, escalate, mark not applicable, mark wrong, save to the answer library.",
186
+ "operations": [
187
+ "approve_questionnaire_answer_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__approve_post",
188
+ "escalate_questionnaire_question_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__escalate_post",
189
+ "flag_questionnaire_answer_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__mark_wrong_post",
190
+ "save_questionnaire_answer_to_library_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__save_to_library_post",
191
+ "skip_questionnaire_question_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__mark_skip_post",
192
+ "update_questionnaire_answer_accounts__account_id__security_questionnaires__questionnaire_id__questions__question_id__patch"
193
+ ],
194
+ "tiers": [
195
+ "write"
196
+ ]
197
+ },
198
+ {
199
+ "name": "CorrespondencePanel",
200
+ "file": "components/correspondence-panel.tsx",
201
+ "purpose": "What has been said to an account: list filtered by channel and person with Load more, the selected message, record one, import, and delete behind a confirmation.",
202
+ "operations": [
203
+ "delete_account_correspondence_accounts__account_id__correspondence__correspondence_id__delete",
204
+ "list_account_correspondence_accounts__account_id__correspondence_get",
205
+ "list_contacts_contacts_get"
206
+ ],
207
+ "tiers": [
208
+ "read",
209
+ "destructive"
210
+ ]
211
+ },
212
+ {
213
+ "name": "CorrespondenceForm",
214
+ "file": "components/correspondence-form.tsx",
215
+ "purpose": "Record one message, call or note against an account, dated when it happened, with an optional person at the account.",
216
+ "operations": [
217
+ "create_account_correspondence_accounts__account_id__correspondence_post",
218
+ "list_contacts_contacts_get"
219
+ ],
220
+ "tiers": [
221
+ "read",
222
+ "write"
223
+ ]
224
+ },
225
+ {
226
+ "name": "CorrespondenceImport",
227
+ "file": "components/correspondence-import.tsx",
228
+ "purpose": "Import a JSON batch of messages (partial success reported, external_id makes a re-run safe) or record one text file.",
229
+ "operations": [
230
+ "import_account_correspondence_accounts__account_id__correspondence_import_post",
231
+ "upload_account_correspondence_accounts__account_id__correspondence_upload_post"
232
+ ],
233
+ "tiers": [
234
+ "write"
235
+ ]
236
+ },
237
+ {
238
+ "name": "AccountBar",
239
+ "file": "components/account-bar.tsx",
240
+ "purpose": "Choose the account (company) the questionnaire and correspondence tabs work on; shows a name for an id that arrives in the URL.",
241
+ "operations": [
242
+ "get_company_companies__company_id__get",
243
+ "list_companies_companies_get"
244
+ ],
245
+ "tiers": [
246
+ "read"
247
+ ]
248
+ },
249
+ {
250
+ "name": "RecordDocumentsTab",
251
+ "file": "components/record-documents-tab.tsx",
252
+ "purpose": "The latest messages and questionnaires for the account behind a company, contact or deal; an extraDetailTabs entry for CompaniesScreen, ContactsScreen and DealsScreen.",
253
+ "operations": [
254
+ "get_contact_contacts__contact_id__get",
255
+ "list_account_correspondence_accounts__account_id__correspondence_get",
256
+ "list_security_questionnaires_accounts__account_id__security_questionnaires_get"
257
+ ],
258
+ "tiers": [
259
+ "read"
260
+ ]
261
+ }
262
+ ],
263
+ "screens": [
264
+ {
265
+ "component": "DocumentsScreen",
266
+ "path": "/documents",
267
+ "label": "Documents",
268
+ "icon": "FileText",
269
+ "group": "Documents",
270
+ "description": "Library, security questionnaires and account correspondence"
271
+ }
272
+ ],
273
+ "hooks": [],
274
+ "lib": [
275
+ {
276
+ "file": "lib/documents-types.ts",
277
+ "purpose": "Library, folder, questionnaire, question and correspondence shapes; the API's file types, channels and statuses; size, folder-name and import checks; the review-state helper."
278
+ },
279
+ {
280
+ "file": "lib/download.ts",
281
+ "purpose": "Save a raw-bytes response (an original Library file, a filled workbook) through the /api/g8 proxy as a download; the key stays on the server."
282
+ }
283
+ ],
284
+ "recipes": [
285
+ {
286
+ "file": "recipes/organize-the-library.ts",
287
+ "title": "Create a folder and a text document, then list what is in it",
288
+ "when": "Seeding the Library from a script; nothing is sent to anyone."
289
+ },
290
+ {
291
+ "file": "recipes/log-account-correspondence.ts",
292
+ "title": "Import an account's messages so a re-run skips what is already there",
293
+ "when": "Bringing emails or call notes in from another system; external_id makes it re-runnable."
294
+ },
295
+ {
296
+ "file": "recipes/follow-a-questionnaire.ts",
297
+ "title": "Follow a security questionnaire to completion and list what needs review",
298
+ "when": "After uploading a questionnaire in the app; reads only, approves nothing."
299
+ }
300
+ ],
301
+ "prerequisites": [
302
+ {
303
+ "id": "documents-scopes",
304
+ "description": "The key needs knowledge:read, knowledge:write and knowledge:delete for the Library, companies:read, companies:write and companies:delete for questionnaires and correspondence, and knowledge:run to upload a questionnaire (a billable operation separate from knowledge:write). The pickers need contacts:read.",
305
+ "where": "api",
306
+ "verify": "g8.api.me.describeCurrentKey() lists the scopes."
307
+ },
308
+ {
309
+ "id": "proxy-allowlist",
310
+ "description": "Add \"library\", \"accounts\", \"companies\" and \"contacts\" to allowedPrefixes in app/api/g8/[...path]/route.ts. The documents endpoints live under /library and /accounts, not /documents.",
311
+ "where": "app",
312
+ "verify": "The route file's allowedPrefixes contains them."
313
+ },
314
+ {
315
+ "id": "upload-size",
316
+ "description": "The /api/g8 proxy caps the whole request body at 5 MiB by default, while the Library accepts files up to 50 MB. The screen keeps every file, and every request of a multi-file upload (split into several), under that cap; to allow more, raise maxBodyBytes in the proxy route AND pass the same number as maxBytes to DocumentsScreen.",
317
+ "where": "app",
318
+ "verify": "The route file sets maxBodyBytes, and an upload near the limit succeeds."
319
+ },
320
+ {
321
+ "id": "answer-library",
322
+ "description": "Questionnaires are answered from your Library and policy documents. Upload your security policies and past answers first; an empty library gives empty or weak answers. Answering uses credits and a person confirms before it starts.",
323
+ "where": "app",
324
+ "verify": "The Library has the security documents the buyer's questions draw on."
325
+ }
326
+ ],
327
+ "scopes": [
328
+ "companies:delete",
329
+ "companies:read",
330
+ "companies:write",
331
+ "contacts:read",
332
+ "knowledge:delete",
333
+ "knowledge:read",
334
+ "knowledge:run",
335
+ "knowledge:write"
336
+ ],
337
+ "defaults": [
338
+ {
339
+ "decision": "Which library",
340
+ "default": "The organization's (global) Library; the API's campaign and account libraries use different ids on read and write, so they are not offered",
341
+ "askHuman": false
342
+ },
343
+ {
344
+ "decision": "Where an upload lands",
345
+ "default": "The folder currently open, else the Library root; the person can change it",
346
+ "askHuman": false
347
+ },
348
+ {
349
+ "decision": "File size limit",
350
+ "default": "5 MiB, the proxy's default body limit",
351
+ "askHuman": false
352
+ },
353
+ {
354
+ "decision": "Uploading a questionnaire",
355
+ "default": "Never without a person confirming; it uses credits and the API publishes no price",
356
+ "askHuman": true
357
+ },
358
+ {
359
+ "decision": "Approving an answer",
360
+ "default": "A person reads it and approves; nothing is approved automatically",
361
+ "askHuman": true
362
+ },
363
+ {
364
+ "decision": "Message channel and direction",
365
+ "default": "None: a person chooses, because a wrong guess misplaces the message on the account timeline",
366
+ "askHuman": true
367
+ },
368
+ {
369
+ "decision": "Deleting",
370
+ "default": "Always confirmed; a deleted document, questionnaire or message cannot be brought back",
371
+ "askHuman": false
372
+ }
373
+ ],
374
+ "peerDependencies": {
375
+ "react": ">=18",
376
+ "lucide-react": ">=0.400.0"
377
+ }
378
+ }
@@ -0,0 +1,48 @@
1
+ "use client";
2
+
3
+ /**
4
+ * AccountBar: choose the account (company) whose questionnaires or correspondence you are working on.
5
+ *
6
+ * SDK operations, in order:
7
+ * 1. listCompanies, through CompanyPicker read find the company by name or domain
8
+ * 2. getCompany (GET /companies/{company_id}) read the name of a company that arrives as an id in the URL (a shared link, a reload), so the picker shows a name, not a number
9
+ * The id is the screen's to keep (`?account=`); this only reports it. Nothing here is billable, external or destructive.
10
+ */
11
+
12
+ import { useState } from "react";
13
+ import { Label } from "@graph8/sdk/ui";
14
+ import { CompanyPicker } from "@/g8/pickers/components/company-picker";
15
+ import type { CompanyOption } from "@/g8/pickers/components/company-picker";
16
+ import { g8Get } from "@/g8/lib/g8-client";
17
+ import { useG8Query } from "@/g8/hooks/use-g8-query";
18
+
19
+ export interface AccountBarProps {
20
+ /** The chosen company id, or null. */
21
+ accountId: number | null;
22
+ onChange: (companyId: number) => void;
23
+ className?: string;
24
+ }
25
+
26
+ interface CompanyRow { id?: number | null; name?: string | null; domain?: string | null; industry?: string | null }
27
+
28
+ export function AccountBar({ accountId, onChange, className }: AccountBarProps) {
29
+ const [picked, setPicked] = useState<CompanyOption | null>(null);
30
+ const known = picked !== null && picked.id === accountId;
31
+ const company = useG8Query(
32
+ (signal) => g8Get<CompanyRow>(`/companies/${accountId}`, {}, { signal }).then((r) => r.data),
33
+ [accountId],
34
+ { enabled: accountId != null && !known, key: ["documents", "account", accountId ?? ""] },
35
+ );
36
+ let value: CompanyOption | null = known ? picked : null;
37
+ if (!value && accountId != null) {
38
+ const c = company.data;
39
+ if (c) value = { id: accountId, name: c.name || c.domain || `Company ${accountId}`, hint: [c.domain, c.industry].filter(Boolean).join(" · ") || undefined };
40
+ else if (company.error) value = { id: accountId, name: `Company ${accountId}` };
41
+ }
42
+ return (
43
+ <div className={className}>
44
+ <Label htmlFor="g8-ab-company" className="mb-1">Account</Label>
45
+ <CompanyPicker id="g8-ab-company" label="Account" value={value} onChange={(c) => { setPicked(c); onChange(c.id); }} />
46
+ </div>
47
+ );
48
+ }
@@ -0,0 +1,95 @@
1
+ "use client";
2
+
3
+ /**
4
+ * CorrespondenceForm: record ONE message, call or note against an account.
5
+ *
6
+ * SDK operations, in order:
7
+ * 1. listContacts, through ContactPicker read find the person at the account (optional)
8
+ * 2. createAccountCorrespondence (POST /accounts/{account_id}/correspondence) write stores the record and indexes it so generated documents can read it
9
+ * `correspondence_date` is when it HAPPENED, not when it was recorded: generated documents read it as the relationship's
10
+ * timeline, so it is required and sent as the exact moment (never as a date alone). Channel and direction have no default:
11
+ * a wrong guess would put the message on the wrong side of the timeline. Nothing here is billable, external or destructive.
12
+ */
13
+
14
+ import { useState } from "react";
15
+ import { Button, Input, Label, Textarea } from "@graph8/sdk/ui";
16
+ import { ApiError } from "@/g8/components/api-error";
17
+ import { g8Post } from "@/g8/lib/g8-client";
18
+ import { useG8Mutation } from "@/g8/hooks/use-g8-mutation";
19
+ import { ContactPicker } from "@/g8/pickers/components/contact-picker";
20
+ import type { ContactOption } from "@/g8/pickers/components/contact-picker";
21
+ import { CORRESPONDENCE_CHANNELS, DIRECTIONS } from "../lib/documents-types";
22
+ import type { Correspondence } from "../lib/documents-types";
23
+
24
+ export interface CorrespondenceFormProps {
25
+ accountId: number;
26
+ /** Pre-select the person (for example from a contact page). */
27
+ stakeholder?: ContactOption | null;
28
+ onSaved: (record: Correspondence) => void;
29
+ onCancel?: () => void;
30
+ }
31
+
32
+ const SELECT = "border-input bg-background h-9 w-full rounded-md border px-2 text-sm";
33
+
34
+ export function CorrespondenceForm({ accountId, stakeholder, onSaved, onCancel }: CorrespondenceFormProps) {
35
+ const [channel, setChannel] = useState("");
36
+ const [direction, setDirection] = useState("");
37
+ const [when, setWhen] = useState("");
38
+ const [subject, setSubject] = useState("");
39
+ const [content, setContent] = useState("");
40
+ const [person, setPerson] = useState<ContactOption | null>(stakeholder ?? null);
41
+ const [externalId, setExternalId] = useState("");
42
+ const date = when ? new Date(when) : null;
43
+ const valid = channel !== "" && direction !== "" && content.trim() !== "" && date !== null && !Number.isNaN(date.getTime());
44
+
45
+ const save = useG8Mutation(
46
+ async (): Promise<Correspondence> => {
47
+ const body: Record<string, unknown> = { channel, direction, content: content.trim(), correspondence_date: date!.toISOString() };
48
+ if (subject.trim()) body.subject = subject.trim();
49
+ if (person) body.stakeholder_id = String(person.id);
50
+ if (externalId.trim()) body.external_id = externalId.trim();
51
+ return (await g8Post<Correspondence>(`/accounts/${encodeURIComponent(String(accountId))}/correspondence`, body)).data;
52
+ },
53
+ { onSuccess: onSaved, invalidates: [["documents", "correspondence"]] },
54
+ );
55
+
56
+ return (
57
+ <form className="grid gap-3" onSubmit={(e) => { e.preventDefault(); if (valid) void save.mutate(undefined); }}>
58
+ <div className="grid gap-3 sm:grid-cols-2">
59
+ <div>
60
+ <Label htmlFor="g8-dc-channel" className="mb-1">Channel</Label>
61
+ <select id="g8-dc-channel" className={SELECT} value={channel} onChange={(e) => setChannel(e.target.value)}>
62
+ <option value="">Choose a channel</option>
63
+ {CORRESPONDENCE_CHANNELS.map((c) => <option key={c.value} value={c.value}>{c.label}</option>)}
64
+ </select>
65
+ </div>
66
+ <div>
67
+ <Label htmlFor="g8-dc-direction" className="mb-1">Direction</Label>
68
+ <select id="g8-dc-direction" className={SELECT} value={direction} onChange={(e) => setDirection(e.target.value)}>
69
+ <option value="">Choose a direction</option>
70
+ {DIRECTIONS.map((d) => <option key={d.value} value={d.value}>{d.label}</option>)}
71
+ </select>
72
+ </div>
73
+ </div>
74
+ <div>
75
+ <Label htmlFor="g8-dc-when" className="mb-1">When it happened</Label>
76
+ <Input id="g8-dc-when" type="datetime-local" value={when} onChange={(e) => setWhen(e.target.value)} />
77
+ </div>
78
+ <div><Label htmlFor="g8-dc-subject" className="mb-1">Subject (optional)</Label><Input id="g8-dc-subject" value={subject} onChange={(e) => setSubject(e.target.value)} /></div>
79
+ <div><Label htmlFor="g8-dc-content" className="mb-1">What was said</Label><Textarea id="g8-dc-content" rows={8} value={content} onChange={(e) => setContent(e.target.value)} /></div>
80
+ <div>
81
+ <Label htmlFor="g8-dc-person" className="mb-1">Person at the account (optional)</Label>
82
+ <div className="flex items-center gap-2">
83
+ <ContactPicker id="g8-dc-person" label="Person" value={person} onChange={setPerson} />
84
+ {person ? <Button type="button" variant="ghost" size="sm" onClick={() => setPerson(null)}>Clear</Button> : null}
85
+ </div>
86
+ </div>
87
+ <div><Label htmlFor="g8-dc-ext" className="mb-1">Your id for it (optional)</Label><Input id="g8-dc-ext" value={externalId} onChange={(e) => setExternalId(e.target.value)} /></div>
88
+ {save.error ? <ApiError error={save.error} title="Could not record the message" /> : null}
89
+ <div className="flex gap-2">
90
+ <Button type="submit" loading={save.loading} disabled={!valid}>Record message</Button>
91
+ {onCancel ? <Button type="button" variant="outline" onClick={onCancel}>Cancel</Button> : null}
92
+ </div>
93
+ </form>
94
+ );
95
+ }