odoo-addon-dms 16.0.1.8.0.3__py3-none-any.whl → 17.0.1.0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. odoo/addons/dms/README.rst +132 -78
  2. odoo/addons/dms/__manifest__.py +34 -16
  3. odoo/addons/dms/actions/file.xml +1 -3
  4. odoo/addons/dms/controllers/main.py +0 -34
  5. odoo/addons/dms/controllers/portal.py +178 -92
  6. odoo/addons/dms/data/onboarding_data.xml +77 -0
  7. odoo/addons/dms/demo/access_group.xml +3 -9
  8. odoo/addons/dms/i18n/de.po +13 -117
  9. odoo/addons/dms/i18n/dms.pot +137 -174
  10. odoo/addons/dms/i18n/es.po +15 -58
  11. odoo/addons/dms/i18n/fr.po +296 -450
  12. odoo/addons/dms/i18n/he_IL.po +13 -117
  13. odoo/addons/dms/i18n/it.po +15 -131
  14. odoo/addons/dms/i18n/nl.po +13 -117
  15. odoo/addons/dms/i18n/pt.po +13 -121
  16. odoo/addons/dms/i18n/pt_BR.po +28 -147
  17. odoo/addons/dms/i18n/ru.po +13 -117
  18. odoo/addons/dms/models/__init__.py +7 -1
  19. odoo/addons/dms/models/abstract_dms_mixin.py +1 -1
  20. odoo/addons/dms/models/access_groups.py +18 -11
  21. odoo/addons/dms/models/base.py +10 -2
  22. odoo/addons/dms/models/directory.py +46 -75
  23. odoo/addons/dms/models/{category.py → dms_category.py} +10 -42
  24. odoo/addons/dms/models/dms_file.py +125 -147
  25. odoo/addons/dms/models/dms_security_mixin.py +26 -22
  26. odoo/addons/dms/models/ir_attachment.py +0 -1
  27. odoo/addons/dms/models/ir_binary.py +19 -0
  28. odoo/addons/dms/models/mail_thread.py +2 -4
  29. odoo/addons/dms/models/mixins_thumbnail.py +13 -8
  30. odoo/addons/dms/models/onboarding_onboarding.py +16 -0
  31. odoo/addons/dms/models/onboarding_onboarding_step.py +50 -0
  32. odoo/addons/dms/models/res_company.py +22 -47
  33. odoo/addons/dms/models/res_config_settings.py +0 -1
  34. odoo/addons/dms/models/storage.py +4 -24
  35. odoo/addons/dms/models/tag.py +1 -1
  36. odoo/addons/dms/readme/CONFIGURE.md +59 -0
  37. odoo/addons/dms/readme/CONTRIBUTORS.md +14 -0
  38. odoo/addons/dms/readme/CREDITS.md +6 -0
  39. odoo/addons/dms/readme/DESCRIPTION.md +9 -0
  40. odoo/addons/dms/readme/INSTALL.md +4 -0
  41. odoo/addons/dms/readme/ROADMAP.md +19 -0
  42. odoo/addons/dms/readme/USAGE.md +11 -0
  43. odoo/addons/dms/security/security.xml +1 -0
  44. odoo/addons/dms/static/description/icon.png +0 -0
  45. odoo/addons/dms/static/description/icon.svg +4 -1
  46. odoo/addons/dms/static/description/index.html +133 -88
  47. odoo/addons/dms/static/description/portal_icon.svg +12 -0
  48. odoo/addons/dms/static/src/js/fields/{path_owl.esm.js → path_json/path_owl.esm.js} +22 -4
  49. odoo/addons/dms/static/src/js/fields/{path_owl.xml → path_json/path_owl.xml} +7 -4
  50. odoo/addons/dms/static/src/js/fields/preview_binary/preview_record.esm.js +47 -0
  51. odoo/addons/dms/static/src/js/{views/fields/binary → fields/preview_binary}/preview_record.xml +5 -4
  52. odoo/addons/dms/static/src/js/views/dms_file_upload.esm.js +155 -148
  53. odoo/addons/dms/static/src/js/views/file_kanban_controller.xml +0 -1
  54. odoo/addons/dms/static/src/js/views/file_kanban_record.esm.js +26 -27
  55. odoo/addons/dms/static/src/js/views/file_kanban_renderer.esm.js +1 -2
  56. odoo/addons/dms/static/src/js/views/file_kanban_renderer.xml +12 -16
  57. odoo/addons/dms/static/src/js/views/file_kanban_view.esm.js +11 -9
  58. odoo/addons/dms/static/src/js/views/file_list_controller.esm.js +1 -1
  59. odoo/addons/dms/static/src/js/views/file_list_renderer.xml +1 -7
  60. odoo/addons/dms/static/src/js/views/file_list_view.esm.js +11 -9
  61. odoo/addons/dms/static/src/js/views/search_panel.esm.js +9 -10
  62. odoo/addons/dms/static/src/models/attachment.esm.js +83 -82
  63. odoo/addons/dms/static/src/models/attachment_image.esm.js +30 -28
  64. odoo/addons/dms/static/src/models/attachment_viewer_viewable.esm.js +27 -25
  65. odoo/addons/dms/static/src/scss/directory_kanban.scss +28 -73
  66. odoo/addons/dms/static/src/scss/dms_common.scss +69 -0
  67. odoo/addons/dms/static/src/scss/file_kanban.scss +22 -34
  68. odoo/addons/dms/static/src/scss/portal.scss +12 -0
  69. odoo/addons/dms/static/tests/tours/dms_portal_tour.esm.js +46 -0
  70. odoo/addons/dms/{views/dms_portal_templates.xml → template/portal.xml} +13 -3
  71. odoo/addons/dms/tests/common.py +20 -4
  72. odoo/addons/dms/tests/data/mail01.eml +2 -2
  73. odoo/addons/dms/tests/data/mail02.eml +2 -2
  74. odoo/addons/dms/tests/test_benchmark.py +16 -21
  75. odoo/addons/dms/tests/test_directory.py +128 -40
  76. odoo/addons/dms/tests/test_file.py +112 -30
  77. odoo/addons/dms/tests/test_file_database.py +50 -24
  78. odoo/addons/dms/tests/test_portal.py +50 -37
  79. odoo/addons/dms/tests/test_storage_attachment.py +85 -63
  80. odoo/addons/dms/tests/test_storage_database.py +89 -35
  81. odoo/addons/dms/tools/file.py +63 -11
  82. odoo/addons/dms/views/dms_access_groups_views.xml +2 -17
  83. odoo/addons/dms/views/{category.xml → dms_category.xml} +4 -9
  84. odoo/addons/dms/views/{directory.xml → dms_directory.xml} +168 -176
  85. odoo/addons/dms/views/dms_file.xml +170 -191
  86. odoo/addons/dms/views/{tag.xml → dms_tag.xml} +50 -53
  87. odoo/addons/dms/views/menu.xml +52 -21
  88. odoo/addons/dms/views/res_config_settings.xml +31 -82
  89. odoo/addons/dms/views/storage.xml +7 -13
  90. odoo_addon_dms-17.0.1.0.0.2.dist-info/METADATA +257 -0
  91. {odoo_addon_dms-16.0.1.8.0.3.dist-info → odoo_addon_dms-17.0.1.0.0.2.dist-info}/RECORD +93 -93
  92. {odoo_addon_dms-16.0.1.8.0.3.dist-info → odoo_addon_dms-17.0.1.0.0.2.dist-info}/WHEEL +1 -1
  93. odoo_addon_dms-17.0.1.0.0.2.dist-info/top_level.txt +1 -0
  94. odoo/addons/dms/readme/CONFIGURE.rst +0 -40
  95. odoo/addons/dms/readme/CONTRIBUTORS.rst +0 -16
  96. odoo/addons/dms/readme/CREDITS.rst +0 -6
  97. odoo/addons/dms/readme/DESCRIPTION.rst +0 -6
  98. odoo/addons/dms/readme/INSTALL.rst +0 -9
  99. odoo/addons/dms/readme/ROADMAP.rst +0 -8
  100. odoo/addons/dms/readme/USAGE.rst +0 -8
  101. odoo/addons/dms/static/src/js/components/path/path.esm.js +0 -0
  102. odoo/addons/dms/static/src/js/dms_portal_tour.js +0 -57
  103. odoo/addons/dms/static/src/js/fields/path.js +0 -81
  104. odoo/addons/dms/static/src/js/views/fields/binary/preview_record.esm.js +0 -35
  105. odoo/addons/dms/static/src/js/views/many_drop_target.js +0 -98
  106. odoo/addons/dms/static/src/scss/variables.scss +0 -9
  107. odoo/addons/dms/static/src/xml/views.xml +0 -72
  108. odoo/addons/dms/template/assets.xml +0 -44
  109. odoo/addons/dms/template/onboarding.xml +0 -97
  110. odoo_addon_dms-16.0.1.8.0.3.dist-info/METADATA +0 -203
  111. odoo_addon_dms-16.0.1.8.0.3.dist-info/top_level.txt +0 -1
@@ -1,165 +1,172 @@
1
1
  /** @odoo-module */
2
2
 
3
+ // /** ********************************************************************************
4
+ // Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
5
+ // License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
6
+ // **********************************************************************************/
7
+
3
8
  import {useBus, useService} from "@web/core/utils/hooks";
4
- import {_t} from "web.core";
9
+ import {_t} from "@web/core/l10n/translation";
5
10
 
6
11
  const {useRef, useEffect, useState} = owl;
7
12
 
8
- export const FileDropZone = {
9
- setup() {
10
- this._super();
11
- this.dragState = useState({
12
- showDragZone: false,
13
- });
14
- this.root = useRef("root");
15
- this.rpc = useService("rpc");
16
-
17
- useEffect(
18
- (el) => {
19
- if (!el) {
20
- return;
21
- }
22
- const highlight = this.highlight.bind(this);
23
- const unhighlight = this.unhighlight.bind(this);
24
- const drop = this.onDrop.bind(this);
25
- el.addEventListener("dragover", highlight);
26
- el.addEventListener("dragleave", unhighlight);
27
- el.addEventListener("drop", drop);
28
- return () => {
29
- el.removeEventListener("dragover", highlight);
30
- el.removeEventListener("dragleave", unhighlight);
31
- el.removeEventListener("drop", drop);
32
- };
33
- },
34
-
35
- () => [document.querySelector(".o_content")]
36
- );
37
- },
38
-
39
- highlight(ev) {
40
- ev.stopPropagation();
41
- ev.preventDefault();
42
- this.dragState.showDragZone = true;
43
- },
44
-
45
- unhighlight(ev) {
46
- ev.stopPropagation();
47
- ev.preventDefault();
48
- this.dragState.showDragZone = false;
49
- },
50
-
51
- async onDrop(ev) {
52
- ev.preventDefault();
53
- await this.env.bus.trigger("change_file_input", {
54
- files: ev.dataTransfer.files,
55
- });
56
- },
57
- };
58
-
59
- export const FileUpload = {
60
- setup() {
61
- this._super();
62
- this.actionService = useService("action");
63
- this.notification = useService("notification");
64
- this.orm = useService("orm");
65
- this.http = useService("http");
66
- this.fileInput = useRef("fileInput");
67
- this.root = useRef("root");
68
-
69
- this.rpc = useService("rpc");
70
-
71
- useBus(this.env.bus, "change_file_input", async (ev) => {
72
- this.fileInput.el.files = ev.detail.files;
73
- await this.onChangeFileInput();
74
- });
75
- },
76
-
77
- uploadDocument() {
78
- this.fileInput.el.click();
79
- },
80
-
81
- async onChangeFileInput() {
82
- const params = {
83
- csrf_token: odoo.csrf_token,
84
- ufile: [...this.fileInput.el.files],
85
- model: "dms.file",
86
- id: 0,
87
- };
88
-
89
- const fileData = await this.http.post(
90
- "/web/binary/upload_attachment",
91
- params,
92
- "text"
93
- );
94
- const attachments = JSON.parse(fileData);
95
- if (attachments.error) {
96
- throw new Error(attachments.error);
97
- }
98
-
99
- this.onUpload(attachments);
100
- },
101
-
102
- async onUpload(attachments) {
103
- const self = this;
104
- const attachmentIds = attachments.map((a) => a.id);
105
- const ctx = this.props.context;
106
- const controllerID = this.actionService.currentController.jsId;
107
-
108
- if (!attachmentIds.length) {
109
- this.notification.add(_t("An error occurred during the upload"));
110
- return;
111
- }
112
-
113
- // Search the correct directory_id value according to the domain
114
- ctx.default_directory_id = false;
115
- if (this.props.domain) {
116
- for (const domain_item of this.props.domain) {
117
- if (domain_item.length === 3) {
118
- if (domain_item[0] === "directory_id" && domain_item[1] === "=") {
119
- ctx.default_directory_id = domain_item[2];
13
+ export function createFileDropZoneExtension() {
14
+ return {
15
+ setup() {
16
+ super.setup(...arguments);
17
+ this.dragState = useState({
18
+ showDragZone: false,
19
+ });
20
+ this.root = useRef("root");
21
+
22
+ useEffect(
23
+ (el) => {
24
+ if (!el) {
25
+ return;
120
26
  }
121
- }
27
+ const highlight = this.highlight.bind(this);
28
+ const unhighlight = this.unhighlight.bind(this);
29
+ const drop = this.onDrop.bind(this);
30
+ el.addEventListener("dragover", highlight);
31
+ el.addEventListener("dragleave", unhighlight);
32
+ el.addEventListener("drop", drop);
33
+ return () => {
34
+ el.removeEventListener("dragover", highlight);
35
+ el.removeEventListener("dragleave", unhighlight);
36
+ el.removeEventListener("drop", drop);
37
+ };
38
+ },
39
+
40
+ () => [document.querySelector(".o_content")]
41
+ );
42
+ },
43
+
44
+ highlight(ev) {
45
+ ev.stopPropagation();
46
+ ev.preventDefault();
47
+ this.dragState.showDragZone = true;
48
+ },
49
+
50
+ unhighlight(ev) {
51
+ ev.stopPropagation();
52
+ ev.preventDefault();
53
+ this.dragState.showDragZone = false;
54
+ },
55
+
56
+ async onDrop(ev) {
57
+ ev.preventDefault();
58
+ this.dragState.showDragZone = false;
59
+ await this.env.bus.trigger("change_file_input", {
60
+ files: ev.dataTransfer.files,
61
+ });
62
+ },
63
+ };
64
+ }
65
+
66
+ export function createFileUploadExtension() {
67
+ return {
68
+ setup() {
69
+ super.setup();
70
+ this.notification = useService("notification");
71
+ this.orm = useService("orm");
72
+ this.http = useService("http");
73
+ this.fileInput = useRef("fileInput");
74
+
75
+ useBus(this.env.bus, "change_file_input", async (ev) => {
76
+ this.fileInput.el.files = ev.detail.files;
77
+ await this.onChangeFileInput();
78
+ });
79
+ },
80
+
81
+ uploadDocument() {
82
+ this.fileInput.el.click();
83
+ },
84
+
85
+ async onChangeFileInput() {
86
+ const params = {
87
+ csrf_token: odoo.csrf_token,
88
+ ufile: [...this.fileInput.el.files],
89
+ model: "dms.file",
90
+ id: 0,
91
+ };
92
+
93
+ const fileData = await this.http.post(
94
+ "/web/binary/upload_attachment",
95
+ params,
96
+ "text"
97
+ );
98
+ const attachments = JSON.parse(fileData);
99
+ if (attachments.error) {
100
+ throw new Error(attachments.error);
122
101
  }
123
- }
124
102
 
125
- if (ctx.default_directory_id === false) {
126
- self.actionService.restore(controllerID);
127
- return self.notification.add(
128
- this.env._t("You must select a directory first"),
129
- {
130
- type: "danger",
131
- }
132
- );
133
- }
103
+ await this.onUpload(attachments);
104
+ },
134
105
 
135
- const attachment_datas = await this.orm.call(
136
- "dms.file",
137
- "get_dms_files_from_attachments",
138
- ["", attachmentIds]
139
- );
106
+ async onUpload(attachments) {
107
+ const self = this;
108
+ const attachmentIds = attachments.map((a) => a.id);
109
+ const ctx = this.props.context;
110
+ const controllerID = this.actionService.currentController.jsId;
140
111
 
141
- const attachments_args = [];
112
+ if (!attachmentIds.length) {
113
+ this.notification.add(_t("An error occurred during the upload"));
114
+ return;
115
+ }
142
116
 
143
- attachment_datas.forEach((attachment_data) => {
144
- attachments_args.push({
145
- name: attachment_data.name,
146
- content: attachment_data.datas,
147
- mimetype: attachment_data.mimetype,
148
- });
149
- });
117
+ // Search the correct directory_id value according to the domain
118
+ let directory_id = false;
119
+ if (this.props.domain) {
120
+ for (const domain_item of this.props.domain) {
121
+ if (domain_item.length === 3) {
122
+ if (
123
+ domain_item[0] === "directory_id" &&
124
+ ["=", "child_of"].includes(domain_item[1])
125
+ ) {
126
+ directory_id = domain_item[2];
127
+ }
128
+ }
129
+ }
130
+ }
150
131
 
151
- this.orm
152
- .call("dms.file", "create", [attachments_args], {
153
- context: ctx,
154
- })
155
- .then(() => {
132
+ if (directory_id === false) {
156
133
  self.actionService.restore(controllerID);
157
- })
158
- .catch((error) => {
159
- self.notification.add(error.data.message, {
134
+ return self.notification.add(_t("You must select a directory first"), {
160
135
  type: "danger",
161
136
  });
162
- self.actionService.restore(controllerID);
137
+ }
138
+
139
+ const attachment_datas = await this.orm.call(
140
+ "dms.file",
141
+ "get_dms_files_from_attachments",
142
+ [],
143
+ {attachment_ids: attachmentIds}
144
+ );
145
+
146
+ const attachments_args = [];
147
+
148
+ attachment_datas.forEach((attachment_data) => {
149
+ attachments_args.push({
150
+ name: attachment_data.name,
151
+ content: attachment_data.datas,
152
+ mimetype: attachment_data.mimetype,
153
+ directory_id,
154
+ });
163
155
  });
164
- },
165
- };
156
+
157
+ this.orm
158
+ .call("dms.file", "create", [attachments_args], {
159
+ context: ctx,
160
+ })
161
+ .then(() => {
162
+ self.actionService.restore(controllerID);
163
+ })
164
+ .catch((error) => {
165
+ self.notification.add(error.data.message, {
166
+ type: "danger",
167
+ });
168
+ self.actionService.restore(controllerID);
169
+ });
170
+ },
171
+ };
172
+ }
@@ -4,7 +4,6 @@
4
4
  t-name="dms.FileKanbanView.Buttons"
5
5
  t-inherit="web.KanbanView.Buttons"
6
6
  t-inherit-mode="primary"
7
- owl="1"
8
7
  >
9
8
  <div role="toolbar" position="inside">
10
9
  <input
@@ -1,6 +1,11 @@
1
1
  /** @odoo-module **/
2
2
 
3
+ // /** ********************************************************************************
4
+ // Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
5
+ // License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
6
+ // **********************************************************************************/
3
7
  import {KanbanRecord} from "@web/views/kanban/kanban_record";
8
+ import {useFileViewer} from "@web/core/file_viewer/file_viewer_hook";
4
9
  import {useService} from "@web/core/utils/hooks";
5
10
 
6
11
  const videoReadableTypes = ["x-matroska", "mp4", "webm"];
@@ -9,8 +14,8 @@ const audioReadableTypes = ["mp3", "ogg", "wav", "aac", "mpa", "flac", "m4a"];
9
14
  export class FileKanbanRecord extends KanbanRecord {
10
15
  setup() {
11
16
  super.setup();
12
- this.messaging = useService("messaging");
13
- this.dialog = useService("dialog");
17
+ this.store = useService("mail.store");
18
+ this.fileViewer = useFileViewer();
14
19
  }
15
20
 
16
21
  isVideo(mimetype) {
@@ -30,33 +35,27 @@ export class FileKanbanRecord extends KanbanRecord {
30
35
  const self = this;
31
36
 
32
37
  if (ev.target.closest(".o_kanban_dms_file_preview")) {
33
- this.messaging.get().then((messaging) => {
34
- const file_type = self.props.record.data.name.split(".")[1];
35
- let mimetype = "";
36
-
37
- if (self.isVideo(file_type)) {
38
- mimetype = `video/${file_type}`;
39
- } else if (self.isAudio(file_type)) {
40
- mimetype = "audio/mpeg";
41
- } else {
42
- mimetype = self.props.record.data.mimetype;
43
- }
44
-
45
- const attachmentList = messaging.models.AttachmentList.insert({
46
- selectedAttachment: messaging.models.Attachment.insert({
47
- id: self.props.record.data.id,
48
- filename: self.props.record.data.name,
49
- name: self.props.record.data.name,
50
- mimetype: mimetype,
51
- model_name: self.props.record.resModel,
52
- }),
53
- });
54
- this.dialog = messaging.models.Dialog.insert({
55
- attachmentListOwnerAsAttachmentView: attachmentList,
56
- });
38
+ const file_type = self.props.record.data.name.split(".")[1];
39
+ let mimetype = "";
40
+
41
+ if (self.isVideo(file_type)) {
42
+ mimetype = `video/${file_type}`;
43
+ } else if (self.isAudio(file_type)) {
44
+ mimetype = "audio/mpeg";
45
+ } else {
46
+ mimetype = self.props.record.data.mimetype;
47
+ }
48
+
49
+ const attachment = this.store.Attachment.insert({
50
+ id: self.props.record.data.id,
51
+ filename: self.props.record.data.name,
52
+ name: self.props.record.data.name,
53
+ mimetype: mimetype,
54
+ model_name: self.props.record.resModel,
57
55
  });
56
+ this.fileViewer.open(attachment);
58
57
  return;
59
58
  }
60
- return super.onGlobalClick(...arguments);
59
+ return super.onGlobalClick(ev);
61
60
  }
62
61
  }
@@ -4,9 +4,8 @@
4
4
  // Copyright 2020 Creu Blanca
5
5
  // License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
6
6
  // **********************************************************************************/
7
- import {KanbanRenderer} from "@web/views/kanban/kanban_renderer";
8
-
9
7
  import {FileKanbanRecord} from "./file_kanban_record.esm";
8
+ import {KanbanRenderer} from "@web/views/kanban/kanban_renderer";
10
9
 
11
10
  export class FileKanbanRenderer extends KanbanRenderer {
12
11
  setup() {
@@ -1,10 +1,13 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?>
2
+ <!--
3
+ Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
4
+ License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
5
+ -->
2
6
  <templates xml:space="preserve">
3
7
  <t
4
8
  t-name="dms.KanbanRenderer"
5
9
  t-inherit="web.KanbanRenderer"
6
10
  t-inherit-mode="primary"
7
- owl="1"
8
11
  >
9
12
  <xpath expr="//div[hasclass('o_kanban_renderer')]" position="before">
10
13
  <div t-if="dragState.showDragZone" class="o_dropzone">
@@ -17,19 +20,8 @@
17
20
  t-name="dms.KanbanButtons"
18
21
  t-inherit="web.KanbanView.Buttons"
19
22
  t-inherit-mode="primary"
20
- owl="1"
21
23
  >
22
- <xpath expr="//t[@t-if='canCreate']" position="after">
23
- <button
24
- type="button"
25
- class="d-none d-md-inline btn btn-primary mx-1"
26
- t-on-click.prevent="uploadDocument"
27
- >
28
- Upload
29
- </button>
30
- </xpath>
31
-
32
- <xpath expr="//t[@t-if='canCreate']" position="before">
24
+ <xpath expr="//div" position="inside">
33
25
  <button
34
26
  type="button"
35
27
  class="d-inline d-md-none btn btn-primary mx-1"
@@ -37,9 +29,6 @@
37
29
  >
38
30
  Scan
39
31
  </button>
40
- </xpath>
41
-
42
- <xpath expr="//div" position="inside">
43
32
  <input
44
33
  type="file"
45
34
  name="ufile"
@@ -49,6 +38,13 @@
49
38
  accept="*"
50
39
  t-on-change="onChangeFileInput"
51
40
  />
41
+ <button
42
+ type="button"
43
+ class="d-none d-md-inline btn btn-primary mx-1"
44
+ t-on-click.prevent="uploadDocument"
45
+ >
46
+ Upload
47
+ </button>
52
48
  </xpath>
53
49
  </t>
54
50
  </templates>
@@ -3,25 +3,27 @@
3
3
  // /** ********************************************************************************
4
4
  // Copyright 2020 Creu Blanca
5
5
  // Copyright 2017-2019 MuK IT GmbH
6
+ // Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
6
7
  // License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
7
8
  // **********************************************************************************/
8
9
 
9
- import {registry} from "@web/core/registry";
10
- import {patch} from "@web/core/utils/patch";
11
- import {kanbanView} from "@web/views/kanban/kanban_view";
10
+ import {
11
+ createFileDropZoneExtension,
12
+ createFileUploadExtension,
13
+ } from "./dms_file_upload.esm";
12
14
  import {FileKanbanRenderer} from "./file_kanban_renderer.esm";
13
- import {FileKanbanController} from "./file_kanban_controller.esm";
14
-
15
- import {FileDropZone, FileUpload} from "./dms_file_upload.esm";
15
+ import {KanbanController} from "@web/views/kanban/kanban_controller";
16
+ import {kanbanView} from "@web/views/kanban/kanban_view";
17
+ import {patch} from "@web/core/utils/patch";
18
+ import {registry} from "@web/core/registry";
16
19
 
17
- patch(FileKanbanRenderer.prototype, "file_kanban_renderer_dzone", FileDropZone);
18
- patch(FileKanbanController.prototype, "filee_kanban_controller_upload", FileUpload);
20
+ patch(FileKanbanRenderer.prototype, createFileDropZoneExtension());
21
+ patch(KanbanController.prototype, createFileUploadExtension());
19
22
  FileKanbanRenderer.template = "dms.KanbanRenderer";
20
23
 
21
24
  export const FileKanbanView = {
22
25
  ...kanbanView,
23
26
  buttonTemplate: "dms.KanbanButtons",
24
- Controller: FileKanbanController,
25
27
  Renderer: FileKanbanRenderer,
26
28
  };
27
29
 
@@ -10,6 +10,6 @@ import {ListController} from "@web/views/list/list_controller";
10
10
 
11
11
  export class FileListController extends ListController {
12
12
  setup() {
13
- super.setup();
13
+ super.setup(...arguments);
14
14
  }
15
15
  }
@@ -1,11 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?>
2
2
  <templates xml:space="preserve">
3
- <t
4
- t-name="dms.ListRenderer"
5
- t-inherit="web.ListRenderer"
6
- t-inherit-mode="primary"
7
- owl="1"
8
- >
3
+ <t t-name="dms.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="primary">
9
4
  <xpath expr="//div[hasclass('o_list_renderer')]" position="before">
10
5
  <div t-if="dragState.showDragZone" class="o_dropzone">
11
6
  <i class="fa fa-cloud-upload fa-10x" />
@@ -17,7 +12,6 @@
17
12
  t-name="dms.ListButtons"
18
13
  t-inherit="web.ListView.Buttons"
19
14
  t-inherit-mode="primary"
20
- owl="1"
21
15
  >
22
16
  <xpath expr="//div[hasclass('o_list_buttons')]" position="inside">
23
17
  <button
@@ -3,25 +3,27 @@
3
3
  // /** ********************************************************************************
4
4
  // Copyright 2020 Creu Blanca
5
5
  // Copyright 2017-2019 MuK IT GmbH
6
+ // Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
6
7
  // License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
7
8
  // **********************************************************************************/
8
9
 
9
- import {registry} from "@web/core/registry";
10
- import {patch} from "@web/core/utils/patch";
11
- import {listView} from "@web/views/list/list_view";
10
+ import {
11
+ createFileDropZoneExtension,
12
+ createFileUploadExtension,
13
+ } from "./dms_file_upload.esm";
12
14
  import {FileListRenderer} from "./file_list_renderer.esm";
13
- import {FileListController} from "./file_list_controller.esm";
14
-
15
- import {FileDropZone, FileUpload} from "./dms_file_upload.esm";
15
+ import {ListController} from "@web/views/list/list_controller";
16
+ import {listView} from "@web/views/list/list_view";
17
+ import {patch} from "@web/core/utils/patch";
18
+ import {registry} from "@web/core/registry";
16
19
 
17
- patch(FileListRenderer.prototype, "file_list_renderer_dzone", FileDropZone);
18
- patch(FileListController.prototype, "file_list_controller_upload", FileUpload);
20
+ patch(FileListRenderer.prototype, createFileDropZoneExtension());
21
+ patch(ListController.prototype, createFileUploadExtension());
19
22
  FileListRenderer.template = "dms.ListRenderer";
20
23
 
21
24
  export const FileListView = {
22
25
  ...listView,
23
26
  buttonTemplate: "dms.ListButtons",
24
- Controller: FileListController,
25
27
  Renderer: FileListRenderer,
26
28
  };
27
29
 
@@ -1,19 +1,16 @@
1
1
  /** @odoo-module **/
2
2
  /* Copyright 2021-2024 Tecnativa - Víctor Martínez
3
+ * Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
3
4
  * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
4
5
 
5
6
  import {SearchModel} from "@web/search/search_model";
6
- import {patch} from "@web/core/utils/patch";
7
-
8
- patch(SearchModel.prototype, "dms.SearchPanel", {
9
- setup() {
10
- this._super(...arguments);
11
- },
7
+ import {registry} from "@web/core/registry";
12
8
 
9
+ class DMSSearchPanel extends SearchModel {
13
10
  _getCategoryDomain(excludedCategoryId) {
14
- const domain = this._super.apply(this, arguments);
11
+ const domain = super._getCategoryDomain(...arguments);
15
12
  for (const category of this.categories) {
16
- if (category.id === excludedCategoryId) {
13
+ if (category.id === Number(excludedCategoryId)) {
17
14
  continue;
18
15
  }
19
16
 
@@ -25,5 +22,7 @@ patch(SearchModel.prototype, "dms.SearchPanel", {
25
22
  }
26
23
  }
27
24
  return domain;
28
- },
29
- });
25
+ }
26
+ }
27
+
28
+ registry.category("views").add("dms_search_panel", DMSSearchPanel);