Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
52
dms/static/src/js/fields/path_json/path_owl.esm.js
Normal file
52
dms/static/src/js/fields/path_json/path_owl.esm.js
Normal file
@@ -0,0 +1,52 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
import {Component, onWillUpdateProps} from "@odoo/owl";
|
||||
import {_t} from "@web/core/l10n/translation";
|
||||
import {registry} from "@web/core/registry";
|
||||
import {standardFieldProps} from "@web/views/fields/standard_field_props";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
|
||||
class DmsPathField extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.action = useService("action");
|
||||
this.formatData(this.props);
|
||||
onWillUpdateProps((nextProps) => this.formatData(nextProps));
|
||||
}
|
||||
|
||||
formatData(props) {
|
||||
const path_json = props.record.data && props.record.data.path_json;
|
||||
this.data = JSON.parse(path_json || "[]");
|
||||
}
|
||||
|
||||
_onNodeClicked(event) {
|
||||
event.preventDefault();
|
||||
const target = event.currentTarget;
|
||||
this.action.doAction({
|
||||
type: "ir.actions.act_window",
|
||||
res_model: target.getAttribute("data-model"),
|
||||
res_id: Number(target.getAttribute("data-id")),
|
||||
views: [[false, "form"]],
|
||||
target: "current",
|
||||
context: {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DmsPathField.template = "dms.DmsPathField";
|
||||
DmsPathField.props = {
|
||||
...standardFieldProps,
|
||||
};
|
||||
|
||||
const dmsPathField = {
|
||||
component: DmsPathField,
|
||||
displayName: _t("Dms Path Field"),
|
||||
supportedTypes: ["text"],
|
||||
extractProps: () => {
|
||||
return {};
|
||||
},
|
||||
};
|
||||
|
||||
registry.category("fields").add("path_json", dmsPathField);
|
||||
30
dms/static/src/js/fields/path_json/path_owl.xml
Normal file
30
dms/static/src/js/fields/path_json/path_owl.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
-->
|
||||
<templates xml:space="preserve" id="template">
|
||||
<t t-name="dms.DmsPathField">
|
||||
<t t-set="path_length" t-value="data.length - 1" />
|
||||
<t t-foreach="data" t-as="elem" t-key="elem_index" style="display: inline">
|
||||
<t t-if="elem_index !== path_length">
|
||||
<span style="display: inline" t-if="elem_index !== 0">/</span>
|
||||
<a
|
||||
class="oe_form_uri"
|
||||
data-model="dms.directory"
|
||||
t-att-data-id="elem.id"
|
||||
href="#"
|
||||
t-on-click.prevent="(ev) => this._onNodeClicked(ev)"
|
||||
>
|
||||
<t t-esc="elem.name" />
|
||||
</a>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span style="display: inline">/</span>
|
||||
<span style="display: inline">
|
||||
<t t-esc="elem.name" />
|
||||
</span>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -0,0 +1,45 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
import {BinaryField} from "@web/views/fields/binary/binary_field";
|
||||
import {_t} from "@web/core/l10n/translation";
|
||||
import {registry} from "@web/core/registry";
|
||||
import {standardFieldProps} from "@web/views/fields/standard_field_props";
|
||||
import {useFileViewer} from "@web/core/file_viewer/file_viewer_hook";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
|
||||
export class PreviewRecordField extends BinaryField {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.store = useService("mail.store");
|
||||
this.fileViewer = useFileViewer();
|
||||
}
|
||||
|
||||
onFilePreview() {
|
||||
const self = this;
|
||||
const attachment = this.store.Attachment.insert({
|
||||
id: self.props.record.resId,
|
||||
filename: self.props.record.data.display_name || "",
|
||||
name: self.props.record.data.display_name || "",
|
||||
mimetype: self.props.record.data.mimetype,
|
||||
model_name: self.props.record.resModel,
|
||||
});
|
||||
this.fileViewer.open(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
PreviewRecordField.template = "dms.FilePreviewField";
|
||||
PreviewRecordField.props = {
|
||||
...standardFieldProps,
|
||||
};
|
||||
|
||||
const previewRecordField = {
|
||||
component: PreviewRecordField,
|
||||
displayName: _t("Preview Record"),
|
||||
supportedTypes: ["binary"],
|
||||
extractProps: () => {
|
||||
return {};
|
||||
},
|
||||
};
|
||||
registry.category("fields").add("preview_binary", previewRecordField);
|
||||
40
dms/static/src/js/fields/preview_binary/preview_record.xml
Normal file
40
dms/static/src/js/fields/preview_binary/preview_record.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
-->
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t
|
||||
t-name="dms.FilePreviewField"
|
||||
t-inherit="web.BinaryField"
|
||||
t-inherit-mode="primary"
|
||||
>
|
||||
<xpath expr="//div[hasclass('d-inline-flex')]" position="inside">
|
||||
<t
|
||||
t-set="readable_types"
|
||||
t-value="[
|
||||
'image/bmp',
|
||||
'image/gif',
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/svg+xml',
|
||||
'image/tiff',
|
||||
'image/x-icon',
|
||||
'application/pdf',
|
||||
'audio/mpeg',
|
||||
'video/x-matroska',
|
||||
'video/mp4',
|
||||
'video/webm'
|
||||
]"
|
||||
/>
|
||||
<t t-if="readable_types.includes(props.record.data.mimetype)">
|
||||
<button
|
||||
class="btn btn-secondary fa fa-search preview_file"
|
||||
data-tooltip="Preview"
|
||||
aria-label="Preview"
|
||||
t-on-click="onFilePreview"
|
||||
/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
169
dms/static/src/js/views/dms_file_upload.esm.js
Normal file
169
dms/static/src/js/views/dms_file_upload.esm.js
Normal file
@@ -0,0 +1,169 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
|
||||
import {useBus, useService} from "@web/core/utils/hooks";
|
||||
import {useEffect, useRef, useState} from "@odoo/owl";
|
||||
import {_t} from "@web/core/l10n/translation";
|
||||
|
||||
export function createFileDropZoneExtension() {
|
||||
return {
|
||||
setup() {
|
||||
super.setup(...arguments);
|
||||
this.dragState = useState({
|
||||
showDragZone: false,
|
||||
});
|
||||
this.root = useRef("root");
|
||||
|
||||
useEffect(
|
||||
(el) => {
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
const highlight = this.highlight.bind(this);
|
||||
const unhighlight = this.unhighlight.bind(this);
|
||||
const drop = this.onDrop.bind(this);
|
||||
el.addEventListener("dragover", highlight);
|
||||
el.addEventListener("dragleave", unhighlight);
|
||||
el.addEventListener("drop", drop);
|
||||
return () => {
|
||||
el.removeEventListener("dragover", highlight);
|
||||
el.removeEventListener("dragleave", unhighlight);
|
||||
el.removeEventListener("drop", drop);
|
||||
};
|
||||
},
|
||||
|
||||
() => [document.querySelector(".o_content")]
|
||||
);
|
||||
},
|
||||
|
||||
highlight(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.dragState.showDragZone = true;
|
||||
},
|
||||
|
||||
unhighlight(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.dragState.showDragZone = false;
|
||||
},
|
||||
|
||||
async onDrop(ev) {
|
||||
ev.preventDefault();
|
||||
this.dragState.showDragZone = false;
|
||||
await this.env.bus.trigger("change_file_input", {
|
||||
files: ev.dataTransfer.files,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createFileUploadExtension() {
|
||||
return {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.notification = useService("notification");
|
||||
this.orm = useService("orm");
|
||||
this.http = useService("http");
|
||||
this.fileInput = useRef("fileInput");
|
||||
|
||||
useBus(this.env.bus, "change_file_input", async (ev) => {
|
||||
this.fileInput.el.files = ev.detail.files;
|
||||
await this.onChangeFileInput();
|
||||
});
|
||||
},
|
||||
|
||||
uploadDocument() {
|
||||
this.fileInput.el.click();
|
||||
},
|
||||
|
||||
async onChangeFileInput() {
|
||||
const params = {
|
||||
csrf_token: odoo.csrf_token,
|
||||
ufile: [...this.fileInput.el.files],
|
||||
model: "dms.file",
|
||||
id: 0,
|
||||
};
|
||||
|
||||
const fileData = await this.http.post(
|
||||
"/web/binary/upload_attachment",
|
||||
params,
|
||||
"text"
|
||||
);
|
||||
const attachments = JSON.parse(fileData);
|
||||
if (attachments.error) {
|
||||
throw new Error(attachments.error);
|
||||
}
|
||||
|
||||
await this.onUpload(attachments);
|
||||
},
|
||||
|
||||
async onUpload(attachments) {
|
||||
const self = this;
|
||||
const attachmentIds = attachments.map((a) => a.id);
|
||||
const ctx = this.props.context;
|
||||
const controllerID = this.actionService.currentController.jsId;
|
||||
|
||||
if (!attachmentIds.length) {
|
||||
this.notification.add(_t("An error occurred during the upload"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Search the correct directory_id value according to the domain
|
||||
let directory_id = false;
|
||||
if (this.props.domain) {
|
||||
for (const domain_item of this.props.domain) {
|
||||
if (domain_item.length === 3) {
|
||||
if (
|
||||
domain_item[0] === "directory_id" &&
|
||||
["=", "child_of"].includes(domain_item[1])
|
||||
) {
|
||||
directory_id = domain_item[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (directory_id === false) {
|
||||
self.actionService.restore(controllerID);
|
||||
return self.notification.add(_t("You must select a directory first"), {
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
|
||||
const attachment_datas = await this.orm.call(
|
||||
"dms.file",
|
||||
"get_dms_files_from_attachments",
|
||||
[],
|
||||
{attachment_ids: attachmentIds}
|
||||
);
|
||||
|
||||
const attachments_args = [];
|
||||
|
||||
attachment_datas.forEach((attachment_data) => {
|
||||
attachments_args.push({
|
||||
name: attachment_data.name,
|
||||
content: attachment_data.datas,
|
||||
mimetype: attachment_data.mimetype,
|
||||
directory_id,
|
||||
});
|
||||
});
|
||||
|
||||
this.orm
|
||||
.call("dms.file", "create", [attachments_args], {
|
||||
context: ctx,
|
||||
})
|
||||
.then(() => {
|
||||
self.actionService.restore(controllerID);
|
||||
})
|
||||
.catch((error) => {
|
||||
self.notification.add(error.data.message, {
|
||||
type: "danger",
|
||||
});
|
||||
self.actionService.restore(controllerID);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
12
dms/static/src/js/views/file_kanban_controller.esm.js
Normal file
12
dms/static/src/js/views/file_kanban_controller.esm.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2020 Creu Blanca
|
||||
// Copyright 2017-2019 MuK IT GmbH
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
|
||||
import {KanbanController} from "@web/views/kanban/kanban_controller";
|
||||
export class FileKanbanController extends KanbanController {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
}
|
||||
25
dms/static/src/js/views/file_kanban_controller.xml
Normal file
25
dms/static/src/js/views/file_kanban_controller.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates>
|
||||
<t
|
||||
t-name="dms.FileKanbanView.Buttons"
|
||||
t-inherit="web.KanbanView.Buttons"
|
||||
t-inherit-mode="primary"
|
||||
>
|
||||
<div role="toolbar" position="inside">
|
||||
<input
|
||||
type="file"
|
||||
multiple="true"
|
||||
t-ref="uploadFileInput"
|
||||
class="o_input_file o_hidden"
|
||||
t-on-change.stop="onFileInputChange"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
t-attf-class="btn btn-primary o_file_kanban_upload"
|
||||
t-on-click.stop.prevent="() => this.uploadFileInputRef.el.click()"
|
||||
>
|
||||
Upload
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
59
dms/static/src/js/views/file_kanban_record.esm.js
Normal file
59
dms/static/src/js/views/file_kanban_record.esm.js
Normal file
@@ -0,0 +1,59 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
import {KanbanRecord} from "@web/views/kanban/kanban_record";
|
||||
import {useFileViewer} from "@web/core/file_viewer/file_viewer_hook";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
|
||||
const videoReadableTypes = ["x-matroska", "mp4", "webm"];
|
||||
const audioReadableTypes = ["mp3", "ogg", "wav", "aac", "mpa", "flac", "m4a"];
|
||||
|
||||
export class FileKanbanRecord extends KanbanRecord {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.store = useService("mail.store");
|
||||
this.fileViewer = useFileViewer();
|
||||
}
|
||||
|
||||
isVideo(mimetype) {
|
||||
return videoReadableTypes.includes(mimetype);
|
||||
}
|
||||
|
||||
isAudio(mimetype) {
|
||||
return audioReadableTypes.includes(mimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*
|
||||
* Override to open the preview upon clicking the image, if compatible.
|
||||
*/
|
||||
onGlobalClick(ev) {
|
||||
const self = this;
|
||||
|
||||
if (ev.target.closest(".o_kanban_dms_file_preview")) {
|
||||
const file_type = self.props.record.data.name.split(".")[1];
|
||||
let mimetype = "";
|
||||
|
||||
if (self.isVideo(file_type)) {
|
||||
mimetype = `video/${file_type}`;
|
||||
} else if (self.isAudio(file_type)) {
|
||||
mimetype = "audio/mpeg";
|
||||
} else {
|
||||
mimetype = self.props.record.data.mimetype;
|
||||
}
|
||||
|
||||
const attachment = this.store.Attachment.insert({
|
||||
id: self.props.record.data.id,
|
||||
filename: self.props.record.data.name,
|
||||
name: self.props.record.data.name,
|
||||
mimetype: mimetype,
|
||||
model_name: self.props.record.resModel,
|
||||
});
|
||||
this.fileViewer.open(attachment);
|
||||
return;
|
||||
}
|
||||
return super.onGlobalClick(ev);
|
||||
}
|
||||
}
|
||||
17
dms/static/src/js/views/file_kanban_renderer.esm.js
Normal file
17
dms/static/src/js/views/file_kanban_renderer.esm.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2020 Creu Blanca
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
import {FileKanbanRecord} from "./file_kanban_record.esm";
|
||||
import {KanbanRenderer} from "@web/views/kanban/kanban_renderer";
|
||||
|
||||
export class FileKanbanRenderer extends KanbanRenderer {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
}
|
||||
|
||||
FileKanbanRenderer.components = {
|
||||
...KanbanRenderer.components,
|
||||
KanbanRecord: FileKanbanRecord,
|
||||
};
|
||||
52
dms/static/src/js/views/file_kanban_renderer.xml
Normal file
52
dms/static/src/js/views/file_kanban_renderer.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
-->
|
||||
<templates xml:space="preserve">
|
||||
<t
|
||||
t-name="dms.KanbanRenderer"
|
||||
t-inherit="web.KanbanRenderer"
|
||||
t-inherit-mode="primary"
|
||||
>
|
||||
<xpath expr="//div[hasclass('o_kanban_renderer')]" position="before">
|
||||
<div t-if="dragState.showDragZone" class="o_dropzone">
|
||||
<i class="fa fa-cloud-upload fa-10x" />
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
t-name="dms.KanbanButtons"
|
||||
t-inherit="web.KanbanView.Buttons"
|
||||
t-inherit-mode="primary"
|
||||
>
|
||||
<xpath expr="." position="inside">
|
||||
<t t-if="props.archInfo.activeActions.create">
|
||||
<button
|
||||
type="button"
|
||||
class="d-inline d-md-none btn btn-primary mx-1"
|
||||
t-on-click.prevent="uploadDocument"
|
||||
>
|
||||
Scan
|
||||
</button>
|
||||
<input
|
||||
type="file"
|
||||
name="ufile"
|
||||
class="d-none"
|
||||
t-ref="fileInput"
|
||||
multiple="1"
|
||||
accept="*"
|
||||
t-on-change="onChangeFileInput"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="d-none d-md-inline btn btn-primary mx-1"
|
||||
t-on-click.prevent="uploadDocument"
|
||||
>
|
||||
Upload
|
||||
</button>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
28
dms/static/src/js/views/file_kanban_view.esm.js
Normal file
28
dms/static/src/js/views/file_kanban_view.esm.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2020 Creu Blanca
|
||||
// Copyright 2017-2019 MuK IT GmbH
|
||||
// Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
|
||||
import {
|
||||
createFileDropZoneExtension,
|
||||
createFileUploadExtension,
|
||||
} from "./dms_file_upload.esm";
|
||||
import {FileKanbanRenderer} from "./file_kanban_renderer.esm";
|
||||
import {KanbanController} from "@web/views/kanban/kanban_controller";
|
||||
import {kanbanView} from "@web/views/kanban/kanban_view";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {registry} from "@web/core/registry";
|
||||
|
||||
patch(FileKanbanRenderer.prototype, createFileDropZoneExtension());
|
||||
patch(KanbanController.prototype, createFileUploadExtension());
|
||||
FileKanbanRenderer.template = "dms.KanbanRenderer";
|
||||
|
||||
export const FileKanbanView = {
|
||||
...kanbanView,
|
||||
buttonTemplate: "dms.KanbanButtons",
|
||||
Renderer: FileKanbanRenderer,
|
||||
};
|
||||
|
||||
registry.category("views").add("file_kanban", FileKanbanView);
|
||||
13
dms/static/src/js/views/file_list_controller.esm.js
Normal file
13
dms/static/src/js/views/file_list_controller.esm.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2020 Creu Blanca
|
||||
// Copyright 2017-2019 MuK IT GmbH
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
|
||||
import {ListController} from "@web/views/list/list_controller";
|
||||
|
||||
export class FileListController extends ListController {
|
||||
setup() {
|
||||
super.setup(...arguments);
|
||||
}
|
||||
}
|
||||
16
dms/static/src/js/views/file_list_renderer.esm.js
Normal file
16
dms/static/src/js/views/file_list_renderer.esm.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2020 Creu Blanca
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
|
||||
export class FileListRenderer extends ListRenderer {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
}
|
||||
|
||||
FileListRenderer.components = {
|
||||
...FileListRenderer.components,
|
||||
};
|
||||
48
dms/static/src/js/views/file_list_renderer.xml
Normal file
48
dms/static/src/js/views/file_list_renderer.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="dms.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="primary">
|
||||
<xpath expr="//div[hasclass('o_list_renderer')]" position="before">
|
||||
<div t-if="dragState.showDragZone" class="o_dropzone">
|
||||
<i class="fa fa-cloud-upload fa-10x" />
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
t-name="dms.ListButtons"
|
||||
t-inherit="web.ListView.Buttons"
|
||||
t-inherit-mode="primary"
|
||||
>
|
||||
<xpath expr="." position="inside">
|
||||
<button
|
||||
type="button"
|
||||
class="d-none d-md-inline o_button_upload_expense btn btn-primary mx-1"
|
||||
t-on-click.prevent="uploadDocument"
|
||||
>
|
||||
Upload
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="." position="inside">
|
||||
<button
|
||||
type="button"
|
||||
class="d-inline d-md-none o_button_upload_expense btn btn-primary mx-1"
|
||||
t-on-click.prevent="uploadDocument"
|
||||
>
|
||||
Scan
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="." position="inside">
|
||||
<input
|
||||
type="file"
|
||||
name="ufile"
|
||||
class="d-none"
|
||||
t-ref="fileInput"
|
||||
multiple="1"
|
||||
accept="*"
|
||||
t-on-change="onChangeFileInput"
|
||||
/>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
28
dms/static/src/js/views/file_list_view.esm.js
Normal file
28
dms/static/src/js/views/file_list_view.esm.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// /** ********************************************************************************
|
||||
// Copyright 2020 Creu Blanca
|
||||
// Copyright 2017-2019 MuK IT GmbH
|
||||
// Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
// **********************************************************************************/
|
||||
|
||||
import {
|
||||
createFileDropZoneExtension,
|
||||
createFileUploadExtension,
|
||||
} from "./dms_file_upload.esm";
|
||||
import {FileListRenderer} from "./file_list_renderer.esm";
|
||||
import {ListController} from "@web/views/list/list_controller";
|
||||
import {listView} from "@web/views/list/list_view";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {registry} from "@web/core/registry";
|
||||
|
||||
patch(FileListRenderer.prototype, createFileDropZoneExtension());
|
||||
patch(ListController.prototype, createFileUploadExtension());
|
||||
FileListRenderer.template = "dms.ListRenderer";
|
||||
|
||||
export const FileListView = {
|
||||
...listView,
|
||||
buttonTemplate: "dms.ListButtons",
|
||||
Renderer: FileListRenderer,
|
||||
};
|
||||
|
||||
registry.category("views").add("file_list", FileListView);
|
||||
27
dms/static/src/js/views/search_panel.esm.js
Normal file
27
dms/static/src/js/views/search_panel.esm.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright 2021-2024 Tecnativa - Víctor Martínez
|
||||
* Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
|
||||
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
||||
|
||||
import {SearchModel} from "@web/search/search_model";
|
||||
|
||||
export class DMSSearchPanel extends SearchModel {
|
||||
_getCategoryDomain(excludedCategoryId) {
|
||||
const domain = super._getCategoryDomain(...arguments);
|
||||
for (const category of this.categories) {
|
||||
if (category.id === Number(excludedCategoryId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure to filter selected category only for DMS hierarchies,
|
||||
// not other Odoo models such as product categories
|
||||
// where child_of could be better than "=" operator
|
||||
if (category.activeValueId && this.resModel.startsWith("dms")) {
|
||||
domain.push([category.fieldName, "=", category.activeValueId]);
|
||||
}
|
||||
if (domain.length === 0 && this.resModel === "dms.directory") {
|
||||
domain.push([category.fieldName, "=", false]);
|
||||
}
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user