@webiny/app-record-locking 0.0.0-unstable.eb196ccd2f → 0.0.0-unstable.eb81deee7e
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/README.md +8 -9
- package/RecordLockingModule.d.ts +2 -0
- package/RecordLockingModule.js +74 -0
- package/RecordLockingModule.js.map +1 -0
- package/SecurityPermissions.d.ts +2 -0
- package/SecurityPermissions.js +15 -0
- package/SecurityPermissions.js.map +1 -0
- package/features/acquireLock/AcquireLockGateway.d.ts +12 -0
- package/features/acquireLock/AcquireLockGateway.js +43 -0
- package/features/acquireLock/AcquireLockGateway.js.map +1 -0
- package/features/acquireLock/AcquireLockUseCase.d.ts +10 -0
- package/features/acquireLock/AcquireLockUseCase.js +18 -0
- package/features/acquireLock/AcquireLockUseCase.js.map +1 -0
- package/features/acquireLock/abstractions.d.ts +19 -0
- package/features/acquireLock/abstractions.js +6 -0
- package/features/acquireLock/abstractions.js.map +1 -0
- package/features/acquireLock/feature.d.ts +3 -0
- package/features/acquireLock/feature.js +19 -0
- package/features/acquireLock/feature.js.map +1 -0
- package/features/checkLockStatus/CheckLockStatusGateway.d.ts +12 -0
- package/features/checkLockStatus/CheckLockStatusGateway.js +43 -0
- package/features/checkLockStatus/CheckLockStatusGateway.js.map +1 -0
- package/features/checkLockStatus/CheckLockStatusUseCase.d.ts +10 -0
- package/features/checkLockStatus/CheckLockStatusUseCase.js +18 -0
- package/features/checkLockStatus/CheckLockStatusUseCase.js.map +1 -0
- package/features/checkLockStatus/abstractions.d.ts +19 -0
- package/features/checkLockStatus/abstractions.js +6 -0
- package/features/checkLockStatus/abstractions.js.map +1 -0
- package/features/checkLockStatus/feature.d.ts +3 -0
- package/features/checkLockStatus/feature.js +19 -0
- package/features/checkLockStatus/feature.js.map +1 -0
- package/features/feature.d.ts +1 -0
- package/features/feature.js +19 -0
- package/features/feature.js.map +1 -0
- package/features/forceUnlock/ForceUnlockGateway.d.ts +12 -0
- package/features/forceUnlock/ForceUnlockGateway.js +44 -0
- package/features/forceUnlock/ForceUnlockGateway.js.map +1 -0
- package/features/forceUnlock/ForceUnlockUseCase.d.ts +10 -0
- package/features/forceUnlock/ForceUnlockUseCase.js +18 -0
- package/features/forceUnlock/ForceUnlockUseCase.js.map +1 -0
- package/features/forceUnlock/abstractions.d.ts +19 -0
- package/features/forceUnlock/abstractions.js +6 -0
- package/features/forceUnlock/abstractions.js.map +1 -0
- package/features/forceUnlock/feature.d.ts +3 -0
- package/features/forceUnlock/feature.js +19 -0
- package/features/forceUnlock/feature.js.map +1 -0
- package/{domain/graphql/fields.js → features/graphqlFields.js} +4 -3
- package/features/graphqlFields.js.map +1 -0
- package/features/listLockRecords/ListLockRecordsGateway.d.ts +12 -0
- package/features/listLockRecords/ListLockRecordsGateway.js +48 -0
- package/features/listLockRecords/ListLockRecordsGateway.js.map +1 -0
- package/features/listLockRecords/ListLockRecordsUseCase.d.ts +10 -0
- package/features/listLockRecords/ListLockRecordsUseCase.js +18 -0
- package/features/listLockRecords/ListLockRecordsUseCase.js.map +1 -0
- package/features/listLockRecords/abstractions.d.ts +22 -0
- package/features/listLockRecords/abstractions.js +6 -0
- package/features/listLockRecords/abstractions.js.map +1 -0
- package/features/listLockRecords/feature.d.ts +3 -0
- package/features/listLockRecords/feature.js +19 -0
- package/features/listLockRecords/feature.js.map +1 -0
- package/features/permissions/abstractions.d.ts +17 -0
- package/features/permissions/abstractions.js +6 -0
- package/features/permissions/abstractions.js.map +1 -0
- package/features/permissions/feature.d.ts +14 -0
- package/features/permissions/feature.js +7 -0
- package/features/permissions/feature.js.map +1 -0
- package/features/releaseLock/ReleaseLockGateway.d.ts +12 -0
- package/features/releaseLock/ReleaseLockGateway.js +44 -0
- package/features/releaseLock/ReleaseLockGateway.js.map +1 -0
- package/features/releaseLock/ReleaseLockUseCase.d.ts +10 -0
- package/features/releaseLock/ReleaseLockUseCase.js +18 -0
- package/features/releaseLock/ReleaseLockUseCase.js.map +1 -0
- package/features/releaseLock/abstractions.d.ts +19 -0
- package/features/releaseLock/abstractions.js +6 -0
- package/features/releaseLock/abstractions.js.map +1 -0
- package/features/releaseLock/feature.d.ts +3 -0
- package/features/releaseLock/feature.js +19 -0
- package/features/releaseLock/feature.js.map +1 -0
- package/index.d.ts +0 -5
- package/index.js +21 -26
- package/index.js.map +1 -1
- package/package.json +26 -33
- package/permissions/permissionsSchema.d.ts +6 -0
- package/permissions/permissionsSchema.js +10 -0
- package/permissions/permissionsSchema.js.map +1 -0
- package/presentation/entryLocking/ContentEntryFormPresenterDecorator.d.ts +23 -0
- package/presentation/entryLocking/ContentEntryFormPresenterDecorator.js +64 -0
- package/presentation/entryLocking/ContentEntryFormPresenterDecorator.js.map +1 -0
- package/presentation/entryLocking/RecordLockingPresenter.d.ts +32 -0
- package/presentation/entryLocking/RecordLockingPresenter.js +164 -0
- package/presentation/entryLocking/RecordLockingPresenter.js.map +1 -0
- package/presentation/entryLocking/SingleEntryContentDecorator.d.ts +2 -0
- package/presentation/entryLocking/SingleEntryContentDecorator.js +72 -0
- package/presentation/entryLocking/SingleEntryContentDecorator.js.map +1 -0
- package/presentation/entryLocking/SingleEntryPresenterDecorator.d.ts +15 -0
- package/presentation/entryLocking/SingleEntryPresenterDecorator.js +40 -0
- package/presentation/entryLocking/SingleEntryPresenterDecorator.js.map +1 -0
- package/presentation/entryLocking/abstractions.d.ts +26 -0
- package/presentation/entryLocking/abstractions.js +5 -0
- package/presentation/entryLocking/abstractions.js.map +1 -0
- package/presentation/entryLocking/components/ForceUnlockButton.d.ts +11 -0
- package/presentation/entryLocking/components/ForceUnlockButton.js +37 -0
- package/presentation/entryLocking/components/ForceUnlockButton.js.map +1 -0
- package/presentation/entryLocking/components/LockedEntryOverlay.d.ts +10 -0
- package/presentation/entryLocking/components/LockedEntryOverlay.js +52 -0
- package/presentation/entryLocking/components/LockedEntryOverlay.js.map +1 -0
- package/presentation/entryLocking/components/RecordLockingGuard.d.ts +12 -0
- package/presentation/entryLocking/components/RecordLockingGuard.js +74 -0
- package/presentation/entryLocking/components/RecordLockingGuard.js.map +1 -0
- package/presentation/entryLocking/feature.d.ts +3 -0
- package/presentation/entryLocking/feature.js +21 -0
- package/presentation/entryLocking/feature.js.map +1 -0
- package/presentation/listLocking/ContentEntriesPresenterDecorator.d.ts +25 -0
- package/presentation/listLocking/ContentEntriesPresenterDecorator.js +70 -0
- package/presentation/listLocking/ContentEntriesPresenterDecorator.js.map +1 -0
- package/presentation/listLocking/ListLockRecordsPresenter.d.ts +17 -0
- package/presentation/listLocking/ListLockRecordsPresenter.js +52 -0
- package/presentation/listLocking/ListLockRecordsPresenter.js.map +1 -0
- package/presentation/listLocking/abstractions.d.ts +16 -0
- package/presentation/listLocking/abstractions.js +5 -0
- package/presentation/listLocking/abstractions.js.map +1 -0
- package/presentation/listLocking/components/ListLockRecordsSync.d.ts +4 -0
- package/presentation/listLocking/components/ListLockRecordsSync.js +26 -0
- package/presentation/listLocking/components/ListLockRecordsSync.js.map +1 -0
- package/presentation/listLocking/components/LockIndicatorCell.d.ts +2 -0
- package/presentation/listLocking/components/LockIndicatorCell.js +39 -0
- package/presentation/listLocking/components/LockIndicatorCell.js.map +1 -0
- package/presentation/listLocking/feature.d.ts +3 -0
- package/presentation/listLocking/feature.js +19 -0
- package/presentation/listLocking/feature.js.map +1 -0
- package/types.d.ts +5 -49
- package/types.js +0 -3
- package/components/HeadlessCmsActionsAcoCell.d.ts +0 -2
- package/components/HeadlessCmsActionsAcoCell.js +0 -60
- package/components/HeadlessCmsActionsAcoCell.js.map +0 -1
- package/components/HeadlessCmsContentEntry/ContentEntryGuard.d.ts +0 -9
- package/components/HeadlessCmsContentEntry/ContentEntryGuard.js +0 -40
- package/components/HeadlessCmsContentEntry/ContentEntryGuard.js.map +0 -1
- package/components/HeadlessCmsContentEntry/ContentEntryLocker.d.ts +0 -18
- package/components/HeadlessCmsContentEntry/ContentEntryLocker.js +0 -106
- package/components/HeadlessCmsContentEntry/ContentEntryLocker.js.map +0 -1
- package/components/HeadlessCmsContentEntry/HeadlessCmsContentEntry.d.ts +0 -2
- package/components/HeadlessCmsContentEntry/HeadlessCmsContentEntry.js +0 -90
- package/components/HeadlessCmsContentEntry/HeadlessCmsContentEntry.js.map +0 -1
- package/components/HeadlessCmsContentEntry/index.d.ts +0 -1
- package/components/HeadlessCmsContentEntry/index.js +0 -3
- package/components/HeadlessCmsContentEntry/index.js.map +0 -1
- package/components/LockedRecord/LockedRecord.d.ts +0 -6
- package/components/LockedRecord/LockedRecord.js +0 -66
- package/components/LockedRecord/LockedRecord.js.map +0 -1
- package/components/LockedRecord/LockedRecordForceUnlock.d.ts +0 -9
- package/components/LockedRecord/LockedRecordForceUnlock.js +0 -75
- package/components/LockedRecord/LockedRecordForceUnlock.js.map +0 -1
- package/components/LockedRecord/index.d.ts +0 -1
- package/components/LockedRecord/index.js +0 -3
- package/components/LockedRecord/index.js.map +0 -1
- package/components/RecordLockingProvider.d.ts +0 -7
- package/components/RecordLockingProvider.js +0 -125
- package/components/RecordLockingProvider.js.map +0 -1
- package/components/decorators/UseContentEntriesListHookDecorator.d.ts +0 -2
- package/components/decorators/UseContentEntriesListHookDecorator.js +0 -21
- package/components/decorators/UseContentEntriesListHookDecorator.js.map +0 -1
- package/components/decorators/UseRecordsDecorator.d.ts +0 -9
- package/components/decorators/UseRecordsDecorator.js +0 -25
- package/components/decorators/UseRecordsDecorator.js.map +0 -1
- package/components/decorators/UseSaveEntryDecorator.d.ts +0 -2
- package/components/decorators/UseSaveEntryDecorator.js +0 -55
- package/components/decorators/UseSaveEntryDecorator.js.map +0 -1
- package/components/permissionRenderer/RecordLockingPermissions.d.ts +0 -7
- package/components/permissionRenderer/RecordLockingPermissions.js +0 -71
- package/components/permissionRenderer/RecordLockingPermissions.js.map +0 -1
- package/components/permissionRenderer/index.d.ts +0 -2
- package/components/permissionRenderer/index.js +0 -21
- package/components/permissionRenderer/index.js.map +0 -1
- package/domain/RecordLocking.d.ts +0 -28
- package/domain/RecordLocking.js +0 -320
- package/domain/RecordLocking.js.map +0 -1
- package/domain/RecordLockingClient.d.ts +0 -12
- package/domain/RecordLockingClient.js +0 -19
- package/domain/RecordLockingClient.js.map +0 -1
- package/domain/RecordLockingGetLockRecord.d.ts +0 -11
- package/domain/RecordLockingGetLockRecord.js +0 -21
- package/domain/RecordLockingGetLockRecord.js.map +0 -1
- package/domain/RecordLockingGetLockedEntryLockRecord.d.ts +0 -11
- package/domain/RecordLockingGetLockedEntryLockRecord.js +0 -19
- package/domain/RecordLockingGetLockedEntryLockRecord.js.map +0 -1
- package/domain/RecordLockingIsEntryLocked.d.ts +0 -11
- package/domain/RecordLockingIsEntryLocked.js +0 -19
- package/domain/RecordLockingIsEntryLocked.js.map +0 -1
- package/domain/RecordLockingListLockRecords.d.ts +0 -12
- package/domain/RecordLockingListLockRecords.js +0 -31
- package/domain/RecordLockingListLockRecords.js.map +0 -1
- package/domain/RecordLockingLockEntry.d.ts +0 -11
- package/domain/RecordLockingLockEntry.js +0 -15
- package/domain/RecordLockingLockEntry.js.map +0 -1
- package/domain/RecordLockingUnlockEntry.d.ts +0 -11
- package/domain/RecordLockingUnlockEntry.js +0 -19
- package/domain/RecordLockingUnlockEntry.js.map +0 -1
- package/domain/RecordLockingUpdateEntryLock.d.ts +0 -11
- package/domain/RecordLockingUpdateEntryLock.js +0 -19
- package/domain/RecordLockingUpdateEntryLock.js.map +0 -1
- package/domain/abstractions/IRecordLocking.d.ts +0 -25
- package/domain/abstractions/IRecordLocking.js +0 -3
- package/domain/abstractions/IRecordLocking.js.map +0 -1
- package/domain/abstractions/IRecordLockingClient.d.ts +0 -6
- package/domain/abstractions/IRecordLockingClient.js +0 -3
- package/domain/abstractions/IRecordLockingClient.js.map +0 -1
- package/domain/abstractions/IRecordLockingGetLockRecord.d.ts +0 -12
- package/domain/abstractions/IRecordLockingGetLockRecord.js +0 -3
- package/domain/abstractions/IRecordLockingGetLockRecord.js.map +0 -1
- package/domain/abstractions/IRecordLockingGetLockedEntryLockRecord.d.ts +0 -12
- package/domain/abstractions/IRecordLockingGetLockedEntryLockRecord.js +0 -3
- package/domain/abstractions/IRecordLockingGetLockedEntryLockRecord.js.map +0 -1
- package/domain/abstractions/IRecordLockingIsEntryLocked.d.ts +0 -8
- package/domain/abstractions/IRecordLockingIsEntryLocked.js +0 -3
- package/domain/abstractions/IRecordLockingIsEntryLocked.js.map +0 -1
- package/domain/abstractions/IRecordLockingListLockRecords.d.ts +0 -19
- package/domain/abstractions/IRecordLockingListLockRecords.js +0 -3
- package/domain/abstractions/IRecordLockingListLockRecords.js.map +0 -1
- package/domain/abstractions/IRecordLockingLockEntry.d.ts +0 -12
- package/domain/abstractions/IRecordLockingLockEntry.js +0 -3
- package/domain/abstractions/IRecordLockingLockEntry.js.map +0 -1
- package/domain/abstractions/IRecordLockingUnlockEntry.d.ts +0 -13
- package/domain/abstractions/IRecordLockingUnlockEntry.js +0 -3
- package/domain/abstractions/IRecordLockingUnlockEntry.js.map +0 -1
- package/domain/abstractions/IRecordLockingUpdateEntryLock.d.ts +0 -12
- package/domain/abstractions/IRecordLockingUpdateEntryLock.js +0 -3
- package/domain/abstractions/IRecordLockingUpdateEntryLock.js.map +0 -1
- package/domain/graphql/fields.js.map +0 -1
- package/domain/graphql/getLockRecord.d.ts +0 -12
- package/domain/graphql/getLockRecord.js +0 -18
- package/domain/graphql/getLockRecord.js.map +0 -1
- package/domain/graphql/getLockedEntryLockRecord.d.ts +0 -12
- package/domain/graphql/getLockedEntryLockRecord.js +0 -18
- package/domain/graphql/getLockedEntryLockRecord.js.map +0 -1
- package/domain/graphql/isEntryLocked.d.ts +0 -12
- package/domain/graphql/isEntryLocked.js +0 -16
- package/domain/graphql/isEntryLocked.js.map +0 -1
- package/domain/graphql/listLockRecords.d.ts +0 -17
- package/domain/graphql/listLockRecords.js +0 -26
- package/domain/graphql/listLockRecords.js.map +0 -1
- package/domain/graphql/lockEntry.d.ts +0 -12
- package/domain/graphql/lockEntry.js +0 -20
- package/domain/graphql/lockEntry.js.map +0 -1
- package/domain/graphql/unlockEntry.d.ts +0 -12
- package/domain/graphql/unlockEntry.js +0 -18
- package/domain/graphql/unlockEntry.js.map +0 -1
- package/domain/graphql/updateEntryLock.d.ts +0 -12
- package/domain/graphql/updateEntryLock.js +0 -18
- package/domain/graphql/updateEntryLock.js.map +0 -1
- package/domain/utils/createRecordLockingClient.d.ts +0 -3
- package/domain/utils/createRecordLockingClient.js +0 -12
- package/domain/utils/createRecordLockingClient.js.map +0 -1
- package/domain/utils/createRecordLockingError.d.ts +0 -6
- package/domain/utils/createRecordLockingError.js +0 -16
- package/domain/utils/createRecordLockingError.js.map +0 -1
- package/hooks/index.d.ts +0 -2
- package/hooks/index.js +0 -4
- package/hooks/index.js.map +0 -1
- package/hooks/usePermission.d.ts +0 -3
- package/hooks/usePermission.js +0 -21
- package/hooks/usePermission.js.map +0 -1
- package/hooks/useRecordLocking.d.ts +0 -2
- package/hooks/useRecordLocking.js +0 -12
- package/hooks/useRecordLocking.js.map +0 -1
- package/types.js.map +0 -1
- package/utils/createCacheKey.d.ts +0 -3
- package/utils/createCacheKey.js +0 -15
- package/utils/createCacheKey.js.map +0 -1
- /package/{domain/graphql/fields.d.ts → features/graphqlFields.d.ts} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import react, { useCallback } from "react";
|
|
2
|
+
import { Alert, Button, Text } from "@webiny/admin-ui";
|
|
3
|
+
import { useConfirmationDialog, useSnackbar } from "@webiny/app-admin";
|
|
4
|
+
const ForceUnlockButton = ({ canForceUnlock, lockedBy, entryTitle, onForceUnlock, onNavigateBack })=>{
|
|
5
|
+
const { showSnackbar } = useSnackbar();
|
|
6
|
+
const { showConfirmation } = useConfirmationDialog({
|
|
7
|
+
title: "Force unlock the entry",
|
|
8
|
+
message: /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement(Alert, {
|
|
9
|
+
type: "warning",
|
|
10
|
+
title: "Warning",
|
|
11
|
+
className: "mb-md"
|
|
12
|
+
}, /*#__PURE__*/ react.createElement("strong", null, lockedBy?.displayName || "Unknown user"), " is currently editing this record.", /*#__PURE__*/ react.createElement("br", null), "If you force unlock it, they could potentially lose their changes."), /*#__PURE__*/ react.createElement(Text, null, "You are about to forcefully unlock the ", /*#__PURE__*/ react.createElement("strong", null, entryTitle || "entry"), ". Are you sure you want to continue?"))
|
|
13
|
+
});
|
|
14
|
+
const onClick = useCallback(()=>{
|
|
15
|
+
showConfirmation(async ()=>{
|
|
16
|
+
const success = await onForceUnlock();
|
|
17
|
+
if (!success) return void showSnackbar("Failed to force unlock the entry.");
|
|
18
|
+
onNavigateBack();
|
|
19
|
+
});
|
|
20
|
+
}, [
|
|
21
|
+
onForceUnlock,
|
|
22
|
+
onNavigateBack
|
|
23
|
+
]);
|
|
24
|
+
if (!canForceUnlock) return null;
|
|
25
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
26
|
+
className: "mt-md"
|
|
27
|
+
}, /*#__PURE__*/ react.createElement(Text, {
|
|
28
|
+
as: "div",
|
|
29
|
+
className: "mb-md"
|
|
30
|
+
}, "Because you have full access to the system, you can force unlock the record."), /*#__PURE__*/ react.createElement(Button, {
|
|
31
|
+
onClick: onClick,
|
|
32
|
+
text: "Unlock and go back"
|
|
33
|
+
}));
|
|
34
|
+
};
|
|
35
|
+
export { ForceUnlockButton };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=ForceUnlockButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/entryLocking/components/ForceUnlockButton.js","sources":["../../../../src/presentation/entryLocking/components/ForceUnlockButton.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { Alert, Button, Text } from \"@webiny/admin-ui\";\nimport { useConfirmationDialog, useSnackbar } from \"@webiny/app-admin\";\nimport type { IRecordLockingIdentity } from \"~/types.js\";\n\ninterface ForceUnlockButtonProps {\n canForceUnlock: boolean;\n lockedBy: IRecordLockingIdentity | null;\n entryTitle?: string;\n onForceUnlock: () => Promise<boolean>;\n onNavigateBack: () => void;\n}\n\nexport const ForceUnlockButton = ({\n canForceUnlock,\n lockedBy,\n entryTitle,\n onForceUnlock,\n onNavigateBack\n}: ForceUnlockButtonProps) => {\n const { showSnackbar } = useSnackbar();\n const { showConfirmation } = useConfirmationDialog({\n title: \"Force unlock the entry\",\n message: (\n <div>\n <Alert type=\"warning\" title=\"Warning\" className={\"mb-md\"}>\n <strong>{lockedBy?.displayName || \"Unknown user\"}</strong> is currently editing\n this record.\n <br />\n If you force unlock it, they could potentially lose their changes.\n </Alert>\n <Text>\n You are about to forcefully unlock the <strong>{entryTitle || \"entry\"}</strong>.\n Are you sure you want to continue?\n </Text>\n </div>\n )\n });\n\n const onClick = useCallback(() => {\n showConfirmation(async () => {\n const success = await onForceUnlock();\n if (!success) {\n showSnackbar(\"Failed to force unlock the entry.\");\n return;\n }\n onNavigateBack();\n });\n }, [onForceUnlock, onNavigateBack]);\n\n if (!canForceUnlock) {\n return null;\n }\n\n return (\n <div className=\"mt-md\">\n <Text as={\"div\"} className={\"mb-md\"}>\n Because you have full access to the system, you can force unlock the record.\n </Text>\n <Button onClick={onClick} text={\"Unlock and go back\"} />\n </div>\n );\n};\n"],"names":["ForceUnlockButton","canForceUnlock","lockedBy","entryTitle","onForceUnlock","onNavigateBack","showSnackbar","useSnackbar","showConfirmation","useConfirmationDialog","Alert","Text","onClick","useCallback","success","Button"],"mappings":";;;AAaO,MAAMA,oBAAoB,CAAC,EAC9BC,cAAc,EACdC,QAAQ,EACRC,UAAU,EACVC,aAAa,EACbC,cAAc,EACO;IACrB,MAAM,EAAEC,YAAY,EAAE,GAAGC;IACzB,MAAM,EAAEC,gBAAgB,EAAE,GAAGC,sBAAsB;QAC/C,OAAO;QACP,SAAS,WAAT,GACI,oBAAC,2BACG,oBAACC,OAAKA;YAAC,MAAK;YAAU,OAAM;YAAU,WAAW;yBAC7C,oBAAC,gBAAQR,UAAU,eAAe,iBAAwB,oDAE1D,oBAAC,aAAK,qFAGV,oBAACS,MAAIA,MAAC,yDACqC,oBAAC,gBAAQR,cAAc,UAAiB;IAK/F;IAEA,MAAMS,UAAUC,YAAY;QACxBL,iBAAiB;YACb,MAAMM,UAAU,MAAMV;YACtB,IAAI,CAACU,SAAS,YACVR,aAAa;YAGjBD;QACJ;IACJ,GAAG;QAACD;QAAeC;KAAe;IAElC,IAAI,CAACJ,gBACD,OAAO;IAGX,OAAO,WAAP,GACI,oBAAC;QAAI,WAAU;qBACX,oBAACU,MAAIA;QAAC,IAAI;QAAO,WAAW;OAAS,+FAGrC,oBAACI,QAAMA;QAAC,SAASH;QAAS,MAAM;;AAG5C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { IRecordLockingViewModel } from "../abstractions.js";
|
|
3
|
+
interface LockedEntryOverlayProps {
|
|
4
|
+
vm: IRecordLockingViewModel;
|
|
5
|
+
entryTitle?: string;
|
|
6
|
+
onForceUnlock: () => Promise<boolean>;
|
|
7
|
+
onNavigateBack: () => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const LockedEntryOverlay: ({ vm, entryTitle, onForceUnlock, onNavigateBack }: LockedEntryOverlayProps) => React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { ReactComponent } from "@webiny/icons/lock.svg";
|
|
3
|
+
import { Grid, Heading, Icon, Text } from "@webiny/admin-ui";
|
|
4
|
+
import { ForceUnlockButton } from "./ForceUnlockButton.js";
|
|
5
|
+
const LockedEntryOverlay = ({ vm, entryTitle, onForceUnlock, onNavigateBack })=>{
|
|
6
|
+
const title = entryTitle ? `Record (${entryTitle}) is locked!` : "Record is locked!";
|
|
7
|
+
if (!vm.lockRecord?.lockedBy) return /*#__PURE__*/ react.createElement(Wrapper, null, /*#__PURE__*/ react.createElement(Heading, {
|
|
8
|
+
level: 4,
|
|
9
|
+
className: "mb-sm"
|
|
10
|
+
}, title), /*#__PURE__*/ react.createElement(Text, null, "This record is locked, but the system cannot find the user that created the record lock. A force-unlock is required to regain editing capabilities for this record."), /*#__PURE__*/ react.createElement(ForceUnlockButton, {
|
|
11
|
+
canForceUnlock: vm.canForceUnlock,
|
|
12
|
+
lockedBy: null,
|
|
13
|
+
entryTitle: entryTitle,
|
|
14
|
+
onForceUnlock: onForceUnlock,
|
|
15
|
+
onNavigateBack: onNavigateBack
|
|
16
|
+
}));
|
|
17
|
+
return /*#__PURE__*/ react.createElement(Wrapper, null, /*#__PURE__*/ react.createElement(Heading, {
|
|
18
|
+
level: 4,
|
|
19
|
+
className: "mb-sm"
|
|
20
|
+
}, title), /*#__PURE__*/ react.createElement(Text, null, "It is locked because ", /*#__PURE__*/ react.createElement("strong", null, vm.lockedByUserName), " is currently editing this record. You can either contact the user and ask them to unlock the record, or you can wait for the lock to expire."), /*#__PURE__*/ react.createElement(ForceUnlockButton, {
|
|
21
|
+
canForceUnlock: vm.canForceUnlock,
|
|
22
|
+
lockedBy: vm.lockRecord.lockedBy,
|
|
23
|
+
entryTitle: entryTitle,
|
|
24
|
+
onForceUnlock: onForceUnlock,
|
|
25
|
+
onNavigateBack: onNavigateBack
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
const Wrapper = ({ children })=>/*#__PURE__*/ react.createElement("div", {
|
|
29
|
+
className: "w-5/12 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50"
|
|
30
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
31
|
+
className: "flex p-lg border-sm border-neutral-dimmed-darker rounded-3xl bg-neutral-base"
|
|
32
|
+
}, /*#__PURE__*/ react.createElement(Grid, null, /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
33
|
+
span: 3
|
|
34
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
35
|
+
className: "h-full flex items-center justify-center bg-neutral-dimmed rounded-md p-lg"
|
|
36
|
+
}, /*#__PURE__*/ react.createElement(Icon, {
|
|
37
|
+
style: {
|
|
38
|
+
width: "64px",
|
|
39
|
+
height: "64px"
|
|
40
|
+
},
|
|
41
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
42
|
+
label: "Locked Record",
|
|
43
|
+
color: "accent",
|
|
44
|
+
size: "lg"
|
|
45
|
+
}))), /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
46
|
+
span: 9
|
|
47
|
+
}, /*#__PURE__*/ react.createElement("div", {
|
|
48
|
+
className: "flex flex-col justify-center"
|
|
49
|
+
}, children)))));
|
|
50
|
+
export { LockedEntryOverlay };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=LockedEntryOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/entryLocking/components/LockedEntryOverlay.js","sources":["../../../../src/presentation/entryLocking/components/LockedEntryOverlay.tsx"],"sourcesContent":["import React from \"react\";\nimport { ReactComponent as LockIcon } from \"@webiny/icons/lock.svg\";\nimport { Grid, Heading, Icon, Text } from \"@webiny/admin-ui\";\nimport { ForceUnlockButton } from \"./ForceUnlockButton.js\";\nimport type { IRecordLockingViewModel } from \"../abstractions.js\";\n\ninterface LockedEntryOverlayProps {\n vm: IRecordLockingViewModel;\n entryTitle?: string;\n onForceUnlock: () => Promise<boolean>;\n onNavigateBack: () => void;\n}\n\nexport const LockedEntryOverlay = ({\n vm,\n entryTitle,\n onForceUnlock,\n onNavigateBack\n}: LockedEntryOverlayProps) => {\n const title = entryTitle ? `Record (${entryTitle}) is locked!` : \"Record is locked!\";\n\n if (!vm.lockRecord?.lockedBy) {\n return (\n <Wrapper>\n <Heading level={4} className={\"mb-sm\"}>\n {title}\n </Heading>\n <Text>\n This record is locked, but the system cannot find the user that created the\n record lock. A force-unlock is required to regain editing capabilities for this\n record.\n </Text>\n <ForceUnlockButton\n canForceUnlock={vm.canForceUnlock}\n lockedBy={null}\n entryTitle={entryTitle}\n onForceUnlock={onForceUnlock}\n onNavigateBack={onNavigateBack}\n />\n </Wrapper>\n );\n }\n\n return (\n <Wrapper>\n <Heading level={4} className={\"mb-sm\"}>\n {title}\n </Heading>\n <Text>\n It is locked because <strong>{vm.lockedByUserName}</strong> is currently editing\n this record. You can either contact the user and ask them to unlock the record, or\n you can wait for the lock to expire.\n </Text>\n <ForceUnlockButton\n canForceUnlock={vm.canForceUnlock}\n lockedBy={vm.lockRecord.lockedBy}\n entryTitle={entryTitle}\n onForceUnlock={onForceUnlock}\n onNavigateBack={onNavigateBack}\n />\n </Wrapper>\n );\n};\n\nconst Wrapper = ({ children }: { children: React.ReactNode }) => {\n return (\n <div className=\"w-5/12 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50\">\n <div\n className={\n \"flex p-lg border-sm border-neutral-dimmed-darker rounded-3xl bg-neutral-base\"\n }\n >\n <Grid>\n <Grid.Column span={3}>\n <div className=\"h-full flex items-center justify-center bg-neutral-dimmed rounded-md p-lg\">\n <Icon\n style={{ width: \"64px\", height: \"64px\" }}\n icon={<LockIcon />}\n label={\"Locked Record\"}\n color={\"accent\"}\n size={\"lg\"}\n />\n </div>\n </Grid.Column>\n <Grid.Column span={9}>\n <div className={\"flex flex-col justify-center\"}>{children}</div>\n </Grid.Column>\n </Grid>\n </div>\n </div>\n );\n};\n"],"names":["LockedEntryOverlay","vm","entryTitle","onForceUnlock","onNavigateBack","title","Wrapper","Heading","Text","ForceUnlockButton","children","Grid","Icon","LockIcon"],"mappings":";;;;AAaO,MAAMA,qBAAqB,CAAC,EAC/BC,EAAE,EACFC,UAAU,EACVC,aAAa,EACbC,cAAc,EACQ;IACtB,MAAMC,QAAQH,aAAa,CAAC,QAAQ,EAAEA,WAAW,YAAY,CAAC,GAAG;IAEjE,IAAI,CAACD,GAAG,UAAU,EAAE,UAChB,OAAO,WAAP,GACI,oBAACK,SAAOA,MAAAA,WAAAA,GACJ,oBAACC,SAAOA;QAAC,OAAO;QAAG,WAAW;OACzBF,QAAAA,WAAAA,GAEL,oBAACG,MAAIA,MAAC,sLAKN,oBAACC,mBAAiBA;QACd,gBAAgBR,GAAG,cAAc;QACjC,UAAU;QACV,YAAYC;QACZ,eAAeC;QACf,gBAAgBC;;IAMhC,OAAO,WAAP,GACI,oBAACE,SAAOA,MAAAA,WAAAA,GACJ,oBAACC,SAAOA;QAAC,OAAO;QAAG,WAAW;OACzBF,QAAAA,WAAAA,GAEL,oBAACG,MAAIA,MAAC,uCACmB,oBAAC,gBAAQP,GAAG,gBAAgB,GAAU,gKAI/D,oBAACQ,mBAAiBA;QACd,gBAAgBR,GAAG,cAAc;QACjC,UAAUA,GAAG,UAAU,CAAC,QAAQ;QAChC,YAAYC;QACZ,eAAeC;QACf,gBAAgBC;;AAIhC;AAEA,MAAME,UAAU,CAAC,EAAEI,QAAQ,EAAiC,GACjD,WAAP,GACI,oBAAC;QAAI,WAAU;qBACX,oBAAC;QACG,WACI;qBAGJ,oBAACC,MAAIA,MAAAA,WAAAA,GACD,oBAACA,KAAK,MAAM;QAAC,MAAM;qBACf,oBAAC;QAAI,WAAU;qBACX,oBAACC,MAAIA;QACD,OAAO;YAAE,OAAO;YAAQ,QAAQ;QAAO;QACvC,oBAAM,oBAACC,gBAAQA;QACf,OAAO;QACP,OAAO;QACP,MAAM;wBAIlB,oBAACF,KAAK,MAAM;QAAC,MAAM;qBACf,oBAAC;QAAI,WAAW;OAAiCD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface RecordLockingGuardProps {
|
|
3
|
+
entryId: string;
|
|
4
|
+
modelId: string;
|
|
5
|
+
entryTitle?: string;
|
|
6
|
+
onNavigateBack: () => void;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare const RecordLockingGuard: (({ entryId, modelId, entryTitle, onNavigateBack, children }: RecordLockingGuardProps) => React.JSX.Element) & React.NamedExoticComponent<RecordLockingGuardProps> & {
|
|
10
|
+
readonly type: ({ entryId, modelId, entryTitle, onNavigateBack, children }: RecordLockingGuardProps) => React.JSX.Element;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import react, { useEffect } from "react";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
3
|
+
import { useContainer, useRouter } from "@webiny/app";
|
|
4
|
+
import { useDialogs } from "@webiny/app-admin";
|
|
5
|
+
import { OverlayLoader } from "@webiny/admin-ui";
|
|
6
|
+
import { useWebsockets } from "@webiny/app-websockets";
|
|
7
|
+
import { parseIdentifier } from "@webiny/utils";
|
|
8
|
+
import { RecordLockingPresenter } from "../abstractions.js";
|
|
9
|
+
import { LockedEntryOverlay } from "./LockedEntryOverlay.js";
|
|
10
|
+
const RecordLockingGuard = observer(({ entryId, modelId, entryTitle, onNavigateBack, children })=>{
|
|
11
|
+
const container = useContainer();
|
|
12
|
+
const presenter = react.useMemo(()=>container.resolve(RecordLockingPresenter), [
|
|
13
|
+
container
|
|
14
|
+
]);
|
|
15
|
+
const websockets = useWebsockets();
|
|
16
|
+
const router = useRouter();
|
|
17
|
+
const { showDialog } = useDialogs();
|
|
18
|
+
useEffect(()=>{
|
|
19
|
+
presenter.init(entryId, modelId);
|
|
20
|
+
return ()=>{
|
|
21
|
+
presenter.dispose();
|
|
22
|
+
};
|
|
23
|
+
}, [
|
|
24
|
+
entryId,
|
|
25
|
+
modelId
|
|
26
|
+
]);
|
|
27
|
+
useEffect(()=>{
|
|
28
|
+
const { id } = parseIdentifier(entryId);
|
|
29
|
+
const sub = websockets.onMessage(`recordLocking.entry.kickOut.${id}`, (incoming)=>{
|
|
30
|
+
presenter.handleKickOut(incoming.data);
|
|
31
|
+
});
|
|
32
|
+
return ()=>{
|
|
33
|
+
sub.off();
|
|
34
|
+
};
|
|
35
|
+
}, [
|
|
36
|
+
entryId,
|
|
37
|
+
modelId
|
|
38
|
+
]);
|
|
39
|
+
useEffect(()=>{
|
|
40
|
+
if ("kicked-out" !== presenter.vm.status) return;
|
|
41
|
+
router.unblockTransition();
|
|
42
|
+
showDialog({
|
|
43
|
+
title: "Entry was forcefully unlocked!",
|
|
44
|
+
content: /*#__PURE__*/ react.createElement(react.Fragment, null, "The entry you were editing was forcefully unlocked by", " ", /*#__PURE__*/ react.createElement("strong", null, presenter.vm.lockRecord?.lockedBy?.displayName || "Unknown user"), ". Unfortunately, this means you lost the unsaved changes."),
|
|
45
|
+
acceptLabel: "Ok",
|
|
46
|
+
onClose: void 0,
|
|
47
|
+
cancelLabel: null
|
|
48
|
+
});
|
|
49
|
+
onNavigateBack();
|
|
50
|
+
}, [
|
|
51
|
+
presenter.vm.status
|
|
52
|
+
]);
|
|
53
|
+
const { vm } = presenter;
|
|
54
|
+
if ("checking" === vm.status) return /*#__PURE__*/ react.createElement("div", {
|
|
55
|
+
className: "h-screen w-screen fixed top-0 left-0 z-20"
|
|
56
|
+
}, /*#__PURE__*/ react.createElement(OverlayLoader, {
|
|
57
|
+
text: "Checking record status..."
|
|
58
|
+
}));
|
|
59
|
+
if ("locked" === vm.status) return /*#__PURE__*/ react.createElement(LockedEntryOverlay, {
|
|
60
|
+
vm: vm,
|
|
61
|
+
entryTitle: entryTitle,
|
|
62
|
+
onForceUnlock: ()=>presenter.forceUnlock(),
|
|
63
|
+
onNavigateBack: onNavigateBack
|
|
64
|
+
});
|
|
65
|
+
if ("error" === vm.status) return /*#__PURE__*/ react.createElement("div", {
|
|
66
|
+
className: "h-screen w-screen fixed top-0 left-0 z-20"
|
|
67
|
+
}, /*#__PURE__*/ react.createElement(OverlayLoader, {
|
|
68
|
+
text: "Failed to check record lock status."
|
|
69
|
+
}));
|
|
70
|
+
return /*#__PURE__*/ react.createElement(react.Fragment, null, children);
|
|
71
|
+
});
|
|
72
|
+
export { RecordLockingGuard };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=RecordLockingGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/entryLocking/components/RecordLockingGuard.js","sources":["../../../../src/presentation/entryLocking/components/RecordLockingGuard.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useContainer, useRouter } from \"@webiny/app\";\nimport { useDialogs } from \"@webiny/app-admin\";\nimport { OverlayLoader } from \"@webiny/admin-ui\";\nimport { useWebsockets } from \"@webiny/app-websockets\";\nimport { parseIdentifier } from \"@webiny/utils\";\nimport { RecordLockingPresenter } from \"../abstractions.js\";\nimport { LockedEntryOverlay } from \"./LockedEntryOverlay.js\";\nimport type { IKickOutData } from \"../abstractions.js\";\nimport type { IncomingGenericData } from \"@webiny/app-websockets\";\n\ninterface KickOutMessage extends IncomingGenericData {\n data: IKickOutData;\n}\n\ninterface RecordLockingGuardProps {\n entryId: string;\n modelId: string;\n entryTitle?: string;\n onNavigateBack: () => void;\n children: React.ReactNode;\n}\n\nexport const RecordLockingGuard = observer(\n ({ entryId, modelId, entryTitle, onNavigateBack, children }: RecordLockingGuardProps) => {\n const container = useContainer();\n const presenter = React.useMemo(\n () => container.resolve(RecordLockingPresenter),\n [container]\n );\n const websockets = useWebsockets();\n const router = useRouter();\n const { showDialog } = useDialogs();\n\n useEffect(() => {\n presenter.init(entryId, modelId);\n\n return () => {\n presenter.dispose();\n };\n }, [entryId, modelId]);\n\n useEffect(() => {\n const { id } = parseIdentifier(entryId);\n\n const sub = websockets.onMessage<KickOutMessage>(\n `recordLocking.entry.kickOut.${id}`,\n incoming => {\n presenter.handleKickOut(incoming.data);\n }\n );\n\n return () => {\n sub.off();\n };\n }, [entryId, modelId]);\n\n useEffect(() => {\n if (presenter.vm.status !== \"kicked-out\") {\n return;\n }\n\n router.unblockTransition();\n\n showDialog({\n title: \"Entry was forcefully unlocked!\",\n content: (\n <>\n The entry you were editing was forcefully unlocked by{\" \"}\n <strong>\n {presenter.vm.lockRecord?.lockedBy?.displayName || \"Unknown user\"}\n </strong>\n . Unfortunately, this means you lost the unsaved changes.\n </>\n ),\n acceptLabel: \"Ok\",\n onClose: undefined,\n cancelLabel: null\n });\n\n onNavigateBack();\n }, [presenter.vm.status]);\n\n const { vm } = presenter;\n\n if (vm.status === \"checking\") {\n return (\n <div className={\"h-screen w-screen fixed top-0 left-0 z-20\"}>\n <OverlayLoader text={\"Checking record status...\"} />\n </div>\n );\n }\n\n if (vm.status === \"locked\") {\n return (\n <LockedEntryOverlay\n vm={vm}\n entryTitle={entryTitle}\n onForceUnlock={() => presenter.forceUnlock()}\n onNavigateBack={onNavigateBack}\n />\n );\n }\n\n if (vm.status === \"error\") {\n return (\n <div className={\"h-screen w-screen fixed top-0 left-0 z-20\"}>\n <OverlayLoader text={\"Failed to check record lock status.\"} />\n </div>\n );\n }\n\n return <>{children}</>;\n }\n);\n"],"names":["RecordLockingGuard","observer","entryId","modelId","entryTitle","onNavigateBack","children","container","useContainer","presenter","React","RecordLockingPresenter","websockets","useWebsockets","router","useRouter","showDialog","useDialogs","useEffect","id","parseIdentifier","sub","incoming","undefined","vm","OverlayLoader","LockedEntryOverlay"],"mappings":";;;;;;;;;AAwBO,MAAMA,qBAAqBC,SAC9B,CAAC,EAAEC,OAAO,EAAEC,OAAO,EAAEC,UAAU,EAAEC,cAAc,EAAEC,QAAQ,EAA2B;IAChF,MAAMC,YAAYC;IAClB,MAAMC,YAAYC,MAAAA,OAAa,CAC3B,IAAMH,UAAU,OAAO,CAACI,yBACxB;QAACJ;KAAU;IAEf,MAAMK,aAAaC;IACnB,MAAMC,SAASC;IACf,MAAM,EAAEC,UAAU,EAAE,GAAGC;IAEvBC,UAAU;QACNT,UAAU,IAAI,CAACP,SAASC;QAExB,OAAO;YACHM,UAAU,OAAO;QACrB;IACJ,GAAG;QAACP;QAASC;KAAQ;IAErBe,UAAU;QACN,MAAM,EAAEC,EAAE,EAAE,GAAGC,gBAAgBlB;QAE/B,MAAMmB,MAAMT,WAAW,SAAS,CAC5B,CAAC,4BAA4B,EAAEO,IAAI,EACnCG,CAAAA;YACIb,UAAU,aAAa,CAACa,SAAS,IAAI;QACzC;QAGJ,OAAO;YACHD,IAAI,GAAG;QACX;IACJ,GAAG;QAACnB;QAASC;KAAQ;IAErBe,UAAU;QACN,IAAIT,AAAwB,iBAAxBA,UAAU,EAAE,CAAC,MAAM,EACnB;QAGJK,OAAO,iBAAiB;QAExBE,WAAW;YACP,OAAO;YACP,SAAS,WAAT,GACI,0CAAE,yDACwD,mBACtD,oBAAC,gBACIP,UAAU,EAAE,CAAC,UAAU,EAAE,UAAU,eAAe,iBAC9C;YAIjB,aAAa;YACb,SAASc;YACT,aAAa;QACjB;QAEAlB;IACJ,GAAG;QAACI,UAAU,EAAE,CAAC,MAAM;KAAC;IAExB,MAAM,EAAEe,EAAE,EAAE,GAAGf;IAEf,IAAIe,AAAc,eAAdA,GAAG,MAAM,EACT,OAAO,WAAP,GACI,oBAAC;QAAI,WAAW;qBACZ,oBAACC,eAAaA;QAAC,MAAM;;IAKjC,IAAID,AAAc,aAAdA,GAAG,MAAM,EACT,OAAO,WAAP,GACI,oBAACE,oBAAkBA;QACf,IAAIF;QACJ,YAAYpB;QACZ,eAAe,IAAMK,UAAU,WAAW;QAC1C,gBAAgBJ;;IAK5B,IAAImB,AAAc,YAAdA,GAAG,MAAM,EACT,OAAO,WAAP,GACI,oBAAC;QAAI,WAAW;qBACZ,oBAACC,eAAaA;QAAC,MAAM;;IAKjC,OAAO,WAAP,GAAO,0CAAGnB;AACd"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/admin";
|
|
2
|
+
import { RecordLockingPresenter } from "./abstractions.js";
|
|
3
|
+
import { RecordLockingPresenter as external_RecordLockingPresenter_js_RecordLockingPresenter } from "./RecordLockingPresenter.js";
|
|
4
|
+
import { ContentEntryFormPresenterLockingDecorator } from "./ContentEntryFormPresenterDecorator.js";
|
|
5
|
+
import { SingleEntryPresenterLockingDecorator } from "./SingleEntryPresenterDecorator.js";
|
|
6
|
+
const RecordLockingPresenterFeature = createFeature({
|
|
7
|
+
name: "RecordLocking/EntryLockingPresenter",
|
|
8
|
+
register (container) {
|
|
9
|
+
container.register(external_RecordLockingPresenter_js_RecordLockingPresenter).inSingletonScope();
|
|
10
|
+
container.registerDecorator(ContentEntryFormPresenterLockingDecorator);
|
|
11
|
+
container.registerDecorator(SingleEntryPresenterLockingDecorator);
|
|
12
|
+
},
|
|
13
|
+
resolve (container) {
|
|
14
|
+
return {
|
|
15
|
+
presenter: container.resolve(RecordLockingPresenter)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
export { RecordLockingPresenterFeature };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/entryLocking/feature.js","sources":["../../../src/presentation/entryLocking/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { RecordLockingPresenter as Abstraction } from \"./abstractions.js\";\nimport { RecordLockingPresenter } from \"./RecordLockingPresenter.js\";\nimport { ContentEntryFormPresenterLockingDecorator } from \"./ContentEntryFormPresenterDecorator.js\";\nimport { SingleEntryPresenterLockingDecorator } from \"./SingleEntryPresenterDecorator.js\";\n\nexport const RecordLockingPresenterFeature = createFeature({\n name: \"RecordLocking/EntryLockingPresenter\",\n register(container) {\n container.register(RecordLockingPresenter).inSingletonScope();\n container.registerDecorator(ContentEntryFormPresenterLockingDecorator);\n container.registerDecorator(SingleEntryPresenterLockingDecorator);\n },\n resolve(container) {\n return {\n presenter: container.resolve(Abstraction)\n };\n }\n});\n"],"names":["RecordLockingPresenterFeature","createFeature","container","RecordLockingPresenter","ContentEntryFormPresenterLockingDecorator","SingleEntryPresenterLockingDecorator","Abstraction"],"mappings":";;;;;AAMO,MAAMA,gCAAgCC,cAAc;IACvD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,2DAAwB,gBAAgB;QAC3DD,UAAU,iBAAiB,CAACE;QAC5BF,UAAU,iBAAiB,CAACG;IAChC;IACA,SAAQH,SAAS;QACb,OAAO;YACH,WAAWA,UAAU,OAAO,CAACI;QACjC;IACJ;AACJ"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type IContentEntriesPresenter, type IContentEntriesInitConfig } from "@webiny/app-headless-cms/presentation/contentEntries/list/abstractions.js";
|
|
2
|
+
import { ListLockRecordsPresenter } from "./abstractions.js";
|
|
3
|
+
declare class ContentEntriesPresenterWithLocking implements IContentEntriesPresenter {
|
|
4
|
+
private lockRecordsPresenter;
|
|
5
|
+
private original;
|
|
6
|
+
private _disposeReaction;
|
|
7
|
+
constructor(lockRecordsPresenter: ListLockRecordsPresenter.Interface, original: IContentEntriesPresenter);
|
|
8
|
+
get vm(): import("@webiny/app-headless-cms/presentation/contentEntries/list/abstractions.js").IContentEntriesViewModel;
|
|
9
|
+
get list(): import("@webiny/app-admin/presentation/listPresenter/abstractions.js").IListPresenter<import("@webiny/app-headless-cms/types.js").CmsContentEntry<import("@webiny/app/types.js").GenericRecord>>;
|
|
10
|
+
get folders(): import("@webiny/app-aco/index.js").IFolderTreePresenter;
|
|
11
|
+
init(config?: IContentEntriesInitConfig): void;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
selectEntry(id: string): void;
|
|
14
|
+
deselectEntry(): void;
|
|
15
|
+
createEntry(): void;
|
|
16
|
+
deleteEntry(id: string): Promise<boolean>;
|
|
17
|
+
publishEntry(id: string): Promise<boolean>;
|
|
18
|
+
unpublishEntry(id: string): Promise<boolean>;
|
|
19
|
+
moveEntry(id: string, folderId: string): Promise<boolean>;
|
|
20
|
+
duplicateEntry(entry: Parameters<IContentEntriesPresenter["duplicateEntry"]>[0]): Promise<false | import("@webiny/app-headless-cms/presentation/contentEntries/list/abstractions.js").IDuplicateEntryResult>;
|
|
21
|
+
}
|
|
22
|
+
export declare const ContentEntriesPresenterLockingDecorator: typeof ContentEntriesPresenterWithLocking & {
|
|
23
|
+
__abstraction: import("@webiny/di").Abstraction<IContentEntriesPresenter>;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { compareStructural, reaction } from "mobx";
|
|
2
|
+
import { ContentEntriesPresenter } from "@webiny/app-headless-cms/presentation/contentEntries/list/abstractions.js";
|
|
3
|
+
import { ListLockRecordsPresenter } from "./abstractions.js";
|
|
4
|
+
class ContentEntriesPresenterWithLocking {
|
|
5
|
+
constructor(lockRecordsPresenter, original){
|
|
6
|
+
this.lockRecordsPresenter = lockRecordsPresenter;
|
|
7
|
+
this.original = original;
|
|
8
|
+
this._disposeReaction = null;
|
|
9
|
+
}
|
|
10
|
+
get vm() {
|
|
11
|
+
return this.original.vm;
|
|
12
|
+
}
|
|
13
|
+
get list() {
|
|
14
|
+
return this.original.list;
|
|
15
|
+
}
|
|
16
|
+
get folders() {
|
|
17
|
+
return this.original.folders;
|
|
18
|
+
}
|
|
19
|
+
init(config) {
|
|
20
|
+
this.original.init(config);
|
|
21
|
+
this._disposeReaction = reaction(()=>this.original.list.vm.rows.map((r)=>r.id), (entryIds)=>{
|
|
22
|
+
if (0 === entryIds.length) return;
|
|
23
|
+
this.lockRecordsPresenter.fetchForEntries(entryIds, this.original.vm.model.modelId);
|
|
24
|
+
}, {
|
|
25
|
+
fireImmediately: true,
|
|
26
|
+
equals: compareStructural
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
dispose() {
|
|
30
|
+
if (this._disposeReaction) {
|
|
31
|
+
this._disposeReaction();
|
|
32
|
+
this._disposeReaction = null;
|
|
33
|
+
}
|
|
34
|
+
this.lockRecordsPresenter.dispose();
|
|
35
|
+
this.original.dispose();
|
|
36
|
+
}
|
|
37
|
+
selectEntry(id) {
|
|
38
|
+
this.original.selectEntry(id);
|
|
39
|
+
}
|
|
40
|
+
deselectEntry() {
|
|
41
|
+
this.original.deselectEntry();
|
|
42
|
+
}
|
|
43
|
+
createEntry() {
|
|
44
|
+
this.original.createEntry();
|
|
45
|
+
}
|
|
46
|
+
deleteEntry(id) {
|
|
47
|
+
return this.original.deleteEntry(id);
|
|
48
|
+
}
|
|
49
|
+
publishEntry(id) {
|
|
50
|
+
return this.original.publishEntry(id);
|
|
51
|
+
}
|
|
52
|
+
unpublishEntry(id) {
|
|
53
|
+
return this.original.unpublishEntry(id);
|
|
54
|
+
}
|
|
55
|
+
moveEntry(id, folderId) {
|
|
56
|
+
return this.original.moveEntry(id, folderId);
|
|
57
|
+
}
|
|
58
|
+
duplicateEntry(entry) {
|
|
59
|
+
return this.original.duplicateEntry(entry);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const ContentEntriesPresenterLockingDecorator = ContentEntriesPresenter.createDecorator({
|
|
63
|
+
decorator: ContentEntriesPresenterWithLocking,
|
|
64
|
+
dependencies: [
|
|
65
|
+
ListLockRecordsPresenter
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
export { ContentEntriesPresenterLockingDecorator };
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=ContentEntriesPresenterDecorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/listLocking/ContentEntriesPresenterDecorator.js","sources":["../../../src/presentation/listLocking/ContentEntriesPresenterDecorator.ts"],"sourcesContent":["import { compareStructural, reaction } from \"mobx\";\nimport type { IReactionDisposer } from \"mobx\";\nimport {\n ContentEntriesPresenter,\n type IContentEntriesPresenter,\n type IContentEntriesInitConfig\n} from \"@webiny/app-headless-cms/presentation/contentEntries/list/abstractions.js\";\nimport { ListLockRecordsPresenter } from \"./abstractions.js\";\n\nclass ContentEntriesPresenterWithLocking implements IContentEntriesPresenter {\n private _disposeReaction: IReactionDisposer | null = null;\n\n constructor(\n private lockRecordsPresenter: ListLockRecordsPresenter.Interface,\n private original: IContentEntriesPresenter\n ) {}\n\n get vm() {\n return this.original.vm;\n }\n\n get list() {\n return this.original.list;\n }\n\n get folders() {\n return this.original.folders;\n }\n\n init(config?: IContentEntriesInitConfig): void {\n this.original.init(config);\n\n this._disposeReaction = reaction(\n () => this.original.list.vm.rows.map(r => r.id),\n entryIds => {\n if (entryIds.length === 0) {\n return;\n }\n this.lockRecordsPresenter.fetchForEntries(entryIds, this.original.vm.model.modelId);\n },\n { fireImmediately: true, equals: compareStructural }\n );\n }\n\n dispose(): void {\n if (this._disposeReaction) {\n this._disposeReaction();\n this._disposeReaction = null;\n }\n this.lockRecordsPresenter.dispose();\n this.original.dispose();\n }\n\n selectEntry(id: string) {\n this.original.selectEntry(id);\n }\n\n deselectEntry() {\n this.original.deselectEntry();\n }\n\n createEntry() {\n this.original.createEntry();\n }\n\n deleteEntry(id: string) {\n return this.original.deleteEntry(id);\n }\n\n publishEntry(id: string) {\n return this.original.publishEntry(id);\n }\n\n unpublishEntry(id: string) {\n return this.original.unpublishEntry(id);\n }\n\n moveEntry(id: string, folderId: string) {\n return this.original.moveEntry(id, folderId);\n }\n\n duplicateEntry(entry: Parameters<IContentEntriesPresenter[\"duplicateEntry\"]>[0]) {\n return this.original.duplicateEntry(entry);\n }\n}\n\nexport const ContentEntriesPresenterLockingDecorator = ContentEntriesPresenter.createDecorator({\n decorator: ContentEntriesPresenterWithLocking,\n dependencies: [ListLockRecordsPresenter]\n});\n"],"names":["ContentEntriesPresenterWithLocking","lockRecordsPresenter","original","config","reaction","r","entryIds","compareStructural","id","folderId","entry","ContentEntriesPresenterLockingDecorator","ContentEntriesPresenter","ListLockRecordsPresenter"],"mappings":";;;AASA,MAAMA;IAGF,YACYC,oBAAwD,EACxDC,QAAkC,CAC5C;aAFUD,oBAAoB,GAApBA;aACAC,QAAQ,GAARA;aAJJ,gBAAgB,GAA6B;IAKlD;IAEH,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE;IAC3B;IAEA,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI;IAC7B;IAEA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO;IAChC;IAEA,KAAKC,MAAkC,EAAQ;QAC3C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAACA;QAEnB,IAAI,CAAC,gBAAgB,GAAGC,SACpB,IAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAACC,CAAAA,IAAKA,EAAE,EAAE,GAC9CC,CAAAA;YACI,IAAIA,AAAoB,MAApBA,SAAS,MAAM,EACf;YAEJ,IAAI,CAAC,oBAAoB,CAAC,eAAe,CAACA,UAAU,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO;QACtF,GACA;YAAE,iBAAiB;YAAM,QAAQC;QAAkB;IAE3D;IAEA,UAAgB;QACZ,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACvB,IAAI,CAAC,gBAAgB;YACrB,IAAI,CAAC,gBAAgB,GAAG;QAC5B;QACA,IAAI,CAAC,oBAAoB,CAAC,OAAO;QACjC,IAAI,CAAC,QAAQ,CAAC,OAAO;IACzB;IAEA,YAAYC,EAAU,EAAE;QACpB,IAAI,CAAC,QAAQ,CAAC,WAAW,CAACA;IAC9B;IAEA,gBAAgB;QACZ,IAAI,CAAC,QAAQ,CAAC,aAAa;IAC/B;IAEA,cAAc;QACV,IAAI,CAAC,QAAQ,CAAC,WAAW;IAC7B;IAEA,YAAYA,EAAU,EAAE;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAACA;IACrC;IAEA,aAAaA,EAAU,EAAE;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAACA;IACtC;IAEA,eAAeA,EAAU,EAAE;QACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,CAACA;IACxC;IAEA,UAAUA,EAAU,EAAEC,QAAgB,EAAE;QACpC,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAACD,IAAIC;IACvC;IAEA,eAAeC,KAAgE,EAAE;QAC7E,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,CAACA;IACxC;AACJ;AAEO,MAAMC,0CAA0CC,wBAAwB,eAAe,CAAC;IAC3F,WAAWZ;IACX,cAAc;QAACa;KAAyB;AAC5C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ListLockRecordsUseCase } from "../../features/listLockRecords/abstractions.js";
|
|
2
|
+
import { type IListLockRecordsPresenter, type IListLockRecordsViewModel } from "./abstractions.js";
|
|
3
|
+
import type { IRecordLockingLockRecord } from "../../types.js";
|
|
4
|
+
declare class ListLockRecordsPresenterImpl implements IListLockRecordsPresenter {
|
|
5
|
+
private listLockRecordsUseCase;
|
|
6
|
+
private _lockMap;
|
|
7
|
+
constructor(listLockRecordsUseCase: ListLockRecordsUseCase.Interface);
|
|
8
|
+
get vm(): IListLockRecordsViewModel;
|
|
9
|
+
fetchForEntries(entryIds: string[], type: string): Promise<void>;
|
|
10
|
+
isLocked(entryId: string): boolean;
|
|
11
|
+
getLockRecord(entryId: string): IRecordLockingLockRecord | undefined;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
}
|
|
14
|
+
export declare const ListLockRecordsPresenter: typeof ListLockRecordsPresenterImpl & {
|
|
15
|
+
__abstraction: import("@webiny/di").Abstraction<IListLockRecordsPresenter>;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { computed, makeAutoObservable, observable, runInAction } from "mobx";
|
|
2
|
+
import { ListLockRecordsUseCase } from "../../features/listLockRecords/abstractions.js";
|
|
3
|
+
import { ListLockRecordsPresenter } from "./abstractions.js";
|
|
4
|
+
class ListLockRecordsPresenterImpl {
|
|
5
|
+
constructor(listLockRecordsUseCase){
|
|
6
|
+
this.listLockRecordsUseCase = listLockRecordsUseCase;
|
|
7
|
+
this._lockMap = observable.map();
|
|
8
|
+
makeAutoObservable(this, {
|
|
9
|
+
listLockRecordsUseCase: false,
|
|
10
|
+
vm: computed
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
get vm() {
|
|
14
|
+
return {
|
|
15
|
+
lockedCount: this._lockMap.size
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async fetchForEntries(entryIds, type) {
|
|
19
|
+
if (0 === entryIds.length) return;
|
|
20
|
+
try {
|
|
21
|
+
const records = await this.listLockRecordsUseCase.execute({
|
|
22
|
+
where: {
|
|
23
|
+
id_in: entryIds,
|
|
24
|
+
type
|
|
25
|
+
},
|
|
26
|
+
limit: entryIds.length
|
|
27
|
+
});
|
|
28
|
+
runInAction(()=>{
|
|
29
|
+
this._lockMap.clear();
|
|
30
|
+
for (const record of records)this._lockMap.set(record.targetId, record);
|
|
31
|
+
});
|
|
32
|
+
} catch {}
|
|
33
|
+
}
|
|
34
|
+
isLocked(entryId) {
|
|
35
|
+
return this._lockMap.has(entryId);
|
|
36
|
+
}
|
|
37
|
+
getLockRecord(entryId) {
|
|
38
|
+
return this._lockMap.get(entryId);
|
|
39
|
+
}
|
|
40
|
+
dispose() {
|
|
41
|
+
this._lockMap.clear();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const ListLockRecordsPresenter_ListLockRecordsPresenter = ListLockRecordsPresenter.createImplementation({
|
|
45
|
+
implementation: ListLockRecordsPresenterImpl,
|
|
46
|
+
dependencies: [
|
|
47
|
+
ListLockRecordsUseCase
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
export { ListLockRecordsPresenter_ListLockRecordsPresenter as ListLockRecordsPresenter };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=ListLockRecordsPresenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/listLocking/ListLockRecordsPresenter.js","sources":["../../../src/presentation/listLocking/ListLockRecordsPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, observable, runInAction } from \"mobx\";\nimport { ListLockRecordsUseCase } from \"~/features/listLockRecords/abstractions.js\";\nimport {\n ListLockRecordsPresenter as Abstraction,\n type IListLockRecordsPresenter,\n type IListLockRecordsViewModel\n} from \"./abstractions.js\";\nimport type { IRecordLockingLockRecord } from \"~/types.js\";\n\nclass ListLockRecordsPresenterImpl implements IListLockRecordsPresenter {\n private _lockMap = observable.map<string, IRecordLockingLockRecord>();\n\n constructor(private listLockRecordsUseCase: ListLockRecordsUseCase.Interface) {\n makeAutoObservable<ListLockRecordsPresenterImpl, \"listLockRecordsUseCase\">(this, {\n listLockRecordsUseCase: false,\n vm: computed\n });\n }\n\n get vm(): IListLockRecordsViewModel {\n return {\n lockedCount: this._lockMap.size\n };\n }\n\n async fetchForEntries(entryIds: string[], type: string): Promise<void> {\n if (entryIds.length === 0) {\n return;\n }\n\n try {\n const records = await this.listLockRecordsUseCase.execute({\n where: { id_in: entryIds, type },\n limit: entryIds.length\n });\n\n runInAction(() => {\n this._lockMap.clear();\n for (const record of records) {\n this._lockMap.set(record.targetId, record);\n }\n });\n } catch {\n // Silently fail — list still works without lock indicators\n }\n }\n\n isLocked(entryId: string): boolean {\n return this._lockMap.has(entryId);\n }\n\n getLockRecord(entryId: string): IRecordLockingLockRecord | undefined {\n return this._lockMap.get(entryId);\n }\n\n dispose(): void {\n this._lockMap.clear();\n }\n}\n\nexport const ListLockRecordsPresenter = Abstraction.createImplementation({\n implementation: ListLockRecordsPresenterImpl,\n dependencies: [ListLockRecordsUseCase]\n});\n"],"names":["ListLockRecordsPresenterImpl","listLockRecordsUseCase","observable","makeAutoObservable","computed","entryIds","type","records","runInAction","record","entryId","ListLockRecordsPresenter","Abstraction","ListLockRecordsUseCase"],"mappings":";;;AASA,MAAMA;IAGF,YAAoBC,sBAAwD,CAAE;aAA1DA,sBAAsB,GAAtBA;aAFZ,QAAQ,GAAGC,WAAW,GAAG;QAG7BC,mBAA2E,IAAI,EAAE;YAC7E,wBAAwB;YACxB,IAAIC;QACR;IACJ;IAEA,IAAI,KAAgC;QAChC,OAAO;YACH,aAAa,IAAI,CAAC,QAAQ,CAAC,IAAI;QACnC;IACJ;IAEA,MAAM,gBAAgBC,QAAkB,EAAEC,IAAY,EAAiB;QACnE,IAAID,AAAoB,MAApBA,SAAS,MAAM,EACf;QAGJ,IAAI;YACA,MAAME,UAAU,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC;gBACtD,OAAO;oBAAE,OAAOF;oBAAUC;gBAAK;gBAC/B,OAAOD,SAAS,MAAM;YAC1B;YAEAG,YAAY;gBACR,IAAI,CAAC,QAAQ,CAAC,KAAK;gBACnB,KAAK,MAAMC,UAAUF,QACjB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAACE,OAAO,QAAQ,EAAEA;YAE3C;QACJ,EAAE,OAAM,CAER;IACJ;IAEA,SAASC,OAAe,EAAW;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAACA;IAC7B;IAEA,cAAcA,OAAe,EAAwC;QACjE,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAACA;IAC7B;IAEA,UAAgB;QACZ,IAAI,CAAC,QAAQ,CAAC,KAAK;IACvB;AACJ;AAEO,MAAMC,oDAA2BC,yBAAAA,oBAAgC,CAAC;IACrE,gBAAgBZ;IAChB,cAAc;QAACa;KAAuB;AAC1C"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IRecordLockingLockRecord } from "../../types.js";
|
|
2
|
+
export interface IListLockRecordsViewModel {
|
|
3
|
+
lockedCount: number;
|
|
4
|
+
}
|
|
5
|
+
export interface IListLockRecordsPresenter {
|
|
6
|
+
readonly vm: IListLockRecordsViewModel;
|
|
7
|
+
fetchForEntries(entryIds: string[], type: string): Promise<void>;
|
|
8
|
+
isLocked(entryId: string): boolean;
|
|
9
|
+
getLockRecord(entryId: string): IRecordLockingLockRecord | undefined;
|
|
10
|
+
dispose(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare const ListLockRecordsPresenter: import("@webiny/di").Abstraction<IListLockRecordsPresenter>;
|
|
13
|
+
export declare namespace ListLockRecordsPresenter {
|
|
14
|
+
type Interface = IListLockRecordsPresenter;
|
|
15
|
+
type ViewModel = IListLockRecordsViewModel;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/listLocking/abstractions.js","sources":["../../../src/presentation/listLocking/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { IRecordLockingLockRecord } from \"~/types.js\";\n\nexport interface IListLockRecordsViewModel {\n lockedCount: number;\n}\n\nexport interface IListLockRecordsPresenter {\n readonly vm: IListLockRecordsViewModel;\n fetchForEntries(entryIds: string[], type: string): Promise<void>;\n isLocked(entryId: string): boolean;\n getLockRecord(entryId: string): IRecordLockingLockRecord | undefined;\n dispose(): void;\n}\n\nexport const ListLockRecordsPresenter = createAbstraction<IListLockRecordsPresenter>(\n \"ListLockRecordsPresenter\"\n);\n\nexport namespace ListLockRecordsPresenter {\n export type Interface = IListLockRecordsPresenter;\n export type ViewModel = IListLockRecordsViewModel;\n}\n"],"names":["ListLockRecordsPresenter","createAbstraction"],"mappings":";AAeO,MAAMA,2BAA2BC,kBACpC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import react, { useEffect } from "react";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
3
|
+
import { useContainer } from "@webiny/app";
|
|
4
|
+
import { useContentEntriesPresenter } from "@webiny/app-headless-cms/presentation/contentEntries/list/useContentEntriesPresenter.js";
|
|
5
|
+
import { ListLockRecordsPresenter } from "../abstractions.js";
|
|
6
|
+
const ListLockRecordsSync = observer(()=>{
|
|
7
|
+
const container = useContainer();
|
|
8
|
+
const presenter = react.useMemo(()=>container.resolve(ListLockRecordsPresenter), [
|
|
9
|
+
container
|
|
10
|
+
]);
|
|
11
|
+
const entriesPresenter = useContentEntriesPresenter();
|
|
12
|
+
const rows = entriesPresenter.list.vm.rows;
|
|
13
|
+
const modelId = entriesPresenter.vm.model.modelId;
|
|
14
|
+
useEffect(()=>{
|
|
15
|
+
if (0 === rows.length) return;
|
|
16
|
+
const entryIds = rows.map((row)=>row.id);
|
|
17
|
+
presenter.fetchForEntries(entryIds, modelId);
|
|
18
|
+
}, [
|
|
19
|
+
rows,
|
|
20
|
+
modelId
|
|
21
|
+
]);
|
|
22
|
+
return null;
|
|
23
|
+
});
|
|
24
|
+
export { ListLockRecordsSync };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=ListLockRecordsSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/listLocking/components/ListLockRecordsSync.js","sources":["../../../../src/presentation/listLocking/components/ListLockRecordsSync.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useContainer } from \"@webiny/app\";\nimport { useContentEntriesPresenter } from \"@webiny/app-headless-cms/presentation/contentEntries/list/useContentEntriesPresenter.js\";\nimport { ListLockRecordsPresenter } from \"../abstractions.js\";\n\nexport const ListLockRecordsSync = observer(() => {\n const container = useContainer();\n const presenter = React.useMemo(() => container.resolve(ListLockRecordsPresenter), [container]);\n const entriesPresenter = useContentEntriesPresenter();\n\n const rows = entriesPresenter.list.vm.rows;\n const modelId = entriesPresenter.vm.model.modelId;\n\n useEffect(() => {\n if (rows.length === 0) {\n return;\n }\n\n const entryIds = rows.map(row => row.id);\n presenter.fetchForEntries(entryIds, modelId);\n }, [rows, modelId]);\n\n return null;\n});\n"],"names":["ListLockRecordsSync","observer","container","useContainer","presenter","React","ListLockRecordsPresenter","entriesPresenter","useContentEntriesPresenter","rows","modelId","useEffect","entryIds","row"],"mappings":";;;;;AAMO,MAAMA,sBAAsBC,SAAS;IACxC,MAAMC,YAAYC;IAClB,MAAMC,YAAYC,MAAAA,OAAa,CAAC,IAAMH,UAAU,OAAO,CAACI,2BAA2B;QAACJ;KAAU;IAC9F,MAAMK,mBAAmBC;IAEzB,MAAMC,OAAOF,iBAAiB,IAAI,CAAC,EAAE,CAAC,IAAI;IAC1C,MAAMG,UAAUH,iBAAiB,EAAE,CAAC,KAAK,CAAC,OAAO;IAEjDI,UAAU;QACN,IAAIF,AAAgB,MAAhBA,KAAK,MAAM,EACX;QAGJ,MAAMG,WAAWH,KAAK,GAAG,CAACI,CAAAA,MAAOA,IAAI,EAAE;QACvCT,UAAU,eAAe,CAACQ,UAAUF;IACxC,GAAG;QAACD;QAAMC;KAAQ;IAElB,OAAO;AACX"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
3
|
+
import { useContainer } from "@webiny/app";
|
|
4
|
+
import { ReactComponent } from "@webiny/icons/lock.svg";
|
|
5
|
+
import { Icon, Tooltip } from "@webiny/admin-ui";
|
|
6
|
+
import { ContentEntryListConfig, useModel } from "@webiny/app-headless-cms";
|
|
7
|
+
import { ListLockRecordsPresenter } from "../abstractions.js";
|
|
8
|
+
const { Browser: Browser } = ContentEntryListConfig;
|
|
9
|
+
const ActionsCell = observer(({ children })=>{
|
|
10
|
+
const { model } = useModel();
|
|
11
|
+
const container = useContainer();
|
|
12
|
+
const presenter = react.useMemo(()=>container.resolve(ListLockRecordsPresenter), [
|
|
13
|
+
container
|
|
14
|
+
]);
|
|
15
|
+
const { useTableRow, isFolderRow } = Browser.Table.Column;
|
|
16
|
+
const { row } = useTableRow();
|
|
17
|
+
if (isFolderRow(row)) return /*#__PURE__*/ react.createElement(react.Fragment, null, children);
|
|
18
|
+
const lockRecord = presenter.getLockRecord(row.id);
|
|
19
|
+
if (!lockRecord) return /*#__PURE__*/ react.createElement(react.Fragment, null, children);
|
|
20
|
+
return /*#__PURE__*/ react.createElement(Tooltip, {
|
|
21
|
+
side: "left",
|
|
22
|
+
content: `This ${model.name} is currently locked by ${lockRecord.lockedBy.displayName}.`,
|
|
23
|
+
trigger: /*#__PURE__*/ react.createElement(Icon, {
|
|
24
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
25
|
+
label: "Locked entry",
|
|
26
|
+
color: "neutral-light"
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
const RecordLockingCellActionsDecorator = Browser.Table.Column.createDecorator((Original)=>function(props) {
|
|
31
|
+
if ("actions" === props.name && props.cell) return /*#__PURE__*/ react.createElement(Original, {
|
|
32
|
+
...props,
|
|
33
|
+
cell: /*#__PURE__*/ react.createElement(ActionsCell, null, props.cell)
|
|
34
|
+
});
|
|
35
|
+
return /*#__PURE__*/ react.createElement(Original, props);
|
|
36
|
+
});
|
|
37
|
+
export { RecordLockingCellActionsDecorator };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=LockIndicatorCell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/listLocking/components/LockIndicatorCell.js","sources":["../../../../src/presentation/listLocking/components/LockIndicatorCell.tsx"],"sourcesContent":["import React from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useContainer } from \"@webiny/app\";\nimport { ReactComponent as LockedIcon } from \"@webiny/icons/lock.svg\";\nimport { Icon, Tooltip } from \"@webiny/admin-ui\";\nimport { useModel, ContentEntryListConfig } from \"@webiny/app-headless-cms\";\nimport { ListLockRecordsPresenter } from \"../abstractions.js\";\n\nconst { Browser } = ContentEntryListConfig;\n\nconst ActionsCell = observer(({ children }: { children: React.ReactNode }) => {\n const { model } = useModel();\n const container = useContainer();\n const presenter = React.useMemo(() => container.resolve(ListLockRecordsPresenter), [container]);\n const { useTableRow, isFolderRow } = Browser.Table.Column;\n const { row } = useTableRow();\n\n if (isFolderRow(row)) {\n return <>{children}</>;\n }\n\n const lockRecord = presenter.getLockRecord(row.id);\n\n if (!lockRecord) {\n return <>{children}</>;\n }\n\n return (\n <Tooltip\n side={\"left\"}\n content={`This ${model.name} is currently locked by ${lockRecord.lockedBy.displayName}.`}\n trigger={<Icon icon={<LockedIcon />} label={\"Locked entry\"} color={\"neutral-light\"} />}\n />\n );\n});\n\nexport const RecordLockingCellActionsDecorator = Browser.Table.Column.createDecorator(Original => {\n return function RecordLockingCellActions(props) {\n if (props.name === \"actions\" && props.cell) {\n return <Original {...props} cell={<ActionsCell>{props.cell}</ActionsCell>} />;\n }\n\n return <Original {...props} />;\n };\n});\n"],"names":["Browser","ContentEntryListConfig","ActionsCell","observer","children","model","useModel","container","useContainer","presenter","React","ListLockRecordsPresenter","useTableRow","isFolderRow","row","lockRecord","Tooltip","Icon","LockedIcon","RecordLockingCellActionsDecorator","Original","props"],"mappings":";;;;;;;AAQA,MAAM,EAAEA,SAAAA,OAAO,EAAE,GAAGC;AAEpB,MAAMC,cAAcC,SAAS,CAAC,EAAEC,QAAQ,EAAiC;IACrE,MAAM,EAAEC,KAAK,EAAE,GAAGC;IAClB,MAAMC,YAAYC;IAClB,MAAMC,YAAYC,MAAAA,OAAa,CAAC,IAAMH,UAAU,OAAO,CAACI,2BAA2B;QAACJ;KAAU;IAC9F,MAAM,EAAEK,WAAW,EAAEC,WAAW,EAAE,GAAGb,QAAQ,KAAK,CAAC,MAAM;IACzD,MAAM,EAAEc,GAAG,EAAE,GAAGF;IAEhB,IAAIC,YAAYC,MACZ,OAAO,WAAP,GAAO,0CAAGV;IAGd,MAAMW,aAAaN,UAAU,aAAa,CAACK,IAAI,EAAE;IAEjD,IAAI,CAACC,YACD,OAAO,WAAP,GAAO,0CAAGX;IAGd,OAAO,WAAP,GACI,oBAACY,SAAOA;QACJ,MAAM;QACN,SAAS,CAAC,KAAK,EAAEX,MAAM,IAAI,CAAC,wBAAwB,EAAEU,WAAW,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;QACxF,uBAAS,oBAACE,MAAIA;YAAC,oBAAM,oBAACC,gBAAUA;YAAK,OAAO;YAAgB,OAAO;;;AAG/E;AAEO,MAAMC,oCAAoCnB,QAAQ,KAAK,CAAC,MAAM,CAAC,eAAe,CAACoB,CAAAA,WAC3E,SAAkCC,KAAK;QAC1C,IAAIA,AAAe,cAAfA,MAAM,IAAI,IAAkBA,MAAM,IAAI,EACtC,OAAO,WAAP,GAAO,oBAACD,UAAAA;YAAU,GAAGC,KAAK;YAAE,oBAAM,oBAACnB,aAAWA,MAAEmB,MAAM,IAAI;;QAG9D,OAAO,WAAP,GAAO,oBAACD,UAAaC;IACzB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/admin";
|
|
2
|
+
import { ListLockRecordsPresenter } from "./abstractions.js";
|
|
3
|
+
import { ListLockRecordsPresenter as external_ListLockRecordsPresenter_js_ListLockRecordsPresenter } from "./ListLockRecordsPresenter.js";
|
|
4
|
+
import { ContentEntriesPresenterLockingDecorator } from "./ContentEntriesPresenterDecorator.js";
|
|
5
|
+
const ListLockRecordsPresenterFeature = createFeature({
|
|
6
|
+
name: "RecordLocking/ListLockRecordsPresenter",
|
|
7
|
+
register (container) {
|
|
8
|
+
container.register(external_ListLockRecordsPresenter_js_ListLockRecordsPresenter).inSingletonScope();
|
|
9
|
+
container.registerDecorator(ContentEntriesPresenterLockingDecorator);
|
|
10
|
+
},
|
|
11
|
+
resolve (container) {
|
|
12
|
+
return {
|
|
13
|
+
presenter: container.resolve(ListLockRecordsPresenter)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
export { ListLockRecordsPresenterFeature };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/listLocking/feature.js","sources":["../../../src/presentation/listLocking/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { ListLockRecordsPresenter as Abstraction } from \"./abstractions.js\";\nimport { ListLockRecordsPresenter } from \"./ListLockRecordsPresenter.js\";\nimport { ContentEntriesPresenterLockingDecorator } from \"./ContentEntriesPresenterDecorator.js\";\n\nexport const ListLockRecordsPresenterFeature = createFeature({\n name: \"RecordLocking/ListLockRecordsPresenter\",\n register(container) {\n container.register(ListLockRecordsPresenter).inSingletonScope();\n container.registerDecorator(ContentEntriesPresenterLockingDecorator);\n },\n resolve(container) {\n return {\n presenter: container.resolve(Abstraction)\n };\n }\n});\n"],"names":["ListLockRecordsPresenterFeature","createFeature","container","ListLockRecordsPresenter","ContentEntriesPresenterLockingDecorator","Abstraction"],"mappings":";;;;AAKO,MAAMA,kCAAkCC,cAAc;IACzD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,+DAA0B,gBAAgB;QAC7DD,UAAU,iBAAiB,CAACE;IAChC;IACA,SAAQF,SAAS;QACb,OAAO;YACH,WAAWA,UAAU,OAAO,CAACG;QACjC;IACJ;AACJ"}
|