@kelpie/ui 0.1.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.
- package/LICENSE +661 -0
- package/README.md +44 -0
- package/dist/ServiceStatus.d.ts +6 -0
- package/dist/ServiceStatus.d.ts.map +1 -0
- package/dist/ServiceStatus.js +35 -0
- package/dist/ServiceStatus.js.map +1 -0
- package/dist/api/ApiProvider.d.ts +19 -0
- package/dist/api/ApiProvider.d.ts.map +1 -0
- package/dist/api/ApiProvider.js +18 -0
- package/dist/api/ApiProvider.js.map +1 -0
- package/dist/api/client.d.ts +83 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +162 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/context.d.ts +14 -0
- package/dist/api/context.d.ts.map +1 -0
- package/dist/api/context.js +20 -0
- package/dist/api/context.js.map +1 -0
- package/dist/api/errors.d.ts +9 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +14 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/health.d.ts +15 -0
- package/dist/api/health.d.ts.map +1 -0
- package/dist/api/health.js +22 -0
- package/dist/api/health.js.map +1 -0
- package/dist/api/json.d.ts +3 -0
- package/dist/api/json.d.ts.map +1 -0
- package/dist/api/json.js +5 -0
- package/dist/api/json.js.map +1 -0
- package/dist/api/queryClient.d.ts +17 -0
- package/dist/api/queryClient.d.ts.map +1 -0
- package/dist/api/queryClient.js +33 -0
- package/dist/api/queryClient.js.map +1 -0
- package/dist/api/resource.d.ts +110 -0
- package/dist/api/resource.d.ts.map +1 -0
- package/dist/api/resource.js +238 -0
- package/dist/api/resource.js.map +1 -0
- package/dist/api/resources/account.d.ts +49 -0
- package/dist/api/resources/account.d.ts.map +1 -0
- package/dist/api/resources/account.js +146 -0
- package/dist/api/resources/account.js.map +1 -0
- package/dist/api/resources/activities.d.ts +8 -0
- package/dist/api/resources/activities.d.ts.map +1 -0
- package/dist/api/resources/activities.js +21 -0
- package/dist/api/resources/activities.js.map +1 -0
- package/dist/api/resources/agentTasks.d.ts +31 -0
- package/dist/api/resources/agentTasks.d.ts.map +1 -0
- package/dist/api/resources/agentTasks.js +103 -0
- package/dist/api/resources/agentTasks.js.map +1 -0
- package/dist/api/resources/candidates.d.ts +17 -0
- package/dist/api/resources/candidates.d.ts.map +1 -0
- package/dist/api/resources/candidates.js +40 -0
- package/dist/api/resources/candidates.js.map +1 -0
- package/dist/api/resources/companies.d.ts +22 -0
- package/dist/api/resources/companies.d.ts.map +1 -0
- package/dist/api/resources/companies.js +36 -0
- package/dist/api/resources/companies.js.map +1 -0
- package/dist/api/resources/dashboard.d.ts +8 -0
- package/dist/api/resources/dashboard.d.ts.map +1 -0
- package/dist/api/resources/dashboard.js +27 -0
- package/dist/api/resources/dashboard.js.map +1 -0
- package/dist/api/resources/deals.d.ts +30 -0
- package/dist/api/resources/deals.d.ts.map +1 -0
- package/dist/api/resources/deals.js +38 -0
- package/dist/api/resources/deals.js.map +1 -0
- package/dist/api/resources/decisions.d.ts +13 -0
- package/dist/api/resources/decisions.d.ts.map +1 -0
- package/dist/api/resources/decisions.js +38 -0
- package/dist/api/resources/decisions.js.map +1 -0
- package/dist/api/resources/forms.d.ts +82 -0
- package/dist/api/resources/forms.d.ts.map +1 -0
- package/dist/api/resources/forms.js +129 -0
- package/dist/api/resources/forms.js.map +1 -0
- package/dist/api/resources/handbookPages.d.ts +33 -0
- package/dist/api/resources/handbookPages.d.ts.map +1 -0
- package/dist/api/resources/handbookPages.js +49 -0
- package/dist/api/resources/handbookPages.js.map +1 -0
- package/dist/api/resources/importJobs.d.ts +72 -0
- package/dist/api/resources/importJobs.d.ts.map +1 -0
- package/dist/api/resources/importJobs.js +145 -0
- package/dist/api/resources/importJobs.js.map +1 -0
- package/dist/api/resources/invites.d.ts +19 -0
- package/dist/api/resources/invites.d.ts.map +1 -0
- package/dist/api/resources/invites.js +78 -0
- package/dist/api/resources/invites.js.map +1 -0
- package/dist/api/resources/mcpTools.d.ts +8 -0
- package/dist/api/resources/mcpTools.d.ts.map +1 -0
- package/dist/api/resources/mcpTools.js +23 -0
- package/dist/api/resources/mcpTools.js.map +1 -0
- package/dist/api/resources/members.d.ts +40 -0
- package/dist/api/resources/members.d.ts.map +1 -0
- package/dist/api/resources/members.js +67 -0
- package/dist/api/resources/members.js.map +1 -0
- package/dist/api/resources/moduleSettings.d.ts +14 -0
- package/dist/api/resources/moduleSettings.d.ts.map +1 -0
- package/dist/api/resources/moduleSettings.js +43 -0
- package/dist/api/resources/moduleSettings.js.map +1 -0
- package/dist/api/resources/mutation.d.ts +18 -0
- package/dist/api/resources/mutation.d.ts.map +1 -0
- package/dist/api/resources/mutation.js +12 -0
- package/dist/api/resources/mutation.js.map +1 -0
- package/dist/api/resources/notes.d.ts +14 -0
- package/dist/api/resources/notes.d.ts.map +1 -0
- package/dist/api/resources/notes.js +39 -0
- package/dist/api/resources/notes.js.map +1 -0
- package/dist/api/resources/opportunities.d.ts +29 -0
- package/dist/api/resources/opportunities.d.ts.map +1 -0
- package/dist/api/resources/opportunities.js +38 -0
- package/dist/api/resources/opportunities.js.map +1 -0
- package/dist/api/resources/partnerships.d.ts +33 -0
- package/dist/api/resources/partnerships.d.ts.map +1 -0
- package/dist/api/resources/partnerships.js +39 -0
- package/dist/api/resources/partnerships.js.map +1 -0
- package/dist/api/resources/people.d.ts +22 -0
- package/dist/api/resources/people.d.ts.map +1 -0
- package/dist/api/resources/people.js +36 -0
- package/dist/api/resources/people.js.map +1 -0
- package/dist/api/resources/pipelineStages.d.ts +22 -0
- package/dist/api/resources/pipelineStages.d.ts.map +1 -0
- package/dist/api/resources/pipelineStages.js +61 -0
- package/dist/api/resources/pipelineStages.js.map +1 -0
- package/dist/api/resources/planItems.d.ts +31 -0
- package/dist/api/resources/planItems.d.ts.map +1 -0
- package/dist/api/resources/planItems.js +60 -0
- package/dist/api/resources/planItems.js.map +1 -0
- package/dist/api/resources/positions.d.ts +23 -0
- package/dist/api/resources/positions.d.ts.map +1 -0
- package/dist/api/resources/positions.js +31 -0
- package/dist/api/resources/positions.js.map +1 -0
- package/dist/api/resources/raises.d.ts +30 -0
- package/dist/api/resources/raises.d.ts.map +1 -0
- package/dist/api/resources/raises.js +38 -0
- package/dist/api/resources/raises.js.map +1 -0
- package/dist/api/resources/roles.d.ts +20 -0
- package/dist/api/resources/roles.d.ts.map +1 -0
- package/dist/api/resources/roles.js +31 -0
- package/dist/api/resources/roles.js.map +1 -0
- package/dist/api/resources/search.d.ts +12 -0
- package/dist/api/resources/search.d.ts.map +1 -0
- package/dist/api/resources/search.js +37 -0
- package/dist/api/resources/search.js.map +1 -0
- package/dist/api/resources/session.d.ts +58 -0
- package/dist/api/resources/session.d.ts.map +1 -0
- package/dist/api/resources/session.js +157 -0
- package/dist/api/resources/session.js.map +1 -0
- package/dist/api/resources/webhooks.d.ts +45 -0
- package/dist/api/resources/webhooks.d.ts.map +1 -0
- package/dist/api/resources/webhooks.js +106 -0
- package/dist/api/resources/webhooks.js.map +1 -0
- package/dist/api/resources/workspace.d.ts +20 -0
- package/dist/api/resources/workspace.d.ts.map +1 -0
- package/dist/api/resources/workspace.js +63 -0
- package/dist/api/resources/workspace.js.map +1 -0
- package/dist/app/KelpieApp.d.ts +18 -0
- package/dist/app/KelpieApp.d.ts.map +1 -0
- package/dist/app/KelpieApp.js +59 -0
- package/dist/app/KelpieApp.js.map +1 -0
- package/dist/app/SessionGate.d.ts +14 -0
- package/dist/app/SessionGate.d.ts.map +1 -0
- package/dist/app/SessionGate.js +33 -0
- package/dist/app/SessionGate.js.map +1 -0
- package/dist/components/ActivitiesPanel.d.ts +28 -0
- package/dist/components/ActivitiesPanel.d.ts.map +1 -0
- package/dist/components/ActivitiesPanel.js +75 -0
- package/dist/components/ActivitiesPanel.js.map +1 -0
- package/dist/components/AgentTasks.d.ts +16 -0
- package/dist/components/AgentTasks.d.ts.map +1 -0
- package/dist/components/AgentTasks.js +166 -0
- package/dist/components/AgentTasks.js.map +1 -0
- package/dist/components/Chip.d.ts +10 -0
- package/dist/components/Chip.d.ts.map +1 -0
- package/dist/components/Chip.js +21 -0
- package/dist/components/Chip.js.map +1 -0
- package/dist/components/CopyButton.d.ts +7 -0
- package/dist/components/CopyButton.d.ts.map +1 -0
- package/dist/components/CopyButton.js +30 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/DataTable.d.ts +36 -0
- package/dist/components/DataTable.d.ts.map +1 -0
- package/dist/components/DataTable.js +43 -0
- package/dist/components/DataTable.js.map +1 -0
- package/dist/components/DecisionsPanel.d.ts +14 -0
- package/dist/components/DecisionsPanel.d.ts.map +1 -0
- package/dist/components/DecisionsPanel.js +73 -0
- package/dist/components/DecisionsPanel.js.map +1 -0
- package/dist/components/DeleteRecord.d.ts +19 -0
- package/dist/components/DeleteRecord.d.ts.map +1 -0
- package/dist/components/DeleteRecord.js +22 -0
- package/dist/components/DeleteRecord.js.map +1 -0
- package/dist/components/EntitySearch.d.ts +33 -0
- package/dist/components/EntitySearch.d.ts.map +1 -0
- package/dist/components/EntitySearch.js +111 -0
- package/dist/components/EntitySearch.js.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +21 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.js +26 -0
- package/dist/components/ErrorBoundary.js.map +1 -0
- package/dist/components/InlineEdit.d.ts +37 -0
- package/dist/components/InlineEdit.d.ts.map +1 -0
- package/dist/components/InlineEdit.js +77 -0
- package/dist/components/InlineEdit.js.map +1 -0
- package/dist/components/KanbanBoard.d.ts +24 -0
- package/dist/components/KanbanBoard.d.ts.map +1 -0
- package/dist/components/KanbanBoard.js +92 -0
- package/dist/components/KanbanBoard.js.map +1 -0
- package/dist/components/MarkdownView.d.ts +4 -0
- package/dist/components/MarkdownView.d.ts.map +1 -0
- package/dist/components/MarkdownView.js +45 -0
- package/dist/components/MarkdownView.js.map +1 -0
- package/dist/components/NotesPanel.d.ts +17 -0
- package/dist/components/NotesPanel.d.ts.map +1 -0
- package/dist/components/NotesPanel.js +53 -0
- package/dist/components/NotesPanel.js.map +1 -0
- package/dist/components/PageHeader.d.ts +20 -0
- package/dist/components/PageHeader.d.ts.map +1 -0
- package/dist/components/PageHeader.js +15 -0
- package/dist/components/PageHeader.js.map +1 -0
- package/dist/components/PhonesField.d.ts +7 -0
- package/dist/components/PhonesField.d.ts.map +1 -0
- package/dist/components/PhonesField.js +92 -0
- package/dist/components/PhonesField.js.map +1 -0
- package/dist/components/PlanAttention.d.ts +40 -0
- package/dist/components/PlanAttention.d.ts.map +1 -0
- package/dist/components/PlanAttention.js +86 -0
- package/dist/components/PlanAttention.js.map +1 -0
- package/dist/components/PlanPanel.d.ts +18 -0
- package/dist/components/PlanPanel.d.ts.map +1 -0
- package/dist/components/PlanPanel.js +102 -0
- package/dist/components/PlanPanel.js.map +1 -0
- package/dist/components/QueryState.d.ts +24 -0
- package/dist/components/QueryState.d.ts.map +1 -0
- package/dist/components/QueryState.js +34 -0
- package/dist/components/QueryState.js.map +1 -0
- package/dist/components/RecordTabs.d.ts +16 -0
- package/dist/components/RecordTabs.d.ts.map +1 -0
- package/dist/components/RecordTabs.js +15 -0
- package/dist/components/RecordTabs.js.map +1 -0
- package/dist/components/SectionHeader.d.ts +15 -0
- package/dist/components/SectionHeader.d.ts.map +1 -0
- package/dist/components/SectionHeader.js +14 -0
- package/dist/components/SectionHeader.js.map +1 -0
- package/dist/components/SegmentedControl.d.ts +13 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -0
- package/dist/components/SegmentedControl.js +14 -0
- package/dist/components/SegmentedControl.js.map +1 -0
- package/dist/components/Shell.d.ts +2 -0
- package/dist/components/Shell.d.ts.map +1 -0
- package/dist/components/Shell.js +143 -0
- package/dist/components/Shell.js.map +1 -0
- package/dist/components/SidebarField.d.ts +8 -0
- package/dist/components/SidebarField.d.ts.map +1 -0
- package/dist/components/SidebarField.js +6 -0
- package/dist/components/SidebarField.js.map +1 -0
- package/dist/components/SocialProfilesField.d.ts +8 -0
- package/dist/components/SocialProfilesField.d.ts.map +1 -0
- package/dist/components/SocialProfilesField.js +176 -0
- package/dist/components/SocialProfilesField.js.map +1 -0
- package/dist/components/StageSettings.d.ts +16 -0
- package/dist/components/StageSettings.d.ts.map +1 -0
- package/dist/components/StageSettings.js +107 -0
- package/dist/components/StageSettings.js.map +1 -0
- package/dist/components/SummaryBlock.d.ts +12 -0
- package/dist/components/SummaryBlock.d.ts.map +1 -0
- package/dist/components/SummaryBlock.js +12 -0
- package/dist/components/SummaryBlock.js.map +1 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/dates.d.ts +26 -0
- package/dist/lib/dates.d.ts.map +1 -0
- package/dist/lib/dates.js +71 -0
- package/dist/lib/dates.js.map +1 -0
- package/dist/lib/money.d.ts +7 -0
- package/dist/lib/money.d.ts.map +1 -0
- package/dist/lib/money.js +13 -0
- package/dist/lib/money.js.map +1 -0
- package/dist/lib/names.d.ts +9 -0
- package/dist/lib/names.d.ts.map +1 -0
- package/dist/lib/names.js +13 -0
- package/dist/lib/names.js.map +1 -0
- package/dist/lib/plan.d.ts +67 -0
- package/dist/lib/plan.d.ts.map +1 -0
- package/dist/lib/plan.js +96 -0
- package/dist/lib/plan.js.map +1 -0
- package/dist/lib/theme.d.ts +19 -0
- package/dist/lib/theme.d.ts.map +1 -0
- package/dist/lib/theme.js +30 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/pages/CompaniesPage.d.ts +2 -0
- package/dist/pages/CompaniesPage.d.ts.map +1 -0
- package/dist/pages/CompaniesPage.js +77 -0
- package/dist/pages/CompaniesPage.js.map +1 -0
- package/dist/pages/CompanyDetail.d.ts +2 -0
- package/dist/pages/CompanyDetail.d.ts.map +1 -0
- package/dist/pages/CompanyDetail.js +177 -0
- package/dist/pages/CompanyDetail.js.map +1 -0
- package/dist/pages/DealDetail.d.ts +2 -0
- package/dist/pages/DealDetail.d.ts.map +1 -0
- package/dist/pages/DealDetail.js +192 -0
- package/dist/pages/DealDetail.js.map +1 -0
- package/dist/pages/DealStageSettingsPage.d.ts +7 -0
- package/dist/pages/DealStageSettingsPage.d.ts.map +1 -0
- package/dist/pages/DealStageSettingsPage.js +38 -0
- package/dist/pages/DealStageSettingsPage.js.map +1 -0
- package/dist/pages/DealsPage.d.ts +2 -0
- package/dist/pages/DealsPage.d.ts.map +1 -0
- package/dist/pages/DealsPage.js +177 -0
- package/dist/pages/DealsPage.js.map +1 -0
- package/dist/pages/DecisionsPage.d.ts +2 -0
- package/dist/pages/DecisionsPage.d.ts.map +1 -0
- package/dist/pages/DecisionsPage.js +121 -0
- package/dist/pages/DecisionsPage.js.map +1 -0
- package/dist/pages/FormDetail.d.ts +2 -0
- package/dist/pages/FormDetail.d.ts.map +1 -0
- package/dist/pages/FormDetail.js +56 -0
- package/dist/pages/FormDetail.js.map +1 -0
- package/dist/pages/FormsPage.d.ts +2 -0
- package/dist/pages/FormsPage.d.ts.map +1 -0
- package/dist/pages/FormsPage.js +67 -0
- package/dist/pages/FormsPage.js.map +1 -0
- package/dist/pages/FundraisingPage.d.ts +2 -0
- package/dist/pages/FundraisingPage.d.ts.map +1 -0
- package/dist/pages/FundraisingPage.js +187 -0
- package/dist/pages/FundraisingPage.js.map +1 -0
- package/dist/pages/HiringPage.d.ts +9 -0
- package/dist/pages/HiringPage.d.ts.map +1 -0
- package/dist/pages/HiringPage.js +73 -0
- package/dist/pages/HiringPage.js.map +1 -0
- package/dist/pages/NotFoundPage.d.ts +10 -0
- package/dist/pages/NotFoundPage.d.ts.map +1 -0
- package/dist/pages/NotFoundPage.js +14 -0
- package/dist/pages/NotFoundPage.js.map +1 -0
- package/dist/pages/OpportunitiesPage.d.ts +2 -0
- package/dist/pages/OpportunitiesPage.d.ts.map +1 -0
- package/dist/pages/OpportunitiesPage.js +184 -0
- package/dist/pages/OpportunitiesPage.js.map +1 -0
- package/dist/pages/OpportunityDetail.d.ts +2 -0
- package/dist/pages/OpportunityDetail.d.ts.map +1 -0
- package/dist/pages/OpportunityDetail.js +132 -0
- package/dist/pages/OpportunityDetail.js.map +1 -0
- package/dist/pages/OpportunityStageSettingsPage.d.ts +3 -0
- package/dist/pages/OpportunityStageSettingsPage.d.ts.map +1 -0
- package/dist/pages/OpportunityStageSettingsPage.js +34 -0
- package/dist/pages/OpportunityStageSettingsPage.js.map +1 -0
- package/dist/pages/PartnershipDetail.d.ts +2 -0
- package/dist/pages/PartnershipDetail.d.ts.map +1 -0
- package/dist/pages/PartnershipDetail.js +179 -0
- package/dist/pages/PartnershipDetail.js.map +1 -0
- package/dist/pages/PartnershipStageSettingsPage.d.ts +3 -0
- package/dist/pages/PartnershipStageSettingsPage.d.ts.map +1 -0
- package/dist/pages/PartnershipStageSettingsPage.js +34 -0
- package/dist/pages/PartnershipStageSettingsPage.js.map +1 -0
- package/dist/pages/PartnershipsPage.d.ts +2 -0
- package/dist/pages/PartnershipsPage.d.ts.map +1 -0
- package/dist/pages/PartnershipsPage.js +182 -0
- package/dist/pages/PartnershipsPage.js.map +1 -0
- package/dist/pages/PeoplePage.d.ts +10 -0
- package/dist/pages/PeoplePage.d.ts.map +1 -0
- package/dist/pages/PeoplePage.js +71 -0
- package/dist/pages/PeoplePage.js.map +1 -0
- package/dist/pages/PersonDetail.d.ts +2 -0
- package/dist/pages/PersonDetail.d.ts.map +1 -0
- package/dist/pages/PersonDetail.js +193 -0
- package/dist/pages/PersonDetail.js.map +1 -0
- package/dist/pages/PlanningPage.d.ts +2 -0
- package/dist/pages/PlanningPage.d.ts.map +1 -0
- package/dist/pages/PlanningPage.js +112 -0
- package/dist/pages/PlanningPage.js.map +1 -0
- package/dist/pages/RaiseDetail.d.ts +2 -0
- package/dist/pages/RaiseDetail.d.ts.map +1 -0
- package/dist/pages/RaiseDetail.js +198 -0
- package/dist/pages/RaiseDetail.js.map +1 -0
- package/dist/pages/RaiseStageSettingsPage.d.ts +3 -0
- package/dist/pages/RaiseStageSettingsPage.d.ts.map +1 -0
- package/dist/pages/RaiseStageSettingsPage.js +34 -0
- package/dist/pages/RaiseStageSettingsPage.js.map +1 -0
- package/dist/pages/RoleDetail.d.ts +2 -0
- package/dist/pages/RoleDetail.d.ts.map +1 -0
- package/dist/pages/RoleDetail.js +177 -0
- package/dist/pages/RoleDetail.js.map +1 -0
- package/dist/pages/SearchPage.d.ts +2 -0
- package/dist/pages/SearchPage.d.ts.map +1 -0
- package/dist/pages/SearchPage.js +51 -0
- package/dist/pages/SearchPage.js.map +1 -0
- package/dist/pages/account/AccountLayout.d.ts +2 -0
- package/dist/pages/account/AccountLayout.d.ts.map +1 -0
- package/dist/pages/account/AccountLayout.js +25 -0
- package/dist/pages/account/AccountLayout.js.map +1 -0
- package/dist/pages/account/Field.d.ts +8 -0
- package/dist/pages/account/Field.d.ts.map +1 -0
- package/dist/pages/account/Field.js +6 -0
- package/dist/pages/account/Field.js.map +1 -0
- package/dist/pages/account/PreferencesPage.d.ts +2 -0
- package/dist/pages/account/PreferencesPage.d.ts.map +1 -0
- package/dist/pages/account/PreferencesPage.js +92 -0
- package/dist/pages/account/PreferencesPage.js.map +1 -0
- package/dist/pages/account/ProfilePage.d.ts +14 -0
- package/dist/pages/account/ProfilePage.d.ts.map +1 -0
- package/dist/pages/account/ProfilePage.js +71 -0
- package/dist/pages/account/ProfilePage.js.map +1 -0
- package/dist/pages/account/SecurityPage.d.ts +11 -0
- package/dist/pages/account/SecurityPage.d.ts.map +1 -0
- package/dist/pages/account/SecurityPage.js +78 -0
- package/dist/pages/account/SecurityPage.js.map +1 -0
- package/dist/pages/admin/DataPage.d.ts +3 -0
- package/dist/pages/admin/DataPage.d.ts.map +1 -0
- package/dist/pages/admin/DataPage.js +210 -0
- package/dist/pages/admin/DataPage.js.map +1 -0
- package/dist/pages/admin/McpPage.d.ts +2 -0
- package/dist/pages/admin/McpPage.d.ts.map +1 -0
- package/dist/pages/admin/McpPage.js +128 -0
- package/dist/pages/admin/McpPage.js.map +1 -0
- package/dist/pages/admin/ModulesPage.d.ts +2 -0
- package/dist/pages/admin/ModulesPage.d.ts.map +1 -0
- package/dist/pages/admin/ModulesPage.js +53 -0
- package/dist/pages/admin/ModulesPage.js.map +1 -0
- package/dist/pages/admin/TeamPage.d.ts +2 -0
- package/dist/pages/admin/TeamPage.d.ts.map +1 -0
- package/dist/pages/admin/TeamPage.js +99 -0
- package/dist/pages/admin/TeamPage.js.map +1 -0
- package/dist/pages/admin/WebhookDeliveries.d.ts +4 -0
- package/dist/pages/admin/WebhookDeliveries.d.ts.map +1 -0
- package/dist/pages/admin/WebhookDeliveries.js +88 -0
- package/dist/pages/admin/WebhookDeliveries.js.map +1 -0
- package/dist/pages/admin/WebhooksPage.d.ts +2 -0
- package/dist/pages/admin/WebhooksPage.d.ts.map +1 -0
- package/dist/pages/admin/WebhooksPage.js +152 -0
- package/dist/pages/admin/WebhooksPage.js.map +1 -0
- package/dist/pages/admin/WorkspaceSettingsPage.d.ts +2 -0
- package/dist/pages/admin/WorkspaceSettingsPage.d.ts.map +1 -0
- package/dist/pages/admin/WorkspaceSettingsPage.js +117 -0
- package/dist/pages/admin/WorkspaceSettingsPage.js.map +1 -0
- package/dist/pages/auth/AuthForm.d.ts +46 -0
- package/dist/pages/auth/AuthForm.d.ts.map +1 -0
- package/dist/pages/auth/AuthForm.js +32 -0
- package/dist/pages/auth/AuthForm.js.map +1 -0
- package/dist/pages/auth/AuthLayout.d.ts +24 -0
- package/dist/pages/auth/AuthLayout.d.ts.map +1 -0
- package/dist/pages/auth/AuthLayout.js +19 -0
- package/dist/pages/auth/AuthLayout.js.map +1 -0
- package/dist/pages/auth/ForgotPasswordPage.d.ts +13 -0
- package/dist/pages/auth/ForgotPasswordPage.d.ts.map +1 -0
- package/dist/pages/auth/ForgotPasswordPage.js +39 -0
- package/dist/pages/auth/ForgotPasswordPage.js.map +1 -0
- package/dist/pages/auth/JoinPage.d.ts +12 -0
- package/dist/pages/auth/JoinPage.d.ts.map +1 -0
- package/dist/pages/auth/JoinPage.js +43 -0
- package/dist/pages/auth/JoinPage.js.map +1 -0
- package/dist/pages/auth/ResetPasswordPage.d.ts +13 -0
- package/dist/pages/auth/ResetPasswordPage.d.ts.map +1 -0
- package/dist/pages/auth/ResetPasswordPage.js +58 -0
- package/dist/pages/auth/ResetPasswordPage.js.map +1 -0
- package/dist/pages/auth/SignInPage.d.ts +2 -0
- package/dist/pages/auth/SignInPage.d.ts.map +1 -0
- package/dist/pages/auth/SignInPage.js +38 -0
- package/dist/pages/auth/SignInPage.js.map +1 -0
- package/dist/pages/auth/SignUpPage.d.ts +13 -0
- package/dist/pages/auth/SignUpPage.d.ts.map +1 -0
- package/dist/pages/auth/SignUpPage.js +43 -0
- package/dist/pages/auth/SignUpPage.js.map +1 -0
- package/dist/pages/candidateFields.d.ts +22 -0
- package/dist/pages/candidateFields.d.ts.map +1 -0
- package/dist/pages/candidateFields.js +82 -0
- package/dist/pages/candidateFields.js.map +1 -0
- package/dist/pages/dashboard/DashboardPage.d.ts +2 -0
- package/dist/pages/dashboard/DashboardPage.d.ts.map +1 -0
- package/dist/pages/dashboard/DashboardPage.js +40 -0
- package/dist/pages/dashboard/DashboardPage.js.map +1 -0
- package/dist/pages/dashboard/attention.d.ts +41 -0
- package/dist/pages/dashboard/attention.d.ts.map +1 -0
- package/dist/pages/dashboard/attention.js +146 -0
- package/dist/pages/dashboard/attention.js.map +1 -0
- package/dist/pages/dashboard/sections.d.ts +20 -0
- package/dist/pages/dashboard/sections.d.ts.map +1 -0
- package/dist/pages/dashboard/sections.js +60 -0
- package/dist/pages/dashboard/sections.js.map +1 -0
- package/dist/pages/fields.d.ts +11 -0
- package/dist/pages/fields.d.ts.map +1 -0
- package/dist/pages/fields.js +17 -0
- package/dist/pages/fields.js.map +1 -0
- package/dist/pages/forms/EmbedPanel.d.ts +14 -0
- package/dist/pages/forms/EmbedPanel.d.ts.map +1 -0
- package/dist/pages/forms/EmbedPanel.js +19 -0
- package/dist/pages/forms/EmbedPanel.js.map +1 -0
- package/dist/pages/forms/FieldsEditor.d.ts +6 -0
- package/dist/pages/forms/FieldsEditor.d.ts.map +1 -0
- package/dist/pages/forms/FieldsEditor.js +115 -0
- package/dist/pages/forms/FieldsEditor.js.map +1 -0
- package/dist/pages/forms/FormSettings.d.ts +6 -0
- package/dist/pages/forms/FormSettings.d.ts.map +1 -0
- package/dist/pages/forms/FormSettings.js +47 -0
- package/dist/pages/forms/FormSettings.js.map +1 -0
- package/dist/pages/forms/SubmissionsTable.d.ts +8 -0
- package/dist/pages/forms/SubmissionsTable.d.ts.map +1 -0
- package/dist/pages/forms/SubmissionsTable.js +91 -0
- package/dist/pages/forms/SubmissionsTable.js.map +1 -0
- package/dist/pages/forms/fieldList.d.ts +70 -0
- package/dist/pages/forms/fieldList.d.ts.map +1 -0
- package/dist/pages/forms/fieldList.js +126 -0
- package/dist/pages/forms/fieldList.js.map +1 -0
- package/dist/pages/forms/template.d.ts +18 -0
- package/dist/pages/forms/template.d.ts.map +1 -0
- package/dist/pages/forms/template.js +34 -0
- package/dist/pages/forms/template.js.map +1 -0
- package/dist/pages/handbook/HandbookPage.d.ts +2 -0
- package/dist/pages/handbook/HandbookPage.d.ts.map +1 -0
- package/dist/pages/handbook/HandbookPage.js +197 -0
- package/dist/pages/handbook/HandbookPage.js.map +1 -0
- package/dist/pages/handbook/tree.d.ts +62 -0
- package/dist/pages/handbook/tree.d.ts.map +1 -0
- package/dist/pages/handbook/tree.js +222 -0
- package/dist/pages/handbook/tree.js.map +1 -0
- package/dist/pages/hiringDirectory.d.ts +60 -0
- package/dist/pages/hiringDirectory.d.ts.map +1 -0
- package/dist/pages/hiringDirectory.js +81 -0
- package/dist/pages/hiringDirectory.js.map +1 -0
- package/dist/pages/onboarding/HandbookStepPage.d.ts +14 -0
- package/dist/pages/onboarding/HandbookStepPage.d.ts.map +1 -0
- package/dist/pages/onboarding/HandbookStepPage.js +29 -0
- package/dist/pages/onboarding/HandbookStepPage.js.map +1 -0
- package/dist/pages/onboarding/InvitesStepPage.d.ts +2 -0
- package/dist/pages/onboarding/InvitesStepPage.d.ts.map +1 -0
- package/dist/pages/onboarding/InvitesStepPage.js +77 -0
- package/dist/pages/onboarding/InvitesStepPage.js.map +1 -0
- package/dist/pages/onboarding/WorkspaceStepPage.d.ts +2 -0
- package/dist/pages/onboarding/WorkspaceStepPage.d.ts.map +1 -0
- package/dist/pages/onboarding/WorkspaceStepPage.js +72 -0
- package/dist/pages/onboarding/WorkspaceStepPage.js.map +1 -0
- package/dist/pages/positionDirectory.d.ts +20 -0
- package/dist/pages/positionDirectory.d.ts.map +1 -0
- package/dist/pages/positionDirectory.js +58 -0
- package/dist/pages/positionDirectory.js.map +1 -0
- package/dist/registry/UiExtensionProvider.d.ts +12 -0
- package/dist/registry/UiExtensionProvider.d.ts.map +1 -0
- package/dist/registry/UiExtensionProvider.js +10 -0
- package/dist/registry/UiExtensionProvider.js.map +1 -0
- package/dist/registry/context.d.ts +31 -0
- package/dist/registry/context.d.ts.map +1 -0
- package/dist/registry/context.js +45 -0
- package/dist/registry/context.js.map +1 -0
- package/dist/registry/contributions.d.ts +71 -0
- package/dist/registry/contributions.d.ts.map +1 -0
- package/dist/registry/contributions.js +25 -0
- package/dist/registry/contributions.js.map +1 -0
- package/dist/registry/overridable.d.ts +27 -0
- package/dist/registry/overridable.d.ts.map +1 -0
- package/dist/registry/overridable.js +29 -0
- package/dist/registry/overridable.js.map +1 -0
- package/dist/registry/registry.d.ts +68 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +112 -0
- package/dist/registry/registry.js.map +1 -0
- package/dist/testing/inputs.d.ts +13 -0
- package/dist/testing/inputs.d.ts.map +1 -0
- package/dist/testing/inputs.js +16 -0
- package/dist/testing/inputs.js.map +1 -0
- package/dist/testing/stubClient.d.ts +42 -0
- package/dist/testing/stubClient.d.ts.map +1 -0
- package/dist/testing/stubClient.js +29 -0
- package/dist/testing/stubClient.js.map +1 -0
- package/package.json +73 -0
- package/src/ServiceStatus.tsx +61 -0
- package/src/api/ApiProvider.tsx +40 -0
- package/src/api/client.ts +267 -0
- package/src/api/context.ts +25 -0
- package/src/api/errors.ts +14 -0
- package/src/api/health.ts +38 -0
- package/src/api/json.ts +4 -0
- package/src/api/queryClient.ts +35 -0
- package/src/api/resource.ts +412 -0
- package/src/api/resources/account.ts +220 -0
- package/src/api/resources/activities.ts +31 -0
- package/src/api/resources/agentTasks.ts +172 -0
- package/src/api/resources/candidates.ts +69 -0
- package/src/api/resources/companies.ts +72 -0
- package/src/api/resources/dashboard.ts +39 -0
- package/src/api/resources/deals.ts +82 -0
- package/src/api/resources/decisions.ts +60 -0
- package/src/api/resources/forms.ts +218 -0
- package/src/api/resources/handbookPages.ts +77 -0
- package/src/api/resources/importJobs.ts +229 -0
- package/src/api/resources/invites.ts +112 -0
- package/src/api/resources/mcpTools.ts +28 -0
- package/src/api/resources/members.ts +105 -0
- package/src/api/resources/moduleSettings.ts +67 -0
- package/src/api/resources/mutation.ts +31 -0
- package/src/api/resources/notes.ts +62 -0
- package/src/api/resources/opportunities.ts +84 -0
- package/src/api/resources/partnerships.ts +89 -0
- package/src/api/resources/people.ts +72 -0
- package/src/api/resources/pipelineStages.ts +93 -0
- package/src/api/resources/planItems.ts +103 -0
- package/src/api/resources/positions.ts +70 -0
- package/src/api/resources/raises.ts +82 -0
- package/src/api/resources/roles.ts +65 -0
- package/src/api/resources/search.ts +49 -0
- package/src/api/resources/session.ts +220 -0
- package/src/api/resources/webhooks.ts +157 -0
- package/src/api/resources/workspace.ts +81 -0
- package/src/app/KelpieApp.tsx +162 -0
- package/src/app/SessionGate.tsx +42 -0
- package/src/components/ActivitiesPanel.tsx +235 -0
- package/src/components/AgentTasks.tsx +473 -0
- package/src/components/Chip.tsx +36 -0
- package/src/components/CopyButton.tsx +48 -0
- package/src/components/DataTable.tsx +209 -0
- package/src/components/DecisionsPanel.tsx +233 -0
- package/src/components/DeleteRecord.tsx +73 -0
- package/src/components/EntitySearch.tsx +268 -0
- package/src/components/ErrorBoundary.tsx +58 -0
- package/src/components/InlineEdit.tsx +179 -0
- package/src/components/KanbanBoard.tsx +234 -0
- package/src/components/MarkdownView.tsx +73 -0
- package/src/components/NotesPanel.tsx +169 -0
- package/src/components/PageHeader.tsx +61 -0
- package/src/components/PhonesField.tsx +204 -0
- package/src/components/PlanAttention.tsx +249 -0
- package/src/components/PlanPanel.tsx +317 -0
- package/src/components/QueryState.tsx +83 -0
- package/src/components/RecordTabs.tsx +69 -0
- package/src/components/SectionHeader.tsx +63 -0
- package/src/components/SegmentedControl.tsx +48 -0
- package/src/components/Shell.tsx +300 -0
- package/src/components/SidebarField.tsx +18 -0
- package/src/components/SocialProfilesField.tsx +356 -0
- package/src/components/StageSettings.tsx +319 -0
- package/src/components/SummaryBlock.tsx +27 -0
- package/src/index.ts +190 -0
- package/src/lib/dates.ts +90 -0
- package/src/lib/money.ts +12 -0
- package/src/lib/names.ts +13 -0
- package/src/lib/plan.ts +147 -0
- package/src/lib/theme.ts +53 -0
- package/src/pages/CompaniesPage.tsx +143 -0
- package/src/pages/CompanyDetail.tsx +502 -0
- package/src/pages/DealDetail.tsx +512 -0
- package/src/pages/DealStageSettingsPage.tsx +67 -0
- package/src/pages/DealsPage.tsx +342 -0
- package/src/pages/DecisionsPage.tsx +211 -0
- package/src/pages/FormDetail.tsx +130 -0
- package/src/pages/FormsPage.tsx +151 -0
- package/src/pages/FundraisingPage.tsx +354 -0
- package/src/pages/HiringPage.tsx +169 -0
- package/src/pages/NotFoundPage.tsx +27 -0
- package/src/pages/OpportunitiesPage.tsx +349 -0
- package/src/pages/OpportunityDetail.tsx +337 -0
- package/src/pages/OpportunityStageSettingsPage.tsx +63 -0
- package/src/pages/PartnershipDetail.tsx +490 -0
- package/src/pages/PartnershipStageSettingsPage.tsx +63 -0
- package/src/pages/PartnershipsPage.tsx +353 -0
- package/src/pages/PeoplePage.tsx +145 -0
- package/src/pages/PersonDetail.tsx +526 -0
- package/src/pages/PlanningPage.tsx +318 -0
- package/src/pages/RaiseDetail.tsx +498 -0
- package/src/pages/RaiseStageSettingsPage.tsx +63 -0
- package/src/pages/RoleDetail.tsx +455 -0
- package/src/pages/SearchPage.tsx +135 -0
- package/src/pages/account/AccountLayout.tsx +38 -0
- package/src/pages/account/Field.tsx +20 -0
- package/src/pages/account/PreferencesPage.tsx +224 -0
- package/src/pages/account/ProfilePage.tsx +147 -0
- package/src/pages/account/SecurityPage.tsx +237 -0
- package/src/pages/admin/DataPage.tsx +772 -0
- package/src/pages/admin/McpPage.tsx +404 -0
- package/src/pages/admin/ModulesPage.tsx +113 -0
- package/src/pages/admin/TeamPage.tsx +386 -0
- package/src/pages/admin/WebhookDeliveries.tsx +184 -0
- package/src/pages/admin/WebhooksPage.tsx +443 -0
- package/src/pages/admin/WorkspaceSettingsPage.tsx +274 -0
- package/src/pages/auth/AuthForm.tsx +118 -0
- package/src/pages/auth/AuthLayout.tsx +74 -0
- package/src/pages/auth/ForgotPasswordPage.tsx +80 -0
- package/src/pages/auth/JoinPage.tsx +85 -0
- package/src/pages/auth/ResetPasswordPage.tsx +124 -0
- package/src/pages/auth/SignInPage.tsx +83 -0
- package/src/pages/auth/SignUpPage.tsx +93 -0
- package/src/pages/candidateFields.tsx +175 -0
- package/src/pages/dashboard/DashboardPage.tsx +108 -0
- package/src/pages/dashboard/attention.ts +206 -0
- package/src/pages/dashboard/sections.tsx +269 -0
- package/src/pages/fields.ts +21 -0
- package/src/pages/forms/EmbedPanel.tsx +95 -0
- package/src/pages/forms/FieldsEditor.tsx +412 -0
- package/src/pages/forms/FormSettings.tsx +159 -0
- package/src/pages/forms/SubmissionsTable.tsx +171 -0
- package/src/pages/forms/fieldList.ts +209 -0
- package/src/pages/forms/template.ts +37 -0
- package/src/pages/handbook/HandbookPage.tsx +500 -0
- package/src/pages/handbook/tree.ts +327 -0
- package/src/pages/hiringDirectory.ts +146 -0
- package/src/pages/onboarding/HandbookStepPage.tsx +75 -0
- package/src/pages/onboarding/InvitesStepPage.tsx +180 -0
- package/src/pages/onboarding/WorkspaceStepPage.tsx +122 -0
- package/src/pages/positionDirectory.ts +98 -0
- package/src/registry/UiExtensionProvider.tsx +20 -0
- package/src/registry/context.ts +67 -0
- package/src/registry/contributions.ts +89 -0
- package/src/registry/overridable.ts +62 -0
- package/src/registry/registry.ts +204 -0
- package/src/styles.css +175 -0
- package/src/testing/inputs.ts +18 -0
- package/src/testing/stubClient.ts +78 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createWebhookBody,
|
|
3
|
+
createdWebhookSchema,
|
|
4
|
+
rotateWebhookSecretBody,
|
|
5
|
+
webhookBody,
|
|
6
|
+
webhookDeliverySchema,
|
|
7
|
+
webhookSchema,
|
|
8
|
+
} from '@kelpie/schemas'
|
|
9
|
+
import type {
|
|
10
|
+
CreateWebhookInput,
|
|
11
|
+
CreatedWebhook,
|
|
12
|
+
RotateWebhookSecretInput,
|
|
13
|
+
Webhook,
|
|
14
|
+
WebhookDelivery,
|
|
15
|
+
WebhookInput,
|
|
16
|
+
} from '@kelpie/schemas'
|
|
17
|
+
import { keepPreviousData, useInfiniteQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
18
|
+
|
|
19
|
+
import type { QueryParameters } from '../client.ts'
|
|
20
|
+
import { useApiClient } from '../context.ts'
|
|
21
|
+
import { toError } from '../errors.ts'
|
|
22
|
+
import { createResourceHooks } from '../resource.ts'
|
|
23
|
+
import type { MutationResult, RecordListResult, UpdateArguments } from '../resource.ts'
|
|
24
|
+
import { asMutationResult } from './mutation.ts'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* `/v1/webhooks`: outbound event delivery.
|
|
28
|
+
*
|
|
29
|
+
* Every verb needs the admin role, reads included, so a member's list request
|
|
30
|
+
* answers `403` and the page renders that rather than an empty table. A webhook
|
|
31
|
+
* URL routinely carries its own credential in the path, which is what puts
|
|
32
|
+
* reading them alongside API keys.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
const webhooks = createResourceHooks<Webhook, CreateWebhookInput, WebhookInput>({
|
|
36
|
+
name: 'webhooks',
|
|
37
|
+
path: '/webhooks',
|
|
38
|
+
decode: webhookSchema.parse,
|
|
39
|
+
createBody: createWebhookBody,
|
|
40
|
+
updateBody: webhookBody,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export interface WebhookFilters {
|
|
44
|
+
readonly status?: Webhook['status']
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function webhookQuery(filters: WebhookFilters): QueryParameters {
|
|
48
|
+
return { status: filters.status }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function useWebhooks(filters: WebhookFilters = {}): RecordListResult<Webhook> {
|
|
52
|
+
return webhooks.useList(webhookQuery(filters))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function useUpdateWebhook(): MutationResult<UpdateArguments<WebhookInput>, Webhook> {
|
|
56
|
+
return webhooks.useUpdate()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function useDeleteWebhook(): MutationResult<string, void> {
|
|
60
|
+
return webhooks.useRemove()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface WebhookDeliveryFilters {
|
|
64
|
+
readonly status?: WebhookDelivery['status']
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* One webhook's deliveries, newest first.
|
|
69
|
+
*
|
|
70
|
+
* Written out rather than built from `createResourceHooks`, for the reason
|
|
71
|
+
* `useFormSubmissions` gives: the path carries the parent id, and generalising
|
|
72
|
+
* the factory for a nested list would complicate every resource to shorten one.
|
|
73
|
+
*
|
|
74
|
+
* The status is part of the cache key. Without it, switching the filter would
|
|
75
|
+
* read the previous filter's pages out of the cache and append the new filter's
|
|
76
|
+
* next page to them.
|
|
77
|
+
*/
|
|
78
|
+
export function useWebhookDeliveries(
|
|
79
|
+
webhookId: string,
|
|
80
|
+
filters: WebhookDeliveryFilters = {},
|
|
81
|
+
): RecordListResult<WebhookDelivery> {
|
|
82
|
+
const client = useApiClient()
|
|
83
|
+
const result = useInfiniteQuery({
|
|
84
|
+
queryKey: ['webhooks', 'deliveries', webhookId, filters.status ?? 'all'],
|
|
85
|
+
queryFn: ({ pageParam }) =>
|
|
86
|
+
client.list(`/webhooks/${webhookId}/deliveries`, webhookDeliverySchema.parse, {
|
|
87
|
+
status: filters.status,
|
|
88
|
+
...(pageParam === null ? {} : { cursor: pageParam }),
|
|
89
|
+
}),
|
|
90
|
+
initialPageParam: null as string | null,
|
|
91
|
+
getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
92
|
+
placeholderData: keepPreviousData,
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
records: result.data?.pages.flatMap((page) => page.items) ?? [],
|
|
97
|
+
isLoading: result.isPending,
|
|
98
|
+
error: toError(result.error),
|
|
99
|
+
hasMore: result.hasNextPage,
|
|
100
|
+
isLoadingMore: result.isFetchingNextPage,
|
|
101
|
+
loadMore: () => {
|
|
102
|
+
void result.fetchNextPage()
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Registers a webhook.
|
|
109
|
+
*
|
|
110
|
+
* Written out rather than taken from `createResourceHooks`, because the `201`
|
|
111
|
+
* is the only response that ever carries the signing secret and the shared hook
|
|
112
|
+
* decodes with the schema that has no such field. The secret has to survive the
|
|
113
|
+
* decode: it cannot be fetched again, so a page that dropped it would have
|
|
114
|
+
* created a webhook nobody can verify deliveries from.
|
|
115
|
+
*/
|
|
116
|
+
export function useCreateWebhook(): MutationResult<CreateWebhookInput, CreatedWebhook> {
|
|
117
|
+
const client = useApiClient()
|
|
118
|
+
const queryClient = useQueryClient()
|
|
119
|
+
const mutation = useMutation({
|
|
120
|
+
mutationFn: (input: CreateWebhookInput) =>
|
|
121
|
+
client.post('/webhooks', createWebhookBody(input), createdWebhookSchema.parse),
|
|
122
|
+
onSettled: () => {
|
|
123
|
+
void queryClient.invalidateQueries({ queryKey: ['webhooks', 'list'] })
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
return asMutationResult(mutation)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface RotateSecretArguments extends RotateWebhookSecretInput {
|
|
131
|
+
readonly id: string
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Replaces a webhook's signing secret.
|
|
136
|
+
*
|
|
137
|
+
* Written out for the same reason `useCreateWebhook` is: the response carries
|
|
138
|
+
* the new secret, which no later request can retrieve, so it has to survive a
|
|
139
|
+
* decode that the shared `Webhook` schema would drop.
|
|
140
|
+
*/
|
|
141
|
+
export function useRotateWebhookSecret(): MutationResult<RotateSecretArguments, CreatedWebhook> {
|
|
142
|
+
const client = useApiClient()
|
|
143
|
+
const queryClient = useQueryClient()
|
|
144
|
+
const mutation = useMutation({
|
|
145
|
+
mutationFn: ({ id, ...input }: RotateSecretArguments) =>
|
|
146
|
+
client.post(
|
|
147
|
+
`/webhooks/${id}/rotate_secret`,
|
|
148
|
+
rotateWebhookSecretBody(input),
|
|
149
|
+
createdWebhookSchema.parse,
|
|
150
|
+
),
|
|
151
|
+
onSettled: () => {
|
|
152
|
+
void queryClient.invalidateQueries({ queryKey: ['webhooks', 'list'] })
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
return asMutationResult(mutation)
|
|
157
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { updateWorkspaceBody, workspaceSchema } from '@kelpie/schemas'
|
|
2
|
+
import type { UpdateWorkspaceInput, Workspace } from '@kelpie/schemas'
|
|
3
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
4
|
+
|
|
5
|
+
import { useApiClient } from '../context.ts'
|
|
6
|
+
import { toError } from '../errors.ts'
|
|
7
|
+
import type { MutationResult } from '../resource.ts'
|
|
8
|
+
import { asMutationResult } from './mutation.ts'
|
|
9
|
+
import { useSession } from './session.ts'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The workspace the session is in.
|
|
13
|
+
*
|
|
14
|
+
* Not a CRM resource: there is one of them, its id comes from the session rather
|
|
15
|
+
* than a route, and there is no list. `createResourceHooks` would have nothing
|
|
16
|
+
* to configure.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const WORKSPACE_KEY = 'workspace'
|
|
20
|
+
|
|
21
|
+
export interface WorkspaceState {
|
|
22
|
+
readonly workspace: Workspace | undefined
|
|
23
|
+
readonly isLoading: boolean
|
|
24
|
+
readonly error: Error | null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function useWorkspace(): WorkspaceState {
|
|
28
|
+
const client = useApiClient()
|
|
29
|
+
const { session } = useSession()
|
|
30
|
+
const workspaceId = session?.workspaceId ?? undefined
|
|
31
|
+
const result = useQuery({
|
|
32
|
+
queryKey: [WORKSPACE_KEY, workspaceId],
|
|
33
|
+
queryFn: () => client.get(`/workspaces/${workspaceId ?? ''}`, workspaceSchema.parse),
|
|
34
|
+
enabled: workspaceId !== undefined,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
workspace: result.data,
|
|
39
|
+
isLoading: result.isPending && workspaceId !== undefined,
|
|
40
|
+
error: toError(result.error),
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function useUpdateWorkspace(): MutationResult<UpdateWorkspaceInput, Workspace> {
|
|
45
|
+
const client = useApiClient()
|
|
46
|
+
const queryClient = useQueryClient()
|
|
47
|
+
const { session } = useSession()
|
|
48
|
+
const workspaceId = session?.workspaceId ?? ''
|
|
49
|
+
const mutation = useMutation({
|
|
50
|
+
mutationFn: (input: UpdateWorkspaceInput) =>
|
|
51
|
+
client.patch(`/workspaces/${workspaceId}`, updateWorkspaceBody(input), workspaceSchema.parse),
|
|
52
|
+
onSuccess: (workspace) => {
|
|
53
|
+
queryClient.setQueryData([WORKSPACE_KEY, workspaceId], workspace)
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
return asMutationResult(mutation)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Deletes the workspace, everything in it, and the caller's way back.
|
|
62
|
+
*
|
|
63
|
+
* The slug goes with the request because the API asks the caller to name what it
|
|
64
|
+
* is destroying. Afterwards the whole cache is dropped: every cached list
|
|
65
|
+
* belongs to a workspace that no longer exists.
|
|
66
|
+
*/
|
|
67
|
+
export function useDeleteWorkspace(): MutationResult<{ readonly slug: string }, void> {
|
|
68
|
+
const client = useApiClient()
|
|
69
|
+
const queryClient = useQueryClient()
|
|
70
|
+
const { session } = useSession()
|
|
71
|
+
const workspaceId = session?.workspaceId ?? ''
|
|
72
|
+
const mutation = useMutation({
|
|
73
|
+
mutationFn: ({ slug }: { readonly slug: string }) =>
|
|
74
|
+
client.delete(`/workspaces/${workspaceId}`, { slug }),
|
|
75
|
+
onSuccess: () => {
|
|
76
|
+
queryClient.clear()
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return asMutationResult(mutation)
|
|
81
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { BrowserRouter, Navigate, Route, Routes } from 'react-router'
|
|
2
|
+
|
|
3
|
+
import { ApiProvider } from '../api/ApiProvider.tsx'
|
|
4
|
+
import { Shell } from '../components/Shell.tsx'
|
|
5
|
+
import { CompaniesPage } from '../pages/CompaniesPage.tsx'
|
|
6
|
+
import { CompanyDetail } from '../pages/CompanyDetail.tsx'
|
|
7
|
+
import { DealDetail } from '../pages/DealDetail.tsx'
|
|
8
|
+
import { DealStageSettingsPage } from '../pages/DealStageSettingsPage.tsx'
|
|
9
|
+
import { DealsPage } from '../pages/DealsPage.tsx'
|
|
10
|
+
import { DecisionsPage } from '../pages/DecisionsPage.tsx'
|
|
11
|
+
import { SearchPage } from '../pages/SearchPage.tsx'
|
|
12
|
+
import { FormDetail } from '../pages/FormDetail.tsx'
|
|
13
|
+
import { FormsPage } from '../pages/FormsPage.tsx'
|
|
14
|
+
import { FundraisingPage } from '../pages/FundraisingPage.tsx'
|
|
15
|
+
import { HiringPage } from '../pages/HiringPage.tsx'
|
|
16
|
+
import { NotFoundPage } from '../pages/NotFoundPage.tsx'
|
|
17
|
+
import { OpportunitiesPage } from '../pages/OpportunitiesPage.tsx'
|
|
18
|
+
import { OpportunityDetail } from '../pages/OpportunityDetail.tsx'
|
|
19
|
+
import { OpportunityStageSettingsPage } from '../pages/OpportunityStageSettingsPage.tsx'
|
|
20
|
+
import { PartnershipDetail } from '../pages/PartnershipDetail.tsx'
|
|
21
|
+
import { PartnershipStageSettingsPage } from '../pages/PartnershipStageSettingsPage.tsx'
|
|
22
|
+
import { PartnershipsPage } from '../pages/PartnershipsPage.tsx'
|
|
23
|
+
import { PeoplePage } from '../pages/PeoplePage.tsx'
|
|
24
|
+
import { PersonDetail } from '../pages/PersonDetail.tsx'
|
|
25
|
+
import { PlanningPage } from '../pages/PlanningPage.tsx'
|
|
26
|
+
import { RaiseDetail } from '../pages/RaiseDetail.tsx'
|
|
27
|
+
import { RaiseStageSettingsPage } from '../pages/RaiseStageSettingsPage.tsx'
|
|
28
|
+
import { RoleDetail } from '../pages/RoleDetail.tsx'
|
|
29
|
+
import { AccountLayout } from '../pages/account/AccountLayout.tsx'
|
|
30
|
+
import { PreferencesPage } from '../pages/account/PreferencesPage.tsx'
|
|
31
|
+
import { ProfilePage } from '../pages/account/ProfilePage.tsx'
|
|
32
|
+
import { SecurityPage } from '../pages/account/SecurityPage.tsx'
|
|
33
|
+
import { DataPage } from '../pages/admin/DataPage.tsx'
|
|
34
|
+
import { McpPage } from '../pages/admin/McpPage.tsx'
|
|
35
|
+
import { ModulesPage } from '../pages/admin/ModulesPage.tsx'
|
|
36
|
+
import { TeamPage } from '../pages/admin/TeamPage.tsx'
|
|
37
|
+
import { WebhooksPage } from '../pages/admin/WebhooksPage.tsx'
|
|
38
|
+
import { WorkspaceSettingsPage } from '../pages/admin/WorkspaceSettingsPage.tsx'
|
|
39
|
+
import { ForgotPasswordPage } from '../pages/auth/ForgotPasswordPage.tsx'
|
|
40
|
+
import { JoinPage } from '../pages/auth/JoinPage.tsx'
|
|
41
|
+
import { ResetPasswordPage } from '../pages/auth/ResetPasswordPage.tsx'
|
|
42
|
+
import { SignInPage } from '../pages/auth/SignInPage.tsx'
|
|
43
|
+
import { SignUpPage } from '../pages/auth/SignUpPage.tsx'
|
|
44
|
+
import { DashboardPage } from '../pages/dashboard/DashboardPage.tsx'
|
|
45
|
+
import { HandbookLayout } from '../pages/handbook/HandbookPage.tsx'
|
|
46
|
+
import { HandbookStepPage } from '../pages/onboarding/HandbookStepPage.tsx'
|
|
47
|
+
import { InvitesStepPage } from '../pages/onboarding/InvitesStepPage.tsx'
|
|
48
|
+
import { WorkspaceStepPage } from '../pages/onboarding/WorkspaceStepPage.tsx'
|
|
49
|
+
import { UiExtensionProvider } from '../registry/UiExtensionProvider.tsx'
|
|
50
|
+
import { useModuleRoutes } from '../registry/context.ts'
|
|
51
|
+
import type { UiExtensions } from '../registry/registry.ts'
|
|
52
|
+
import { SessionGate } from './SessionGate.tsx'
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The whole application: providers, router, and the route table.
|
|
56
|
+
*
|
|
57
|
+
* It lives in `@kelpie/ui` rather than in `apps/kelpie` so the cloud assembly
|
|
58
|
+
* gets the same application and differs only by the modules it registers. The
|
|
59
|
+
* assembly's job is to build the registry and render this.
|
|
60
|
+
*
|
|
61
|
+
* Routes here are the ported pages. The mockup's other routes arrive with the
|
|
62
|
+
* features behind them; module routes mount alongside through the registry.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
export interface KelpieAppProps {
|
|
66
|
+
readonly extensions: UiExtensions
|
|
67
|
+
/** Origin plus base path for the API. Defaults to same-origin `/v1`. */
|
|
68
|
+
readonly baseUrl?: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function KelpieApp({ extensions, baseUrl }: KelpieAppProps): React.JSX.Element {
|
|
72
|
+
return (
|
|
73
|
+
<ApiProvider baseUrl={baseUrl}>
|
|
74
|
+
<UiExtensionProvider extensions={extensions}>
|
|
75
|
+
<BrowserRouter>
|
|
76
|
+
<AppRoutes />
|
|
77
|
+
</BrowserRouter>
|
|
78
|
+
</UiExtensionProvider>
|
|
79
|
+
</ApiProvider>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function AppRoutes(): React.JSX.Element {
|
|
84
|
+
const moduleRoutes = useModuleRoutes()
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Routes>
|
|
88
|
+
{/* Signed out, or on the way to being signed in. Route names are the
|
|
89
|
+
mockup's. */}
|
|
90
|
+
<Route path="/login" element={<SignInPage />} />
|
|
91
|
+
<Route path="/signup" element={<SignUpPage />} />
|
|
92
|
+
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
|
|
93
|
+
<Route path="/reset-password" element={<ResetPasswordPage />} />
|
|
94
|
+
{/* Outside the gate: an invitee may have no workspace yet, and this is how
|
|
95
|
+
they get one. Same for the first onboarding step, which is what the
|
|
96
|
+
gate sends an account with no workspace to. */}
|
|
97
|
+
<Route path="/join" element={<JoinPage />} />
|
|
98
|
+
<Route path="/onboarding/workspace" element={<WorkspaceStepPage />} />
|
|
99
|
+
|
|
100
|
+
<Route element={<SessionGate />}>
|
|
101
|
+
{/* Inside the gate and outside the Shell: both steps need the workspace
|
|
102
|
+
that step 1 created, and neither is a place to start navigating the
|
|
103
|
+
app from. */}
|
|
104
|
+
<Route path="/onboarding/invites" element={<InvitesStepPage />} />
|
|
105
|
+
<Route path="/onboarding/handbook" element={<HandbookStepPage />} />
|
|
106
|
+
|
|
107
|
+
<Route element={<Shell />}>
|
|
108
|
+
{/* The mockup's default route, and where the shell's wordmark goes. */}
|
|
109
|
+
<Route index element={<Navigate to="/dashboard" replace />} />
|
|
110
|
+
<Route path="dashboard" element={<DashboardPage />} />
|
|
111
|
+
<Route path="search" element={<SearchPage />} />
|
|
112
|
+
<Route path="people" element={<PeoplePage />} />
|
|
113
|
+
<Route path="people/:id" element={<PersonDetail />} />
|
|
114
|
+
<Route path="hiring" element={<HiringPage />} />
|
|
115
|
+
<Route path="hiring/:id" element={<RoleDetail />} />
|
|
116
|
+
<Route path="companies" element={<CompaniesPage />} />
|
|
117
|
+
<Route path="companies/:id" element={<CompanyDetail />} />
|
|
118
|
+
<Route path="deals" element={<DealsPage />} />
|
|
119
|
+
<Route path="deals/settings" element={<DealStageSettingsPage />} />
|
|
120
|
+
<Route path="deals/:id" element={<DealDetail />} />
|
|
121
|
+
<Route path="opportunities" element={<OpportunitiesPage />} />
|
|
122
|
+
<Route path="opportunities/settings" element={<OpportunityStageSettingsPage />} />
|
|
123
|
+
<Route path="opportunities/:id" element={<OpportunityDetail />} />
|
|
124
|
+
<Route path="fundraising" element={<FundraisingPage />} />
|
|
125
|
+
<Route path="fundraising/settings" element={<RaiseStageSettingsPage />} />
|
|
126
|
+
<Route path="fundraising/:id" element={<RaiseDetail />} />
|
|
127
|
+
<Route path="partnerships" element={<PartnershipsPage />} />
|
|
128
|
+
<Route path="partnerships/settings" element={<PartnershipStageSettingsPage />} />
|
|
129
|
+
<Route path="partnerships/:id" element={<PartnershipDetail />} />
|
|
130
|
+
<Route path="planning" element={<PlanningPage />} />
|
|
131
|
+
<Route path="decisions" element={<DecisionsPage />} />
|
|
132
|
+
<Route path="forms" element={<FormsPage />} />
|
|
133
|
+
<Route path="forms/:id" element={<FormDetail />} />
|
|
134
|
+
{/* The optional segment is the mockup's: /handbook opens the first page. */}
|
|
135
|
+
<Route path="handbook" element={<HandbookLayout />} />
|
|
136
|
+
<Route path="handbook/:pageId" element={<HandbookLayout />} />
|
|
137
|
+
<Route path="admin/workspace" element={<WorkspaceSettingsPage />} />
|
|
138
|
+
<Route path="admin/team" element={<TeamPage />} />
|
|
139
|
+
<Route path="admin/data" element={<DataPage />} />
|
|
140
|
+
<Route path="admin/mcp" element={<McpPage />} />
|
|
141
|
+
<Route path="admin/webhooks" element={<WebhooksPage />} />
|
|
142
|
+
<Route path="admin/modules" element={<ModulesPage />} />
|
|
143
|
+
{/* The mockup's own shape: /account opens the first tab. */}
|
|
144
|
+
<Route path="account" element={<AccountLayout />}>
|
|
145
|
+
<Route index element={<Navigate to="/account/profile" replace />} />
|
|
146
|
+
<Route path="profile" element={<ProfilePage />} />
|
|
147
|
+
<Route path="security" element={<SecurityPage />} />
|
|
148
|
+
<Route path="preferences" element={<PreferencesPage />} />
|
|
149
|
+
</Route>
|
|
150
|
+
{moduleRoutes.map((route) => (
|
|
151
|
+
<Route key={route.path} path={route.path} element={route.element} />
|
|
152
|
+
))}
|
|
153
|
+
{/* Last so every named route above wins first. Nested here rather than
|
|
154
|
+
outside the gate, so a signed-out visitor is redirected to /login by
|
|
155
|
+
`SessionGate` before this ever renders, and a signed-in one keeps the
|
|
156
|
+
Shell's nav instead of landing on a bare page with no way back in. */}
|
|
157
|
+
<Route path="*" element={<NotFoundPage />} />
|
|
158
|
+
</Route>
|
|
159
|
+
</Route>
|
|
160
|
+
</Routes>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Navigate, Outlet } from 'react-router'
|
|
2
|
+
|
|
3
|
+
import { useSession } from '../api/resources/session.ts'
|
|
4
|
+
import { ErrorPanel, LoadingPanel } from '../components/QueryState.tsx'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* What stands between a URL and a page that needs a workspace.
|
|
8
|
+
*
|
|
9
|
+
* Three answers, and they are not the same thing:
|
|
10
|
+
*
|
|
11
|
+
* - `401` means sign in. That is a redirect.
|
|
12
|
+
* - Signed in with no workspace means create one. Also a redirect, to a
|
|
13
|
+
* different place, because sending someone to a sign-in form they have
|
|
14
|
+
* already passed is a loop.
|
|
15
|
+
* - Anything else is the service being unreachable or broken, and redirecting
|
|
16
|
+
* on that would hide it behind a sign-in form that will also fail.
|
|
17
|
+
*/
|
|
18
|
+
export function SessionGate(): React.JSX.Element {
|
|
19
|
+
const { isLoading, isSignedOut, needsWorkspace, error } = useSession()
|
|
20
|
+
|
|
21
|
+
if (isSignedOut) {
|
|
22
|
+
return <Navigate to="/login" replace />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (error !== null) {
|
|
26
|
+
return (
|
|
27
|
+
<div className="mx-auto max-w-xl px-6 py-16">
|
|
28
|
+
<ErrorPanel error={error} />
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (isLoading) {
|
|
34
|
+
return <LoadingPanel />
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (needsWorkspace) {
|
|
38
|
+
return <Navigate to="/onboarding/workspace" replace />
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return <Outlet />
|
|
42
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import type { Activity, ActivityKind, RecordTargetType } from '@kelpie/schemas'
|
|
2
|
+
|
|
3
|
+
import { useActivities } from '../api/resources/activities.ts'
|
|
4
|
+
import { useMembers } from '../api/resources/members.ts'
|
|
5
|
+
import { formatRelativeTime, monthLabel } from '../lib/dates.ts'
|
|
6
|
+
import { ErrorPanel } from './QueryState.tsx'
|
|
7
|
+
import { SectionHeader } from './SectionHeader.tsx'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* What happened to one record, newest first, grouped by month.
|
|
11
|
+
*
|
|
12
|
+
* Read-only, because the API is. Every row here was written by the service that
|
|
13
|
+
* made the change.
|
|
14
|
+
*
|
|
15
|
+
* The roll-up is the server's: a person's timeline already carries the deals and
|
|
16
|
+
* partnerships they are on, so nothing here fetches related records to merge in.
|
|
17
|
+
*
|
|
18
|
+
* A rolled-up row says which kind of record it came from and stops there. The
|
|
19
|
+
* mockup also names it and links to it, which needs the Deals, Opportunities and
|
|
20
|
+
* Partnerships endpoints. Naming a record this page cannot fetch would mean
|
|
21
|
+
* printing an id or inventing a label, and both are worse than the type alone.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export interface ActivitiesPanelProps {
|
|
25
|
+
readonly targetType: RecordTargetType
|
|
26
|
+
readonly targetId: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Two letters per kind, as the mockup's timeline gutter shows them. */
|
|
30
|
+
const KIND_GLYPHS: Readonly<Record<ActivityKind, string>> = {
|
|
31
|
+
created: 'Cr',
|
|
32
|
+
updated: 'Up',
|
|
33
|
+
stage_changed: 'St',
|
|
34
|
+
note_added: 'Nt',
|
|
35
|
+
email: 'Em',
|
|
36
|
+
call: 'Ca',
|
|
37
|
+
meeting: 'Mt',
|
|
38
|
+
linked: 'Ln',
|
|
39
|
+
unlinked: 'Un',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const TARGET_TYPE_LABELS: Readonly<Record<RecordTargetType, string>> = {
|
|
43
|
+
person: 'Person',
|
|
44
|
+
company: 'Company',
|
|
45
|
+
deal: 'Deal',
|
|
46
|
+
opportunity: 'Opportunity',
|
|
47
|
+
partnership: 'Partnership',
|
|
48
|
+
raise: 'Raise',
|
|
49
|
+
candidate: 'Candidate',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface MonthGroup {
|
|
53
|
+
readonly label: string
|
|
54
|
+
readonly items: readonly Activity[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Consecutive runs, not a map: the list is already ordered, so a month never recurs. */
|
|
58
|
+
function groupByMonth(activities: readonly Activity[], now: Date): readonly MonthGroup[] {
|
|
59
|
+
const groups: { label: string; items: Activity[] }[] = []
|
|
60
|
+
|
|
61
|
+
for (const activity of activities) {
|
|
62
|
+
const label = monthLabel(activity.createdAt, now)
|
|
63
|
+
const last = groups.at(-1)
|
|
64
|
+
|
|
65
|
+
if (last?.label === label) {
|
|
66
|
+
last.items.push(activity)
|
|
67
|
+
} else {
|
|
68
|
+
groups.push({ label, items: [activity] })
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return groups
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function ActivitiesPanel({
|
|
76
|
+
targetType,
|
|
77
|
+
targetId,
|
|
78
|
+
}: ActivitiesPanelProps): React.JSX.Element {
|
|
79
|
+
const activities = useActivities({ targetType, targetId })
|
|
80
|
+
const members = useMembers()
|
|
81
|
+
const groups = groupByMonth(activities.records, new Date())
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<section>
|
|
85
|
+
<SectionHeader title="Activity" />
|
|
86
|
+
|
|
87
|
+
{activities.error !== null && <ErrorPanel error={activities.error} />}
|
|
88
|
+
{activities.isLoading && <p className="text-[13px] text-ink-faint">Loading activity…</p>}
|
|
89
|
+
|
|
90
|
+
{!activities.isLoading && activities.records.length === 0 && activities.error === null && (
|
|
91
|
+
<p className="text-[13px] text-ink-faint">No activity yet.</p>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
<div className="space-y-4">
|
|
95
|
+
{groups.map((group) => (
|
|
96
|
+
<div key={group.label}>
|
|
97
|
+
<h3 className="mb-2 text-[12px] font-semibold text-ink">{group.label}</h3>
|
|
98
|
+
<ol className="overflow-hidden rounded-md border border-border">
|
|
99
|
+
{group.items.map((activity, index) => (
|
|
100
|
+
<ActivityEvent
|
|
101
|
+
key={activity.id}
|
|
102
|
+
activity={activity}
|
|
103
|
+
actorName={actorNameFor(activity, members.nameById)}
|
|
104
|
+
contextType={targetType}
|
|
105
|
+
contextId={targetId}
|
|
106
|
+
isLast={index === group.items.length - 1}
|
|
107
|
+
/>
|
|
108
|
+
))}
|
|
109
|
+
</ol>
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{activities.hasMore && (
|
|
115
|
+
<button
|
|
116
|
+
type="button"
|
|
117
|
+
onClick={activities.loadMore}
|
|
118
|
+
disabled={activities.isLoadingMore}
|
|
119
|
+
className="mt-3 rounded-md border border-border px-3 py-1.5 text-[12px] font-medium text-ink-muted transition hover:border-border-strong hover:text-ink"
|
|
120
|
+
>
|
|
121
|
+
{activities.isLoadingMore ? 'Loading…' : 'Load more'}
|
|
122
|
+
</button>
|
|
123
|
+
)}
|
|
124
|
+
</section>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The single most recent event, for a record's Overview tab.
|
|
130
|
+
*
|
|
131
|
+
* Its own request rather than a slice of the panel's: the panel lives on a
|
|
132
|
+
* different tab, so on Overview there is no list to take the first row of.
|
|
133
|
+
*/
|
|
134
|
+
export function LatestActivity({
|
|
135
|
+
targetType,
|
|
136
|
+
targetId,
|
|
137
|
+
}: ActivitiesPanelProps): React.JSX.Element {
|
|
138
|
+
const activities = useActivities({ targetType, targetId })
|
|
139
|
+
const members = useMembers()
|
|
140
|
+
const latest = activities.records[0]
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<section>
|
|
144
|
+
<SectionHeader title="Latest activity" />
|
|
145
|
+
|
|
146
|
+
{activities.error !== null && <ErrorPanel error={activities.error} />}
|
|
147
|
+
{activities.isLoading && <p className="text-[13px] text-ink-faint">Loading activity…</p>}
|
|
148
|
+
|
|
149
|
+
{!activities.isLoading && latest === undefined && activities.error === null && (
|
|
150
|
+
<p className="text-[13px] text-ink-faint">No activity yet.</p>
|
|
151
|
+
)}
|
|
152
|
+
|
|
153
|
+
{latest !== undefined && (
|
|
154
|
+
<ol className="overflow-hidden rounded-md border border-border">
|
|
155
|
+
<ActivityEvent
|
|
156
|
+
activity={latest}
|
|
157
|
+
actorName={actorNameFor(latest, members.nameById)}
|
|
158
|
+
contextType={targetType}
|
|
159
|
+
contextId={targetId}
|
|
160
|
+
isLast
|
|
161
|
+
/>
|
|
162
|
+
</ol>
|
|
163
|
+
)}
|
|
164
|
+
</section>
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Exactly one of the two actor columns is set. `actorLabel` carries the display
|
|
170
|
+
* name when nothing on the team did this: "Form", "Gmail", "API key".
|
|
171
|
+
*/
|
|
172
|
+
function actorNameFor(activity: Activity, nameById: ReadonlyMap<string, string>): string {
|
|
173
|
+
if (activity.actorMemberId === null) {
|
|
174
|
+
return activity.actorLabel ?? 'System'
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return nameById.get(activity.actorMemberId) ?? 'Unknown'
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function ActivityEvent({
|
|
181
|
+
activity,
|
|
182
|
+
actorName,
|
|
183
|
+
contextType,
|
|
184
|
+
contextId,
|
|
185
|
+
isLast,
|
|
186
|
+
}: {
|
|
187
|
+
readonly activity: Activity
|
|
188
|
+
readonly actorName: string
|
|
189
|
+
readonly contextType: RecordTargetType
|
|
190
|
+
readonly contextId: string
|
|
191
|
+
readonly isLast: boolean
|
|
192
|
+
}): React.JSX.Element {
|
|
193
|
+
const isRolledUp = activity.targetType !== contextType || activity.targetId !== contextId
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<li className="flex gap-2 border-b border-border px-4 py-3 last:border-0">
|
|
197
|
+
<div className="relative flex w-5 shrink-0 justify-center">
|
|
198
|
+
{!isLast && (
|
|
199
|
+
<span
|
|
200
|
+
aria-hidden
|
|
201
|
+
className="absolute top-5 bottom-[-12px] left-1/2 w-px -translate-x-1/2 bg-border"
|
|
202
|
+
/>
|
|
203
|
+
)}
|
|
204
|
+
<div
|
|
205
|
+
className="relative z-10 flex h-5 w-5 items-center justify-center rounded border border-border bg-surface text-[9px] font-semibold tracking-wide text-ink-muted uppercase"
|
|
206
|
+
title={activity.kind}
|
|
207
|
+
>
|
|
208
|
+
{KIND_GLYPHS[activity.kind]}
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
<div className="min-w-0 flex-1">
|
|
212
|
+
<div className="flex items-baseline justify-between gap-3">
|
|
213
|
+
<p className="min-w-0 text-[12px] leading-snug text-ink">
|
|
214
|
+
<span className="font-semibold">{actorName}</span>{' '}
|
|
215
|
+
<span className="text-ink-muted">{activity.action}</span>
|
|
216
|
+
</p>
|
|
217
|
+
<time
|
|
218
|
+
dateTime={activity.createdAt.toISOString()}
|
|
219
|
+
className="shrink-0 text-[11px] text-ink-faint"
|
|
220
|
+
>
|
|
221
|
+
{formatRelativeTime(activity.createdAt)}
|
|
222
|
+
</time>
|
|
223
|
+
</div>
|
|
224
|
+
{isRolledUp && (
|
|
225
|
+
<p className="text-[11px] leading-snug text-ink-faint">
|
|
226
|
+
on <span className="text-ink-muted">{TARGET_TYPE_LABELS[activity.targetType]}</span>
|
|
227
|
+
</p>
|
|
228
|
+
)}
|
|
229
|
+
{activity.detail !== null && (
|
|
230
|
+
<p className="text-[11px] leading-snug text-ink-faint">{activity.detail}</p>
|
|
231
|
+
)}
|
|
232
|
+
</div>
|
|
233
|
+
</li>
|
|
234
|
+
)
|
|
235
|
+
}
|