214 lines
7.5 KiB
JavaScript
214 lines
7.5 KiB
JavaScript
/** @odoo-module **/
|
|
import { _t } from "@web/core/l10n/translation";
|
|
import { registry } from "@web/core/registry";
|
|
import { useService } from "@web/core/utils/hooks";
|
|
import {standardFieldProps} from "@web/views/fields/standard_field_props";
|
|
import { FileInput } from "@web/core/file_input/file_input";
|
|
import { useX2ManyCrud, useSelectCreate, useOpenMany2XRecord } from "@web/views/fields/relational_utils";
|
|
import { Component } from "@odoo/owl";
|
|
import { TagsList } from "@web/core/tags_list/tags_list";
|
|
import { Dialog } from "@web/core/dialog/dialog";
|
|
import {
|
|
Many2XAutocomplete,
|
|
useActiveActions,
|
|
} from "@web/views/fields/relational_utils";
|
|
import { Many2ManyTagsField, many2ManyTagsField } from "@web/views/fields/many2many_tags/many2many_tags_field";
|
|
|
|
export class Many2ManyBinaryField extends Many2ManyTagsField {
|
|
static template = "web.Many2ManyBinaryField";
|
|
static components = {
|
|
FileInput,
|
|
TagsList,
|
|
Many2XAutocomplete,
|
|
};
|
|
static props = {
|
|
...standardFieldProps,
|
|
acceptedFileExtensions: { type: String, optional: true },
|
|
className: { type: String, optional: true },
|
|
canCreate: { type: Boolean, optional: true },
|
|
canQuickCreate: { type: Boolean, optional: true },
|
|
canCreateEdit: { type: Boolean, optional: true },
|
|
colorField: { type: String, optional: true },
|
|
createDomain: { type: [Array, Boolean], optional: true },
|
|
domain: { type: [Array, Function], optional: true },
|
|
context: { type: Object, optional: true },
|
|
placeholder: { type: String, optional: true },
|
|
nameCreateField: { type: String, optional: true },
|
|
string: { type: String, optional: true },
|
|
noSearchMore: { type: Boolean, optional: true },
|
|
showSelectBtn: { type: Boolean, optional: true },
|
|
previewType: { type: String, optional: true },
|
|
previewString: { type: String, optional: true },
|
|
};
|
|
|
|
setup() {
|
|
super.setup()
|
|
this.orm = useService("orm");
|
|
this.notification = useService("notification");
|
|
this.operations = useX2ManyCrud(() => this.props.record.data[this.props.name], true);
|
|
const isToMany = true;
|
|
this.canCreate = false;
|
|
this.quickCreate = false;
|
|
this.openMany2X = useOpenMany2XRecord({
|
|
resModel: this.relation,
|
|
activeActions: this.activeActions,
|
|
isToMany: isToMany,
|
|
onRecordSaved: (record) => {
|
|
return this.update([{ ...record.data, id: record.resId }]);
|
|
},
|
|
onRecordDiscarded: () => {
|
|
if (!isToMany) {
|
|
this.update(false);
|
|
}
|
|
},
|
|
fieldString: this.string,
|
|
onClose: () => {
|
|
const autoCompleteInput = this.autoCompleteContainer?.el.querySelector("input");
|
|
|
|
if (!autoCompleteInput) {
|
|
return;
|
|
}
|
|
// There are two cases:
|
|
// 1. Value is the same as the input: it means the autocomplete has re-rendered with the right value
|
|
// This is in case we saved the record, triggering all the interface to update.
|
|
// 2. Value is different from the input: it means the input has a manually entered value and nothing
|
|
// happened, that is, we discarded the changes
|
|
if (this.props.value !== autoCompleteInput.value) {
|
|
autoCompleteInput.value = "";
|
|
}
|
|
autoCompleteInput.focus();
|
|
},
|
|
});
|
|
this.selectCreate = useSelectCreate({
|
|
resModel: this.relation,
|
|
activeActions: this.activeActions,
|
|
onSelected: (resId) => {
|
|
const resIds = Array.isArray(resId) ? resId : [resId];
|
|
const values = resIds.map((id) => ({ id }));
|
|
return this.update(values);
|
|
},
|
|
onCreateEdit: ({ context }) => this.openMany2X({ context }),
|
|
onUnselect: isToMany ? undefined : () => this.update(),
|
|
});
|
|
}
|
|
|
|
get uploadText() {
|
|
return this.props.record.fields[this.props.name].string;
|
|
}
|
|
get files() {
|
|
return this.props.record.data[this.props.name].records.map((record) => {
|
|
return {
|
|
...record.data,
|
|
id: record.resId,
|
|
};
|
|
});
|
|
}
|
|
|
|
getUrl(id) {
|
|
return "/web/content/" + id + "?download=true";
|
|
}
|
|
|
|
preview_Obj(id, name) {
|
|
var winStr = 'height=600,width=1000,top=' + (screen.height - 600) / 2 + ',left=' + (screen.width - 1000) / 2 + ',toolbar=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,location=no';
|
|
var newWin = window.open('/web/content/preview/'+ id , name, winStr);
|
|
newWin.focus();
|
|
}
|
|
|
|
getExtension(file) {
|
|
return file.name.replace(/^.*\./, "");
|
|
}
|
|
|
|
async onFileUploaded(files) {
|
|
for (const file of files) {
|
|
if (file.error) {
|
|
return this.notification.add(file.error, {
|
|
title: _t("Uploading error"),
|
|
type: "danger",
|
|
});
|
|
}
|
|
await this.operations.saveRecord([file.id]);
|
|
}
|
|
}
|
|
|
|
async onFileRemove(deleteId) {
|
|
const record = this.props.record.data[this.props.name].records.find(
|
|
(record) => record.resId === deleteId
|
|
);
|
|
this.operations.removeRecord(record);
|
|
}
|
|
|
|
async onExternalBtnClick() {
|
|
|
|
const domain = this.getDomain();
|
|
let dynamicFilters = [];
|
|
const nameGets = await this.orm.call(this.relation, "name_search", [], {
|
|
name: '',
|
|
args: domain,
|
|
operator: "ilike",
|
|
limit: this.props.searchMoreLimit,
|
|
context: this.props.context,
|
|
});
|
|
|
|
dynamicFilters = [
|
|
{
|
|
description: _t("Quick search"),
|
|
domain: [["id", "in", nameGets.map((nameGet) => nameGet[0])]],
|
|
},
|
|
];
|
|
|
|
const title = _t("Search");
|
|
this.selectCreate({
|
|
domain,
|
|
context: this.props.context,
|
|
filters: dynamicFilters,
|
|
title,
|
|
});
|
|
}
|
|
get documentsInstalled() {
|
|
try {
|
|
const result = $.ajax({
|
|
url: "/web/document_module/installed",
|
|
type: "POST",
|
|
async: false, // 设置为 false 表示同步请求
|
|
contentType: "application/json",
|
|
data: "{}"
|
|
});
|
|
return result?.responseJSON?.result?.installed;
|
|
} catch (error) {
|
|
console.error('Error fetching document installed status:', error);
|
|
return false; // 或者其他默认值
|
|
}
|
|
}
|
|
}
|
|
|
|
export const many2ManyBinaryField = {
|
|
component: Many2ManyBinaryField,
|
|
supportedOptions: [
|
|
{
|
|
label: _t("Accepted file extensions"),
|
|
name: "accepted_file_extensions",
|
|
type: "string",
|
|
},
|
|
],
|
|
supportedTypes: ["many2many"],
|
|
isEmpty: () => false,
|
|
relatedFields: [
|
|
{ name: "name", type: "char" },
|
|
{ name: "mimetype", type: "char" },
|
|
],
|
|
extractProps: ({ attrs, options }) => ({
|
|
acceptedFileExtensions: options.accepted_file_extensions,
|
|
showSelectBtn: options.show_select_btn === undefined ? true : options.show_select_btn,
|
|
previewType: options.preview_type,
|
|
previewString: options.preview_string,
|
|
className: attrs.class,
|
|
}),
|
|
};
|
|
|
|
registry.category("fields").add("preview_many2many", many2ManyBinaryField);
|
|
|
|
|
|
|
|
|
|
|