@webiny/app-record-locking 0.0.0-unstable.6f45466a1d → 0.0.0-unstable.7be00a75a9
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/HeadlessCmsActionsAcoCell.js +29 -51
- package/components/HeadlessCmsActionsAcoCell.js.map +1 -1
- package/components/HeadlessCmsContentEntry/ContentEntryGuard.js +26 -34
- package/components/HeadlessCmsContentEntry/ContentEntryGuard.js.map +1 -1
- package/components/HeadlessCmsContentEntry/ContentEntryLocker.d.ts +1 -1
- package/components/HeadlessCmsContentEntry/ContentEntryLocker.js +70 -96
- package/components/HeadlessCmsContentEntry/ContentEntryLocker.js.map +1 -1
- package/components/HeadlessCmsContentEntry/HeadlessCmsContentEntry.js +38 -83
- package/components/HeadlessCmsContentEntry/HeadlessCmsContentEntry.js.map +1 -1
- package/components/HeadlessCmsContentEntry/index.js +0 -2
- package/components/LockedRecord/LockedRecord.js +45 -57
- package/components/LockedRecord/LockedRecord.js.map +1 -1
- package/components/LockedRecord/LockedRecordForceUnlock.js +49 -63
- package/components/LockedRecord/LockedRecordForceUnlock.js.map +1 -1
- package/components/LockedRecord/index.js +0 -2
- package/components/RecordLockingProvider.js +103 -117
- package/components/RecordLockingProvider.js.map +1 -1
- package/components/SecurityPermissions.d.ts +2 -0
- package/components/SecurityPermissions.js +15 -0
- package/components/SecurityPermissions.js.map +1 -0
- package/components/decorators/UseContentEntriesListHookDecorator.js +18 -18
- package/components/decorators/UseContentEntriesListHookDecorator.js.map +1 -1
- package/components/decorators/UseRecordsDecorator.js +13 -22
- package/components/decorators/UseRecordsDecorator.js.map +1 -1
- package/components/decorators/UseSaveEntryDecorator.js +35 -49
- package/components/decorators/UseSaveEntryDecorator.js.map +1 -1
- package/domain/RecordLocking.js +229 -291
- package/domain/RecordLocking.js.map +1 -1
- package/domain/RecordLockingClient.js +17 -16
- package/domain/RecordLockingClient.js.map +1 -1
- package/domain/RecordLockingGetLockRecord.js +13 -15
- package/domain/RecordLockingGetLockRecord.js.map +1 -1
- package/domain/RecordLockingGetLockedEntryLockRecord.js +12 -13
- package/domain/RecordLockingGetLockedEntryLockRecord.js.map +1 -1
- package/domain/RecordLockingIsEntryLocked.js +15 -14
- package/domain/RecordLockingIsEntryLocked.js.map +1 -1
- package/domain/RecordLockingListLockRecords.js +18 -24
- package/domain/RecordLockingListLockRecords.js.map +1 -1
- package/domain/RecordLockingLockEntry.js +8 -9
- package/domain/RecordLockingLockEntry.js.map +1 -1
- package/domain/RecordLockingUnlockEntry.js +12 -13
- package/domain/RecordLockingUnlockEntry.js.map +1 -1
- package/domain/RecordLockingUpdateEntryLock.js +12 -13
- package/domain/RecordLockingUpdateEntryLock.js.map +1 -1
- package/domain/abstractions/IRecordLocking.js +0 -3
- package/domain/abstractions/IRecordLockingClient.js +0 -3
- package/domain/abstractions/IRecordLockingGetLockRecord.js +0 -3
- package/domain/abstractions/IRecordLockingGetLockedEntryLockRecord.js +0 -3
- package/domain/abstractions/IRecordLockingIsEntryLocked.js +0 -3
- package/domain/abstractions/IRecordLockingListLockRecords.js +0 -3
- package/domain/abstractions/IRecordLockingLockEntry.js +0 -3
- package/domain/abstractions/IRecordLockingUnlockEntry.js +0 -3
- package/domain/abstractions/IRecordLockingUpdateEntryLock.js +0 -3
- package/domain/graphql/fields.js +3 -2
- package/domain/graphql/fields.js.map +1 -1
- package/domain/graphql/getLockRecord.js +3 -2
- package/domain/graphql/getLockRecord.js.map +1 -1
- package/domain/graphql/getLockedEntryLockRecord.js +3 -2
- package/domain/graphql/getLockedEntryLockRecord.js.map +1 -1
- package/domain/graphql/isEntryLocked.js +3 -2
- package/domain/graphql/isEntryLocked.js.map +1 -1
- package/domain/graphql/listLockRecords.js +4 -5
- package/domain/graphql/listLockRecords.js.map +1 -1
- package/domain/graphql/lockEntry.js +3 -4
- package/domain/graphql/lockEntry.js.map +1 -1
- package/domain/graphql/unlockEntry.js +3 -2
- package/domain/graphql/unlockEntry.js.map +1 -1
- package/domain/graphql/updateEntryLock.js +3 -2
- package/domain/graphql/updateEntryLock.js.map +1 -1
- package/domain/permissionsSchema.d.ts +6 -0
- package/domain/permissionsSchema.js +10 -0
- package/domain/permissionsSchema.js.map +1 -0
- package/domain/utils/createRecordLockingClient.js +5 -6
- package/domain/utils/createRecordLockingClient.js.map +1 -1
- package/domain/utils/createRecordLockingError.js +10 -11
- package/domain/utils/createRecordLockingError.js.map +1 -1
- 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/hooks/index.js +0 -2
- package/hooks/usePermission.js +14 -15
- package/hooks/usePermission.js.map +1 -1
- package/hooks/useRecordLocking.js +5 -6
- package/hooks/useRecordLocking.js.map +1 -1
- package/index.js +17 -21
- package/index.js.map +1 -1
- package/package.json +25 -22
- package/types.d.ts +1 -1
- package/types.js +0 -3
- package/utils/createCacheKey.js +9 -10
- package/utils/createCacheKey.js.map +1 -1
- package/components/HeadlessCmsContentEntry/index.js.map +0 -1
- package/components/LockedRecord/index.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/abstractions/IRecordLocking.js.map +0 -1
- package/domain/abstractions/IRecordLockingClient.js.map +0 -1
- package/domain/abstractions/IRecordLockingGetLockRecord.js.map +0 -1
- package/domain/abstractions/IRecordLockingGetLockedEntryLockRecord.js.map +0 -1
- package/domain/abstractions/IRecordLockingIsEntryLocked.js.map +0 -1
- package/domain/abstractions/IRecordLockingListLockRecords.js.map +0 -1
- package/domain/abstractions/IRecordLockingLockEntry.js.map +0 -1
- package/domain/abstractions/IRecordLockingUnlockEntry.js.map +0 -1
- package/domain/abstractions/IRecordLockingUpdateEntryLock.js.map +0 -1
- package/hooks/index.js.map +0 -1
- package/types.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components/SecurityPermissions.js","sources":["../../src/components/SecurityPermissions.tsx"],"sourcesContent":["import React from \"react\";\nimport { AdminConfig } from \"@webiny/app-admin\";\nimport { ReactComponent as LockIcon } from \"@webiny/icons/lock.svg\";\nimport { RECORD_LOCKING_PERMISSIONS_SCHEMA } from \"~/domain/permissionsSchema.js\";\n\nconst { Security } = AdminConfig;\n\nexport const SecurityPermissions = () => {\n return (\n <AdminConfig>\n <Security.Permissions\n name=\"record-locking\"\n title=\"Record Locking\"\n description=\"Manage Record Locking permissions.\"\n icon={<LockIcon />}\n schema={RECORD_LOCKING_PERMISSIONS_SCHEMA}\n />\n </AdminConfig>\n );\n};\n"],"names":["Security","AdminConfig","SecurityPermissions","LockIcon","RECORD_LOCKING_PERMISSIONS_SCHEMA"],"mappings":";;;;AAKA,MAAM,EAAEA,UAAAA,QAAQ,EAAE,GAAGC;AAEd,MAAMC,sBAAsB,IACxB,WAAP,GACI,oBAACD,aAAWA,MAAAA,WAAAA,GACR,oBAACD,SAAS,WAAW;QACjB,MAAK;QACL,OAAM;QACN,aAAY;QACZ,oBAAM,oBAACG,gBAAQA;QACf,QAAQC"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
import { ContentEntryListConfig } from "@webiny/app-headless-cms";
|
|
3
3
|
import { useRecordLocking } from "../../hooks/index.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
4
|
+
const UseContentEntriesListHookDecorator = ContentEntryListConfig.ContentEntries.useContentEntriesList.createDecorator((originalHook)=>function() {
|
|
5
|
+
const value = originalHook();
|
|
6
|
+
const recordLocking = useRecordLocking();
|
|
7
|
+
useEffect(()=>{
|
|
8
|
+
if (!value.records) return;
|
|
9
|
+
recordLocking.setRecords(value.folderId, value.modelId, value.records);
|
|
10
|
+
}, [
|
|
11
|
+
value.folderId,
|
|
12
|
+
value.modelId,
|
|
13
|
+
value.records,
|
|
14
|
+
recordLocking
|
|
15
|
+
]);
|
|
16
|
+
return {
|
|
17
|
+
...value,
|
|
18
|
+
records: recordLocking.records
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
export { UseContentEntriesListHookDecorator };
|
|
22
22
|
|
|
23
23
|
//# sourceMappingURL=UseContentEntriesListHookDecorator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"components/decorators/UseContentEntriesListHookDecorator.js","sources":["../../../src/components/decorators/UseContentEntriesListHookDecorator.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { ContentEntryListConfig } from \"@webiny/app-headless-cms\";\nimport { useRecordLocking } from \"~/hooks/index.js\";\nimport type { IPossiblyRecordLockingRecord } from \"~/types.js\";\n\nexport const UseContentEntriesListHookDecorator =\n ContentEntryListConfig.ContentEntries.useContentEntriesList.createDecorator(originalHook => {\n return function RecordLockingUseContentEntriesList() {\n const value = originalHook();\n const recordLocking = useRecordLocking();\n\n useEffect(() => {\n if (!value.records) {\n return;\n }\n recordLocking.setRecords(\n value.folderId,\n value.modelId,\n // TODO determine if this is correct\n value.records as IPossiblyRecordLockingRecord[]\n );\n }, [value.folderId, value.modelId, value.records, recordLocking]);\n\n return {\n ...value,\n records: recordLocking.records\n };\n };\n });\n"],"names":["UseContentEntriesListHookDecorator","ContentEntryListConfig","originalHook","value","recordLocking","useRecordLocking","useEffect"],"mappings":";;;AAKO,MAAMA,qCACTC,uBAAuB,cAAc,CAAC,qBAAqB,CAAC,eAAe,CAACC,CAAAA,eACjE;QACH,MAAMC,QAAQD;QACd,MAAME,gBAAgBC;QAEtBC,UAAU;YACN,IAAI,CAACH,MAAM,OAAO,EACd;YAEJC,cAAc,UAAU,CACpBD,MAAM,QAAQ,EACdA,MAAM,OAAO,EAEbA,MAAM,OAAO;QAErB,GAAG;YAACA,MAAM,QAAQ;YAAEA,MAAM,OAAO;YAAEA,MAAM,OAAO;YAAEC;SAAc;QAEhE,OAAO;YACH,GAAGD,KAAK;YACR,SAASC,cAAc,OAAO;QAClC;IACJ"}
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import { useRecords } from "@webiny/app-aco";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
updateRecordInCache(record) {
|
|
16
|
-
hook.updateRecordInCache({
|
|
17
|
-
...record,
|
|
18
|
-
savedOn: new Date().toISOString()
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
});
|
|
2
|
+
const UseRecordsDecorator = useRecords.createDecorator((baseHook)=>(folderId)=>{
|
|
3
|
+
const hook = baseHook(folderId);
|
|
4
|
+
return {
|
|
5
|
+
...hook,
|
|
6
|
+
updateRecordInCache (record) {
|
|
7
|
+
hook.updateRecordInCache({
|
|
8
|
+
...record,
|
|
9
|
+
savedOn: new Date().toISOString()
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
export { UseRecordsDecorator };
|
|
24
15
|
|
|
25
16
|
//# sourceMappingURL=UseRecordsDecorator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"components/decorators/UseRecordsDecorator.js","sources":["../../../src/components/decorators/UseRecordsDecorator.tsx"],"sourcesContent":["import { useRecords } from \"@webiny/app-aco\";\n\n/**\n * When record locking mechanism is checking for records equality, it compares record `id` and `savedOn`.\n * When you're updating ACO cache, you're just passing the new content entry value(s), and sometimes you might\n * be doing it without the `savedOn`, and that causes record locking to keep its old state.\n *\n * This decorator ensures that calls to `updateRecordInCache` always include a `savedOn` timestamp.\n */\nexport const UseRecordsDecorator = useRecords.createDecorator(baseHook => {\n return (folderId?: string) => {\n const hook = baseHook(folderId);\n\n return {\n ...hook,\n updateRecordInCache(record: any) {\n hook.updateRecordInCache({\n ...record,\n savedOn: new Date().toISOString()\n });\n }\n };\n };\n});\n"],"names":["UseRecordsDecorator","useRecords","baseHook","folderId","hook","record","Date"],"mappings":";AASO,MAAMA,sBAAsBC,WAAW,eAAe,CAACC,CAAAA,WACnD,CAACC;QACJ,MAAMC,OAAOF,SAASC;QAEtB,OAAO;YACH,GAAGC,IAAI;YACP,qBAAoBC,MAAW;gBAC3BD,KAAK,mBAAmB,CAAC;oBACrB,GAAGC,MAAM;oBACT,SAAS,IAAIC,OAAO,WAAW;gBACnC;YACJ;QACJ;IACJ"}
|
|
@@ -2,54 +2,40 @@ import { useCallback } from "react";
|
|
|
2
2
|
import { useRecordLocking } from "../../hooks/index.js";
|
|
3
3
|
import { ContentEntryEditorConfig, useModel } from "@webiny/app-headless-cms";
|
|
4
4
|
import { useSnackbar } from "@webiny/app-admin";
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (saveResult) {
|
|
41
|
-
await updateEntryLock({
|
|
42
|
-
id: saveResult.id,
|
|
43
|
-
$lockingType: model.modelId
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
return saveResult;
|
|
47
|
-
}, [entry?.id, model.modelId, updateEntryLock]);
|
|
48
|
-
return {
|
|
49
|
-
...hook,
|
|
50
|
-
saveEntry
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
});
|
|
5
|
+
const { ContentEntry: { ContentEntryForm: ContentEntryForm } } = ContentEntryEditorConfig;
|
|
6
|
+
const UseSaveEntryDecorator = ContentEntryForm.useContentEntryForm.createDecorator((originalHook)=>function() {
|
|
7
|
+
const hook = originalHook();
|
|
8
|
+
const { fetchLockedEntryLockRecord, updateEntryLock } = useRecordLocking();
|
|
9
|
+
const { showSnackbar } = useSnackbar();
|
|
10
|
+
const { model } = useModel();
|
|
11
|
+
const { entry } = hook;
|
|
12
|
+
const saveEntry = useCallback(async (...params)=>{
|
|
13
|
+
if (!entry.id) return hook.saveEntry(...params);
|
|
14
|
+
const result = await fetchLockedEntryLockRecord({
|
|
15
|
+
id: entry.id,
|
|
16
|
+
$lockingType: model.modelId
|
|
17
|
+
});
|
|
18
|
+
if (result?.lockedBy) {
|
|
19
|
+
const lockedBy = result.lockedBy;
|
|
20
|
+
showSnackbar(`It seems that the entry is locked by ${lockedBy.displayName || lockedBy.id}. You can't save your changes.`);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const saveResult = await hook.saveEntry(...params);
|
|
24
|
+
if (saveResult) await updateEntryLock({
|
|
25
|
+
id: saveResult.id,
|
|
26
|
+
$lockingType: model.modelId
|
|
27
|
+
});
|
|
28
|
+
return saveResult;
|
|
29
|
+
}, [
|
|
30
|
+
entry?.id,
|
|
31
|
+
model.modelId,
|
|
32
|
+
updateEntryLock
|
|
33
|
+
]);
|
|
34
|
+
return {
|
|
35
|
+
...hook,
|
|
36
|
+
saveEntry
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
export { UseSaveEntryDecorator };
|
|
54
40
|
|
|
55
41
|
//# sourceMappingURL=UseSaveEntryDecorator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"components/decorators/UseSaveEntryDecorator.js","sources":["../../../src/components/decorators/UseSaveEntryDecorator.tsx"],"sourcesContent":["import { useCallback } from \"react\";\nimport { useRecordLocking } from \"~/hooks/index.js\";\nimport { ContentEntryEditorConfig, useModel } from \"@webiny/app-headless-cms\";\nimport { useSnackbar } from \"@webiny/app-admin\";\n\nconst {\n ContentEntry: { ContentEntryForm }\n} = ContentEntryEditorConfig;\n\ntype SaveEntry = ReturnType<typeof ContentEntryForm.useContentEntryForm>[\"saveEntry\"];\n\nexport const UseSaveEntryDecorator = ContentEntryForm.useContentEntryForm.createDecorator(\n originalHook => {\n return function useRecordLockingUseSave() {\n const hook = originalHook();\n const { fetchLockedEntryLockRecord, updateEntryLock } = useRecordLocking();\n const { showSnackbar } = useSnackbar();\n const { model } = useModel();\n\n const { entry } = hook;\n\n const saveEntry: SaveEntry = useCallback(\n async (...params) => {\n if (!entry.id) {\n return hook.saveEntry(...params);\n }\n\n const result = await fetchLockedEntryLockRecord({\n id: entry.id,\n $lockingType: model.modelId\n });\n\n if (result?.lockedBy) {\n const lockedBy = result.lockedBy;\n showSnackbar(\n `It seems that the entry is locked by ${\n lockedBy.displayName || lockedBy.id\n }. You can't save your changes.`\n );\n return null;\n }\n\n const saveResult = await hook.saveEntry(...params);\n if (saveResult) {\n await updateEntryLock({\n id: saveResult.id,\n $lockingType: model.modelId\n });\n }\n\n return saveResult;\n },\n [entry?.id, model.modelId, updateEntryLock]\n );\n\n return {\n ...hook,\n saveEntry\n };\n };\n }\n);\n"],"names":["ContentEntryForm","ContentEntryEditorConfig","UseSaveEntryDecorator","originalHook","hook","fetchLockedEntryLockRecord","updateEntryLock","useRecordLocking","showSnackbar","useSnackbar","model","useModel","entry","saveEntry","useCallback","params","result","lockedBy","saveResult"],"mappings":";;;;AAKA,MAAM,EACF,cAAc,EAAEA,kBAAAA,gBAAgB,EAAE,EACrC,GAAGC;AAIG,MAAMC,wBAAwBF,iBAAiB,mBAAmB,CAAC,eAAe,CACrFG,CAAAA,eACW;QACH,MAAMC,OAAOD;QACb,MAAM,EAAEE,0BAA0B,EAAEC,eAAe,EAAE,GAAGC;QACxD,MAAM,EAAEC,YAAY,EAAE,GAAGC;QACzB,MAAM,EAAEC,KAAK,EAAE,GAAGC;QAElB,MAAM,EAAEC,KAAK,EAAE,GAAGR;QAElB,MAAMS,YAAuBC,YACzB,OAAO,GAAGC;YACN,IAAI,CAACH,MAAM,EAAE,EACT,OAAOR,KAAK,SAAS,IAAIW;YAG7B,MAAMC,SAAS,MAAMX,2BAA2B;gBAC5C,IAAIO,MAAM,EAAE;gBACZ,cAAcF,MAAM,OAAO;YAC/B;YAEA,IAAIM,QAAQ,UAAU;gBAClB,MAAMC,WAAWD,OAAO,QAAQ;gBAChCR,aACI,CAAC,qCAAqC,EAClCS,SAAS,WAAW,IAAIA,SAAS,EAAE,CACtC,8BAA8B,CAAC;gBAEpC,OAAO;YACX;YAEA,MAAMC,aAAa,MAAMd,KAAK,SAAS,IAAIW;YAC3C,IAAIG,YACA,MAAMZ,gBAAgB;gBAClB,IAAIY,WAAW,EAAE;gBACjB,cAAcR,MAAM,OAAO;YAC/B;YAGJ,OAAOQ;QACX,GACA;YAACN,OAAO;YAAIF,MAAM,OAAO;YAAEJ;SAAgB;QAG/C,OAAO;YACH,GAAGF,IAAI;YACPS;QACJ;IACJ"}
|