Enhancement: bulk delete objects (#5688)

This commit is contained in:
shamoon 2024-02-08 10:13:15 -08:00 committed by GitHub
parent b60e16fe33
commit b643a68fa3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 535 additions and 221 deletions

View File

@ -375,14 +375,15 @@ The following methods are supported:
### Objects ### Objects
Bulk editing for objects (tags, document types etc.) currently supports only updating permissions, using Bulk editing for objects (tags, document types etc.) currently supports set permissions or delete
the endpoint: `/api/bulk_edit_object_perms/` which requires a json payload of the format: operations, using the endpoint: `/api/bulk_edit_objects/`, which requires a json payload of the format:
```json ```json
{ {
"objects": [LIST_OF_OBJECT_IDS], "objects": [LIST_OF_OBJECT_IDS],
"object_type": "tags", "correspondents", "document_types" or "storage_paths" "object_type": "tags", "correspondents", "document_types" or "storage_paths",
"owner": OWNER_ID // optional "operation": "set_permissions" or "delete",
"owner": OWNER_ID, // optional
"permissions": { "view": { "users": [] ... }, "change": { ... } }, // (see 'set_permissions' format above) "permissions": { "view": { "users": [] ... }, "change": { ... } }, // (see 'set_permissions' format above)
"merge": true / false // defaults to false, see above "merge": true / false // defaults to false, see above
} }

View File

@ -644,19 +644,19 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">51</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">51</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">51</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">51</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4930506384627295710" datatype="html"> <trans-unit id="4930506384627295710" datatype="html">
@ -966,7 +966,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">78</context> <context context-type="linenumber">82</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -1262,35 +1262,35 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">37</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">37</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">37</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">37</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context> <context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
@ -1354,7 +1354,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">84</context> <context context-type="linenumber">88</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context> <context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
@ -1370,19 +1370,19 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">40</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">40</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">40</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">40</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context> <context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
@ -1429,7 +1429,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">136</context> <context context-type="linenumber">140</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context> <context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
@ -1445,39 +1445,55 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">81</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">81</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">81</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">81</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">84</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">84</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">84</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">84</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">96</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">96</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">96</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">96</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">205</context> <context context-type="linenumber">208</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context> <context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
@ -1881,35 +1897,35 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">80</context> <context context-type="linenumber">83</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">80</context> <context context-type="linenumber">83</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">80</context> <context context-type="linenumber">83</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">80</context> <context context-type="linenumber">83</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">90</context> <context context-type="linenumber">93</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">90</context> <context context-type="linenumber">93</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">90</context> <context context-type="linenumber">93</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">90</context> <context context-type="linenumber">93</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context> <context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
@ -1985,11 +2001,11 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">489</context> <context context-type="linenumber">580</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">528</context> <context context-type="linenumber">619</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context> <context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
@ -2003,6 +2019,10 @@
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context> <context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
<context context-type="linenumber">173</context> <context context-type="linenumber">173</context>
</context-group> </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">320</context>
</context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.ts</context> <context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.ts</context>
<context context-type="linenumber">97</context> <context context-type="linenumber">97</context>
@ -2024,7 +2044,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">530</context> <context context-type="linenumber">621</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context> <context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
@ -2038,6 +2058,10 @@
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context> <context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
<context context-type="linenumber">175</context> <context context-type="linenumber">175</context>
</context-group> </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">322</context>
</context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.ts</context> <context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.ts</context>
<context context-type="linenumber">99</context> <context context-type="linenumber">99</context>
@ -2180,19 +2204,19 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">90</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">90</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">90</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">90</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6988090220128974198" datatype="html"> <trans-unit id="6988090220128974198" datatype="html">
@ -2456,19 +2480,19 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">351</context> <context context-type="linenumber">356</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">391</context> <context context-type="linenumber">396</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">429</context> <context context-type="linenumber">434</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">467</context> <context context-type="linenumber">472</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2159130950882492111" datatype="html"> <trans-unit id="2159130950882492111" datatype="html">
@ -3713,18 +3737,45 @@
<context context-type="linenumber">27</context> <context context-type="linenumber">27</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5674286808255988565" datatype="html">
<source>Create</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">50</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-links-dropdown/share-links-dropdown.component.html</context>
<context context-type="linenumber">64</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">12</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">12</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">12</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">12</context>
</context-group>
</trans-unit>
<trans-unit id="4391289919356861627" datatype="html"> <trans-unit id="4391289919356861627" datatype="html">
<source>Apply</source> <source>Apply</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">49</context> <context context-type="linenumber">56</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7780041345210191160" datatype="html"> <trans-unit id="7780041345210191160" datatype="html">
<source>Click again to exclude items.</source> <source>Click again to exclude items.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">55</context> <context context-type="linenumber">63</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7593728289020204896" datatype="html"> <trans-unit id="7593728289020204896" datatype="html">
@ -4248,29 +4299,6 @@
<context context-type="linenumber">51</context> <context context-type="linenumber">51</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5674286808255988565" datatype="html">
<source>Create</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/share-links-dropdown/share-links-dropdown.component.html</context>
<context context-type="linenumber">64</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">9</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">9</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">9</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">9</context>
</context-group>
</trans-unit>
<trans-unit id="4776429682428363094" datatype="html"> <trans-unit id="4776429682428363094" datatype="html">
<source>1 day</source> <source>1 day</source>
<context-group purpose="location"> <context-group purpose="location">
@ -4423,7 +4451,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">36</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@ -4457,7 +4485,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">102</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
@ -4590,7 +4618,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">296</context> <context context-type="linenumber">301</context>
</context-group> </context-group>
<note priority="1" from="description">this string is used to separate processing, failed and added on the file upload widget</note> <note priority="1" from="description">this string is used to separate processing, failed and added on the file upload widget</note>
</trans-unit> </trans-unit>
@ -4683,7 +4711,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">91</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1418444397960583910" datatype="html"> <trans-unit id="1418444397960583910" datatype="html">
@ -4744,7 +4772,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@ -4767,7 +4795,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">61</context> <context context-type="linenumber">64</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@ -4994,7 +5022,11 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">201</context> <context context-type="linenumber">204</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">318</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5382975254277698192" datatype="html"> <trans-unit id="5382975254277698192" datatype="html">
@ -5033,7 +5065,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">526</context> <context context-type="linenumber">617</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="9197453786953646058" datatype="html"> <trans-unit id="9197453786953646058" datatype="html">
@ -5093,7 +5125,7 @@
<source>Filter correspondents</source> <source>Filter correspondents</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">37</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -5104,7 +5136,7 @@
<source>Filter document types</source> <source>Filter document types</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">49</context> <context context-type="linenumber">51</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -5115,7 +5147,7 @@
<source>Filter storage paths</source> <source>Filter storage paths</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">62</context> <context context-type="linenumber">65</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -5126,53 +5158,53 @@
<source>Include:</source> <source>Include:</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">108</context> <context context-type="linenumber">112</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1208547554603365604" datatype="html"> <trans-unit id="1208547554603365604" datatype="html">
<source> Archived files </source> <source> Archived files </source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">112,114</context> <context context-type="linenumber">116,118</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6791570188945688785" datatype="html"> <trans-unit id="6791570188945688785" datatype="html">
<source> Original files </source> <source> Original files </source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">118,120</context> <context context-type="linenumber">122,124</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3608345051493493574" datatype="html"> <trans-unit id="3608345051493493574" datatype="html">
<source> Use formatted filename </source> <source> Use formatted filename </source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">125,127</context> <context context-type="linenumber">129,131</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1215215387232313677" datatype="html"> <trans-unit id="1215215387232313677" datatype="html">
<source>Error executing bulk operation</source> <source>Error executing bulk operation</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">213</context> <context context-type="linenumber">218</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7894972847287473517" datatype="html"> <trans-unit id="7894972847287473517" datatype="html">
<source>&quot;<x id="PH" equiv-text="items[0].name"/>&quot;</source> <source>&quot;<x id="PH" equiv-text="items[0].name"/>&quot;</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">288</context> <context context-type="linenumber">293</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">294</context> <context context-type="linenumber">299</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8639884465898458690" datatype="html"> <trans-unit id="8639884465898458690" datatype="html">
<source>&quot;<x id="PH" equiv-text="items[0].name"/>&quot; and &quot;<x id="PH_1" equiv-text="items[1].name"/>&quot;</source> <source>&quot;<x id="PH" equiv-text="items[0].name"/>&quot; and &quot;<x id="PH_1" equiv-text="items[1].name"/>&quot;</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">290</context> <context context-type="linenumber">295</context>
</context-group> </context-group>
<note priority="1" from="description">This is for messages like &apos;modify &quot;tag1&quot; and &quot;tag2&quot;&apos;</note> <note priority="1" from="description">This is for messages like &apos;modify &quot;tag1&quot; and &quot;tag2&quot;&apos;</note>
</trans-unit> </trans-unit>
@ -5180,7 +5212,7 @@
<source><x id="PH" equiv-text="list"/> and &quot;<x id="PH_1" equiv-text="items[items.length - 1].name"/>&quot;</source> <source><x id="PH" equiv-text="list"/> and &quot;<x id="PH_1" equiv-text="items[items.length - 1].name"/>&quot;</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">298,300</context> <context context-type="linenumber">303,305</context>
</context-group> </context-group>
<note priority="1" from="description">this is for messages like &apos;modify &quot;tag1&quot;, &quot;tag2&quot; and &quot;tag3&quot;&apos;</note> <note priority="1" from="description">this is for messages like &apos;modify &quot;tag1&quot;, &quot;tag2&quot; and &quot;tag3&quot;&apos;</note>
</trans-unit> </trans-unit>
@ -5188,14 +5220,14 @@
<source>Confirm tags assignment</source> <source>Confirm tags assignment</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">315</context> <context context-type="linenumber">320</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6619516195038467207" datatype="html"> <trans-unit id="6619516195038467207" datatype="html">
<source>This operation will add the tag &quot;<x id="PH" equiv-text="tag.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will add the tag &quot;<x id="PH" equiv-text="tag.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">321</context> <context context-type="linenumber">326</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1894412783609570695" datatype="html"> <trans-unit id="1894412783609570695" datatype="html">
@ -5204,14 +5236,14 @@
)"/> to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> )"/> to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">326,328</context> <context context-type="linenumber">331,333</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7181166515756808573" datatype="html"> <trans-unit id="7181166515756808573" datatype="html">
<source>This operation will remove the tag &quot;<x id="PH" equiv-text="tag.name"/>&quot; from <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will remove the tag &quot;<x id="PH" equiv-text="tag.name"/>&quot; from <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">334</context> <context context-type="linenumber">339</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3819792277998068944" datatype="html"> <trans-unit id="3819792277998068944" datatype="html">
@ -5220,7 +5252,7 @@
)"/> from <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> )"/> from <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">339,341</context> <context context-type="linenumber">344,346</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2739066218579571288" datatype="html"> <trans-unit id="2739066218579571288" datatype="html">
@ -5231,98 +5263,98 @@
)"/> on <x id="PH_2" equiv-text="this.list.selected.size"/> selected document(s).</source> )"/> on <x id="PH_2" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">343,347</context> <context context-type="linenumber">348,352</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2996713129519325161" datatype="html"> <trans-unit id="2996713129519325161" datatype="html">
<source>Confirm correspondent assignment</source> <source>Confirm correspondent assignment</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">384</context> <context context-type="linenumber">389</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6900893559485781849" datatype="html"> <trans-unit id="6900893559485781849" datatype="html">
<source>This operation will assign the correspondent &quot;<x id="PH" equiv-text="correspondent.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will assign the correspondent &quot;<x id="PH" equiv-text="correspondent.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">386</context> <context context-type="linenumber">391</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1257522660364398440" datatype="html"> <trans-unit id="1257522660364398440" datatype="html">
<source>This operation will remove the correspondent from <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will remove the correspondent from <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">388</context> <context context-type="linenumber">393</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5393409374423140648" datatype="html"> <trans-unit id="5393409374423140648" datatype="html">
<source>Confirm document type assignment</source> <source>Confirm document type assignment</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">422</context> <context context-type="linenumber">427</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="332180123895325027" datatype="html"> <trans-unit id="332180123895325027" datatype="html">
<source>This operation will assign the document type &quot;<x id="PH" equiv-text="documentType.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will assign the document type &quot;<x id="PH" equiv-text="documentType.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">424</context> <context context-type="linenumber">429</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2236642492594872779" datatype="html"> <trans-unit id="2236642492594872779" datatype="html">
<source>This operation will remove the document type from <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will remove the document type from <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">426</context> <context context-type="linenumber">431</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6386555513013840736" datatype="html"> <trans-unit id="6386555513013840736" datatype="html">
<source>Confirm storage path assignment</source> <source>Confirm storage path assignment</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">460</context> <context context-type="linenumber">465</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8750527458618415924" datatype="html"> <trans-unit id="8750527458618415924" datatype="html">
<source>This operation will assign the storage path &quot;<x id="PH" equiv-text="storagePath.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will assign the storage path &quot;<x id="PH" equiv-text="storagePath.name"/>&quot; to <x id="PH_1" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">462</context> <context context-type="linenumber">467</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="60728365335056946" datatype="html"> <trans-unit id="60728365335056946" datatype="html">
<source>This operation will remove the storage path from <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will remove the storage path from <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">464</context> <context context-type="linenumber">469</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="749430623564850405" datatype="html"> <trans-unit id="749430623564850405" datatype="html">
<source>Delete confirm</source> <source>Delete confirm</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">487</context> <context context-type="linenumber">578</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4303174930844518780" datatype="html"> <trans-unit id="4303174930844518780" datatype="html">
<source>This operation will permanently delete <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will permanently delete <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">488</context> <context context-type="linenumber">579</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6734339521247847366" datatype="html"> <trans-unit id="6734339521247847366" datatype="html">
<source>Delete document(s)</source> <source>Delete document(s)</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">491</context> <context context-type="linenumber">582</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8968869182645922415" datatype="html"> <trans-unit id="8968869182645922415" datatype="html">
<source>This operation will permanently redo OCR for <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source> <source>This operation will permanently redo OCR for <x id="PH" equiv-text="this.list.selected.size"/> selected document(s).</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">527</context> <context context-type="linenumber">618</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8076495233090006322" datatype="html"> <trans-unit id="8076495233090006322" datatype="html">
@ -6188,109 +6220,109 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">301</context> <context context-type="linenumber">305</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4010735610815226758" datatype="html"> <trans-unit id="4010735610815226758" datatype="html">
<source>Filter by:</source> <source>Filter by:</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">19</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">19</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">19</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">19</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1383365546483928780" datatype="html"> <trans-unit id="1383365546483928780" datatype="html">
<source>Matching</source> <source>Matching</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1488347670280290838" datatype="html"> <trans-unit id="1488347670280290838" datatype="html">
<source>Document count</source> <source>Document count</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7376880254267897616" datatype="html"> <trans-unit id="7376880254267897616" datatype="html">
<source>Filter Documents</source> <source>Filter Documents</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">82</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">82</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">82</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">82</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8095412801504464756" datatype="html"> <trans-unit id="8095412801504464756" datatype="html">
<source>{VAR_PLURAL, plural, =1 {One <x id="INTERPOLATION"/>} other {<x id="INTERPOLATION_1"/> total <x id="INTERPOLATION_2"/>}}</source> <source>{VAR_PLURAL, plural, =1 {One <x id="INTERPOLATION"/>} other {<x id="INTERPOLATION_1"/> total <x id="INTERPOLATION_2"/>}}</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">107</context> <context context-type="linenumber">110</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">107</context> <context context-type="linenumber">110</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">107</context> <context context-type="linenumber">110</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
<context context-type="linenumber">107</context> <context context-type="linenumber">110</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="810888510148304696" datatype="html"> <trans-unit id="810888510148304696" datatype="html">
<source>Automatic</source> <source>Automatic</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">113</context> <context context-type="linenumber">116</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/data/matching-model.ts</context> <context context-type="sourcefile">src/app/data/matching-model.ts</context>
@ -6301,7 +6333,7 @@
<source>None</source> <source>None</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">115</context> <context context-type="linenumber">118</context>
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/data/matching-model.ts</context> <context context-type="sourcefile">src/app/data/matching-model.ts</context>
@ -6312,49 +6344,70 @@
<source>Successfully created <x id="PH" equiv-text="this.typeName"/>.</source> <source>Successfully created <x id="PH" equiv-text="this.typeName"/>.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">158</context> <context context-type="linenumber">161</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3928835053823658072" datatype="html"> <trans-unit id="3928835053823658072" datatype="html">
<source>Error occurred while creating <x id="PH" equiv-text="this.typeName"/>.</source> <source>Error occurred while creating <x id="PH" equiv-text="this.typeName"/>.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">163</context> <context context-type="linenumber">166</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2541368547549828690" datatype="html"> <trans-unit id="2541368547549828690" datatype="html">
<source>Successfully updated <x id="PH" equiv-text="this.typeName"/>.</source> <source>Successfully updated <x id="PH" equiv-text="this.typeName"/>.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">178</context> <context context-type="linenumber">181</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6442673774206210733" datatype="html"> <trans-unit id="6442673774206210733" datatype="html">
<source>Error occurred while saving <x id="PH" equiv-text="this.typeName"/>.</source> <source>Error occurred while saving <x id="PH" equiv-text="this.typeName"/>.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">183</context> <context context-type="linenumber">186</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8371896857609524947" datatype="html"> <trans-unit id="8371896857609524947" datatype="html">
<source>Associated documents will not be deleted.</source> <source>Associated documents will not be deleted.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">203</context> <context context-type="linenumber">206</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6639207128255974941" datatype="html"> <trans-unit id="6639207128255974941" datatype="html">
<source>Error while deleting element</source> <source>Error while deleting element</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">219</context> <context context-type="linenumber">222</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4863024195229581844" datatype="html"> <trans-unit id="4863024195229581844" datatype="html">
<source>Permissions updated successfully</source> <source>Permissions updated successfully</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">294</context> <context context-type="linenumber">298</context>
</context-group>
</trans-unit>
<trans-unit id="1464476612812630086" datatype="html">
<source>This operation will permanently delete all objects.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">319</context>
</context-group>
</trans-unit>
<trans-unit id="5897787932098828336" datatype="html">
<source>Objects deleted successfully</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">333</context>
</context-group>
</trans-unit>
<trans-unit id="8273353839648035634" datatype="html">
<source>Error deleting objects</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
<context context-type="linenumber">339</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5101757640976222639" datatype="html"> <trans-unit id="5101757640976222639" datatype="html">

View File

@ -2,9 +2,12 @@
<button class="btn btn-sm btn-outline-secondary me-2" (click)="clearSelection()" [hidden]="selectedObjects.size === 0"> <button class="btn btn-sm btn-outline-secondary me-2" (click)="clearSelection()" [hidden]="selectedObjects.size === 0">
<i-bs name="x"></i-bs>&nbsp;<ng-container i18n>Clear selection</ng-container> <i-bs name="x"></i-bs>&nbsp;<ng-container i18n>Clear selection</ng-container>
</button> </button>
<button type="button" class="btn btn-sm btn-outline-primary me-5" (click)="setPermissions()" [disabled]="!userOwnsAll || selectedObjects.size === 0"> <button type="button" class="btn btn-sm btn-outline-primary me-2" (click)="setPermissions()" [disabled]="!userOwnsAll || selectedObjects.size === 0">
<i-bs name="person-fill-lock"></i-bs>&nbsp;<ng-container i18n>Permissions</ng-container> <i-bs name="person-fill-lock"></i-bs>&nbsp;<ng-container i18n>Permissions</ng-container>
</button> </button>
<button type="button" class="btn btn-sm btn-outline-danger me-5" (click)="delete()" [disabled]="!userOwnsAll || selectedObjects.size === 0">
<i-bs name="trash"></i-bs>&nbsp;<ng-container i18n>Delete</ng-container>
</button>
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" *pngxIfPermissions="{ action: PermissionAction.Add, type: permissionType }"> <button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" *pngxIfPermissions="{ action: PermissionAction.Add, type: permissionType }">
<i-bs name="plus-circle"></i-bs>&nbsp;<ng-container i18n>Create</ng-container> <i-bs name="plus-circle"></i-bs>&nbsp;<ng-container i18n>Create</ng-container>
</button> </button>

View File

@ -37,6 +37,7 @@ import { MATCH_NONE } from 'src/app/data/matching-model'
import { MATCH_LITERAL } from 'src/app/data/matching-model' import { MATCH_LITERAL } from 'src/app/data/matching-model'
import { PermissionsDialogComponent } from '../../common/permissions-dialog/permissions-dialog.component' import { PermissionsDialogComponent } from '../../common/permissions-dialog/permissions-dialog.component'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { BulkEditObjectOperation } from 'src/app/services/rest/abstract-name-filter-service'
const tags: Tag[] = [ const tags: Tag[] = [
{ {
@ -149,7 +150,7 @@ describe('ManagementListComponent', () => {
const toastInfoSpy = jest.spyOn(toastService, 'showInfo') const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const reloadSpy = jest.spyOn(component, 'reloadData') const reloadSpy = jest.spyOn(component, 'reloadData')
const createButton = fixture.debugElement.queryAll(By.css('button'))[2] const createButton = fixture.debugElement.queryAll(By.css('button'))[3]
createButton.triggerEventHandler('click') createButton.triggerEventHandler('click')
expect(modal).not.toBeUndefined() expect(modal).not.toBeUndefined()
@ -173,7 +174,7 @@ describe('ManagementListComponent', () => {
const toastInfoSpy = jest.spyOn(toastService, 'showInfo') const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const reloadSpy = jest.spyOn(component, 'reloadData') const reloadSpy = jest.spyOn(component, 'reloadData')
const editButton = fixture.debugElement.queryAll(By.css('button'))[6] const editButton = fixture.debugElement.queryAll(By.css('button'))[7]
editButton.triggerEventHandler('click') editButton.triggerEventHandler('click')
expect(modal).not.toBeUndefined() expect(modal).not.toBeUndefined()
@ -198,7 +199,7 @@ describe('ManagementListComponent', () => {
const deleteSpy = jest.spyOn(tagService, 'delete') const deleteSpy = jest.spyOn(tagService, 'delete')
const reloadSpy = jest.spyOn(component, 'reloadData') const reloadSpy = jest.spyOn(component, 'reloadData')
const deleteButton = fixture.debugElement.queryAll(By.css('button'))[7] const deleteButton = fixture.debugElement.queryAll(By.css('button'))[8]
deleteButton.triggerEventHandler('click') deleteButton.triggerEventHandler('click')
expect(modal).not.toBeUndefined() expect(modal).not.toBeUndefined()
@ -218,7 +219,7 @@ describe('ManagementListComponent', () => {
it('should support quick filter for objects', () => { it('should support quick filter for objects', () => {
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter') const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
const filterButton = fixture.debugElement.queryAll(By.css('button'))[5] const filterButton = fixture.debugElement.queryAll(By.css('button'))[6]
filterButton.triggerEventHandler('click') filterButton.triggerEventHandler('click')
expect(qfSpy).toHaveBeenCalledWith([ expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_HAS_TAGS_ALL, value: tags[0].id.toString() }, { rule_type: FILTER_HAS_TAGS_ALL, value: tags[0].id.toString() },
@ -246,7 +247,7 @@ describe('ManagementListComponent', () => {
}) })
it('should support bulk edit permissions', () => { it('should support bulk edit permissions', () => {
const bulkEditPermsSpy = jest.spyOn(tagService, 'bulk_update_permissions') const bulkEditPermsSpy = jest.spyOn(tagService, 'bulk_edit_objects')
component.toggleSelected(tags[0]) component.toggleSelected(tags[0])
component.toggleSelected(tags[1]) component.toggleSelected(tags[1])
component.toggleSelected(tags[2]) component.toggleSelected(tags[2])
@ -280,4 +281,35 @@ describe('ManagementListComponent', () => {
expect(bulkEditPermsSpy).toHaveBeenCalled() expect(bulkEditPermsSpy).toHaveBeenCalled()
expect(successToastSpy).toHaveBeenCalled() expect(successToastSpy).toHaveBeenCalled()
}) })
it('should support bulk delete objects', () => {
const bulkEditSpy = jest.spyOn(tagService, 'bulk_edit_objects')
component.toggleSelected(tags[0])
component.toggleSelected(tags[1])
const selected = new Set([tags[0].id, tags[1].id])
expect(component.selectedObjects).toEqual(selected)
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
fixture.detectChanges()
component.delete()
expect(modal).not.toBeUndefined()
// fail first
bulkEditSpy.mockReturnValueOnce(
throwError(() => new Error('error setting permissions'))
)
const errorToastSpy = jest.spyOn(toastService, 'showError')
modal.componentInstance.confirmClicked.emit(null)
expect(bulkEditSpy).toHaveBeenCalledWith(
Array.from(selected),
BulkEditObjectOperation.Delete
)
expect(errorToastSpy).toHaveBeenCalled()
const successToastSpy = jest.spyOn(toastService, 'showInfo')
bulkEditSpy.mockReturnValueOnce(of('OK'))
modal.componentInstance.confirmClicked.emit(null)
expect(bulkEditSpy).toHaveBeenCalled()
expect(successToastSpy).toHaveBeenCalled()
})
}) })

View File

@ -28,7 +28,10 @@ import {
PermissionsService, PermissionsService,
PermissionType, PermissionType,
} from 'src/app/services/permissions.service' } from 'src/app/services/permissions.service'
import { AbstractNameFilterService } from 'src/app/services/rest/abstract-name-filter-service' import {
AbstractNameFilterService,
BulkEditObjectOperation,
} from 'src/app/services/rest/abstract-name-filter-service'
import { ToastService } from 'src/app/services/toast.service' import { ToastService } from 'src/app/services/toast.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component' import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component'
@ -282,8 +285,9 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
({ permissions, merge }) => { ({ permissions, merge }) => {
modal.componentInstance.buttonsEnabled = false modal.componentInstance.buttonsEnabled = false
this.service this.service
.bulk_update_permissions( .bulk_edit_objects(
Array.from(this.selectedObjects), Array.from(this.selectedObjects),
BulkEditObjectOperation.SetPermissions,
permissions, permissions,
merge merge
) )
@ -306,4 +310,37 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
} }
) )
} }
delete() {
let modal = this.modalService.open(ConfirmDialogComponent, {
backdrop: 'static',
})
modal.componentInstance.title = $localize`Confirm delete`
modal.componentInstance.messageBold = $localize`This operation will permanently delete all objects.`
modal.componentInstance.message = $localize`This operation cannot be undone.`
modal.componentInstance.btnClass = 'btn-danger'
modal.componentInstance.btnCaption = $localize`Proceed`
modal.componentInstance.confirmClicked.subscribe(() => {
modal.componentInstance.buttonsEnabled = false
this.service
.bulk_edit_objects(
Array.from(this.selectedObjects),
BulkEditObjectOperation.Delete
)
.subscribe({
next: () => {
modal.close()
this.toastService.showInfo($localize`Objects deleted successfully`)
this.reloadData()
},
error: (error) => {
modal.componentInstance.buttonsEnabled = true
this.toastService.showError(
$localize`Error deleting objects`,
error
)
},
})
})
}
} }

View File

@ -2,7 +2,10 @@ import { HttpTestingController } from '@angular/common/http/testing'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { TestBed } from '@angular/core/testing' import { TestBed } from '@angular/core/testing'
import { environment } from 'src/environments/environment' import { environment } from 'src/environments/environment'
import { AbstractNameFilterService } from './abstract-name-filter-service' import {
AbstractNameFilterService,
BulkEditObjectOperation,
} from './abstract-name-filter-service'
import { commonAbstractPaperlessServiceTests } from './abstract-paperless-service.spec' import { commonAbstractPaperlessServiceTests } from './abstract-paperless-service.spec'
let httpTestingController: HttpTestingController let httpTestingController: HttpTestingController
@ -53,8 +56,9 @@ export const commonAbstractNameFilterPaperlessServiceTests = (
}, },
} }
subscription = service subscription = service
.bulk_update_permissions( .bulk_edit_objects(
[1, 2], [1, 2],
BulkEditObjectOperation.SetPermissions,
{ {
owner, owner,
set_permissions: permissions, set_permissions: permissions,
@ -63,9 +67,33 @@ export const commonAbstractNameFilterPaperlessServiceTests = (
) )
.subscribe() .subscribe()
const req = httpTestingController.expectOne( const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}bulk_edit_object_perms/` `${environment.apiBaseUrl}bulk_edit_objects/`
) )
expect(req.request.method).toEqual('POST') expect(req.request.method).toEqual('POST')
expect(req.request.body).toEqual({
objects: [1, 2],
object_type: endpoint,
operation: BulkEditObjectOperation.SetPermissions,
permissions,
owner,
merge: true,
})
req.flush([])
})
test('should call appropriate api endpoint for bulk delete objects', () => {
subscription = service
.bulk_edit_objects([1, 2], BulkEditObjectOperation.Delete)
.subscribe()
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}bulk_edit_objects/`
)
expect(req.request.method).toEqual('POST')
expect(req.request.body).toEqual({
objects: [1, 2],
object_type: endpoint,
operation: BulkEditObjectOperation.Delete,
})
req.flush([]) req.flush([])
}) })
}) })

View File

@ -3,6 +3,11 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
import { PermissionsObject } from 'src/app/data/object-with-permissions' import { PermissionsObject } from 'src/app/data/object-with-permissions'
import { Observable } from 'rxjs' import { Observable } from 'rxjs'
export enum BulkEditObjectOperation {
SetPermissions = 'set_permissions',
Delete = 'delete',
}
export abstract class AbstractNameFilterService< export abstract class AbstractNameFilterService<
T extends ObjectWithId, T extends ObjectWithId,
> extends AbstractPaperlessService<T> { > extends AbstractPaperlessService<T> {
@ -24,17 +29,22 @@ export abstract class AbstractNameFilterService<
return this.list(page, pageSize, sortField, sortReverse, params) return this.list(page, pageSize, sortField, sortReverse, params)
} }
bulk_update_permissions( bulk_edit_objects(
objects: Array<number>, objects: Array<number>,
permissions: { owner: number; set_permissions: PermissionsObject }, operation: BulkEditObjectOperation,
merge: boolean permissions: { owner: number; set_permissions: PermissionsObject } = null,
merge: boolean = null
): Observable<string> { ): Observable<string> {
return this.http.post<string>(`${this.baseUrl}bulk_edit_object_perms/`, { const params = {
objects, objects,
object_type: this.resourceName, object_type: this.resourceName,
owner: permissions.owner, operation,
permissions: permissions.set_permissions, }
merge, if (operation === BulkEditObjectOperation.SetPermissions) {
}) params['owner'] = permissions?.owner
params['permissions'] = permissions?.set_permissions
params['merge'] = merge
}
return this.http.post<string>(`${this.baseUrl}bulk_edit_objects/`, params)
} }
} }

View File

@ -3,7 +3,7 @@ const base_url = new URL(document.baseURI)
export const environment = { export const environment = {
production: true, production: true,
apiBaseUrl: document.baseURI + 'api/', apiBaseUrl: document.baseURI + 'api/',
apiVersion: '4', apiVersion: '5',
appTitle: 'Paperless-ngx', appTitle: 'Paperless-ngx',
version: '2.4.3-dev', version: '2.4.3-dev',
webSocketHost: window.location.host, webSocketHost: window.location.host,

View File

@ -5,7 +5,7 @@
export const environment = { export const environment = {
production: false, production: false,
apiBaseUrl: 'http://localhost:8000/api/', apiBaseUrl: 'http://localhost:8000/api/',
apiVersion: '4', apiVersion: '5',
appTitle: 'Paperless-ngx', appTitle: 'Paperless-ngx',
version: 'DEVELOPMENT', version: 'DEVELOPMENT',
webSocketHost: 'localhost:8000', webSocketHost: 'localhost:8000',

View File

@ -1281,7 +1281,7 @@ class ShareLinkSerializer(OwnedObjectSerializer):
return super().create(validated_data) return super().create(validated_data)
class BulkEditObjectPermissionsSerializer(serializers.Serializer, SetPermissionsMixin): class BulkEditObjectsSerializer(serializers.Serializer, SetPermissionsMixin):
objects = serializers.ListField( objects = serializers.ListField(
required=True, required=True,
allow_empty=False, allow_empty=False,
@ -1301,6 +1301,16 @@ class BulkEditObjectPermissionsSerializer(serializers.Serializer, SetPermissions
write_only=True, write_only=True,
) )
operation = serializers.ChoiceField(
choices=[
"set_permissions",
"delete",
],
label="Operation",
required=True,
write_only=True,
)
owner = serializers.PrimaryKeyRelatedField( owner = serializers.PrimaryKeyRelatedField(
queryset=User.objects.all(), queryset=User.objects.all(),
required=False, required=False,
@ -1353,11 +1363,14 @@ class BulkEditObjectPermissionsSerializer(serializers.Serializer, SetPermissions
def validate(self, attrs): def validate(self, attrs):
object_type = attrs["object_type"] object_type = attrs["object_type"]
objects = attrs["objects"] objects = attrs["objects"]
permissions = attrs.get("permissions") operation = attrs.get("operation")
self._validate_objects(objects, object_type) self._validate_objects(objects, object_type)
if permissions is not None:
self._validate_permissions(permissions) if operation == "set_permissions":
permissions = attrs.get("permissions")
if permissions is not None:
self._validate_permissions(permissions)
return attrs return attrs

View File

@ -222,3 +222,118 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
args, _ = bulk_update_mock.call_args args, _ = bulk_update_mock.call_args
self.assertCountEqual([document.pk], args[0]) self.assertCountEqual([document.pk], args[0])
class TestBulkEditObjects(APITestCase):
# See test_api_permissions.py for bulk tests on permissions
def setUp(self):
super().setUp()
self.temp_admin = User.objects.create_superuser(username="temp_admin")
self.client.force_authenticate(user=self.temp_admin)
self.t1 = Tag.objects.create(name="t1")
self.t2 = Tag.objects.create(name="t2")
self.c1 = Correspondent.objects.create(name="c1")
self.dt1 = DocumentType.objects.create(name="dt1")
self.sp1 = StoragePath.objects.create(name="sp1")
self.user1 = User.objects.create(username="user1")
self.user2 = User.objects.create(username="user2")
self.user3 = User.objects.create(username="user3")
def test_bulk_objects_delete(self):
"""
GIVEN:
- Existing objects
WHEN:
- bulk_edit_objects API endpoint is called with delete operation
THEN:
- Objects are deleted
"""
response = self.client.post(
"/api/bulk_edit_objects/",
json.dumps(
{
"objects": [self.t1.id, self.t2.id],
"object_type": "tags",
"operation": "delete",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(Tag.objects.count(), 0)
response = self.client.post(
"/api/bulk_edit_objects/",
json.dumps(
{
"objects": [self.c1.id],
"object_type": "correspondents",
"operation": "delete",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(Correspondent.objects.count(), 0)
response = self.client.post(
"/api/bulk_edit_objects/",
json.dumps(
{
"objects": [self.dt1.id],
"object_type": "document_types",
"operation": "delete",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(DocumentType.objects.count(), 0)
response = self.client.post(
"/api/bulk_edit_objects/",
json.dumps(
{
"objects": [self.sp1.id],
"object_type": "storage_paths",
"operation": "delete",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(StoragePath.objects.count(), 0)
def test_bulk_edit_object_permissions_insufficient_perms(self):
"""
GIVEN:
- Objects owned by user other than logged in user
WHEN:
- bulk_edit_objects API endpoint is called with delete operation
THEN:
- User is not able to delete objects
"""
self.t1.owner = User.objects.get(username="temp_admin")
self.t1.save()
self.client.force_authenticate(user=self.user1)
response = self.client.post(
"/api/bulk_edit_objects/",
json.dumps(
{
"objects": [self.t1.id, self.t2.id],
"object_type": "tags",
"operation": "delete",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.content, b"Insufficient permissions")

View File

@ -717,7 +717,7 @@ class TestBulkEditObjectPermissions(APITestCase):
GIVEN: GIVEN:
- Existing objects - Existing objects
WHEN: WHEN:
- bulk_edit_object_perms API endpoint is called - bulk_edit_objects API endpoint is called with set_permissions operation
THEN: THEN:
- Permissions and / or owner are changed - Permissions and / or owner are changed
""" """
@ -733,11 +733,12 @@ class TestBulkEditObjectPermissions(APITestCase):
} }
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.t1.id, self.t2.id], "objects": [self.t1.id, self.t2.id],
"object_type": "tags", "object_type": "tags",
"operation": "set_permissions",
"permissions": permissions, "permissions": permissions,
}, },
), ),
@ -748,11 +749,12 @@ class TestBulkEditObjectPermissions(APITestCase):
self.assertIn(self.user1, get_users_with_perms(self.t1)) self.assertIn(self.user1, get_users_with_perms(self.t1))
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.c1.id], "objects": [self.c1.id],
"object_type": "correspondents", "object_type": "correspondents",
"operation": "set_permissions",
"permissions": permissions, "permissions": permissions,
}, },
), ),
@ -763,11 +765,12 @@ class TestBulkEditObjectPermissions(APITestCase):
self.assertIn(self.user1, get_users_with_perms(self.c1)) self.assertIn(self.user1, get_users_with_perms(self.c1))
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.dt1.id], "objects": [self.dt1.id],
"object_type": "document_types", "object_type": "document_types",
"operation": "set_permissions",
"permissions": permissions, "permissions": permissions,
}, },
), ),
@ -778,11 +781,12 @@ class TestBulkEditObjectPermissions(APITestCase):
self.assertIn(self.user1, get_users_with_perms(self.dt1)) self.assertIn(self.user1, get_users_with_perms(self.dt1))
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.sp1.id], "objects": [self.sp1.id],
"object_type": "storage_paths", "object_type": "storage_paths",
"operation": "set_permissions",
"permissions": permissions, "permissions": permissions,
}, },
), ),
@ -793,11 +797,12 @@ class TestBulkEditObjectPermissions(APITestCase):
self.assertIn(self.user1, get_users_with_perms(self.sp1)) self.assertIn(self.user1, get_users_with_perms(self.sp1))
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.t1.id, self.t2.id], "objects": [self.t1.id, self.t2.id],
"object_type": "tags", "object_type": "tags",
"operation": "set_permissions",
"owner": self.user3.id, "owner": self.user3.id,
}, },
), ),
@ -808,11 +813,12 @@ class TestBulkEditObjectPermissions(APITestCase):
self.assertEqual(Tag.objects.get(pk=self.t2.id).owner, self.user3) self.assertEqual(Tag.objects.get(pk=self.t2.id).owner, self.user3)
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.sp1.id], "objects": [self.sp1.id],
"object_type": "storage_paths", "object_type": "storage_paths",
"operation": "set_permissions",
"owner": self.user3.id, "owner": self.user3.id,
}, },
), ),
@ -827,7 +833,7 @@ class TestBulkEditObjectPermissions(APITestCase):
GIVEN: GIVEN:
- Existing objects - Existing objects
WHEN: WHEN:
- bulk_edit_object_perms API endpoint is called with merge=True or merge=False (default) - bulk_edit_objects API endpoint is called with set_permissions operation with merge=True or merge=False (default)
THEN: THEN:
- Permissions and / or owner are replaced or merged, depending on the merge flag - Permissions and / or owner are replaced or merged, depending on the merge flag
""" """
@ -848,13 +854,14 @@ class TestBulkEditObjectPermissions(APITestCase):
# merge=True # merge=True
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.t1.id, self.t2.id], "objects": [self.t1.id, self.t2.id],
"object_type": "tags", "object_type": "tags",
"owner": self.user1.id, "owner": self.user1.id,
"permissions": permissions, "permissions": permissions,
"operation": "set_permissions",
"merge": True, "merge": True,
}, },
), ),
@ -877,12 +884,13 @@ class TestBulkEditObjectPermissions(APITestCase):
# merge=False (default) # merge=False (default)
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.t1.id, self.t2.id], "objects": [self.t1.id, self.t2.id],
"object_type": "tags", "object_type": "tags",
"permissions": permissions, "permissions": permissions,
"operation": "set_permissions",
"merge": False, "merge": False,
}, },
), ),
@ -900,7 +908,7 @@ class TestBulkEditObjectPermissions(APITestCase):
GIVEN: GIVEN:
- Objects owned by user other than logged in user - Objects owned by user other than logged in user
WHEN: WHEN:
- bulk_edit_object_perms API endpoint is called - bulk_edit_objects API endpoint is called with set_permissions operation
THEN: THEN:
- User is not able to change permissions - User is not able to change permissions
""" """
@ -909,11 +917,12 @@ class TestBulkEditObjectPermissions(APITestCase):
self.client.force_authenticate(user=self.user1) self.client.force_authenticate(user=self.user1)
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.t1.id, self.t2.id], "objects": [self.t1.id, self.t2.id],
"object_type": "tags", "object_type": "tags",
"operation": "set_permissions",
"owner": self.user1.id, "owner": self.user1.id,
}, },
), ),
@ -928,17 +937,18 @@ class TestBulkEditObjectPermissions(APITestCase):
GIVEN: GIVEN:
- Existing objects - Existing objects
WHEN: WHEN:
- bulk_edit_object_perms API endpoint is called with invalid params - bulk_edit_objects API endpoint is called with set_permissions operation with invalid params
THEN: THEN:
- Validation fails - Validation fails
""" """
# not a list # not a list
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": self.t1.id, "objects": self.t1.id,
"object_type": "tags", "object_type": "tags",
"operation": "set_permissions",
"owner": self.user1.id, "owner": self.user1.id,
}, },
), ),
@ -949,7 +959,7 @@ class TestBulkEditObjectPermissions(APITestCase):
# not a list of ints # not a list of ints
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": ["one"], "objects": ["one"],
@ -964,11 +974,12 @@ class TestBulkEditObjectPermissions(APITestCase):
# duplicates # duplicates
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [self.t1.id, self.t2.id, self.t1.id], "objects": [self.t1.id, self.t2.id, self.t1.id],
"object_type": "tags", "object_type": "tags",
"operation": "set_permissions",
"owner": self.user1.id, "owner": self.user1.id,
}, },
), ),
@ -979,11 +990,12 @@ class TestBulkEditObjectPermissions(APITestCase):
# not a valid object type # not a valid object type
response = self.client.post( response = self.client.post(
"/api/bulk_edit_object_perms/", "/api/bulk_edit_objects/",
json.dumps( json.dumps(
{ {
"objects": [1], "objects": [1],
"object_type": "madeup", "object_type": "madeup",
"operation": "set_permissions",
"owner": self.user1.id, "owner": self.user1.id,
}, },
), ),

View File

@ -115,7 +115,7 @@ from documents.permissions import has_perms_owner_aware
from documents.permissions import set_permissions_for_object from documents.permissions import set_permissions_for_object
from documents.serialisers import AcknowledgeTasksViewSerializer from documents.serialisers import AcknowledgeTasksViewSerializer
from documents.serialisers import BulkDownloadSerializer from documents.serialisers import BulkDownloadSerializer
from documents.serialisers import BulkEditObjectPermissionsSerializer from documents.serialisers import BulkEditObjectsSerializer
from documents.serialisers import BulkEditSerializer from documents.serialisers import BulkEditSerializer
from documents.serialisers import CorrespondentSerializer from documents.serialisers import CorrespondentSerializer
from documents.serialisers import CustomFieldSerializer from documents.serialisers import CustomFieldSerializer
@ -1401,9 +1401,9 @@ def serve_file(doc: Document, use_archive: bool, disposition: str):
return response return response
class BulkEditObjectPermissionsView(GenericAPIView, PassUserMixin): class BulkEditObjectsView(GenericAPIView, PassUserMixin):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
serializer_class = BulkEditObjectPermissionsSerializer serializer_class = BulkEditObjectsSerializer
parser_classes = (parsers.JSONParser,) parser_classes = (parsers.JSONParser,)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -1414,42 +1414,52 @@ class BulkEditObjectPermissionsView(GenericAPIView, PassUserMixin):
object_type = serializer.validated_data.get("object_type") object_type = serializer.validated_data.get("object_type")
object_ids = serializer.validated_data.get("objects") object_ids = serializer.validated_data.get("objects")
object_class = serializer.get_object_class(object_type) object_class = serializer.get_object_class(object_type)
permissions = serializer.validated_data.get("permissions") operation = serializer.validated_data.get("operation")
owner = serializer.validated_data.get("owner")
merge = serializer.validated_data.get("merge") objs = object_class.objects.filter(pk__in=object_ids)
if not user.is_superuser: if not user.is_superuser:
objs = object_class.objects.filter(pk__in=object_ids)
has_perms = all((obj.owner == user or obj.owner is None) for obj in objs) has_perms = all((obj.owner == user or obj.owner is None) for obj in objs)
if not has_perms: if not has_perms:
return HttpResponseForbidden("Insufficient permissions") return HttpResponseForbidden("Insufficient permissions")
try: if operation == "set_permissions":
qs = object_class.objects.filter(id__in=object_ids) permissions = serializer.validated_data.get("permissions")
owner = serializer.validated_data.get("owner")
merge = serializer.validated_data.get("merge")
# if merge is true, we dont want to remove the owner try:
if "owner" in serializer.validated_data and ( qs = object_class.objects.filter(id__in=object_ids)
not merge or (merge and owner is not None)
):
# if merge is true, we dont want to overwrite the owner
qs_owner_update = qs.filter(owner__isnull=True) if merge else qs
qs_owner_update.update(owner=owner)
if "permissions" in serializer.validated_data: # if merge is true, we dont want to remove the owner
for obj in qs: if "owner" in serializer.validated_data and (
set_permissions_for_object( not merge or (merge and owner is not None)
permissions=permissions, ):
object=obj, # if merge is true, we dont want to overwrite the owner
merge=merge, qs_owner_update = qs.filter(owner__isnull=True) if merge else qs
) qs_owner_update.update(owner=owner)
return Response({"result": "OK"}) if "permissions" in serializer.validated_data:
except Exception as e: for obj in qs:
logger.warning(f"An error occurred performing bulk permissions edit: {e!s}") set_permissions_for_object(
return HttpResponseBadRequest( permissions=permissions,
"Error performing bulk permissions edit, check logs for more detail.", object=obj,
) merge=merge,
)
except Exception as e:
logger.warning(
f"An error occurred performing bulk permissions edit: {e!s}",
)
return HttpResponseBadRequest(
"Error performing bulk permissions edit, check logs for more detail.",
)
elif operation == "delete":
objs.delete()
return Response({"result": "OK"})
class WorkflowTriggerViewSet(ModelViewSet): class WorkflowTriggerViewSet(ModelViewSet):

View File

@ -322,7 +322,7 @@ REST_FRAMEWORK = {
"DEFAULT_VERSION": "1", "DEFAULT_VERSION": "1",
# Make sure these are ordered and that the most recent version appears # Make sure these are ordered and that the most recent version appears
# last # last
"ALLOWED_VERSIONS": ["1", "2", "3", "4"], "ALLOWED_VERSIONS": ["1", "2", "3", "4", "5"],
} }
if DEBUG: if DEBUG:

View File

@ -16,7 +16,7 @@ from rest_framework.routers import DefaultRouter
from documents.views import AcknowledgeTasksView from documents.views import AcknowledgeTasksView
from documents.views import BulkDownloadView from documents.views import BulkDownloadView
from documents.views import BulkEditObjectPermissionsView from documents.views import BulkEditObjectsView
from documents.views import BulkEditView from documents.views import BulkEditView
from documents.views import CorrespondentViewSet from documents.views import CorrespondentViewSet
from documents.views import CustomFieldViewSet from documents.views import CustomFieldViewSet
@ -129,9 +129,9 @@ urlpatterns = [
), ),
path("token/", views.obtain_auth_token), path("token/", views.obtain_auth_token),
re_path( re_path(
"^bulk_edit_object_perms/", "^bulk_edit_objects/",
BulkEditObjectPermissionsView.as_view(), BulkEditObjectsView.as_view(),
name="bulk_edit_object_permissions", name="bulk_edit_objects",
), ),
path("profile/generate_auth_token/", GenerateAuthTokenView.as_view()), path("profile/generate_auth_token/", GenerateAuthTokenView.as_view()),
path( path(