canopycms 0.0.68-int.98 → 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/CHANGELOG.md +2131 -0
- package/README.md +47 -63
- package/dist/ai/generate.d.ts +5 -0
- package/dist/ai/generate.js +244 -115
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/json-to-markdown.d.ts +21 -1
- package/dist/ai/json-to-markdown.js +120 -57
- package/dist/ai/references.d.ts +72 -0
- package/dist/ai/references.js +223 -0
- package/dist/ai/resolve-branch.js +9 -2
- package/dist/ai/to-plain-text.d.ts +17 -8
- package/dist/ai/to-plain-text.js +18 -15
- package/dist/ai/types.d.ts +84 -3
- package/dist/api/admin-branch-health.d.ts +24 -1
- package/dist/api/admin-branch-health.js +52 -20
- package/dist/api/admin.d.ts +23 -5
- package/dist/api/admin.js +36 -1
- package/dist/api/assets.js +88 -78
- package/dist/api/branch-create-window.d.ts +12 -0
- package/dist/api/branch-create-window.js +13 -0
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +1 -1
- package/dist/api/branch-review.d.ts +3 -3
- package/dist/api/branch-review.js +16 -7
- package/dist/api/branch-status.d.ts +16 -6
- package/dist/api/branch-status.js +57 -12
- package/dist/api/branch-withdraw.d.ts +2 -2
- package/dist/api/branch-withdraw.js +8 -3
- package/dist/api/branch.d.ts +25 -12
- package/dist/api/branch.js +164 -103
- package/dist/api/client.d.ts +78 -58
- package/dist/api/client.js +150 -117
- package/dist/api/comments.d.ts +12 -3
- package/dist/api/comments.js +118 -9
- package/dist/api/content.d.ts +9 -9
- package/dist/api/content.js +131 -22
- package/dist/api/entries-constants.d.ts +14 -3
- package/dist/api/entries-constants.js +14 -3
- package/dist/api/entries.d.ts +40 -2
- package/dist/api/entries.js +102 -6
- package/dist/api/github-sync.d.ts +19 -0
- package/dist/api/github-sync.js +50 -3
- package/dist/api/groups.d.ts +4 -4
- package/dist/api/groups.js +2 -1
- package/dist/api/guards.js +23 -3
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +1 -0
- package/dist/api/permissions.d.ts +21 -2
- package/dist/api/permissions.js +50 -3
- package/dist/api/request-deadline.d.ts +59 -0
- package/dist/api/request-deadline.js +73 -0
- package/dist/api/resolve-references.js +8 -7
- package/dist/api/route-builder.d.ts +14 -0
- package/dist/api/route-builder.js +14 -1
- package/dist/api/schema.d.ts +11 -9
- package/dist/api/schema.js +2 -0
- package/dist/api/settings-helpers.d.ts +5 -1
- package/dist/api/settings-helpers.js +10 -2
- package/dist/api/types.d.ts +18 -0
- package/dist/api/users-constants.d.ts +6 -0
- package/dist/api/users-constants.js +6 -0
- package/dist/assets/asset-url.d.ts +28 -16
- package/dist/assets/asset-url.js +51 -25
- package/dist/assets/finalize.js +3 -0
- package/dist/assets/index.d.ts +1 -1
- package/dist/assets/materialize.d.ts +153 -0
- package/dist/assets/materialize.js +402 -0
- package/dist/assets/store-local.d.ts +19 -5
- package/dist/assets/store-local.js +69 -10
- package/dist/assets/store-s3.d.ts +38 -7
- package/dist/assets/store-s3.js +128 -22
- package/dist/assets/transform-directives.d.ts +52 -13
- package/dist/assets/transform-directives.js +87 -27
- package/dist/assets/transform.d.ts +3 -3
- package/dist/assets/transform.js +13 -8
- package/dist/assets/types.d.ts +31 -4
- package/dist/auth/cache.d.ts +1 -1
- package/dist/auth/cache.js +1 -1
- package/dist/auth/caching-auth-plugin.d.ts +2 -0
- package/dist/auth/caching-auth-plugin.js +12 -2
- package/dist/auth/file-based-auth-cache.d.ts +8 -0
- package/dist/auth/file-based-auth-cache.js +18 -8
- package/dist/auth/person-name.d.ts +5 -0
- package/dist/auth/person-name.js +8 -0
- package/dist/auth/plugin.d.ts +10 -1
- package/dist/auth/types.d.ts +2 -0
- package/dist/auth/user-metadata-lookup.d.ts +21 -0
- package/dist/auth/user-metadata-lookup.js +116 -0
- package/dist/authorization/branch.d.ts +1 -1
- package/dist/authorization/branch.js +12 -13
- package/dist/authorization/groups/schema.d.ts +4 -4
- package/dist/authorization/helpers.d.ts +8 -0
- package/dist/authorization/helpers.js +8 -0
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/protected-branch.d.ts +5 -4
- package/dist/authorization/protected-branch.js +7 -5
- package/dist/branch-health.d.ts +35 -8
- package/dist/branch-health.js +54 -18
- package/dist/branch-metadata-error.d.ts +27 -0
- package/dist/branch-metadata-error.js +23 -0
- package/dist/branch-metadata-file.d.ts +205 -24
- package/dist/branch-metadata-file.js +126 -25
- package/dist/branch-metadata.d.ts +45 -6
- package/dist/branch-metadata.js +142 -50
- package/dist/branch-provisioning.d.ts +167 -0
- package/dist/branch-provisioning.js +501 -0
- package/dist/branch-registry.d.ts +8 -0
- package/dist/branch-registry.js +61 -9
- package/dist/branch-schema-cache.d.ts +29 -12
- package/dist/branch-schema-cache.js +64 -21
- package/dist/branch-sparse.d.ts +23 -0
- package/dist/branch-sparse.js +118 -0
- package/dist/branch-workspace.d.ts +42 -3
- package/dist/branch-workspace.js +239 -100
- package/dist/build/asset-refs.d.ts +94 -0
- package/dist/build/asset-refs.js +267 -0
- package/dist/build/generate-ai-content.js +5 -0
- package/dist/build/inline-flight.d.ts +37 -0
- package/dist/build/inline-flight.js +142 -0
- package/dist/cli/asset-refs.d.ts +52 -0
- package/dist/cli/asset-refs.js +194 -0
- package/dist/cli/cli.d.ts +15 -1
- package/dist/cli/cli.js +8543 -3193
- package/dist/cli/configured-asset-store.d.ts +12 -0
- package/dist/cli/configured-asset-store.js +46 -0
- package/dist/cli/generate-ai-content.js +4244 -1072
- package/dist/cli/init.js +217 -126
- package/dist/cli/project-detect.d.ts +2 -0
- package/dist/cli/project-detect.js +2 -0
- package/dist/cli/template-files/Dockerfile.cms.template +13 -5
- package/dist/cli/template-files/cms-stack.ts.template +16 -13
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/comment-store.d.ts +25 -0
- package/dist/comment-store.js +43 -8
- package/dist/config/flatten.js +2 -0
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schemas/config.d.ts +12 -29
- package/dist/config/schemas/config.js +9 -12
- package/dist/config/schemas/field.d.ts +3 -0
- package/dist/config/schemas/field.js +58 -4
- package/dist/config/schemas/media.d.ts +4 -13
- package/dist/config/schemas/media.js +5 -8
- package/dist/config/schemas/url.d.ts +2 -20
- package/dist/config/schemas/url.js +2 -25
- package/dist/config/types.d.ts +116 -22
- package/dist/config/types.js +3 -9
- package/dist/config/validation.d.ts +25 -4
- package/dist/config/validation.js +116 -3
- package/dist/content-id-index.js +2 -2
- package/dist/content-index-generation.d.ts +1 -1
- package/dist/content-index-generation.js +1 -1
- package/dist/content-listing.d.ts +10 -1
- package/dist/content-listing.js +22 -5
- package/dist/content-reader.d.ts +9 -0
- package/dist/content-reader.js +16 -11
- package/dist/content-store.d.ts +75 -12
- package/dist/content-store.js +249 -86
- package/dist/content-tree.js +2 -2
- package/dist/context.js +5 -2
- package/dist/dangling-reference-log.d.ts +17 -0
- package/dist/dangling-reference-log.js +29 -0
- package/dist/dev-content-watcher.d.ts +1 -1
- package/dist/dev-content-watcher.js +1 -1
- package/dist/editor/BranchManager.d.ts +23 -7
- package/dist/editor/BranchManager.js +119 -54
- package/dist/editor/CanopyEditor.d.ts +1 -1
- package/dist/editor/CanopyEditor.js +1 -2
- package/dist/editor/CommentsPanel.d.ts +14 -0
- package/dist/editor/CommentsPanel.js +68 -43
- package/dist/editor/Editor.d.ts +11 -5
- package/dist/editor/Editor.js +891 -218
- package/dist/editor/EditorAuthGate.d.ts +7 -1
- package/dist/editor/EditorAuthGate.js +41 -9
- package/dist/editor/EntryNavigator.d.ts +22 -0
- package/dist/editor/EntryNavigator.js +353 -105
- package/dist/editor/FormHeader.d.ts +25 -0
- package/dist/editor/FormHeader.js +82 -0
- package/dist/editor/FormRenderer.d.ts +27 -3
- package/dist/editor/FormRenderer.js +171 -76
- package/dist/editor/PreviewFrame.d.ts +40 -0
- package/dist/editor/PreviewFrame.js +215 -0
- package/dist/editor/PreviewPane.d.ts +47 -0
- package/dist/editor/PreviewPane.js +147 -0
- package/dist/editor/PreviewToolbarTools.d.ts +22 -0
- package/dist/editor/PreviewToolbarTools.js +73 -0
- package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
- package/dist/editor/admin/SystemHealthPanel.js +163 -33
- package/dist/editor/admin/useSystemHealth.d.ts +18 -0
- package/dist/editor/admin/useSystemHealth.js +70 -1
- package/dist/editor/branch-status.d.ts +17 -0
- package/dist/editor/branch-status.js +29 -0
- package/dist/editor/canopy-path.d.ts +9 -6
- package/dist/editor/canopy-path.js +8 -11
- package/dist/editor/client-reference-resolver.d.ts +43 -16
- package/dist/editor/client-reference-resolver.js +155 -64
- package/dist/editor/comments/BranchComments.d.ts +1 -1
- package/dist/editor/comments/BranchComments.js +2 -2
- package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
- package/dist/editor/comments/CloseRefusedNotice.js +7 -0
- package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
- package/dist/editor/comments/CommentThreadsPopover.js +274 -0
- package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
- package/dist/editor/comments/CommentWriteAlert.js +13 -0
- package/dist/editor/comments/EntryComments.d.ts +10 -4
- package/dist/editor/comments/EntryComments.js +14 -17
- package/dist/editor/comments/FieldWrapper.d.ts +18 -4
- package/dist/editor/comments/FieldWrapper.js +62 -28
- package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
- package/dist/editor/comments/InlineCommentThread.js +11 -47
- package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
- package/dist/editor/comments/ThreadCarousel.js +18 -21
- package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
- package/dist/editor/comments/ThreadReplyControls.js +92 -0
- package/dist/editor/comments/field-comment-context.d.ts +14 -0
- package/dist/editor/comments/field-comment-context.js +14 -0
- package/dist/editor/comments/form-comments.d.ts +48 -0
- package/dist/editor/comments/form-comments.js +178 -0
- package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
- package/dist/editor/comments/item-anchor-copy.js +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
- package/dist/editor/comments/popover-placement.d.ts +18 -0
- package/dist/editor/comments/popover-placement.js +58 -0
- package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
- package/dist/editor/comments/use-tracked-writes.js +53 -0
- package/dist/editor/components/BranchAccessList.d.ts +15 -0
- package/dist/editor/components/BranchAccessList.js +52 -0
- package/dist/editor/components/BranchLockBanner.d.ts +22 -0
- package/dist/editor/components/BranchLockBanner.js +39 -0
- package/dist/editor/components/BranchPill.d.ts +32 -0
- package/dist/editor/components/BranchPill.js +33 -0
- package/dist/editor/components/BranchesDrawer.d.ts +11 -0
- package/dist/editor/components/BranchesDrawer.js +5 -0
- package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
- package/dist/editor/components/ConfirmDeleteModal.js +3 -2
- package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
- package/dist/editor/components/DestructiveMenuItem.js +8 -0
- package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
- package/dist/editor/components/EditorCrashScreen.js +22 -0
- package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
- package/dist/editor/components/EditorErrorBoundary.js +40 -0
- package/dist/editor/components/EditorHeader.d.ts +56 -106
- package/dist/editor/components/EditorHeader.js +130 -131
- package/dist/editor/components/EditorRail.d.ts +49 -0
- package/dist/editor/components/EditorRail.js +65 -0
- package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
- package/dist/editor/components/EntryBreadcrumb.js +56 -0
- package/dist/editor/components/EntryCreateModal.d.ts +12 -7
- package/dist/editor/components/EntryCreateModal.js +51 -57
- package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
- package/dist/editor/components/NoEditPermissionNotice.js +5 -4
- package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
- package/dist/editor/components/QuickOpenPalette.js +66 -0
- package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
- package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
- package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
- package/dist/editor/components/ReasonedMenuItem.js +15 -0
- package/dist/editor/components/ReferencedByList.d.ts +11 -0
- package/dist/editor/components/ReferencedByList.js +28 -0
- package/dist/editor/components/RelativeTime.d.ts +10 -0
- package/dist/editor/components/RelativeTime.js +10 -0
- package/dist/editor/components/RenameEntryModal.d.ts +9 -1
- package/dist/editor/components/RenameEntryModal.js +19 -31
- package/dist/editor/components/RetryToastMessage.d.ts +9 -0
- package/dist/editor/components/RetryToastMessage.js +6 -0
- package/dist/editor/components/SaveAllResult.d.ts +25 -0
- package/dist/editor/components/SaveAllResult.js +86 -0
- package/dist/editor/components/SaveSplitButton.d.ts +30 -0
- package/dist/editor/components/SaveSplitButton.js +108 -0
- package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
- package/dist/editor/components/StagedChangesDrawer.js +92 -0
- package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
- package/dist/editor/components/UnavailableEntryNotice.js +9 -0
- package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
- package/dist/editor/components/UnavailableTypeMessage.js +9 -0
- package/dist/editor/components/UndoToastMessage.d.ts +18 -0
- package/dist/editor/components/UndoToastMessage.js +10 -0
- package/dist/editor/components/UserBadge.d.ts +2 -5
- package/dist/editor/components/UserBadge.js +62 -33
- package/dist/editor/components/ValidationSummary.d.ts +14 -0
- package/dist/editor/components/ValidationSummary.js +24 -0
- package/dist/editor/components/index.d.ts +2 -2
- package/dist/editor/components/index.js +2 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -2
- package/dist/editor/context/ApiClientContext.js +19 -8
- package/dist/editor/context/AssetContext.d.ts +13 -35
- package/dist/editor/context/AssetContext.js +12 -31
- package/dist/editor/context/EditorStateContext.d.ts +4 -4
- package/dist/editor/context/EditorStateContext.js +4 -4
- package/dist/editor/context/SWRProvider.d.ts +3 -3
- package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
- package/dist/editor/context/SiteMdxAllowContext.js +7 -0
- package/dist/editor/context/index.d.ts +2 -1
- package/dist/editor/context/index.js +2 -1
- package/dist/editor/contrast.d.ts +19 -0
- package/dist/editor/contrast.js +41 -0
- package/dist/editor/copy.d.ts +18 -0
- package/dist/editor/copy.js +18 -0
- package/dist/editor/editor-config.js +16 -0
- package/dist/editor/editor-utils.d.ts +34 -8
- package/dist/editor/editor-utils.js +42 -20
- package/dist/editor/entry-search.d.ts +20 -0
- package/dist/editor/entry-search.js +34 -0
- package/dist/editor/field-breadcrumb.d.ts +12 -0
- package/dist/editor/field-breadcrumb.js +85 -0
- package/dist/editor/field-props.d.ts +86 -0
- package/dist/editor/field-props.js +27 -0
- package/dist/editor/field-target.d.ts +30 -0
- package/dist/editor/field-target.js +77 -0
- package/dist/editor/fields/BlockField.d.ts +12 -0
- package/dist/editor/fields/BlockField.js +89 -73
- package/dist/editor/fields/CodeField.d.ts +2 -0
- package/dist/editor/fields/CodeField.js +6 -2
- package/dist/editor/fields/DateTimeField.d.ts +4 -29
- package/dist/editor/fields/DateTimeField.js +79 -41
- package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
- package/dist/editor/fields/ExpandAllButton.js +4 -0
- package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
- package/dist/editor/fields/FieldCrashFallback.js +30 -0
- package/dist/editor/fields/FieldLabel.d.ts +37 -0
- package/dist/editor/fields/FieldLabel.js +19 -0
- package/dist/editor/fields/ImageField.d.ts +4 -0
- package/dist/editor/fields/ImageField.js +29 -14
- package/dist/editor/fields/InlineGroupField.js +4 -3
- package/dist/editor/fields/ItemList.d.ts +42 -0
- package/dist/editor/fields/ItemList.js +130 -0
- package/dist/editor/fields/MarkdownField.d.ts +32 -0
- package/dist/editor/fields/MarkdownField.js +223 -46
- package/dist/editor/fields/MdxImageDialog.js +1 -1
- package/dist/editor/fields/NumberField.d.ts +2 -0
- package/dist/editor/fields/NumberField.js +8 -5
- package/dist/editor/fields/NumberListField.d.ts +2 -0
- package/dist/editor/fields/NumberListField.js +19 -16
- package/dist/editor/fields/ObjectField.d.ts +2 -7
- package/dist/editor/fields/ObjectField.js +15 -5
- package/dist/editor/fields/ObjectListField.d.ts +29 -0
- package/dist/editor/fields/ObjectListField.js +57 -0
- package/dist/editor/fields/ReferenceField.d.ts +2 -0
- package/dist/editor/fields/ReferenceField.js +34 -9
- package/dist/editor/fields/SelectField.d.ts +2 -0
- package/dist/editor/fields/SelectField.js +11 -2
- package/dist/editor/fields/StringListField.d.ts +4 -1
- package/dist/editor/fields/StringListField.js +22 -8
- package/dist/editor/fields/TextField.d.ts +2 -0
- package/dist/editor/fields/TextField.js +6 -2
- package/dist/editor/fields/ToggleField.d.ts +2 -0
- package/dist/editor/fields/ToggleField.js +8 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
- package/dist/editor/fields/form-expansion.d.ts +9 -0
- package/dist/editor/fields/form-expansion.js +2 -0
- package/dist/editor/fields/item-expansion.d.ts +15 -0
- package/dist/editor/fields/item-expansion.js +60 -0
- package/dist/editor/fields/list-item-keys.d.ts +8 -0
- package/dist/editor/fields/list-item-keys.js +50 -0
- package/dist/editor/fields/list-item-title.d.ts +20 -0
- package/dist/editor/fields/list-item-title.js +85 -0
- package/dist/editor/fields/markdown-export-options.d.ts +2 -0
- package/dist/editor/fields/markdown-export-options.js +8 -0
- package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
- package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
- package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
- package/dist/editor/fields/mdx-jsx-support.js +157 -69
- package/dist/editor/fields/rich-text-failures.d.ts +5 -0
- package/dist/editor/fields/rich-text-failures.js +26 -0
- package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
- package/dist/editor/fields/toolbar-wrap.js +35 -0
- package/dist/editor/form-outline.d.ts +13 -0
- package/dist/editor/form-outline.js +70 -0
- package/dist/editor/group-manager/GroupCard.d.ts +4 -1
- package/dist/editor/group-manager/GroupCard.js +12 -3
- package/dist/editor/group-manager/GroupForm.js +1 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
- package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
- package/dist/editor/group-manager/MemberList.d.ts +2 -1
- package/dist/editor/group-manager/MemberList.js +15 -4
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
- package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
- package/dist/editor/group-manager/index.js +34 -5
- package/dist/editor/group-manager/types.d.ts +5 -2
- package/dist/editor/hooks/create-branch-request.d.ts +20 -0
- package/dist/editor/hooks/create-branch-request.js +54 -0
- package/dist/editor/hooks/save-all.d.ts +68 -0
- package/dist/editor/hooks/save-all.js +61 -0
- package/dist/editor/hooks/useBranchActions.d.ts +11 -1
- package/dist/editor/hooks/useBranchActions.js +42 -19
- package/dist/editor/hooks/useBranchManager.d.ts +21 -0
- package/dist/editor/hooks/useBranchManager.js +321 -125
- package/dist/editor/hooks/useBranchesData.d.ts +8 -4
- package/dist/editor/hooks/useBranchesData.js +9 -5
- package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
- package/dist/editor/hooks/useCommentSystem.js +79 -55
- package/dist/editor/hooks/useCommentsData.d.ts +11 -7
- package/dist/editor/hooks/useCommentsData.js +20 -19
- package/dist/editor/hooks/useDraftManager.d.ts +77 -3
- package/dist/editor/hooks/useDraftManager.js +887 -94
- package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
- package/dist/editor/hooks/useEditorLayout.js +98 -20
- package/dist/editor/hooks/useEntriesData.d.ts +2 -1
- package/dist/editor/hooks/useEntriesData.js +18 -4
- package/dist/editor/hooks/useEntryManager.d.ts +41 -2
- package/dist/editor/hooks/useEntryManager.js +227 -41
- package/dist/editor/hooks/useGroupManager.js +13 -16
- package/dist/editor/hooks/usePermissionManager.js +14 -6
- package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
- package/dist/editor/hooks/usePreviewMarks.js +33 -0
- package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
- package/dist/editor/hooks/useReferenceResolution.js +34 -177
- package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
- package/dist/editor/hooks/useSchemaManager.js +97 -39
- package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
- package/dist/editor/hooks/useUserMetadata.js +76 -47
- package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
- package/dist/editor/hooks/user-metadata-batcher.js +33 -0
- package/dist/editor/media/AssetCard.d.ts +6 -7
- package/dist/editor/media/AssetCard.js +24 -31
- package/dist/editor/media/AssetListRow.d.ts +16 -0
- package/dist/editor/media/AssetListRow.js +41 -0
- package/dist/editor/media/CropStep.js +6 -1
- package/dist/editor/media/MediaLibrary.d.ts +4 -3
- package/dist/editor/media/MediaLibrary.js +11 -4
- package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
- package/dist/editor/media/MediaLibraryBody.js +195 -80
- package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
- package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
- package/dist/editor/media/crop-math.d.ts +3 -4
- package/dist/editor/media/crop-math.js +11 -22
- package/dist/editor/media/editor-image-src.d.ts +8 -0
- package/dist/editor/media/editor-image-src.js +10 -0
- package/dist/editor/media/format-bytes.d.ts +2 -0
- package/dist/editor/media/format-bytes.js +23 -0
- package/dist/editor/media/media-library-prefs.d.ts +23 -0
- package/dist/editor/media/media-library-prefs.js +49 -0
- package/dist/editor/media/media-library-view.d.ts +34 -0
- package/dist/editor/media/media-library-view.js +40 -0
- package/dist/editor/media/useAssetLibrary.d.ts +30 -0
- package/dist/editor/media/useAssetLibrary.js +126 -0
- package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
- package/dist/editor/media/useStableAssetOrder.js +37 -0
- package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
- package/dist/editor/media/useThumbnailFailure.js +16 -0
- package/dist/editor/permission-manager/GroupSelector.js +2 -2
- package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
- package/dist/editor/permission-manager/PermissionEditor.js +15 -4
- package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
- package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.js +3 -3
- package/dist/editor/permission-manager/index.js +12 -3
- package/dist/editor/permission-manager/types.d.ts +5 -2
- package/dist/editor/platform.d.ts +3 -0
- package/dist/editor/platform.js +9 -0
- package/dist/editor/preview-asset-base.d.ts +9 -0
- package/dist/editor/preview-asset-base.js +17 -0
- package/dist/editor/preview-bridge.d.ts +51 -27
- package/dist/editor/preview-bridge.js +103 -144
- package/dist/editor/preview-marks.d.ts +15 -0
- package/dist/editor/preview-marks.js +74 -0
- package/dist/editor/preview-path.d.ts +12 -0
- package/dist/editor/preview-path.js +45 -1
- package/dist/editor/preview-scale.d.ts +27 -0
- package/dist/editor/preview-scale.js +34 -0
- package/dist/editor/raw-asset-base.d.ts +5 -0
- package/dist/editor/raw-asset-base.js +14 -0
- package/dist/editor/relative-time.d.ts +4 -4
- package/dist/editor/relative-time.js +16 -8
- package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
- package/dist/editor/schema-editor/CollectionEditor.js +361 -62
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
- package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
- package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
- package/dist/editor/schema-editor/collection-draft.js +40 -0
- package/dist/editor/schema-editor/index.d.ts +1 -1
- package/dist/editor/schema-label.d.ts +10 -0
- package/dist/editor/schema-label.js +17 -0
- package/dist/editor/settings-conflict.d.ts +5 -0
- package/dist/editor/settings-conflict.js +8 -0
- package/dist/editor/shell/ActivityRail.d.ts +37 -0
- package/dist/editor/shell/ActivityRail.js +91 -0
- package/dist/editor/shell/EditorShell.d.ts +17 -0
- package/dist/editor/shell/EditorShell.js +31 -0
- package/dist/editor/shell/PaneLayout.d.ts +28 -0
- package/dist/editor/shell/PaneLayout.js +116 -0
- package/dist/editor/shell/SidePanelHost.d.ts +35 -0
- package/dist/editor/shell/SidePanelHost.js +184 -0
- package/dist/editor/shell/TopBar.d.ts +12 -0
- package/dist/editor/shell/TopBar.js +14 -0
- package/dist/editor/shell/host-chrome.d.ts +16 -0
- package/dist/editor/shell/host-chrome.js +69 -0
- package/dist/editor/slug.d.ts +16 -0
- package/dist/editor/slug.js +43 -0
- package/dist/editor/theme.d.ts +2 -1
- package/dist/editor/theme.js +314 -13
- package/dist/editor/unanswered.d.ts +17 -0
- package/dist/editor/unanswered.js +26 -0
- package/dist/editor/unavailable-entry-type.d.ts +20 -0
- package/dist/editor/unavailable-entry-type.js +28 -0
- package/dist/editor/undo-removal.d.ts +57 -0
- package/dist/editor/undo-removal.js +163 -0
- package/dist/editor/user-display.d.ts +4 -0
- package/dist/editor/user-display.js +5 -0
- package/dist/editor/utils/confirm-modal.d.ts +8 -0
- package/dist/editor/utils/confirm-modal.js +12 -0
- package/dist/editor/utils/editor-errors.d.ts +19 -0
- package/dist/editor/utils/editor-errors.js +32 -0
- package/dist/editor/utils/focus-return.d.ts +56 -0
- package/dist/editor/utils/focus-return.js +106 -0
- package/dist/entry-link-resolver.d.ts +11 -1
- package/dist/entry-link-resolver.js +65 -5
- package/dist/entry-schema-registry.d.ts +3 -3
- package/dist/entry-schema-registry.js +7 -4
- package/dist/entry-schema.d.ts +49 -3
- package/dist/entry-schema.js +18 -0
- package/dist/git-manager.d.ts +172 -10
- package/dist/git-manager.js +449 -107
- package/dist/github-service.d.ts +39 -2
- package/dist/github-service.js +101 -7
- package/dist/http/handler.js +74 -9
- package/dist/http/types.d.ts +2 -0
- package/dist/http/worker-not-ready.d.ts +9 -4
- package/dist/http/worker-not-ready.js +59 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/item-keys.d.ts +46 -0
- package/dist/item-keys.js +235 -0
- package/dist/operating-mode/editor-mode-check.d.ts +15 -0
- package/dist/operating-mode/editor-mode-check.js +24 -0
- package/dist/operating-mode/mode-env.d.ts +13 -14
- package/dist/operating-mode/mode-env.js +13 -14
- package/dist/operating-mode/types.d.ts +2 -2
- package/dist/paths/branch.d.ts +0 -1
- package/dist/paths/branch.js +1 -8
- package/dist/paths/index.d.ts +1 -1
- package/dist/paths/index.js +1 -1
- package/dist/paths/validation.js +0 -2
- package/dist/preview.d.ts +8 -0
- package/dist/preview.js +7 -0
- package/dist/reference-resolver.js +1 -0
- package/dist/resolve-canopy-user.d.ts +1 -1
- package/dist/resolve-canopy-user.js +1 -1
- package/dist/schema/meta-loader.d.ts +18 -8
- package/dist/schema/meta-loader.js +42 -9
- package/dist/schema/registry-fingerprint.d.ts +14 -0
- package/dist/schema/registry-fingerprint.js +63 -0
- package/dist/schema/resolver.d.ts +7 -4
- package/dist/schema/resolver.js +7 -6
- package/dist/schema/schema-store.d.ts +7 -10
- package/dist/schema/schema-store.js +13 -11
- package/dist/schema/schema-unavailable-error.d.ts +11 -0
- package/dist/schema/schema-unavailable-error.js +15 -0
- package/dist/schema/types.d.ts +22 -0
- package/dist/schema-registry-record.d.ts +35 -0
- package/dist/schema-registry-record.js +134 -0
- package/dist/server.d.ts +79 -9
- package/dist/server.js +62 -8
- package/dist/services.d.ts +33 -5
- package/dist/services.js +155 -37
- package/dist/settings-workspace.d.ts +23 -3
- package/dist/settings-workspace.js +159 -45
- package/dist/stamp-on-publish.d.ts +36 -0
- package/dist/stamp-on-publish.js +71 -0
- package/dist/static/index.d.ts +58 -5
- package/dist/static/index.js +133 -3
- package/dist/static/seo.d.ts +5 -5
- package/dist/static/seo.js +5 -5
- package/dist/submission-attribution.d.ts +8 -0
- package/dist/submission-attribution.js +22 -0
- package/dist/system-users.d.ts +12 -0
- package/dist/system-users.js +12 -0
- package/dist/task-queue/cms-task-queue.d.ts +1 -1
- package/dist/task-queue/cms-task-queue.js +1 -1
- package/dist/task-queue/index.d.ts +1 -1
- package/dist/task-queue/index.js +1 -1
- package/dist/task-queue/task-queue.d.ts +6 -0
- package/dist/task-queue/task-queue.js +29 -0
- package/dist/task-queue/worker-status.d.ts +35 -9
- package/dist/task-queue/worker-status.js +84 -17
- package/dist/types.d.ts +90 -9
- package/dist/url-collision.js +3 -3
- package/dist/url-exclusivity-fixtures.d.ts +8 -1
- package/dist/url-exclusivity-fixtures.js +11 -1
- package/dist/user.js +2 -1
- package/dist/utils/atomic-write.js +2 -1
- package/dist/utils/base-branch.d.ts +13 -0
- package/dist/utils/base-branch.js +23 -0
- package/dist/utils/content-serialize.d.ts +15 -7
- package/dist/utils/content-serialize.js +353 -51
- package/dist/utils/content-write-lock.d.ts +6 -1
- package/dist/utils/content-write-lock.js +21 -6
- package/dist/utils/debug.d.ts +1 -1
- package/dist/utils/debug.js +5 -3
- package/dist/utils/error.js +13 -2
- package/dist/utils/escape-text.d.ts +7 -0
- package/dist/utils/escape-text.js +27 -0
- package/dist/utils/fs.d.ts +12 -4
- package/dist/utils/fs.js +18 -5
- package/dist/utils/git.d.ts +21 -1
- package/dist/utils/git.js +63 -8
- package/dist/utils/json-source-splice.d.ts +14 -0
- package/dist/utils/json-source-splice.js +120 -0
- package/dist/utils/markdown-body-splice.d.ts +39 -0
- package/dist/utils/markdown-body-splice.js +421 -0
- package/dist/utils/occ-json-write.js +18 -12
- package/dist/utils/provision-log.d.ts +25 -0
- package/dist/utils/provision-log.js +49 -0
- package/dist/utils/provisioning-lock.d.ts +32 -1
- package/dist/utils/provisioning-lock.js +78 -32
- package/dist/utils/sanitize-href.d.ts +9 -23
- package/dist/utils/sanitize-href.js +14 -28
- package/dist/utils/title-field.d.ts +10 -0
- package/dist/utils/title-field.js +47 -0
- package/dist/utils/yaml-source-splice.d.ts +58 -0
- package/dist/utils/yaml-source-splice.js +515 -0
- package/dist/validation/block-structural-keys.d.ts +1 -1
- package/dist/validation/block-structural-keys.js +1 -1
- package/dist/validation/deletion-checker.d.ts +21 -29
- package/dist/validation/deletion-checker.js +41 -117
- package/dist/validation/entry-validator.d.ts +6 -10
- package/dist/validation/entry-validator.js +19 -26
- package/dist/validation/field-traversal.d.ts +22 -0
- package/dist/validation/field-traversal.js +39 -8
- package/dist/validation/markdown-safety.d.ts +68 -0
- package/dist/validation/markdown-safety.js +596 -0
- package/dist/validation/mdx-allowlist.d.ts +55 -0
- package/dist/validation/mdx-allowlist.js +183 -0
- package/dist/validation/reference-validator.d.ts +2 -0
- package/dist/validation/reference-validator.js +3 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/branch-policy.d.ts +124 -0
- package/dist/worker/branch-policy.js +243 -0
- package/dist/worker/bundle-header.d.ts +117 -0
- package/dist/worker/bundle-header.js +253 -0
- package/dist/worker/cms-worker.d.ts +236 -142
- package/dist/worker/cms-worker.js +772 -285
- package/dist/worker/gateway-egress.d.ts +43 -0
- package/dist/worker/gateway-egress.js +209 -0
- package/dist/worker/gateway-instance.d.ts +42 -0
- package/dist/worker/gateway-instance.js +129 -0
- package/dist/worker/git-process.d.ts +81 -0
- package/dist/worker/git-process.js +234 -0
- package/dist/worker/git-sync.d.ts +34 -17
- package/dist/worker/git-sync.js +394 -131
- package/dist/worker/github-auth.d.ts +9 -9
- package/dist/worker/github-auth.js +13 -15
- package/dist/worker/github-gateway-http.d.ts +62 -0
- package/dist/worker/github-gateway-http.js +977 -0
- package/dist/worker/github-gateway-wire.d.ts +590 -0
- package/dist/worker/github-gateway-wire.js +488 -0
- package/dist/worker/github-gateway.d.ts +238 -0
- package/dist/worker/github-gateway.js +726 -0
- package/dist/worker/github-mirror-upkeep.d.ts +75 -0
- package/dist/worker/github-mirror-upkeep.js +266 -0
- package/dist/worker/github-mirror.d.ts +364 -0
- package/dist/worker/github-mirror.js +1030 -0
- package/dist/worker/github-transfer.d.ts +56 -0
- package/dist/worker/github-transfer.js +444 -0
- package/dist/worker/history-rewrite.d.ts +4 -5
- package/dist/worker/history-rewrite.js +12 -17
- package/dist/worker/provisioned-workspace.d.ts +5 -5
- package/dist/worker/provisioned-workspace.js +5 -5
- package/dist/worker/rebase.d.ts +1 -1
- package/dist/worker/rebase.js +58 -54
- package/dist/worker/remote-git-maintenance.d.ts +3 -0
- package/dist/worker/remote-git-maintenance.js +12 -0
- package/dist/worker/schema-gate.d.ts +49 -0
- package/dist/worker/schema-gate.js +226 -0
- package/dist/worker/self-checks.d.ts +107 -0
- package/dist/worker/self-checks.js +358 -0
- package/dist/worker/shared-repo-git.d.ts +96 -0
- package/dist/worker/shared-repo-git.js +459 -0
- package/dist/worker/sparse-cone.d.ts +20 -0
- package/dist/worker/sparse-cone.js +136 -0
- package/dist/worker/stale-mirror.d.ts +82 -0
- package/dist/worker/stale-mirror.js +130 -0
- package/dist/worker/task-runner.d.ts +5 -3
- package/dist/worker/task-runner.js +287 -186
- package/dist/worker/worker-context.d.ts +36 -37
- package/package.json +35 -7
- package/dist/editor/EditorPanes.d.ts +0 -10
- package/dist/editor/EditorPanes.js +0 -98
- package/dist/editor/components/EditorFooter.d.ts +0 -11
- package/dist/editor/components/EditorFooter.js +0 -9
- package/dist/editor/components/EditorSidebar.d.ts +0 -67
- package/dist/editor/components/EditorSidebar.js +0 -22
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { useSWRConfig } from 'swr';
|
|
5
|
-
import { Text } from '@mantine/core';
|
|
6
|
-
import {
|
|
5
|
+
import { Alert, Stack, Text } from '@mantine/core';
|
|
6
|
+
import { IconAlertTriangle } from '@tabler/icons-react';
|
|
7
|
+
import { openConfirm } from '../utils/confirm-modal.js';
|
|
8
|
+
import { EDITOR_ACTIONS } from '../copy.js';
|
|
7
9
|
import { notifications } from '@mantine/notifications';
|
|
8
10
|
import { useApiClient } from '../context/index.js';
|
|
9
11
|
import { BRANCHES_KEY, fetchBranches, useBranchesData } from './useBranchesData.js';
|
|
@@ -12,6 +14,18 @@ import { BRANCHES_KEY, fetchBranches, useBranchesData } from './useBranchesData.
|
|
|
12
14
|
// which breaks adopters' production `next build` of the editor bundle.
|
|
13
15
|
// paths/branch-name.ts is the dependency-free home of sanitizeBranchName.
|
|
14
16
|
import { sanitizeBranchName } from '../../paths/branch-name.js';
|
|
17
|
+
import { RetryToastMessage } from '../components/RetryToastMessage.js';
|
|
18
|
+
import { isNonApiResponse } from '../../api/client.js';
|
|
19
|
+
import { isGatewayFailure, isUnanswered, UnansweredError } from '../unanswered.js';
|
|
20
|
+
import { describeUnsaved } from './useBranchActions.js';
|
|
21
|
+
const BRANCHES_LOAD_FAILED_TOAST_ID = 'canopy-branches-load-failed';
|
|
22
|
+
const BRANCH_OUTCOME_UNKNOWN_TOAST_ID = 'canopy-branch-outcome-unknown';
|
|
23
|
+
/** The error a refused branch action throws; a gateway's 5xx says nothing of whether it ran. */
|
|
24
|
+
function actionError(result, fallback) {
|
|
25
|
+
return isGatewayFailure(result) ? new UnansweredError() : new Error(result.error || fallback);
|
|
26
|
+
}
|
|
27
|
+
/** @internal Exported for tests. */
|
|
28
|
+
export const branchActionOutcomeUnknown = (action) => `${action} may have gone through even though the server didn't answer. Check the branch's status before trying again.`;
|
|
15
29
|
/**
|
|
16
30
|
* Wire a confirm modal's exits so exactly ONE of {confirmed, dismissed} runs,
|
|
17
31
|
* whichever happens first.
|
|
@@ -24,6 +38,9 @@ import { sanitizeBranchName } from '../../paths/branch-name.js';
|
|
|
24
38
|
* handler would settle the caller's promise before the confirmed work had
|
|
25
39
|
* even run. Claiming the first exit resolves both.
|
|
26
40
|
*/
|
|
41
|
+
const submittedMessage = (stampedCount) => stampedCount === 0
|
|
42
|
+
? 'Branch submitted for review'
|
|
43
|
+
: `Branch submitted for review. Dates set on ${stampedCount} new ${stampedCount === 1 ? 'entry' : 'entries'}.`;
|
|
27
44
|
const confirmModalHandlers = (onConfirm, onDismiss) => {
|
|
28
45
|
let settled = false;
|
|
29
46
|
const claim = () => {
|
|
@@ -49,40 +66,84 @@ const confirmModalHandlers = (onConfirm, onDismiss) => {
|
|
|
49
66
|
},
|
|
50
67
|
};
|
|
51
68
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
/**
|
|
70
|
+
* With `unsaved` edits on the branch, the dialog says they are left out: a submit sends only what
|
|
71
|
+
* is saved, and the branch is read-only in review, so they wait as drafts until it is editable.
|
|
72
|
+
*/
|
|
73
|
+
const showSubmitConfirmation = (branchName, unsaved, onConfirm, onDismiss) => {
|
|
74
|
+
const leftOut = unsaved && unsaved.count > 0 ? unsaved : undefined;
|
|
75
|
+
openConfirm({
|
|
76
|
+
title: EDITOR_ACTIONS.submitForReview,
|
|
77
|
+
children: (_jsxs(Stack, { gap: "sm", children: [leftOut && (_jsxs(Alert, { color: "yellow", icon: _jsx(IconAlertTriangle, { size: 16 }), title: `${leftOut.count} ${leftOut.count === 1 ? "entry has unsaved changes that won't" : "entries have unsaved changes that won't"} be submitted`, "data-testid": "submit-unsaved-warning", children: [describeUnsaved(leftOut), " To include them, cancel and save first. If you submit now, those changes stay unsaved on this branch while it is in review."] })), _jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Submit "${branchName}" for review?\n\nThis will:\n• Create a pull request for review\n• Change the branch status to "In review"\n• Notify reviewers of pending changes` })] })),
|
|
78
|
+
labels: {
|
|
79
|
+
confirm: leftOut ? 'Submit anyway' : EDITOR_ACTIONS.submitForReview,
|
|
80
|
+
cancel: 'Cancel',
|
|
81
|
+
},
|
|
82
|
+
confirmProps: { color: 'brand', 'data-testid': 'confirm-submit-branch' },
|
|
58
83
|
...confirmModalHandlers(onConfirm, onDismiss),
|
|
59
84
|
});
|
|
60
85
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
86
|
+
/**
|
|
87
|
+
* The withdraw dialog's pull-request bullet, matching what api/branch-withdraw.ts does: an open
|
|
88
|
+
* PR becomes a draft; a closed one is left alone and its number dropped from the branch, so a
|
|
89
|
+
* resubmit opens a new one. A merged PR archives its branch, which withdraw refuses, so that
|
|
90
|
+
* bullet is only seen on a listing that lags.
|
|
91
|
+
* @internal Exported for tests.
|
|
92
|
+
*/
|
|
93
|
+
export function withdrawPullRequestBullet(pr) {
|
|
94
|
+
if (!pr.pullRequestNumber)
|
|
95
|
+
return undefined;
|
|
96
|
+
const label = `pull request #${pr.pullRequestNumber}`;
|
|
97
|
+
if (pr.pullRequestState === 'closed') {
|
|
98
|
+
return `Leave the closed ${label} as it is; submitting again opens a new one`;
|
|
99
|
+
}
|
|
100
|
+
if (pr.pullRequestState === 'merged')
|
|
101
|
+
return `Leave the merged ${label} as it is`;
|
|
102
|
+
return `Convert ${label} to a draft`;
|
|
103
|
+
}
|
|
104
|
+
const showWithdrawConfirmation = (branchName, pr, onConfirm, onDismiss) => {
|
|
105
|
+
const bullets = [
|
|
106
|
+
withdrawPullRequestBullet(pr),
|
|
107
|
+
'Change the branch status back to "editing"',
|
|
108
|
+
'Remove from review queue',
|
|
109
|
+
].filter((b) => b !== undefined);
|
|
110
|
+
openConfirm({
|
|
111
|
+
title: EDITOR_ACTIONS.withdrawFromReview,
|
|
112
|
+
children: (_jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Withdraw "${branchName}" from review?\n\nThis will:\n${bullets.map((b) => `• ${b}`).join('\n')}` })),
|
|
113
|
+
labels: { confirm: EDITOR_ACTIONS.withdrawFromReview, cancel: 'Cancel' },
|
|
114
|
+
confirmProps: { color: 'orange', 'data-testid': 'confirm-withdraw-branch' },
|
|
115
|
+
...confirmModalHandlers(onConfirm, onDismiss),
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const showRequestChangesConfirmation = (branchName, onConfirm, onDismiss) => {
|
|
119
|
+
openConfirm({
|
|
120
|
+
title: EDITOR_ACTIONS.requestChanges,
|
|
121
|
+
children: (_jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Send "${branchName}" back to its editor?\n\nThis will:\n• Change the branch status back to "editing"\n• Let its editor change it and submit again` })),
|
|
122
|
+
labels: { confirm: EDITOR_ACTIONS.requestChanges, cancel: 'Cancel' },
|
|
123
|
+
confirmProps: { color: 'red', 'data-testid': 'confirm-request-changes' },
|
|
67
124
|
...confirmModalHandlers(onConfirm, onDismiss),
|
|
68
125
|
});
|
|
69
126
|
};
|
|
70
127
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* `
|
|
75
|
-
* anywhere in the chain (BranchManager.tsx's delete button calls `onDelete`
|
|
76
|
-
* directly), while submit and withdraw -- both reversible -- each went
|
|
77
|
-
* through this same `modals.openConfirmModal` pattern. This closes that gap;
|
|
78
|
-
* `color: 'red'` marks it as the destructive one, matching the button's own
|
|
79
|
-
* color in BranchManager.tsx.
|
|
128
|
+
* Delete is the one irreversible branch action: it unlinks branch.json and removes the clone,
|
|
129
|
+
* the local mirror's head and, for a branch with a PR, the GitHub branch. BranchManager.tsx's
|
|
130
|
+
* delete menu item calls `onDelete` directly, so this dialog is the only confirmation; `color:
|
|
131
|
+
* 'red'` matches that item.
|
|
80
132
|
*/
|
|
81
|
-
const showDeleteConfirmation = (branchName, onConfirm, onDismiss) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
133
|
+
const showDeleteConfirmation = (branchName, pr, onConfirm, onDismiss) => {
|
|
134
|
+
// The server deletes the GitHub branch only for a branch with a PR (api/github-sync.ts's
|
|
135
|
+
// syncDeleteRemoteBranch); GitHub closes a PR whose branch is deleted.
|
|
136
|
+
const bullets = [
|
|
137
|
+
'Permanently remove the branch and its clone',
|
|
138
|
+
pr.pullRequestNumber
|
|
139
|
+
? `Delete its branch on GitHub too, which closes pull request #${pr.pullRequestNumber} if it is still open`
|
|
140
|
+
: undefined,
|
|
141
|
+
'Discard any unsaved or unmerged changes',
|
|
142
|
+
].filter((b) => b !== undefined);
|
|
143
|
+
openConfirm({
|
|
144
|
+
title: 'Delete branch',
|
|
145
|
+
children: (_jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Delete "${branchName}"?\n\nThis will:\n${bullets.map((b) => `• ${b}`).join('\n')}\n\nThis cannot be undone.` })),
|
|
146
|
+
labels: { confirm: 'Delete branch', cancel: 'Cancel' },
|
|
86
147
|
// data-testid is load-bearing, not decoration: the e2e helper
|
|
87
148
|
// (apps/test-app/e2e/fixtures/branch-page.ts's deleteBranch) already
|
|
88
149
|
// anticipated a delete confirmation and clicks
|
|
@@ -137,7 +198,7 @@ function reconcilePendingBranches(pending, listed, receivedAt) {
|
|
|
137
198
|
*/
|
|
138
199
|
export function useBranchManager(options) {
|
|
139
200
|
const apiClient = useApiClient();
|
|
140
|
-
const { mutate: globalMutate } = useSWRConfig();
|
|
201
|
+
const { cache, mutate: globalMutate } = useSWRConfig();
|
|
141
202
|
const [branchName, setBranchName] = useState(options.initialBranch);
|
|
142
203
|
const { data: branchesData, error: branchesError, isValidating: branchesIsValidating, } = useBranchesData(apiClient);
|
|
143
204
|
const [pendingBranches, setPendingBranches] = useState([]);
|
|
@@ -148,15 +209,25 @@ export function useBranchManager(options) {
|
|
|
148
209
|
{ branch, addedAt: Date.now() },
|
|
149
210
|
]);
|
|
150
211
|
}, []);
|
|
151
|
-
// After a server-side change to a pending branch, its overlaid copy is stale,
|
|
152
|
-
// and a lagging listing would show it (a submitted branch as still writable).
|
|
153
|
-
// Forgetting it leaves the listings alone to decide, failing closed if they lag.
|
|
154
212
|
const forgetCreatedBranch = (name) => {
|
|
155
213
|
setPendingBranches((prev) => {
|
|
156
214
|
const kept = prev.filter((p) => p.branch.name !== name);
|
|
157
215
|
return kept.length === prev.length ? prev : kept;
|
|
158
216
|
});
|
|
159
217
|
};
|
|
218
|
+
// After a workflow action, a pending branch's overlaid copy is stale. The
|
|
219
|
+
// server's returned copy replaces it, so a listing that still lacks the
|
|
220
|
+
// branch shows its new status instead of hiding it; without one, forgetting
|
|
221
|
+
// it fails closed rather than showing the pre-action state.
|
|
222
|
+
const updateCreatedBranch = (name, branch) => {
|
|
223
|
+
if (!branch) {
|
|
224
|
+
forgetCreatedBranch(name);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
setPendingBranches((prev) => prev.some((p) => p.branch.name === name)
|
|
228
|
+
? prev.map((p) => (p.branch.name === name ? { ...p, branch } : p))
|
|
229
|
+
: prev);
|
|
230
|
+
};
|
|
160
231
|
// Each received listing is a new `branchesData` (see `BranchesData.receivedAt`);
|
|
161
232
|
// the grace window is measured to its arrival.
|
|
162
233
|
useEffect(() => {
|
|
@@ -170,25 +241,33 @@ export function useBranchManager(options) {
|
|
|
170
241
|
setBranchName(branchesData.defaultBranch);
|
|
171
242
|
}
|
|
172
243
|
}, [branchesData, branchName]);
|
|
244
|
+
// One toast, replaced on each failure (a shown id ignores `show`); sticky because the editor
|
|
245
|
+
// cannot function without the branch list.
|
|
246
|
+
const showBranchesLoadFailed = (message) => {
|
|
247
|
+
notifications.hide(BRANCHES_LOAD_FAILED_TOAST_ID);
|
|
248
|
+
notifications.show({
|
|
249
|
+
id: BRANCHES_LOAD_FAILED_TOAST_ID,
|
|
250
|
+
title: 'Could not load branches',
|
|
251
|
+
message: (_jsx(RetryToastMessage, { message: message, onRetry: () => {
|
|
252
|
+
notifications.hide(BRANCHES_LOAD_FAILED_TOAST_ID);
|
|
253
|
+
void reloadBranches();
|
|
254
|
+
} })),
|
|
255
|
+
color: 'red',
|
|
256
|
+
autoClose: false,
|
|
257
|
+
});
|
|
258
|
+
};
|
|
173
259
|
// Surfaces/clears the sticky error toast the same way loadBranches() does.
|
|
174
260
|
useEffect(() => {
|
|
175
261
|
if (branchesError) {
|
|
176
262
|
console.error(branchesError);
|
|
177
|
-
|
|
178
|
-
// Fixed id: retries update the existing toast instead of stacking; sticky
|
|
179
|
-
// because the editor cannot function without the branch list.
|
|
180
|
-
notifications.show({
|
|
181
|
-
id: 'canopy-branches-load-failed',
|
|
182
|
-
message,
|
|
183
|
-
color: 'red',
|
|
184
|
-
autoClose: false,
|
|
185
|
-
});
|
|
263
|
+
showBranchesLoadFailed(branchesError instanceof Error ? branchesError.message : 'Failed to load branches');
|
|
186
264
|
}
|
|
187
265
|
else if (branchesData) {
|
|
188
266
|
// A previous failure may have left the sticky error toast up; clear it
|
|
189
267
|
// now that loading succeeded (provisioning failures are often transient).
|
|
190
|
-
notifications.hide(
|
|
268
|
+
notifications.hide(BRANCHES_LOAD_FAILED_TOAST_ID);
|
|
191
269
|
}
|
|
270
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- showBranchesLoadFailed is new every render and reads nothing that changes
|
|
192
271
|
}, [branchesData, branchesError]);
|
|
193
272
|
// Mirrors the automatic load's in-flight state onto the shared busy flag,
|
|
194
273
|
// matching loadBranches()'s own setBusy bracket below for explicit reloads.
|
|
@@ -214,6 +293,9 @@ export function useBranchManager(options) {
|
|
|
214
293
|
access: {
|
|
215
294
|
users: b.access.allowedUsers,
|
|
216
295
|
groups: b.access.allowedGroups,
|
|
296
|
+
managerOrAdminAllowed: b.access.managerOrAdminAllowed,
|
|
297
|
+
withheldUsers: b.withheldAccess?.users,
|
|
298
|
+
withheldGroups: b.withheldAccess?.groups,
|
|
217
299
|
},
|
|
218
300
|
pullRequestUrl: b.pullRequestUrl,
|
|
219
301
|
pullRequestNumber: b.pullRequestNumber,
|
|
@@ -253,136 +335,250 @@ export function useBranchManager(options) {
|
|
|
253
335
|
// bound hook (and anything else reading BRANCHES_KEY) picks it up.
|
|
254
336
|
// Side effects (default-branch adoption, error/success notifications) are
|
|
255
337
|
// driven by the effects above, which react to that same cache write.
|
|
256
|
-
|
|
338
|
+
// Resolves to the fresh listing, or undefined when the fetch failed.
|
|
339
|
+
const reloadBranches = async () => {
|
|
257
340
|
options.setBusy(true);
|
|
258
341
|
try {
|
|
259
|
-
const fresh = await fetchBranches(apiClient);
|
|
342
|
+
const fresh = await fetchBranches(apiClient, { cache, mutate: globalMutate });
|
|
260
343
|
await globalMutate(BRANCHES_KEY, fresh, { revalidate: false });
|
|
344
|
+
return fresh;
|
|
261
345
|
}
|
|
262
346
|
catch (err) {
|
|
263
347
|
console.error(err);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
id: 'canopy-branches-load-failed',
|
|
267
|
-
message,
|
|
268
|
-
color: 'red',
|
|
269
|
-
autoClose: false,
|
|
270
|
-
});
|
|
348
|
+
showBranchesLoadFailed(err instanceof Error ? err.message : 'Failed to load branches');
|
|
349
|
+
return undefined;
|
|
271
350
|
}
|
|
272
351
|
finally {
|
|
273
352
|
options.setBusy(false);
|
|
274
353
|
}
|
|
275
354
|
};
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
355
|
+
const loadBranches = async () => {
|
|
356
|
+
await reloadBranches();
|
|
357
|
+
};
|
|
358
|
+
// The confirm dialogs' handlers run long after the render that opened them, so they read
|
|
359
|
+
// these at confirm time rather than from that render's closure.
|
|
360
|
+
const latest = useRef({ branchName, branches, branchesData });
|
|
361
|
+
latest.current = { branchName, branches, branchesData };
|
|
362
|
+
// A legacy deep link can carry the raw form of a listed name; the actions key, look up and
|
|
363
|
+
// send the listed name, resolved the way `currentBranch` resolves it.
|
|
364
|
+
const listedName = (name) => latest.current.branches.some((b) => b.name === name) ? name : sanitizeBranchName(name);
|
|
365
|
+
const pullRequestOf = (name) => {
|
|
366
|
+
const b = latest.current.branches.find((x) => x.name === name);
|
|
367
|
+
return { pullRequestNumber: b?.pullRequestNumber, pullRequestState: b?.pullRequestState };
|
|
368
|
+
};
|
|
369
|
+
// Keys of the actions whose confirm is open or whose work is in flight.
|
|
370
|
+
const actionsInFlight = useRef(new Set());
|
|
371
|
+
/**
|
|
372
|
+
* Runs `run` unless the same action on the same branch already has its confirm open or its
|
|
373
|
+
* work in flight; then this request opens nothing and resolves at once. Mantine closes only
|
|
374
|
+
* the confirm that was confirmed, so a second one opened by a repeated click would stay up
|
|
375
|
+
* after the action succeeded.
|
|
376
|
+
*/
|
|
377
|
+
const singleFlight = async (action, branch, run) => {
|
|
378
|
+
const key = JSON.stringify([action, branch]);
|
|
379
|
+
if (actionsInFlight.current.has(key))
|
|
380
|
+
return;
|
|
381
|
+
actionsInFlight.current.add(key);
|
|
382
|
+
try {
|
|
383
|
+
await run();
|
|
384
|
+
}
|
|
385
|
+
finally {
|
|
386
|
+
actionsInFlight.current.delete(key);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
// A workflow action that got no answer may have gone through, so the list reloads to show
|
|
390
|
+
// where the branch stands rather than inviting a blind retry.
|
|
391
|
+
const showOutcomeUnknown = (action) => {
|
|
392
|
+
notifications.hide(BRANCH_OUTCOME_UNKNOWN_TOAST_ID);
|
|
393
|
+
notifications.show({
|
|
394
|
+
id: BRANCH_OUTCOME_UNKNOWN_TOAST_ID,
|
|
395
|
+
message: branchActionOutcomeUnknown(action),
|
|
396
|
+
color: 'yellow',
|
|
397
|
+
autoClose: false,
|
|
398
|
+
withCloseButton: true,
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
const reportActionFailure = async (err, fallback, action) => {
|
|
402
|
+
if (isUnanswered(err)) {
|
|
403
|
+
showOutcomeUnknown(action);
|
|
404
|
+
await loadBranches();
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
notifications.show({ message: err instanceof Error ? err.message : fallback, color: 'red' });
|
|
408
|
+
};
|
|
409
|
+
const handleSubmit = (requested) => {
|
|
410
|
+
const branchNameToSubmit = listedName(requested);
|
|
411
|
+
return singleFlight('submit', branchNameToSubmit, async () => {
|
|
412
|
+
// Drafts belong to the open branch, so only its submit can leave edits behind. Without
|
|
413
|
+
// that check the dialog opens in this same tick.
|
|
414
|
+
const checking = branchNameToSubmit === listedName(latest.current.branchName)
|
|
415
|
+
? options.getUnsaved?.().catch((err) => {
|
|
416
|
+
console.error(err);
|
|
417
|
+
return undefined;
|
|
418
|
+
})
|
|
419
|
+
: undefined;
|
|
420
|
+
// Checking can wait on draft verification, so the busy state shows it is working meanwhile.
|
|
421
|
+
if (checking)
|
|
279
422
|
options.setBusy(true);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
423
|
+
const unsaved = checking && (await checking.finally(() => options.setBusy(false)));
|
|
424
|
+
return new Promise((resolve, reject) => {
|
|
425
|
+
showSubmitConfirmation(branchNameToSubmit, unsaved, async () => {
|
|
426
|
+
// A listing that arrived while the dialog was open may show the branch already
|
|
427
|
+
// submitted; submitting it again would only fail.
|
|
428
|
+
const listed = latest.current.branches.find((b) => b.name === branchNameToSubmit);
|
|
429
|
+
if (listed?.status === 'submitted') {
|
|
430
|
+
notifications.show({
|
|
431
|
+
message: 'Branch is already submitted for review',
|
|
432
|
+
color: 'blue',
|
|
433
|
+
});
|
|
434
|
+
resolve();
|
|
435
|
+
return;
|
|
286
436
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
437
|
+
options.setBusy(true);
|
|
438
|
+
try {
|
|
439
|
+
const result = await apiClient.workflow.submit({
|
|
440
|
+
branch: branchNameToSubmit,
|
|
441
|
+
});
|
|
442
|
+
if (!result.ok)
|
|
443
|
+
throw actionError(result, 'Failed to submit branch');
|
|
444
|
+
const stamped = result.data?.stamped;
|
|
445
|
+
if (stamped && branchNameToSubmit === listedName(latest.current.branchName)) {
|
|
446
|
+
options.onStamped?.(stamped);
|
|
447
|
+
}
|
|
448
|
+
notifications.show({
|
|
449
|
+
message: submittedMessage(stamped?.length ?? 0),
|
|
450
|
+
color: 'green',
|
|
451
|
+
});
|
|
452
|
+
updateCreatedBranch(branchNameToSubmit, result.data?.branch);
|
|
453
|
+
await loadBranches();
|
|
454
|
+
resolve();
|
|
455
|
+
}
|
|
456
|
+
catch (err) {
|
|
457
|
+
await reportActionFailure(err, 'Failed to submit branch', EDITOR_ACTIONS.submitForReview);
|
|
458
|
+
reject(err);
|
|
459
|
+
}
|
|
460
|
+
finally {
|
|
461
|
+
options.setBusy(false);
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
// Dismissal is not an error: the call sites log rejections to the console. Settled
|
|
465
|
+
// once, by onCancel OR onClose, so an Escape/overlay dismissal can't leave this pending.
|
|
466
|
+
() => resolve());
|
|
467
|
+
});
|
|
310
468
|
});
|
|
311
469
|
};
|
|
312
|
-
const handleWithdraw =
|
|
313
|
-
|
|
314
|
-
|
|
470
|
+
const handleWithdraw = (requested) => {
|
|
471
|
+
const branchNameToWithdraw = listedName(requested);
|
|
472
|
+
return singleFlight('withdraw', branchNameToWithdraw, () => new Promise((resolve, reject) => {
|
|
473
|
+
showWithdrawConfirmation(branchNameToWithdraw, pullRequestOf(branchNameToWithdraw), async () => {
|
|
315
474
|
options.setBusy(true);
|
|
316
475
|
try {
|
|
317
476
|
const result = await apiClient.workflow.withdraw({
|
|
318
477
|
branch: branchNameToWithdraw,
|
|
319
478
|
});
|
|
320
|
-
if (!result.ok)
|
|
321
|
-
throw
|
|
322
|
-
}
|
|
479
|
+
if (!result.ok)
|
|
480
|
+
throw actionError(result, 'Failed to withdraw branch');
|
|
323
481
|
notifications.show({ message: 'Branch withdrawn', color: 'blue' });
|
|
324
|
-
|
|
482
|
+
updateCreatedBranch(branchNameToWithdraw, result.data?.branch);
|
|
325
483
|
await loadBranches();
|
|
326
484
|
resolve();
|
|
327
485
|
}
|
|
328
486
|
catch (err) {
|
|
329
|
-
|
|
330
|
-
notifications.show({ message, color: 'red' });
|
|
487
|
+
await reportActionFailure(err, 'Failed to withdraw branch', EDITOR_ACTIONS.withdrawFromReview);
|
|
331
488
|
reject(err);
|
|
332
489
|
}
|
|
333
490
|
finally {
|
|
334
491
|
options.setBusy(false);
|
|
335
492
|
}
|
|
336
493
|
}, () => resolve());
|
|
337
|
-
});
|
|
494
|
+
}));
|
|
338
495
|
};
|
|
339
|
-
const handleRequestChanges =
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
496
|
+
const handleRequestChanges = (branchNameForChanges) => singleFlight('request-changes', branchNameForChanges, () => new Promise((resolve) => {
|
|
497
|
+
showRequestChangesConfirmation(branchNameForChanges, async () => {
|
|
498
|
+
options.setBusy(true);
|
|
499
|
+
try {
|
|
500
|
+
const result = await apiClient.workflow.requestChanges({
|
|
501
|
+
branch: branchNameForChanges,
|
|
502
|
+
});
|
|
503
|
+
if (!result.ok)
|
|
504
|
+
throw actionError(result, 'Failed to request changes');
|
|
505
|
+
notifications.show({ message: 'Changes requested', color: 'blue' });
|
|
506
|
+
updateCreatedBranch(branchNameForChanges, result.data?.branch);
|
|
507
|
+
await loadBranches();
|
|
345
508
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
509
|
+
catch (err) {
|
|
510
|
+
await reportActionFailure(err, 'Failed to request changes', EDITOR_ACTIONS.requestChanges);
|
|
511
|
+
}
|
|
512
|
+
finally {
|
|
513
|
+
options.setBusy(false);
|
|
514
|
+
resolve();
|
|
515
|
+
}
|
|
516
|
+
}, () => resolve());
|
|
517
|
+
}));
|
|
518
|
+
/** After a delete: drop it from the created-branch overlay, and leave it if it is open. */
|
|
519
|
+
const leaveDeletedBranch = (deleted, fresh) => {
|
|
520
|
+
forgetCreatedBranch(deleted);
|
|
521
|
+
// Matched the way `currentBranch` resolves a name, since the deleted branch is no longer
|
|
522
|
+
// listed to resolve against.
|
|
523
|
+
const open = latest.current.branchName;
|
|
524
|
+
if (open === deleted || sanitizeBranchName(open) === deleted) {
|
|
525
|
+
// Nothing is left to keep, so no unsaved-changes prompt. With no default known yet, the
|
|
526
|
+
// empty name lets the default-branch adoption effect pick it.
|
|
527
|
+
setBranchName(fresh?.defaultBranch ?? latest.current.branchesData?.defaultBranch ?? '');
|
|
356
528
|
}
|
|
357
529
|
};
|
|
358
|
-
const handleDelete =
|
|
359
|
-
|
|
360
|
-
|
|
530
|
+
const handleDelete = (requested) => {
|
|
531
|
+
const branchNameToDelete = listedName(requested);
|
|
532
|
+
return singleFlight('delete', branchNameToDelete, () => new Promise((resolve) => {
|
|
533
|
+
showDeleteConfirmation(branchNameToDelete, pullRequestOf(branchNameToDelete), async () => {
|
|
361
534
|
options.setBusy(true);
|
|
362
535
|
try {
|
|
363
536
|
const result = await apiClient.branches.delete({
|
|
364
537
|
branch: branchNameToDelete,
|
|
365
538
|
});
|
|
366
|
-
|
|
367
|
-
|
|
539
|
+
// The API's own 404: the branch is already gone, by an earlier unanswered delete or
|
|
540
|
+
// another user's.
|
|
541
|
+
if (!result.ok && result.status === 404 && !isNonApiResponse(result)) {
|
|
542
|
+
notifications.show({ message: 'Branch deleted', color: 'green' });
|
|
543
|
+
leaveDeletedBranch(branchNameToDelete, await reloadBranches());
|
|
544
|
+
return;
|
|
368
545
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
546
|
+
if (!result.ok)
|
|
547
|
+
throw actionError(result, 'Failed to delete branch');
|
|
548
|
+
const cleanupWarning = result.data?.cleanupWarning;
|
|
549
|
+
notifications.show(cleanupWarning
|
|
550
|
+
? {
|
|
551
|
+
message: `Branch deleted, with a warning: ${cleanupWarning}`,
|
|
552
|
+
color: 'yellow',
|
|
553
|
+
autoClose: false,
|
|
554
|
+
}
|
|
555
|
+
: { message: 'Branch deleted', color: 'green' });
|
|
556
|
+
leaveDeletedBranch(branchNameToDelete, await reloadBranches());
|
|
372
557
|
}
|
|
373
558
|
catch (err) {
|
|
374
|
-
|
|
375
|
-
|
|
559
|
+
if (!isUnanswered(err)) {
|
|
560
|
+
await reportActionFailure(err, 'Failed to delete branch', 'Delete branch');
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
// Settled by the list: unlisted, and not created too recently to be listed, means deleted.
|
|
564
|
+
const fresh = await reloadBranches();
|
|
565
|
+
const recent = pendingBranches.filter((p) => Date.now() - p.addedAt <= CREATED_BRANCH_GRACE_MS);
|
|
566
|
+
const listed = mergePendingBranches(fresh?.branches ?? [], recent).some((b) => sanitizeBranchName(b.name) === sanitizeBranchName(branchNameToDelete));
|
|
567
|
+
if (fresh && !listed) {
|
|
568
|
+
notifications.show({ message: 'Branch deleted', color: 'green' });
|
|
569
|
+
leaveDeletedBranch(branchNameToDelete, fresh);
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
showOutcomeUnknown('Delete branch');
|
|
573
|
+
}
|
|
376
574
|
}
|
|
377
575
|
finally {
|
|
378
576
|
options.setBusy(false);
|
|
379
|
-
//
|
|
380
|
-
// pre-confirmation behavior (errors were shown as a toast, not
|
|
381
|
-
// rethrown). Cancellation resolves too -- see below.
|
|
577
|
+
// Failures surface as the toast above, never as a rejection; cancelling resolves too.
|
|
382
578
|
resolve();
|
|
383
579
|
}
|
|
384
580
|
}, () => resolve());
|
|
385
|
-
});
|
|
581
|
+
}));
|
|
386
582
|
};
|
|
387
583
|
const handleReloadBranchData = async () => {
|
|
388
584
|
await loadBranches();
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* })` -- see the comment on `fetchBranches` for why it doesn't just call
|
|
12
12
|
* `mutate()` to revalidate.
|
|
13
13
|
*/
|
|
14
|
-
import { type SWRResponse } from 'swr';
|
|
14
|
+
import { type Cache, type ScopedMutator, type SWRResponse } from 'swr';
|
|
15
15
|
import type { ApiClient } from '../context/index.js';
|
|
16
16
|
import type { BranchListItem } from '../../api/branch.js';
|
|
17
17
|
/** Cache key for the branches list. */
|
|
@@ -27,10 +27,14 @@ export interface BranchesData {
|
|
|
27
27
|
receivedAt: number;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* Fetch the branches list
|
|
31
|
-
*
|
|
30
|
+
* Fetch the branches list, writing the owners it names into the user-metadata cache before the
|
|
31
|
+
* listing lands, so owner badges render named. Exported for direct testing and for the imperative
|
|
32
|
+
* reload path.
|
|
32
33
|
*/
|
|
33
|
-
export declare function fetchBranches(apiClient: Pick<ApiClient, 'branches'
|
|
34
|
+
export declare function fetchBranches(apiClient: Pick<ApiClient, 'branches'>, swr: {
|
|
35
|
+
cache: Cache;
|
|
36
|
+
mutate: ScopedMutator;
|
|
37
|
+
}): Promise<BranchesData>;
|
|
34
38
|
/**
|
|
35
39
|
* How often to re-poll while at least one branch is mid-flight, in ms.
|
|
36
40
|
* Only ever active in the transient window below, so this is not a
|