@webiny/app-headless-cms-workflows 0.0.0-unstable.0156a4c312
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/Components/CmsEntriesList/CmsReviewMoveEntryAction.d.ts +2 -0
- package/Components/CmsEntriesList/CmsReviewMoveEntryAction.js +43 -0
- package/Components/CmsEntriesList/CmsReviewMoveEntryAction.js.map +1 -0
- package/Components/CmsEntriesList/CmsReviewMoveEntryAction.test.d.ts +1 -0
- package/Components/CmsEntriesList/CmsReviewMoveEntryAction.test.js +118 -0
- package/Components/CmsEntriesList/CmsReviewMoveEntryAction.test.js.map +1 -0
- package/Components/CmsEntriesList/CmsReviewScheduleEntryAction.d.ts +2 -0
- package/Components/CmsEntriesList/CmsReviewScheduleEntryAction.js +22 -0
- package/Components/CmsEntriesList/CmsReviewScheduleEntryAction.js.map +1 -0
- package/Components/CmsEntriesList/CmsReviewScheduleEntryAction.test.d.ts +1 -0
- package/Components/CmsEntriesList/CmsReviewScheduleEntryAction.test.js +98 -0
- package/Components/CmsEntriesList/CmsReviewScheduleEntryAction.test.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewBar.d.ts +2 -0
- package/Components/ContentEntryForm/CmsEntryReviewBar.js +32 -0
- package/Components/ContentEntryForm/CmsEntryReviewBar.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewBar.test.d.ts +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewBar.test.js +128 -0
- package/Components/ContentEntryForm/CmsEntryReviewBar.test.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewBlockedActions.d.ts +2 -0
- package/Components/ContentEntryForm/CmsEntryReviewBlockedActions.js +46 -0
- package/Components/ContentEntryForm/CmsEntryReviewBlockedActions.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewBlockedActions.test.d.ts +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewBlockedActions.test.js +222 -0
- package/Components/ContentEntryForm/CmsEntryReviewBlockedActions.test.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewFormLock.d.ts +2 -0
- package/Components/ContentEntryForm/CmsEntryReviewFormLock.js +32 -0
- package/Components/ContentEntryForm/CmsEntryReviewFormLock.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewFormLock.test.d.ts +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewFormLock.test.js +94 -0
- package/Components/ContentEntryForm/CmsEntryReviewFormLock.test.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewNewRevision.d.ts +2 -0
- package/Components/ContentEntryForm/CmsEntryReviewNewRevision.js +56 -0
- package/Components/ContentEntryForm/CmsEntryReviewNewRevision.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewNewRevision.test.d.ts +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewNewRevision.test.js +186 -0
- package/Components/ContentEntryForm/CmsEntryReviewNewRevision.test.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewScheduleMenuItem.d.ts +2 -0
- package/Components/ContentEntryForm/CmsEntryReviewScheduleMenuItem.js +26 -0
- package/Components/ContentEntryForm/CmsEntryReviewScheduleMenuItem.js.map +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewScheduleMenuItem.test.d.ts +1 -0
- package/Components/ContentEntryForm/CmsEntryReviewScheduleMenuItem.test.js +78 -0
- package/Components/ContentEntryForm/CmsEntryReviewScheduleMenuItem.test.js.map +1 -0
- package/Components/ContentEntryForm/getModelFieldLabels.d.ts +3 -0
- package/Components/ContentEntryForm/getModelFieldLabels.js +8 -0
- package/Components/ContentEntryForm/getModelFieldLabels.js.map +1 -0
- package/Components/ContentEntryForm/index.d.ts +5 -0
- package/Components/ContentEntryForm/index.js +5 -0
- package/Components/ContentReviews/CmsContentReviews.d.ts +2 -0
- package/Components/ContentReviews/CmsContentReviews.js +11 -0
- package/Components/ContentReviews/CmsContentReviews.js.map +1 -0
- package/Components/ContentReviews/CmsContentReviews.test.d.ts +1 -0
- package/Components/ContentReviews/CmsContentReviews.test.js +214 -0
- package/Components/ContentReviews/CmsContentReviews.test.js.map +1 -0
- package/Components/ContentReviews/CmsContentReviewsMount.d.ts +4 -0
- package/Components/ContentReviews/CmsContentReviewsMount.js +44 -0
- package/Components/ContentReviews/CmsContentReviewsMount.js.map +1 -0
- package/Components/ContentReviews/CmsContentReviewsSidebarItem.d.ts +2 -0
- package/Components/ContentReviews/CmsContentReviewsSidebarItem.js +20 -0
- package/Components/ContentReviews/CmsContentReviewsSidebarItem.js.map +1 -0
- package/Components/ContentReviews/CmsContentReviewsSidebarItem.test.d.ts +1 -0
- package/Components/ContentReviews/CmsContentReviewsSidebarItem.test.js +83 -0
- package/Components/ContentReviews/CmsContentReviewsSidebarItem.test.js.map +1 -0
- package/Components/ModelDelete/ModelBoundToWorkflowErrorData.d.ts +8 -0
- package/Components/ModelDelete/ModelBoundToWorkflowErrorData.js +0 -0
- package/Components/ModelDelete/ModelDeleteWorkflowCopy.d.ts +10 -0
- package/Components/ModelDelete/ModelDeleteWorkflowCopy.js +0 -0
- package/Components/ModelDelete/ModelDeleteWorkflowError.d.ts +2 -0
- package/Components/ModelDelete/ModelDeleteWorkflowError.js +34 -0
- package/Components/ModelDelete/ModelDeleteWorkflowError.js.map +1 -0
- package/Components/ModelDelete/ModelDeleteWorkflowError.test.d.ts +1 -0
- package/Components/ModelDelete/ModelDeleteWorkflowError.test.js +73 -0
- package/Components/ModelDelete/ModelDeleteWorkflowError.test.js.map +1 -0
- package/Components/ModelDelete/getModelDeleteWorkflowCopy.d.ts +3 -0
- package/Components/ModelDelete/getModelDeleteWorkflowCopy.js +17 -0
- package/Components/ModelDelete/getModelDeleteWorkflowCopy.js.map +1 -0
- package/Components/ModelDelete/getModelDeleteWorkflowCopy.test.d.ts +1 -0
- package/Components/ModelDelete/getModelDeleteWorkflowCopy.test.js +28 -0
- package/Components/ModelDelete/getModelDeleteWorkflowCopy.test.js.map +1 -0
- package/Components/ignoreAction.d.ts +1 -0
- package/Components/ignoreAction.js +4 -0
- package/Components/ignoreAction.js.map +1 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/Routes/CmsWorkflowEditor.d.ts +2 -0
- package/Routes/CmsWorkflowEditor.js +23 -0
- package/Routes/CmsWorkflowEditor.js.map +1 -0
- package/Routes/CmsWorkflowEditor.test.d.ts +1 -0
- package/Routes/CmsWorkflowEditor.test.js +141 -0
- package/Routes/CmsWorkflowEditor.test.js.map +1 -0
- package/Routes/index.d.ts +1 -0
- package/Routes/index.js +1 -0
- package/features/cache/CmsReviewCacheSyncHandler.d.ts +8 -0
- package/features/cache/CmsReviewCacheSyncHandler.js +14 -0
- package/features/cache/CmsReviewCacheSyncHandler.js.map +1 -0
- package/features/cache/CmsReviewCacheWriter.d.ts +14 -0
- package/features/cache/CmsReviewCacheWriter.js +39 -0
- package/features/cache/CmsReviewCacheWriter.js.map +1 -0
- package/features/cache/CmsReviewCacheWriter.test.d.ts +1 -0
- package/features/cache/CmsReviewCacheWriter.test.js +207 -0
- package/features/cache/CmsReviewCacheWriter.test.js.map +1 -0
- package/features/cache/CmsReviewEntriesCacheProviderDecorator.d.ts +12 -0
- package/features/cache/CmsReviewEntriesCacheProviderDecorator.js +17 -0
- package/features/cache/CmsReviewEntriesCacheProviderDecorator.js.map +1 -0
- package/features/cache/CmsReviewEntriesCacheProviderDecorator.test.d.ts +1 -0
- package/features/cache/CmsReviewEntriesCacheProviderDecorator.test.js +129 -0
- package/features/cache/CmsReviewEntriesCacheProviderDecorator.test.js.map +1 -0
- package/features/cache/ReviewPreservingEntriesCache.d.ts +18 -0
- package/features/cache/ReviewPreservingEntriesCache.js +54 -0
- package/features/cache/ReviewPreservingEntriesCache.js.map +1 -0
- package/features/cache/abstractions.d.ts +5 -0
- package/features/cache/abstractions.js +5 -0
- package/features/cache/abstractions.js.map +1 -0
- package/features/editorGateway/CmsWorkflowEditorGateway/CmsWorkflowEditorGateway.d.ts +26 -0
- package/features/editorGateway/CmsWorkflowEditorGateway/CmsWorkflowEditorGateway.js +104 -0
- package/features/editorGateway/CmsWorkflowEditorGateway/CmsWorkflowEditorGateway.js.map +1 -0
- package/features/editorGateway/CmsWorkflowEditorGateway/CmsWorkflowEditorGateway.test.d.ts +1 -0
- package/features/editorGateway/CmsWorkflowEditorGateway/CmsWorkflowEditorGateway.test.js +589 -0
- package/features/editorGateway/CmsWorkflowEditorGateway/CmsWorkflowEditorGateway.test.js.map +1 -0
- package/features/editorGateway/feature.d.ts +1 -0
- package/features/editorGateway/feature.js +11 -0
- package/features/editorGateway/feature.js.map +1 -0
- package/features/editorGateway/feature.test.d.ts +1 -0
- package/features/editorGateway/feature.test.js +272 -0
- package/features/editorGateway/feature.test.js.map +1 -0
- package/features/editorGateway/graphql/cmsEntryFolderExists.d.ts +1 -0
- package/features/editorGateway/graphql/cmsEntryFolderExists.js +16 -0
- package/features/editorGateway/graphql/cmsEntryFolderExists.js.map +1 -0
- package/features/editorGateway/graphql/deleteCmsEntryWorkflow.d.ts +1 -0
- package/features/editorGateway/graphql/deleteCmsEntryWorkflow.js +19 -0
- package/features/editorGateway/graphql/deleteCmsEntryWorkflow.js.map +1 -0
- package/features/editorGateway/graphql/getCmsEntryWorkflow.d.ts +1 -0
- package/features/editorGateway/graphql/getCmsEntryWorkflow.js +19 -0
- package/features/editorGateway/graphql/getCmsEntryWorkflow.js.map +1 -0
- package/features/editorGateway/graphql/inspectCmsEntryRouting.d.ts +1 -0
- package/features/editorGateway/graphql/inspectCmsEntryRouting.js +19 -0
- package/features/editorGateway/graphql/inspectCmsEntryRouting.js.map +1 -0
- package/features/editorGateway/graphql/listCmsEntryWorkflowModels.d.ts +1 -0
- package/features/editorGateway/graphql/listCmsEntryWorkflowModels.js +29 -0
- package/features/editorGateway/graphql/listCmsEntryWorkflowModels.js.map +1 -0
- package/features/editorGateway/graphql/storeCmsEntryWorkflow.d.ts +1 -0
- package/features/editorGateway/graphql/storeCmsEntryWorkflow.js +19 -0
- package/features/editorGateway/graphql/storeCmsEntryWorkflow.js.map +1 -0
- package/features/editorMounting/CmsWorkflowEditorAppAdapter.d.ts +25 -0
- package/features/editorMounting/CmsWorkflowEditorAppAdapter.js +51 -0
- package/features/editorMounting/CmsWorkflowEditorAppAdapter.js.map +1 -0
- package/features/editorMounting/CmsWorkflowEditorAppAdapter.test.d.ts +1 -0
- package/features/editorMounting/CmsWorkflowEditorAppAdapter.test.js +185 -0
- package/features/editorMounting/CmsWorkflowEditorAppAdapter.test.js.map +1 -0
- package/features/editorMounting/abstractions.d.ts +5 -0
- package/features/editorMounting/abstractions.js +5 -0
- package/features/editorMounting/abstractions.js.map +1 -0
- package/features/editorMounting/feature.d.ts +3 -0
- package/features/editorMounting/feature.js +19 -0
- package/features/editorMounting/feature.js.map +1 -0
- package/features/editorMounting/feature.test.d.ts +1 -0
- package/features/editorMounting/feature.test.js +100 -0
- package/features/editorMounting/feature.test.js.map +1 -0
- package/features/editorReview/CmsEntryReview.d.ts +8 -0
- package/features/editorReview/CmsEntryReview.js +14 -0
- package/features/editorReview/CmsEntryReview.js.map +1 -0
- package/features/editorReview/abstractions.d.ts +5 -0
- package/features/editorReview/abstractions.js +5 -0
- package/features/editorReview/abstractions.js.map +1 -0
- package/features/editorReview/feature.d.ts +3 -0
- package/features/editorReview/feature.js +17 -0
- package/features/editorReview/feature.js.map +1 -0
- package/features/editorReview/feature.test.d.ts +1 -0
- package/features/editorReview/feature.test.js +46 -0
- package/features/editorReview/feature.test.js.map +1 -0
- package/features/editorReview/useCmsEntryReview.d.ts +2 -0
- package/features/editorReview/useCmsEntryReview.js +8 -0
- package/features/editorReview/useCmsEntryReview.js.map +1 -0
- package/features/feature.d.ts +1 -0
- package/features/feature.js +15 -0
- package/features/feature.js.map +1 -0
- package/features/gateway/CmsReviewChangeMessageHandler.d.ts +8 -0
- package/features/gateway/CmsReviewChangeMessageHandler.js +16 -0
- package/features/gateway/CmsReviewChangeMessageHandler.js.map +1 -0
- package/features/gateway/CmsReviewContentAdapter/CmsReviewContentAdapter.d.ts +16 -0
- package/features/gateway/CmsReviewContentAdapter/CmsReviewContentAdapter.js +39 -0
- package/features/gateway/CmsReviewContentAdapter/CmsReviewContentAdapter.js.map +1 -0
- package/features/gateway/CmsReviewContentAdapter/CmsReviewContentAdapter.test.d.ts +1 -0
- package/features/gateway/CmsReviewContentAdapter/CmsReviewContentAdapter.test.js +83 -0
- package/features/gateway/CmsReviewContentAdapter/CmsReviewContentAdapter.test.js.map +1 -0
- package/features/gateway/CmsReviewContentAdapter/abstractions.d.ts +5 -0
- package/features/gateway/CmsReviewContentAdapter/abstractions.js +5 -0
- package/features/gateway/CmsReviewContentAdapter/abstractions.js.map +1 -0
- package/features/gateway/CmsReviewGateway/CmsReviewGateway.d.ts +52 -0
- package/features/gateway/CmsReviewGateway/CmsReviewGateway.js +221 -0
- package/features/gateway/CmsReviewGateway/CmsReviewGateway.js.map +1 -0
- package/features/gateway/CmsReviewGateway/CmsReviewGateway.test.d.ts +1 -0
- package/features/gateway/CmsReviewGateway/CmsReviewGateway.test.js +689 -0
- package/features/gateway/CmsReviewGateway/CmsReviewGateway.test.js.map +1 -0
- package/features/gateway/CmsReviewNotificationHandler.d.ts +8 -0
- package/features/gateway/CmsReviewNotificationHandler.js +16 -0
- package/features/gateway/CmsReviewNotificationHandler.js.map +1 -0
- package/features/gateway/CmsReviewRowProvider/CmsReviewRowProvider.d.ts +8 -0
- package/features/gateway/CmsReviewRowProvider/CmsReviewRowProvider.js +14 -0
- package/features/gateway/CmsReviewRowProvider/CmsReviewRowProvider.js.map +1 -0
- package/features/gateway/CmsReviewRowProvider/abstractions.d.ts +5 -0
- package/features/gateway/CmsReviewRowProvider/abstractions.js +5 -0
- package/features/gateway/CmsReviewRowProvider/abstractions.js.map +1 -0
- package/features/gateway/contentReviewsBindings.test.d.ts +1 -0
- package/features/gateway/contentReviewsBindings.test.js +125 -0
- package/features/gateway/contentReviewsBindings.test.js.map +1 -0
- package/features/gateway/feature.d.ts +4 -0
- package/features/gateway/feature.js +27 -0
- package/features/gateway/feature.js.map +1 -0
- package/features/gateway/feature.test.d.ts +1 -0
- package/features/gateway/feature.test.js +79 -0
- package/features/gateway/feature.test.js.map +1 -0
- package/features/gateway/graphql/CmsOperationResponse.d.ts +3 -0
- package/features/gateway/graphql/CmsOperationResponse.js +0 -0
- package/features/gateway/graphql/approveCmsEntryReviewStep.d.ts +1 -0
- package/features/gateway/graphql/approveCmsEntryReviewStep.js +18 -0
- package/features/gateway/graphql/approveCmsEntryReviewStep.js.map +1 -0
- package/features/gateway/graphql/cancelCmsEntryReview.d.ts +1 -0
- package/features/gateway/graphql/cancelCmsEntryReview.js +18 -0
- package/features/gateway/graphql/cancelCmsEntryReview.js.map +1 -0
- package/features/gateway/graphql/cancelCmsEntryReviewsForDelete.d.ts +1 -0
- package/features/gateway/graphql/cancelCmsEntryReviewsForDelete.js +28 -0
- package/features/gateway/graphql/cancelCmsEntryReviewsForDelete.js.map +1 -0
- package/features/gateway/graphql/getCmsEntryReview.d.ts +1 -0
- package/features/gateway/graphql/getCmsEntryReview.js +18 -0
- package/features/gateway/graphql/getCmsEntryReview.js.map +1 -0
- package/features/gateway/graphql/getCmsEntryReviewStepRun.d.ts +1 -0
- package/features/gateway/graphql/getCmsEntryReviewStepRun.js +18 -0
- package/features/gateway/graphql/getCmsEntryReviewStepRun.js.map +1 -0
- package/features/gateway/graphql/getCmsEntryTargetReview.d.ts +1 -0
- package/features/gateway/graphql/getCmsEntryTargetReview.js +18 -0
- package/features/gateway/graphql/getCmsEntryTargetReview.js.map +1 -0
- package/features/gateway/graphql/listCmsEntryBlockingReviews.d.ts +1 -0
- package/features/gateway/graphql/listCmsEntryBlockingReviews.js +18 -0
- package/features/gateway/graphql/listCmsEntryBlockingReviews.js.map +1 -0
- package/features/gateway/graphql/listCmsEntryReviewStepCandidates.d.ts +1 -0
- package/features/gateway/graphql/listCmsEntryReviewStepCandidates.js +18 -0
- package/features/gateway/graphql/listCmsEntryReviewStepCandidates.js.map +1 -0
- package/features/gateway/graphql/listCmsEntryReviews.d.ts +1 -0
- package/features/gateway/graphql/listCmsEntryReviews.js +34 -0
- package/features/gateway/graphql/listCmsEntryReviews.js.map +1 -0
- package/features/gateway/graphql/listCmsEntryStepCandidates.d.ts +1 -0
- package/features/gateway/graphql/listCmsEntryStepCandidates.js +28 -0
- package/features/gateway/graphql/listCmsEntryStepCandidates.js.map +1 -0
- package/features/gateway/graphql/listCmsEntryWorkflows.d.ts +1 -0
- package/features/gateway/graphql/listCmsEntryWorkflows.js +18 -0
- package/features/gateway/graphql/listCmsEntryWorkflows.js.map +1 -0
- package/features/gateway/graphql/reassignCmsEntryReviewStep.d.ts +1 -0
- package/features/gateway/graphql/reassignCmsEntryReviewStep.js +18 -0
- package/features/gateway/graphql/reassignCmsEntryReviewStep.js.map +1 -0
- package/features/gateway/graphql/rejectCmsEntryReviewStep.d.ts +1 -0
- package/features/gateway/graphql/rejectCmsEntryReviewStep.js +18 -0
- package/features/gateway/graphql/rejectCmsEntryReviewStep.js.map +1 -0
- package/features/gateway/graphql/requestCmsEntryReview.d.ts +1 -0
- package/features/gateway/graphql/requestCmsEntryReview.js +28 -0
- package/features/gateway/graphql/requestCmsEntryReview.js.map +1 -0
- package/features/gateway/graphql/restartCmsEntryReviewStep.d.ts +1 -0
- package/features/gateway/graphql/restartCmsEntryReviewStep.js +18 -0
- package/features/gateway/graphql/restartCmsEntryReviewStep.js.map +1 -0
- package/features/gateway/graphql/startCmsEntryReviewStep.d.ts +1 -0
- package/features/gateway/graphql/startCmsEntryReviewStep.js +18 -0
- package/features/gateway/graphql/startCmsEntryReviewStep.js.map +1 -0
- package/features/gateway/graphql/takeOverCmsEntryReviewStep.d.ts +1 -0
- package/features/gateway/graphql/takeOverCmsEntryReviewStep.js +22 -0
- package/features/gateway/graphql/takeOverCmsEntryReviewStep.js.map +1 -0
- package/features/trash/BulkDeletePresenterReviewDecorator.d.ts +20 -0
- package/features/trash/BulkDeletePresenterReviewDecorator.js +81 -0
- package/features/trash/BulkDeletePresenterReviewDecorator.js.map +1 -0
- package/features/trash/BulkDeletePresenterReviewDecorator.test.d.ts +1 -0
- package/features/trash/BulkDeletePresenterReviewDecorator.test.js +693 -0
- package/features/trash/BulkDeletePresenterReviewDecorator.test.js.map +1 -0
- package/features/trash/DeleteEntryRevisionUseCaseReviewDecorator.d.ts +13 -0
- package/features/trash/DeleteEntryRevisionUseCaseReviewDecorator.js +23 -0
- package/features/trash/DeleteEntryRevisionUseCaseReviewDecorator.js.map +1 -0
- package/features/trash/DeleteEntryRevisionUseCaseReviewDecorator.test.d.ts +1 -0
- package/features/trash/DeleteEntryRevisionUseCaseReviewDecorator.test.js +123 -0
- package/features/trash/DeleteEntryRevisionUseCaseReviewDecorator.test.js.map +1 -0
- package/features/trash/DeleteEntryUseCaseReviewDecorator.d.ts +13 -0
- package/features/trash/DeleteEntryUseCaseReviewDecorator.js +23 -0
- package/features/trash/DeleteEntryUseCaseReviewDecorator.js.map +1 -0
- package/features/trash/DeleteEntryUseCaseReviewDecorator.test.d.ts +1 -0
- package/features/trash/DeleteEntryUseCaseReviewDecorator.test.js +139 -0
- package/features/trash/DeleteEntryUseCaseReviewDecorator.test.js.map +1 -0
- package/features/trash/PermanentlyDeleteEntryUseCaseReviewDecorator.d.ts +13 -0
- package/features/trash/PermanentlyDeleteEntryUseCaseReviewDecorator.js +23 -0
- package/features/trash/PermanentlyDeleteEntryUseCaseReviewDecorator.js.map +1 -0
- package/features/trash/PermanentlyDeleteEntryUseCaseReviewDecorator.test.d.ts +1 -0
- package/features/trash/PermanentlyDeleteEntryUseCaseReviewDecorator.test.js +122 -0
- package/features/trash/PermanentlyDeleteEntryUseCaseReviewDecorator.test.js.map +1 -0
- package/features/trash/feature.d.ts +1 -0
- package/features/trash/feature.js +17 -0
- package/features/trash/feature.js.map +1 -0
- package/features/trash/feature.test.d.ts +1 -0
- package/features/trash/feature.test.js +213 -0
- package/features/trash/feature.test.js.map +1 -0
- package/index.d.ts +2 -0
- package/index.editor.test.d.ts +1 -0
- package/index.editor.test.js +149 -0
- package/index.editor.test.js.map +1 -0
- package/index.js +41 -0
- package/index.js.map +1 -0
- package/index.lists.test.d.ts +1 -0
- package/index.lists.test.js +172 -0
- package/index.lists.test.js.map +1 -0
- package/index.mount.test.d.ts +1 -0
- package/index.mount.test.js +49 -0
- package/index.mount.test.js.map +1 -0
- package/index.test.d.ts +1 -0
- package/index.test.js +414 -0
- package/index.test.js.map +1 -0
- package/package.json +54 -0
- package/presentation/CmsEntryContentReloader.d.ts +8 -0
- package/presentation/CmsEntryContentReloader.js +20 -0
- package/presentation/CmsEntryContentReloader.js.map +1 -0
- package/presentation/CmsEntryContentReloader.test.d.ts +1 -0
- package/presentation/CmsEntryContentReloader.test.js +118 -0
- package/presentation/CmsEntryContentReloader.test.js.map +1 -0
- package/presentation/CmsEntryFormPresenterReviewDecorator.d.ts +27 -0
- package/presentation/CmsEntryFormPresenterReviewDecorator.js +167 -0
- package/presentation/CmsEntryFormPresenterReviewDecorator.js.map +1 -0
- package/presentation/CmsEntryFormPresenterReviewDecorator.test.d.ts +1 -0
- package/presentation/CmsEntryFormPresenterReviewDecorator.test.js +601 -0
- package/presentation/CmsEntryFormPresenterReviewDecorator.test.js.map +1 -0
- package/presentation/CmsEntryUnsavedChanges.d.ts +7 -0
- package/presentation/CmsEntryUnsavedChanges.js +12 -0
- package/presentation/CmsEntryUnsavedChanges.js.map +1 -0
- package/presentation/CmsEntryUnsavedChanges.test.d.ts +1 -0
- package/presentation/CmsEntryUnsavedChanges.test.js +23 -0
- package/presentation/CmsEntryUnsavedChanges.test.js.map +1 -0
- package/presentation/CmsReviewFieldSelections.test.d.ts +1 -0
- package/presentation/CmsReviewFieldSelections.test.js +27 -0
- package/presentation/CmsReviewFieldSelections.test.js.map +1 -0
- package/presentation/CmsReviewGetEntryFieldSelection.d.ts +8 -0
- package/presentation/CmsReviewGetEntryFieldSelection.js +16 -0
- package/presentation/CmsReviewGetEntryFieldSelection.js.map +1 -0
- package/presentation/CmsReviewListEntriesFieldSelection.d.ts +8 -0
- package/presentation/CmsReviewListEntriesFieldSelection.js +16 -0
- package/presentation/CmsReviewListEntriesFieldSelection.js.map +1 -0
- package/presentation/CmsReviewTableRowMapperDecorator.d.ts +11 -0
- package/presentation/CmsReviewTableRowMapperDecorator.js +24 -0
- package/presentation/CmsReviewTableRowMapperDecorator.js.map +1 -0
- package/presentation/CmsReviewTableRowMapperDecorator.test.d.ts +1 -0
- package/presentation/CmsReviewTableRowMapperDecorator.test.js +120 -0
- package/presentation/CmsReviewTableRowMapperDecorator.test.js.map +1 -0
- package/presentation/CmsRevisionsListPresenterDecorator.d.ts +24 -0
- package/presentation/CmsRevisionsListPresenterDecorator.js +66 -0
- package/presentation/CmsRevisionsListPresenterDecorator.js.map +1 -0
- package/presentation/CmsRevisionsListPresenterDecorator.test.d.ts +1 -0
- package/presentation/CmsRevisionsListPresenterDecorator.test.js +174 -0
- package/presentation/CmsRevisionsListPresenterDecorator.test.js.map +1 -0
- package/presentation/contentReviews/CmsContentReviewsPresenter.d.ts +28 -0
- package/presentation/contentReviews/CmsContentReviewsPresenter.js +103 -0
- package/presentation/contentReviews/CmsContentReviewsPresenter.js.map +1 -0
- package/presentation/contentReviews/CmsContentReviewsPresenter.test.d.ts +1 -0
- package/presentation/contentReviews/CmsContentReviewsPresenter.test.js +238 -0
- package/presentation/contentReviews/CmsContentReviewsPresenter.test.js.map +1 -0
- package/presentation/contentReviews/abstractions.d.ts +31 -0
- package/presentation/contentReviews/abstractions.js +5 -0
- package/presentation/contentReviews/abstractions.js.map +1 -0
- package/presentation/contentReviews/feature.d.ts +3 -0
- package/presentation/contentReviews/feature.js +17 -0
- package/presentation/contentReviews/feature.js.map +1 -0
- package/presentation/contentReviews/toContentTypes.d.ts +3 -0
- package/presentation/contentReviews/toContentTypes.js +14 -0
- package/presentation/contentReviews/toContentTypes.js.map +1 -0
- package/presentation/contentReviews/toContentTypes.test.d.ts +1 -0
- package/presentation/contentReviews/toContentTypes.test.js +20 -0
- package/presentation/contentReviews/toContentTypes.test.js.map +1 -0
- package/presentation/feature.d.ts +1 -0
- package/presentation/feature.js +19 -0
- package/presentation/feature.js.map +1 -0
- package/presentation/getCmsEntryReviewContext.d.ts +4 -0
- package/presentation/getCmsEntryReviewContext.js +12 -0
- package/presentation/getCmsEntryReviewContext.js.map +1 -0
- package/presentation/getCmsEntryReviewInitParams.d.ts +13 -0
- package/presentation/getCmsEntryReviewInitParams.js +18 -0
- package/presentation/getCmsEntryReviewInitParams.js.map +1 -0
- package/presentation/getCmsEntryReviewInitParams.test.d.ts +1 -0
- package/presentation/getCmsEntryReviewInitParams.test.js +69 -0
- package/presentation/getCmsEntryReviewInitParams.test.js.map +1 -0
- package/routes.d.ts +11 -0
- package/routes.js +21 -0
- package/routes.js.map +1 -0
- package/testing/createEntry.d.ts +3 -0
- package/testing/createEntry.js +22 -0
- package/testing/createEntry.js.map +1 -0
- package/testing/createEntrySession.d.ts +9 -0
- package/testing/createEntrySession.js +29 -0
- package/testing/createEntrySession.js.map +1 -0
- package/testing/createFolder.d.ts +2 -0
- package/testing/createFolder.js +13 -0
- package/testing/createFolder.js.map +1 -0
- package/testing/createFormVm.d.ts +2 -0
- package/testing/createFormVm.js +22 -0
- package/testing/createFormVm.js.map +1 -0
- package/testing/models.d.ts +4 -0
- package/testing/models.js +23 -0
- package/testing/models.js.map +1 -0
- package/testing/renderEditorTree.d.ts +17 -0
- package/testing/renderEditorTree.js +93 -0
- package/testing/renderEditorTree.js.map +1 -0
- package/testing/reviewStates.d.ts +17 -0
- package/testing/reviewStates.js +65 -0
- package/testing/reviewStates.js.map +1 -0
- package/types.d.ts +10 -0
- package/types.js +0 -0
- package/utils/appName.d.ts +4 -0
- package/utils/appName.js +13 -0
- package/utils/appName.js.map +1 -0
- package/utils/isReviewableModel.d.ts +2 -0
- package/utils/isReviewableModel.js +7 -0
- package/utils/isReviewableModel.js.map +1 -0
- package/utils/renderModelIcon.d.ts +3 -0
- package/utils/renderModelIcon.js +19 -0
- package/utils/renderModelIcon.js.map +1 -0
- package/utils/renderModelIconOrFallback.d.ts +3 -0
- package/utils/renderModelIconOrFallback.js +17 -0
- package/utils/renderModelIconOrFallback.js.map +1 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { screen, waitFor } from "@testing-library/react";
|
|
4
|
+
import { CmsEntryReviewBlockedActions } from "./CmsEntryReviewBlockedActions.js";
|
|
5
|
+
import { MODEL, SINGLETON_MODEL } from "../../testing/models.js";
|
|
6
|
+
import { createEntry } from "../../testing/createEntry.js";
|
|
7
|
+
import { renderEditorTree } from "../../testing/renderEditorTree.js";
|
|
8
|
+
import { APPROVED, BOUND_NO_REVIEW, BOUND_UNPUBLISHED, CHECKING, FAILED, FAILED_REASON, IN_REVIEW, IN_REVIEW_REASON, LOADING, NEEDS_REVIEW, NO_WORKFLOW, REJECTED, REJECTED_REASON } from "../../testing/reviewStates.js";
|
|
9
|
+
const permission = vi.hoisted(()=>({
|
|
10
|
+
canPublish: true
|
|
11
|
+
}));
|
|
12
|
+
vi.mock("@webiny/app-headless-cms/admin/hooks/usePermission.js", ()=>({
|
|
13
|
+
usePermission: ()=>({
|
|
14
|
+
canPublish: ()=>permission.canPublish,
|
|
15
|
+
canEdit: ()=>true
|
|
16
|
+
})
|
|
17
|
+
}));
|
|
18
|
+
const BLOCKED = {
|
|
19
|
+
canSave: false,
|
|
20
|
+
canPublish: false
|
|
21
|
+
};
|
|
22
|
+
function renderBlocked(params) {
|
|
23
|
+
return renderEditorTree({
|
|
24
|
+
...params,
|
|
25
|
+
children: /*#__PURE__*/ react.createElement(CmsEntryReviewBlockedActions, null)
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function getDescription(button) {
|
|
29
|
+
const describedBy = button.closest("[aria-describedby]")?.getAttribute("aria-describedby");
|
|
30
|
+
return document.getElementById(describedBy ?? "")?.textContent ?? void 0;
|
|
31
|
+
}
|
|
32
|
+
describe("CmsEntryReviewBlockedActions", ()=>{
|
|
33
|
+
beforeEach(()=>{
|
|
34
|
+
permission.canPublish = true;
|
|
35
|
+
});
|
|
36
|
+
it("is registered as the workflowBlockedActions action and not as a standalone tooltip", async ()=>{
|
|
37
|
+
renderBlocked({
|
|
38
|
+
reviewVm: NO_WORKFLOW
|
|
39
|
+
});
|
|
40
|
+
const names = await screen.findByTestId("button-action-names");
|
|
41
|
+
expect(names.textContent).toContain("workflowBlockedActions");
|
|
42
|
+
expect(names.textContent).not.toContain("workflowStateTooltip");
|
|
43
|
+
});
|
|
44
|
+
it("shows focusable, aria-disabled Save and Publish with the reason while loading", async ()=>{
|
|
45
|
+
renderBlocked({
|
|
46
|
+
formVm: BLOCKED,
|
|
47
|
+
reviewVm: LOADING
|
|
48
|
+
});
|
|
49
|
+
const publish = await screen.findByRole("button", {
|
|
50
|
+
name: "Publish"
|
|
51
|
+
});
|
|
52
|
+
const save = screen.getByRole("button", {
|
|
53
|
+
name: "Save"
|
|
54
|
+
});
|
|
55
|
+
expect(save.getAttribute("aria-disabled")).toBe("true");
|
|
56
|
+
expect(publish.getAttribute("aria-disabled")).toBe("true");
|
|
57
|
+
expect(publish.hasAttribute("disabled")).toBe(false);
|
|
58
|
+
expect(getDescription(publish)).toBe(CHECKING);
|
|
59
|
+
expect(getDescription(save)).toBe(CHECKING);
|
|
60
|
+
});
|
|
61
|
+
it("shows the failed reason", async ()=>{
|
|
62
|
+
renderBlocked({
|
|
63
|
+
formVm: BLOCKED,
|
|
64
|
+
reviewVm: FAILED
|
|
65
|
+
});
|
|
66
|
+
const publish = await screen.findByRole("button", {
|
|
67
|
+
name: "Publish"
|
|
68
|
+
});
|
|
69
|
+
expect(getDescription(publish)).toBe(FAILED_REASON);
|
|
70
|
+
expect(screen.getByRole("button", {
|
|
71
|
+
name: "Save"
|
|
72
|
+
})).toBeTruthy();
|
|
73
|
+
});
|
|
74
|
+
it("shows only Publish while a review is in progress", async ()=>{
|
|
75
|
+
renderBlocked({
|
|
76
|
+
formVm: BLOCKED,
|
|
77
|
+
reviewVm: IN_REVIEW
|
|
78
|
+
});
|
|
79
|
+
const publish = await screen.findByRole("button", {
|
|
80
|
+
name: "Publish"
|
|
81
|
+
});
|
|
82
|
+
expect(getDescription(publish)).toBe(IN_REVIEW_REASON);
|
|
83
|
+
expect(screen.queryByRole("button", {
|
|
84
|
+
name: "Save"
|
|
85
|
+
})).toBeNull();
|
|
86
|
+
});
|
|
87
|
+
it("shows only Publish for a rejected review", async ()=>{
|
|
88
|
+
renderBlocked({
|
|
89
|
+
formVm: BLOCKED,
|
|
90
|
+
reviewVm: REJECTED
|
|
91
|
+
});
|
|
92
|
+
const publish = await screen.findByRole("button", {
|
|
93
|
+
name: "Publish"
|
|
94
|
+
});
|
|
95
|
+
expect(getDescription(publish)).toBe(REJECTED_REASON);
|
|
96
|
+
expect(screen.queryByRole("button", {
|
|
97
|
+
name: "Save"
|
|
98
|
+
})).toBeNull();
|
|
99
|
+
});
|
|
100
|
+
it("shows Publish disabled, and no Save, when a workflow is bound but no review exists", async ()=>{
|
|
101
|
+
renderBlocked({
|
|
102
|
+
formVm: {
|
|
103
|
+
canSave: true,
|
|
104
|
+
canPublish: false
|
|
105
|
+
},
|
|
106
|
+
reviewVm: BOUND_NO_REVIEW
|
|
107
|
+
});
|
|
108
|
+
const publish = await screen.findByRole("button", {
|
|
109
|
+
name: "Publish"
|
|
110
|
+
});
|
|
111
|
+
expect(getDescription(publish)).toBe(NEEDS_REVIEW);
|
|
112
|
+
expect(screen.queryByRole("button", {
|
|
113
|
+
name: "Save"
|
|
114
|
+
})).toBeNull();
|
|
115
|
+
});
|
|
116
|
+
it("never shows more than two buttons while the status is unknown", async ()=>{
|
|
117
|
+
renderBlocked({
|
|
118
|
+
formVm: BLOCKED,
|
|
119
|
+
reviewVm: LOADING
|
|
120
|
+
});
|
|
121
|
+
await screen.findByRole("button", {
|
|
122
|
+
name: "Publish"
|
|
123
|
+
});
|
|
124
|
+
expect(screen.getAllByRole("button")).toHaveLength(2);
|
|
125
|
+
});
|
|
126
|
+
it.each([
|
|
127
|
+
[
|
|
128
|
+
"publishing is allowed (the base Publish button is shown)",
|
|
129
|
+
{
|
|
130
|
+
canSave: false,
|
|
131
|
+
canPublish: true
|
|
132
|
+
},
|
|
133
|
+
APPROVED,
|
|
134
|
+
MODEL
|
|
135
|
+
],
|
|
136
|
+
[
|
|
137
|
+
"an unpublished revision may be published again (Q19)",
|
|
138
|
+
{
|
|
139
|
+
canSave: true,
|
|
140
|
+
canPublish: true
|
|
141
|
+
},
|
|
142
|
+
BOUND_UNPUBLISHED,
|
|
143
|
+
MODEL
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
"no workflow is bound",
|
|
147
|
+
BLOCKED,
|
|
148
|
+
NO_WORKFLOW,
|
|
149
|
+
MODEL
|
|
150
|
+
],
|
|
151
|
+
[
|
|
152
|
+
"the model is a singleton",
|
|
153
|
+
BLOCKED,
|
|
154
|
+
LOADING,
|
|
155
|
+
SINGLETON_MODEL
|
|
156
|
+
]
|
|
157
|
+
])("shows nothing when %s", async (_name, formVm, reviewVm, model)=>{
|
|
158
|
+
renderBlocked({
|
|
159
|
+
formVm: {
|
|
160
|
+
...formVm,
|
|
161
|
+
model
|
|
162
|
+
},
|
|
163
|
+
reviewVm
|
|
164
|
+
});
|
|
165
|
+
await screen.findByTestId("button-actions");
|
|
166
|
+
await waitFor(()=>expect(screen.queryByRole("button", {
|
|
167
|
+
name: "Publish"
|
|
168
|
+
})).toBeNull());
|
|
169
|
+
expect(screen.queryByRole("button", {
|
|
170
|
+
name: "Save"
|
|
171
|
+
})).toBeNull();
|
|
172
|
+
});
|
|
173
|
+
it("shows no Publish for a published entry, only the disabled Save", async ()=>{
|
|
174
|
+
renderBlocked({
|
|
175
|
+
formVm: {
|
|
176
|
+
...BLOCKED,
|
|
177
|
+
entry: createEntry({
|
|
178
|
+
status: "published"
|
|
179
|
+
})
|
|
180
|
+
},
|
|
181
|
+
reviewVm: LOADING
|
|
182
|
+
});
|
|
183
|
+
expect(await screen.findByRole("button", {
|
|
184
|
+
name: "Save"
|
|
185
|
+
})).toBeTruthy();
|
|
186
|
+
expect(screen.queryByRole("button", {
|
|
187
|
+
name: "Publish"
|
|
188
|
+
})).toBeNull();
|
|
189
|
+
});
|
|
190
|
+
it("shows nothing for a new entry", async ()=>{
|
|
191
|
+
renderBlocked({
|
|
192
|
+
formVm: {
|
|
193
|
+
...BLOCKED,
|
|
194
|
+
entry: null,
|
|
195
|
+
isNewEntry: true
|
|
196
|
+
},
|
|
197
|
+
reviewVm: LOADING
|
|
198
|
+
});
|
|
199
|
+
await screen.findByTestId("button-actions");
|
|
200
|
+
await waitFor(()=>expect(screen.queryByRole("button", {
|
|
201
|
+
name: "Publish"
|
|
202
|
+
})).toBeNull());
|
|
203
|
+
expect(screen.queryByRole("button", {
|
|
204
|
+
name: "Save"
|
|
205
|
+
})).toBeNull();
|
|
206
|
+
});
|
|
207
|
+
it("shows no Publish without the publish permission, only the disabled Save", async ()=>{
|
|
208
|
+
permission.canPublish = false;
|
|
209
|
+
renderBlocked({
|
|
210
|
+
formVm: BLOCKED,
|
|
211
|
+
reviewVm: LOADING
|
|
212
|
+
});
|
|
213
|
+
expect(await screen.findByRole("button", {
|
|
214
|
+
name: "Save"
|
|
215
|
+
})).toBeTruthy();
|
|
216
|
+
expect(screen.queryByRole("button", {
|
|
217
|
+
name: "Publish"
|
|
218
|
+
})).toBeNull();
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
//# sourceMappingURL=CmsEntryReviewBlockedActions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Components/ContentEntryForm/CmsEntryReviewBlockedActions.test.js","sources":["../../../src/Components/ContentEntryForm/CmsEntryReviewBlockedActions.test.tsx"],"sourcesContent":["import React from \"react\";\nimport { beforeEach } from \"vitest\";\nimport { describe } from \"vitest\";\nimport { expect } from \"vitest\";\nimport { it } from \"vitest\";\nimport { vi } from \"vitest\";\nimport { screen } from \"@testing-library/react\";\nimport { waitFor } from \"@testing-library/react\";\nimport { CmsEntryReviewBlockedActions } from \"./CmsEntryReviewBlockedActions.js\";\nimport { MODEL } from \"~/testing/models.js\";\nimport { SINGLETON_MODEL } from \"~/testing/models.js\";\nimport { createEntry } from \"~/testing/createEntry.js\";\nimport { renderEditorTree } from \"~/testing/renderEditorTree.js\";\nimport { APPROVED } from \"~/testing/reviewStates.js\";\nimport { BOUND_NO_REVIEW } from \"~/testing/reviewStates.js\";\nimport { BOUND_UNPUBLISHED } from \"~/testing/reviewStates.js\";\nimport { CHECKING } from \"~/testing/reviewStates.js\";\nimport { FAILED } from \"~/testing/reviewStates.js\";\nimport { FAILED_REASON } from \"~/testing/reviewStates.js\";\nimport { IN_REVIEW } from \"~/testing/reviewStates.js\";\nimport { IN_REVIEW_REASON } from \"~/testing/reviewStates.js\";\nimport { LOADING } from \"~/testing/reviewStates.js\";\nimport { NEEDS_REVIEW } from \"~/testing/reviewStates.js\";\nimport { NO_WORKFLOW } from \"~/testing/reviewStates.js\";\nimport { REJECTED } from \"~/testing/reviewStates.js\";\nimport { REJECTED_REASON } from \"~/testing/reviewStates.js\";\n\nconst permission = vi.hoisted(() => {\n return { canPublish: true };\n});\n\nvi.mock(\"@webiny/app-headless-cms/admin/hooks/usePermission.js\", () => {\n return {\n usePermission: () => {\n return { canPublish: () => permission.canPublish, canEdit: () => true };\n }\n };\n});\n\nconst BLOCKED = { canSave: false, canPublish: false };\n\nfunction renderBlocked(params: Parameters<typeof renderEditorTree>[0]) {\n return renderEditorTree({ ...params, children: <CmsEntryReviewBlockedActions /> });\n}\n\nfunction getDescription(button: HTMLElement): string | undefined {\n const describedBy = button.closest(\"[aria-describedby]\")?.getAttribute(\"aria-describedby\");\n return document.getElementById(describedBy ?? \"\")?.textContent ?? undefined;\n}\n\ndescribe(\"CmsEntryReviewBlockedActions\", () => {\n beforeEach(() => {\n permission.canPublish = true;\n });\n\n it(\"is registered as the workflowBlockedActions action and not as a standalone tooltip\", async () => {\n renderBlocked({ reviewVm: NO_WORKFLOW });\n\n const names = await screen.findByTestId(\"button-action-names\");\n\n expect(names.textContent).toContain(\"workflowBlockedActions\");\n expect(names.textContent).not.toContain(\"workflowStateTooltip\");\n });\n\n it(\"shows focusable, aria-disabled Save and Publish with the reason while loading\", async () => {\n renderBlocked({ formVm: BLOCKED, reviewVm: LOADING });\n\n const publish = await screen.findByRole(\"button\", { name: \"Publish\" });\n const save = screen.getByRole(\"button\", { name: \"Save\" });\n\n expect(save.getAttribute(\"aria-disabled\")).toBe(\"true\");\n expect(publish.getAttribute(\"aria-disabled\")).toBe(\"true\");\n expect(publish.hasAttribute(\"disabled\")).toBe(false);\n expect(getDescription(publish)).toBe(CHECKING);\n expect(getDescription(save)).toBe(CHECKING);\n });\n\n it(\"shows the failed reason\", async () => {\n renderBlocked({ formVm: BLOCKED, reviewVm: FAILED });\n\n const publish = await screen.findByRole(\"button\", { name: \"Publish\" });\n\n expect(getDescription(publish)).toBe(FAILED_REASON);\n expect(screen.getByRole(\"button\", { name: \"Save\" })).toBeTruthy();\n });\n\n it(\"shows only Publish while a review is in progress\", async () => {\n renderBlocked({ formVm: BLOCKED, reviewVm: IN_REVIEW });\n\n const publish = await screen.findByRole(\"button\", { name: \"Publish\" });\n\n expect(getDescription(publish)).toBe(IN_REVIEW_REASON);\n expect(screen.queryByRole(\"button\", { name: \"Save\" })).toBeNull();\n });\n\n it(\"shows only Publish for a rejected review\", async () => {\n renderBlocked({ formVm: BLOCKED, reviewVm: REJECTED });\n\n const publish = await screen.findByRole(\"button\", { name: \"Publish\" });\n\n expect(getDescription(publish)).toBe(REJECTED_REASON);\n expect(screen.queryByRole(\"button\", { name: \"Save\" })).toBeNull();\n });\n\n it(\"shows Publish disabled, and no Save, when a workflow is bound but no review exists\", async () => {\n renderBlocked({ formVm: { canSave: true, canPublish: false }, reviewVm: BOUND_NO_REVIEW });\n\n const publish = await screen.findByRole(\"button\", { name: \"Publish\" });\n\n expect(getDescription(publish)).toBe(NEEDS_REVIEW);\n expect(screen.queryByRole(\"button\", { name: \"Save\" })).toBeNull();\n });\n\n it(\"never shows more than two buttons while the status is unknown\", async () => {\n renderBlocked({ formVm: BLOCKED, reviewVm: LOADING });\n\n await screen.findByRole(\"button\", { name: \"Publish\" });\n\n expect(screen.getAllByRole(\"button\")).toHaveLength(2);\n });\n\n it.each([\n [\n \"publishing is allowed (the base Publish button is shown)\",\n { canSave: false, canPublish: true },\n APPROVED,\n MODEL\n ],\n [\n \"an unpublished revision may be published again (Q19)\",\n { canSave: true, canPublish: true },\n BOUND_UNPUBLISHED,\n MODEL\n ],\n [\"no workflow is bound\", BLOCKED, NO_WORKFLOW, MODEL],\n [\"the model is a singleton\", BLOCKED, LOADING, SINGLETON_MODEL]\n ])(\"shows nothing when %s\", async (_name, formVm, reviewVm, model) => {\n renderBlocked({ formVm: { ...formVm, model }, reviewVm });\n\n await screen.findByTestId(\"button-actions\");\n await waitFor(() => expect(screen.queryByRole(\"button\", { name: \"Publish\" })).toBeNull());\n expect(screen.queryByRole(\"button\", { name: \"Save\" })).toBeNull();\n });\n\n it(\"shows no Publish for a published entry, only the disabled Save\", async () => {\n renderBlocked({\n formVm: { ...BLOCKED, entry: createEntry({ status: \"published\" }) },\n reviewVm: LOADING\n });\n\n expect(await screen.findByRole(\"button\", { name: \"Save\" })).toBeTruthy();\n expect(screen.queryByRole(\"button\", { name: \"Publish\" })).toBeNull();\n });\n\n it(\"shows nothing for a new entry\", async () => {\n renderBlocked({\n formVm: { ...BLOCKED, entry: null, isNewEntry: true },\n reviewVm: LOADING\n });\n\n await screen.findByTestId(\"button-actions\");\n await waitFor(() => expect(screen.queryByRole(\"button\", { name: \"Publish\" })).toBeNull());\n expect(screen.queryByRole(\"button\", { name: \"Save\" })).toBeNull();\n });\n\n it(\"shows no Publish without the publish permission, only the disabled Save\", async () => {\n permission.canPublish = false;\n renderBlocked({ formVm: BLOCKED, reviewVm: LOADING });\n\n expect(await screen.findByRole(\"button\", { name: \"Save\" })).toBeTruthy();\n expect(screen.queryByRole(\"button\", { name: \"Publish\" })).toBeNull();\n });\n});\n"],"names":["permission","vi","BLOCKED","renderBlocked","params","renderEditorTree","CmsEntryReviewBlockedActions","getDescription","button","describedBy","document","undefined","describe","beforeEach","it","NO_WORKFLOW","names","screen","expect","LOADING","publish","save","CHECKING","FAILED","FAILED_REASON","IN_REVIEW","IN_REVIEW_REASON","REJECTED","REJECTED_REASON","BOUND_NO_REVIEW","NEEDS_REVIEW","APPROVED","MODEL","BOUND_UNPUBLISHED","SINGLETON_MODEL","_name","formVm","reviewVm","model","waitFor","createEntry"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import react, { useEffect, useRef } from "react";
|
|
2
|
+
import { createReactiveComponent } from "@webiny/app-admin";
|
|
3
|
+
import { ContentEntryForm } from "@webiny/app-headless-cms/presentation/contentEntries/views/layout/index.js";
|
|
4
|
+
import { useContentEntryFormPresenter } from "@webiny/app-headless-cms/presentation/contentEntries/form/useContentEntryFormPresenter.js";
|
|
5
|
+
import { useCmsEntryReview } from "../../features/editorReview/useCmsEntryReview.js";
|
|
6
|
+
import { isReviewableModel } from "../../utils/isReviewableModel.js";
|
|
7
|
+
const FormLock = ({ isLocked, children })=>{
|
|
8
|
+
const wrapper = useRef(null);
|
|
9
|
+
useEffect(()=>{
|
|
10
|
+
if (wrapper.current) wrapper.current.inert = isLocked;
|
|
11
|
+
}, [
|
|
12
|
+
isLocked
|
|
13
|
+
]);
|
|
14
|
+
return /*#__PURE__*/ react.createElement("fieldset", {
|
|
15
|
+
ref: wrapper,
|
|
16
|
+
disabled: isLocked,
|
|
17
|
+
className: "m-0 min-w-0 p-0"
|
|
18
|
+
}, children);
|
|
19
|
+
};
|
|
20
|
+
const CmsEntryReviewFormLock = ContentEntryForm.createDecorator((Original)=>createReactiveComponent(function() {
|
|
21
|
+
const formPresenter = useContentEntryFormPresenter();
|
|
22
|
+
const session = useCmsEntryReview();
|
|
23
|
+
const { entry, model } = formPresenter.vm;
|
|
24
|
+
const isReviewed = null !== entry && isReviewableModel(model);
|
|
25
|
+
const isLocked = isReviewed && !session.presenter.vm.allowsEditing;
|
|
26
|
+
return /*#__PURE__*/ react.createElement(FormLock, {
|
|
27
|
+
isLocked: isLocked
|
|
28
|
+
}, /*#__PURE__*/ react.createElement(Original, null));
|
|
29
|
+
}));
|
|
30
|
+
export { CmsEntryReviewFormLock };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=CmsEntryReviewFormLock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Components/ContentEntryForm/CmsEntryReviewFormLock.js","sources":["../../../src/Components/ContentEntryForm/CmsEntryReviewFormLock.tsx"],"sourcesContent":["import React from \"react\";\nimport { useEffect } from \"react\";\nimport { useRef } from \"react\";\nimport { createReactiveComponent } from \"@webiny/app-admin\";\nimport { ContentEntryForm } from \"@webiny/app-headless-cms/presentation/contentEntries/views/layout/index.js\";\nimport { useContentEntryFormPresenter } from \"@webiny/app-headless-cms/presentation/contentEntries/form/useContentEntryFormPresenter.js\";\nimport { useCmsEntryReview } from \"~/features/editorReview/useCmsEntryReview.js\";\nimport { isReviewableModel } from \"~/utils/isReviewableModel.js\";\n\ninterface FormLockProps {\n isLocked: boolean;\n children: React.ReactNode;\n}\n\n/*\n * One stable wrapper, always rendered, so toggling the lock never remounts the form. A disabled\n * fieldset stops native inputs; `inert` stops everything else (rich text editors, custom field\n * renderers). Trade-off: `inert` also blocks text selection and copy inside the form while it is\n * locked; nothing else can stop contenteditable editors from being edited, and the server stays\n * authoritative (`TargetLocked`).\n */\nconst FormLock = ({ isLocked, children }: FormLockProps) => {\n const wrapper = useRef<HTMLFieldSetElement>(null);\n\n useEffect(() => {\n if (wrapper.current) {\n wrapper.current.inert = isLocked;\n }\n }, [isLocked]);\n\n return (\n <fieldset ref={wrapper} disabled={isLocked} className={\"m-0 min-w-0 p-0\"}>\n {children}\n </fieldset>\n );\n};\n\nexport const CmsEntryReviewFormLock = ContentEntryForm.createDecorator(Original => {\n return createReactiveComponent(function CmsEntryReviewFormLockDecorator() {\n const formPresenter = useContentEntryFormPresenter();\n const session = useCmsEntryReview();\n const { entry, model } = formPresenter.vm;\n const isReviewed = entry !== null && isReviewableModel(model);\n const isLocked = isReviewed && !session.presenter.vm.allowsEditing;\n\n return (\n <FormLock isLocked={isLocked}>\n <Original />\n </FormLock>\n );\n });\n});\n"],"names":["FormLock","isLocked","children","wrapper","useRef","useEffect","CmsEntryReviewFormLock","ContentEntryForm","Original","createReactiveComponent","formPresenter","useContentEntryFormPresenter","session","useCmsEntryReview","entry","model","isReviewed","isReviewableModel"],"mappings":";;;;;;AAqBA,MAAMA,WAAW,CAAC,EAAEC,QAAQ,EAAEC,QAAQ,EAAiB;IACnD,MAAMC,UAAUC,OAA4B;IAE5CC,UAAU;QACN,IAAIF,QAAQ,OAAO,EACfA,QAAQ,OAAO,CAAC,KAAK,GAAGF;IAEhC,GAAG;QAACA;KAAS;IAEb,OAAO,WAAP,GACI,oBAAC;QAAS,KAAKE;QAAS,UAAUF;QAAU,WAAW;OAClDC;AAGb;AAEO,MAAMI,yBAAyBC,iBAAiB,eAAe,CAACC,CAAAA,WAC5DC,wBAAwB;QAC3B,MAAMC,gBAAgBC;QACtB,MAAMC,UAAUC;QAChB,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGL,cAAc,EAAE;QACzC,MAAMM,aAAaF,AAAU,SAAVA,SAAkBG,kBAAkBF;QACvD,MAAMd,WAAWe,cAAc,CAACJ,QAAQ,SAAS,CAAC,EAAE,CAAC,aAAa;QAElE,OAAO,WAAP,GACI,oBAACZ,UAAQA;YAAC,UAAUC;yBAChB,oBAACO,UAAAA;IAGb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { act, waitFor } from "@testing-library/react";
|
|
4
|
+
import { ContentEntryForm } from "@webiny/app-headless-cms/presentation/contentEntries/views/layout/index.js";
|
|
5
|
+
import { CmsEntryReviewFormLock } from "./CmsEntryReviewFormLock.js";
|
|
6
|
+
import { SINGLETON_MODEL } from "../../testing/models.js";
|
|
7
|
+
import { renderEditorTree } from "../../testing/renderEditorTree.js";
|
|
8
|
+
import { BOUND_NO_REVIEW, FAILED, IN_REVIEW, LOADING, NO_WORKFLOW } from "../../testing/reviewStates.js";
|
|
9
|
+
function renderForm(params) {
|
|
10
|
+
return renderEditorTree({
|
|
11
|
+
...params,
|
|
12
|
+
children: /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(CmsEntryReviewFormLock, null), /*#__PURE__*/ react.createElement(ContentEntryForm, null))
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async function findWrapper() {
|
|
16
|
+
await waitFor(()=>expect(document.querySelector("fieldset")).not.toBeNull());
|
|
17
|
+
return document.querySelector("fieldset");
|
|
18
|
+
}
|
|
19
|
+
describe("CmsEntryReviewFormLock", ()=>{
|
|
20
|
+
it.each([
|
|
21
|
+
[
|
|
22
|
+
"loading",
|
|
23
|
+
LOADING
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
"failed",
|
|
27
|
+
FAILED
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"in review",
|
|
31
|
+
IN_REVIEW
|
|
32
|
+
]
|
|
33
|
+
])("makes the form read-only while the status is %s", async (_name, reviewVm)=>{
|
|
34
|
+
renderForm({
|
|
35
|
+
reviewVm
|
|
36
|
+
});
|
|
37
|
+
const wrapper = await findWrapper();
|
|
38
|
+
expect(wrapper.disabled).toBe(true);
|
|
39
|
+
expect(wrapper.inert).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it.each([
|
|
42
|
+
[
|
|
43
|
+
"no workflow",
|
|
44
|
+
NO_WORKFLOW
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
"a bound workflow and no review",
|
|
48
|
+
BOUND_NO_REVIEW
|
|
49
|
+
]
|
|
50
|
+
])("leaves the form editable for %s", async (_name, reviewVm)=>{
|
|
51
|
+
renderForm({
|
|
52
|
+
reviewVm
|
|
53
|
+
});
|
|
54
|
+
const wrapper = await findWrapper();
|
|
55
|
+
expect(wrapper.disabled).toBe(false);
|
|
56
|
+
expect(wrapper.inert).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it("keeps the same wrapper element when the lock toggles, so the form does not remount", async ()=>{
|
|
59
|
+
const view = renderForm({
|
|
60
|
+
reviewVm: LOADING
|
|
61
|
+
});
|
|
62
|
+
const before = await findWrapper();
|
|
63
|
+
act(()=>{
|
|
64
|
+
view.setVm(BOUND_NO_REVIEW);
|
|
65
|
+
});
|
|
66
|
+
const after = await findWrapper();
|
|
67
|
+
expect(after).toBe(before);
|
|
68
|
+
expect(after.disabled).toBe(false);
|
|
69
|
+
expect(after.inert).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
it("leaves a new entry editable while nothing is known", async ()=>{
|
|
72
|
+
renderForm({
|
|
73
|
+
formVm: {
|
|
74
|
+
entry: null,
|
|
75
|
+
isNewEntry: true
|
|
76
|
+
},
|
|
77
|
+
reviewVm: LOADING
|
|
78
|
+
});
|
|
79
|
+
const wrapper = await findWrapper();
|
|
80
|
+
expect(wrapper.disabled).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
it("leaves a singleton model editable", async ()=>{
|
|
83
|
+
renderForm({
|
|
84
|
+
formVm: {
|
|
85
|
+
model: SINGLETON_MODEL
|
|
86
|
+
},
|
|
87
|
+
reviewVm: LOADING
|
|
88
|
+
});
|
|
89
|
+
const wrapper = await findWrapper();
|
|
90
|
+
expect(wrapper.disabled).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=CmsEntryReviewFormLock.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Components/ContentEntryForm/CmsEntryReviewFormLock.test.js","sources":["../../../src/Components/ContentEntryForm/CmsEntryReviewFormLock.test.tsx"],"sourcesContent":["import React from \"react\";\nimport { describe } from \"vitest\";\nimport { expect } from \"vitest\";\nimport { it } from \"vitest\";\nimport { act } from \"@testing-library/react\";\nimport { waitFor } from \"@testing-library/react\";\nimport { ContentEntryForm } from \"@webiny/app-headless-cms/presentation/contentEntries/views/layout/index.js\";\nimport { CmsEntryReviewFormLock } from \"./CmsEntryReviewFormLock.js\";\nimport { SINGLETON_MODEL } from \"~/testing/models.js\";\nimport { renderEditorTree } from \"~/testing/renderEditorTree.js\";\nimport { BOUND_NO_REVIEW } from \"~/testing/reviewStates.js\";\nimport { FAILED } from \"~/testing/reviewStates.js\";\nimport { IN_REVIEW } from \"~/testing/reviewStates.js\";\nimport { LOADING } from \"~/testing/reviewStates.js\";\nimport { NO_WORKFLOW } from \"~/testing/reviewStates.js\";\n\nfunction renderForm(params: Parameters<typeof renderEditorTree>[0]) {\n return renderEditorTree({\n ...params,\n children: (\n <>\n <CmsEntryReviewFormLock />\n <ContentEntryForm />\n </>\n )\n });\n}\n\nasync function findWrapper(): Promise<HTMLFieldSetElement> {\n await waitFor(() => expect(document.querySelector(\"fieldset\")).not.toBeNull());\n return document.querySelector(\"fieldset\") as HTMLFieldSetElement;\n}\n\ndescribe(\"CmsEntryReviewFormLock\", () => {\n it.each([\n [\"loading\", LOADING],\n [\"failed\", FAILED],\n [\"in review\", IN_REVIEW]\n ])(\"makes the form read-only while the status is %s\", async (_name, reviewVm) => {\n renderForm({ reviewVm });\n\n const wrapper = await findWrapper();\n\n expect(wrapper.disabled).toBe(true);\n expect(wrapper.inert).toBe(true);\n });\n\n it.each([\n [\"no workflow\", NO_WORKFLOW],\n [\"a bound workflow and no review\", BOUND_NO_REVIEW]\n ])(\"leaves the form editable for %s\", async (_name, reviewVm) => {\n renderForm({ reviewVm });\n\n const wrapper = await findWrapper();\n\n expect(wrapper.disabled).toBe(false);\n expect(wrapper.inert).toBe(false);\n });\n\n it(\"keeps the same wrapper element when the lock toggles, so the form does not remount\", async () => {\n const view = renderForm({ reviewVm: LOADING });\n const before = await findWrapper();\n\n act(() => {\n view.setVm(BOUND_NO_REVIEW);\n });\n\n const after = await findWrapper();\n expect(after).toBe(before);\n expect(after.disabled).toBe(false);\n expect(after.inert).toBe(false);\n });\n\n it(\"leaves a new entry editable while nothing is known\", async () => {\n renderForm({ formVm: { entry: null, isNewEntry: true }, reviewVm: LOADING });\n\n const wrapper = await findWrapper();\n\n expect(wrapper.disabled).toBe(false);\n });\n\n it(\"leaves a singleton model editable\", async () => {\n renderForm({ formVm: { model: SINGLETON_MODEL }, reviewVm: LOADING });\n\n const wrapper = await findWrapper();\n\n expect(wrapper.disabled).toBe(false);\n });\n});\n"],"names":["renderForm","params","renderEditorTree","CmsEntryReviewFormLock","ContentEntryForm","findWrapper","waitFor","expect","document","describe","it","LOADING","FAILED","IN_REVIEW","_name","reviewVm","wrapper","NO_WORKFLOW","BOUND_NO_REVIEW","view","before","act","after","SINGLETON_MODEL"],"mappings":";;;;;;;;AAgBA,SAASA,WAAWC,MAA8C;IAC9D,OAAOC,iBAAiB;QACpB,GAAGD,MAAM;QACT,UAAU,WAAV,GACI,wDACI,oBAACE,wBAAsBA,OAAAA,WAAAA,GACvB,oBAACC,kBAAgBA;IAG7B;AACJ;AAEA,eAAeC;IACX,MAAMC,QAAQ,IAAMC,OAAOC,SAAS,aAAa,CAAC,aAAa,GAAG,CAAC,QAAQ;IAC3E,OAAOA,SAAS,aAAa,CAAC;AAClC;AAEAC,SAAS,0BAA0B;IAC/BC,GAAG,IAAI,CAAC;QACJ;YAAC;YAAWC;SAAQ;QACpB;YAAC;YAAUC;SAAO;QAClB;YAAC;YAAaC;SAAU;KAC3B,EAAE,mDAAmD,OAAOC,OAAOC;QAChEf,WAAW;YAAEe;QAAS;QAEtB,MAAMC,UAAU,MAAMX;QAEtBE,OAAOS,QAAQ,QAAQ,EAAE,IAAI,CAAC;QAC9BT,OAAOS,QAAQ,KAAK,EAAE,IAAI,CAAC;IAC/B;IAEAN,GAAG,IAAI,CAAC;QACJ;YAAC;YAAeO;SAAY;QAC5B;YAAC;YAAkCC;SAAgB;KACtD,EAAE,mCAAmC,OAAOJ,OAAOC;QAChDf,WAAW;YAAEe;QAAS;QAEtB,MAAMC,UAAU,MAAMX;QAEtBE,OAAOS,QAAQ,QAAQ,EAAE,IAAI,CAAC;QAC9BT,OAAOS,QAAQ,KAAK,EAAE,IAAI,CAAC;IAC/B;IAEAN,GAAG,sFAAsF;QACrF,MAAMS,OAAOnB,WAAW;YAAE,UAAUW;QAAQ;QAC5C,MAAMS,SAAS,MAAMf;QAErBgB,IAAI;YACAF,KAAK,KAAK,CAACD;QACf;QAEA,MAAMI,QAAQ,MAAMjB;QACpBE,OAAOe,OAAO,IAAI,CAACF;QACnBb,OAAOe,MAAM,QAAQ,EAAE,IAAI,CAAC;QAC5Bf,OAAOe,MAAM,KAAK,EAAE,IAAI,CAAC;IAC7B;IAEAZ,GAAG,sDAAsD;QACrDV,WAAW;YAAE,QAAQ;gBAAE,OAAO;gBAAM,YAAY;YAAK;YAAG,UAAUW;QAAQ;QAE1E,MAAMK,UAAU,MAAMX;QAEtBE,OAAOS,QAAQ,QAAQ,EAAE,IAAI,CAAC;IAClC;IAEAN,GAAG,qCAAqC;QACpCV,WAAW;YAAE,QAAQ;gBAAE,OAAOuB;YAAgB;YAAG,UAAUZ;QAAQ;QAEnE,MAAMK,UAAU,MAAMX;QAEtBE,OAAOS,QAAQ,QAAQ,EAAE,IAAI,CAAC;IAClC;AACJ"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import react, { useCallback } from "react";
|
|
2
|
+
import { useFeature, useRoute } from "@webiny/app";
|
|
3
|
+
import { useToast } from "@webiny/admin-ui";
|
|
4
|
+
import { OptionsMenuItem, createReactiveComponent } from "@webiny/app-admin";
|
|
5
|
+
import { InternalContentEntryEditorConfig } from "@webiny/app-headless-cms/admin/config/contentEntries/index.js";
|
|
6
|
+
import { IsModelPublishable } from "@webiny/app-headless-cms/admin/components/IsModelPublishable.js";
|
|
7
|
+
import { usePermission } from "@webiny/app-headless-cms/admin/hooks/usePermission.js";
|
|
8
|
+
import { useContentEntryFormPresenter } from "@webiny/app-headless-cms/presentation/contentEntries/form/useContentEntryFormPresenter.js";
|
|
9
|
+
import { RevisionsListFeature } from "@webiny/app-headless-cms/presentation/contentEntries/revisionsList/feature.js";
|
|
10
|
+
import { ReactComponent } from "@webiny/icons/new_releases.svg";
|
|
11
|
+
import { useCmsEntryReview } from "../../features/editorReview/useCmsEntryReview.js";
|
|
12
|
+
import { isReviewableModel } from "../../utils/isReviewableModel.js";
|
|
13
|
+
const { Actions: Actions } = InternalContentEntryEditorConfig;
|
|
14
|
+
const CreateNewRevisionMenuItem = createReactiveComponent(()=>{
|
|
15
|
+
const toast = useToast();
|
|
16
|
+
const { setRouteParams } = useRoute();
|
|
17
|
+
const { canEdit } = usePermission();
|
|
18
|
+
const formPresenter = useContentEntryFormPresenter();
|
|
19
|
+
const session = useCmsEntryReview();
|
|
20
|
+
const { presenter: revisionsPresenter } = useFeature(RevisionsListFeature);
|
|
21
|
+
const { entry, model } = formPresenter.vm;
|
|
22
|
+
const status = session.presenter.vm.status;
|
|
23
|
+
const isStatusUnknown = "loading" === status || "failed" === status;
|
|
24
|
+
const isBlocked = isReviewableModel(model) && isStatusUnknown;
|
|
25
|
+
const onClick = useCallback(async ()=>{
|
|
26
|
+
if (!entry) return;
|
|
27
|
+
const newEntry = await revisionsPresenter.createRevision(entry.id);
|
|
28
|
+
if (!newEntry) return void toast.showWarningToast({
|
|
29
|
+
title: "Could not create a new revision."
|
|
30
|
+
});
|
|
31
|
+
setRouteParams((params)=>({
|
|
32
|
+
...params,
|
|
33
|
+
id: newEntry.id
|
|
34
|
+
}));
|
|
35
|
+
}, [
|
|
36
|
+
entry,
|
|
37
|
+
revisionsPresenter,
|
|
38
|
+
toast,
|
|
39
|
+
setRouteParams
|
|
40
|
+
]);
|
|
41
|
+
if (!entry || !canEdit(entry, "cms.contentEntry")) return null;
|
|
42
|
+
return /*#__PURE__*/ react.createElement(OptionsMenuItem, {
|
|
43
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
44
|
+
disabled: !entry.id || isBlocked,
|
|
45
|
+
label: "Create New Revision",
|
|
46
|
+
onAction: onClick,
|
|
47
|
+
"data-testid": "cms.content-form.header.createNewRevision"
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
const CmsEntryReviewNewRevision = ()=>/*#__PURE__*/ react.createElement(InternalContentEntryEditorConfig, null, /*#__PURE__*/ react.createElement(IsModelPublishable, null, /*#__PURE__*/ react.createElement(Actions.MenuItemAction, {
|
|
51
|
+
name: "createNewRevision",
|
|
52
|
+
element: /*#__PURE__*/ react.createElement(CreateNewRevisionMenuItem, null)
|
|
53
|
+
})));
|
|
54
|
+
export { CmsEntryReviewNewRevision };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=CmsEntryReviewNewRevision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Components/ContentEntryForm/CmsEntryReviewNewRevision.js","sources":["../../../src/Components/ContentEntryForm/CmsEntryReviewNewRevision.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { useFeature } from \"@webiny/app\";\nimport { useRoute } from \"@webiny/app\";\nimport { useToast } from \"@webiny/admin-ui\";\nimport { createReactiveComponent } from \"@webiny/app-admin\";\nimport { OptionsMenuItem } from \"@webiny/app-admin\";\nimport { InternalContentEntryEditorConfig } from \"@webiny/app-headless-cms/admin/config/contentEntries/index.js\";\nimport { IsModelPublishable } from \"@webiny/app-headless-cms/admin/components/IsModelPublishable.js\";\nimport { usePermission } from \"@webiny/app-headless-cms/admin/hooks/usePermission.js\";\nimport { useContentEntryFormPresenter } from \"@webiny/app-headless-cms/presentation/contentEntries/form/useContentEntryFormPresenter.js\";\nimport { RevisionsListFeature } from \"@webiny/app-headless-cms/presentation/contentEntries/revisionsList/feature.js\";\nimport { ReactComponent as NewReleaseIcon } from \"@webiny/icons/new_releases.svg\";\nimport { useCmsEntryReview } from \"~/features/editorReview/useCmsEntryReview.js\";\nimport { isReviewableModel } from \"~/utils/isReviewableModel.js\";\n\nconst { Actions } = InternalContentEntryEditorConfig;\n\nconst CreateNewRevisionMenuItem = createReactiveComponent(() => {\n const toast = useToast();\n const { setRouteParams } = useRoute();\n const { canEdit } = usePermission();\n const formPresenter = useContentEntryFormPresenter();\n const session = useCmsEntryReview();\n const { presenter: revisionsPresenter } = useFeature(RevisionsListFeature);\n\n const { entry, model } = formPresenter.vm;\n const status = session.presenter.vm.status;\n const isStatusUnknown = status === \"loading\" || status === \"failed\";\n const isBlocked = isReviewableModel(model) && isStatusUnknown;\n\n const onClick = useCallback(async () => {\n if (!entry) {\n return;\n }\n\n const newEntry = await revisionsPresenter.createRevision(entry.id);\n\n if (!newEntry) {\n toast.showWarningToast({\n title: \"Could not create a new revision.\"\n });\n return;\n }\n\n setRouteParams(params => {\n return { ...params, id: newEntry.id };\n });\n }, [entry, revisionsPresenter, toast, setRouteParams]);\n\n if (!entry || !canEdit(entry, \"cms.contentEntry\")) {\n return null;\n }\n\n return (\n <OptionsMenuItem\n icon={<NewReleaseIcon />}\n disabled={!entry.id || isBlocked}\n label={`Create New Revision`}\n onAction={onClick}\n data-testid={\"cms.content-form.header.createNewRevision\"}\n />\n );\n});\n\n/*\n * The base \"New Revision\" button needs `canCreateNewRevision`, which the review rules turn off for\n * rejected, approved and in-review revisions. This menu item does not depend on it, so a new\n * revision can always be started once the review status is known (for a rejected revision this is\n * the way, and the bar's lock text names it).\n */\nexport const CmsEntryReviewNewRevision = () => {\n return (\n <InternalContentEntryEditorConfig>\n <IsModelPublishable>\n <Actions.MenuItemAction\n name={\"createNewRevision\"}\n element={<CreateNewRevisionMenuItem />}\n />\n </IsModelPublishable>\n </InternalContentEntryEditorConfig>\n );\n};\n"],"names":["Actions","InternalContentEntryEditorConfig","CreateNewRevisionMenuItem","createReactiveComponent","toast","useToast","setRouteParams","useRoute","canEdit","usePermission","formPresenter","useContentEntryFormPresenter","session","useCmsEntryReview","revisionsPresenter","useFeature","RevisionsListFeature","entry","model","status","isStatusUnknown","isBlocked","isReviewableModel","onClick","useCallback","newEntry","params","OptionsMenuItem","NewReleaseIcon","CmsEntryReviewNewRevision","IsModelPublishable"],"mappings":";;;;;;;;;;;;AAeA,MAAM,EAAEA,SAAAA,OAAO,EAAE,GAAGC;AAEpB,MAAMC,4BAA4BC,wBAAwB;IACtD,MAAMC,QAAQC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGC;IAC3B,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAMC,gBAAgBC;IACtB,MAAMC,UAAUC;IAChB,MAAM,EAAE,WAAWC,kBAAkB,EAAE,GAAGC,WAAWC;IAErD,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGR,cAAc,EAAE;IACzC,MAAMS,SAASP,QAAQ,SAAS,CAAC,EAAE,CAAC,MAAM;IAC1C,MAAMQ,kBAAkBD,AAAW,cAAXA,UAAwBA,AAAW,aAAXA;IAChD,MAAME,YAAYC,kBAAkBJ,UAAUE;IAE9C,MAAMG,UAAUC,YAAY;QACxB,IAAI,CAACP,OACD;QAGJ,MAAMQ,WAAW,MAAMX,mBAAmB,cAAc,CAACG,MAAM,EAAE;QAEjE,IAAI,CAACQ,UAAU,YACXrB,MAAM,gBAAgB,CAAC;YACnB,OAAO;QACX;QAIJE,eAAeoB,CAAAA,SACJ;gBAAE,GAAGA,MAAM;gBAAE,IAAID,SAAS,EAAE;YAAC;IAE5C,GAAG;QAACR;QAAOH;QAAoBV;QAAOE;KAAe;IAErD,IAAI,CAACW,SAAS,CAACT,QAAQS,OAAO,qBAC1B,OAAO;IAGX,OAAO,WAAP,GACI,oBAACU,iBAAeA;QACZ,oBAAM,oBAACC,gBAAcA;QACrB,UAAU,CAACX,MAAM,EAAE,IAAII;QACvB,OAAO;QACP,UAAUE;QACV,eAAa;;AAGzB;AAQO,MAAMM,4BAA4B,IAC9B,WAAP,GACI,oBAAC5B,kCAAgCA,MAAAA,WAAAA,GAC7B,oBAAC6B,oBAAkBA,MAAAA,WAAAA,GACf,oBAAC9B,QAAQ,cAAc;QACnB,MAAM;QACN,uBAAS,oBAACE,2BAAyBA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|