484 lines
15 KiB
JavaScript
484 lines
15 KiB
JavaScript
import { Domain } from "@web/core/domain";
|
|
import { user } from "@web/core/user";
|
|
|
|
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
|
import { fields, models, serverState, webModels } from "@web/../tests/web_test_helpers";
|
|
|
|
export class DocumentsDocument extends models.Model {
|
|
_name = "documents.document";
|
|
_parent_name = "folder_id";
|
|
|
|
access_internal = fields.Selection({
|
|
selection: [
|
|
["edit", "Editor"],
|
|
["view", "Viewer"],
|
|
["none", "None"],
|
|
],
|
|
default: "edit",
|
|
});
|
|
access_via_link = fields.Selection({
|
|
selection: [
|
|
["edit", "Editor"],
|
|
["view", "Viewer"],
|
|
["none", "None"],
|
|
],
|
|
default: "none",
|
|
});
|
|
is_access_via_link_hidden = fields.Boolean();
|
|
|
|
activity_state = fields.Selection({
|
|
selection: [
|
|
["overdue", "Overdue"],
|
|
["today", "Today"],
|
|
["planned", "Planned"],
|
|
],
|
|
});
|
|
name = fields.Char();
|
|
thumbnail = fields.Binary();
|
|
favorited_ids = fields.Many2many({ relation: "res.users" });
|
|
is_favorited = fields.Boolean({ string: "Name" });
|
|
is_folder = fields.Boolean(); // used for ordering
|
|
is_multipage = fields.Boolean();
|
|
|
|
user_can_move = fields.Boolean({ default: true });
|
|
is_editable_attachment = fields.Boolean();
|
|
mimetype = fields.Char();
|
|
partner_id = fields.Many2one({ string: "Related partner", relation: "res.partner" });
|
|
owner_id = fields.Many2one({ relation: "res.users" });
|
|
previous_attachment_ids = fields.Many2many({ string: "History", relation: "ir.attachment" });
|
|
tag_ids = fields.Many2many({ relation: "documents.tag" });
|
|
folder_id = fields.Many2one({ relation: "documents.document" });
|
|
user_folder_id = fields.Char({ string: "Parent" });
|
|
res_model = fields.Char({ string: "Model (technical)" });
|
|
attachment_id = fields.Many2one({ relation: "ir.attachment" });
|
|
company_id = fields.Many2one({ relation: "res.company" });
|
|
active = fields.Boolean({ default: true });
|
|
activity_ids = fields.One2many({ relation: "mail.activity" });
|
|
my_activity_date_deadline = fields.Date();
|
|
checksum = fields.Char();
|
|
file_extension = fields.Char();
|
|
thumbnail_status = fields.Selection({
|
|
selection: [
|
|
["present", "Present"],
|
|
["error", "Error"],
|
|
["client_generated", "Client_Generated"],
|
|
["restricted", "Inaccessible"],
|
|
],
|
|
});
|
|
lock_uid = fields.Many2one({ relation: "res.users" });
|
|
message_attachment_count = fields.Integer();
|
|
message_follower_ids = fields.One2many({ relation: "mail.followers" });
|
|
message_ids = fields.One2many({ relation: "mail.message" });
|
|
res_id = fields.Integer({ string: "Resource ID" });
|
|
res_name = fields.Char({ string: "Resource Name" });
|
|
res_model_name = fields.Char({ string: "Resource Model Name" });
|
|
type = fields.Selection({
|
|
selection: [
|
|
["binary", "File"],
|
|
["url", "Url"],
|
|
["folder", "Folder"],
|
|
],
|
|
default: "binary",
|
|
});
|
|
shortcut_document_id = fields.Many2one({ relation: "documents.document" });
|
|
url = fields.Char();
|
|
url_preview_image = fields.Char({ string: "URL preview image" });
|
|
file_size = fields.Integer();
|
|
raw = fields.Char();
|
|
access_token = fields.Char();
|
|
user_permission = fields.Selection({
|
|
selection: [
|
|
["edit", "Editor"],
|
|
["view", "Viewer"],
|
|
["none", "None"],
|
|
],
|
|
default: "edit",
|
|
});
|
|
available_embedded_actions_ids = fields.Many2many({
|
|
string: "Available Actions",
|
|
relation: "ir.embedded.actions",
|
|
});
|
|
alias_id = fields.Many2one({ relation: "mail.alias" });
|
|
alias_domain_id = fields.Many2one({ relation: "mail.alias.domain" });
|
|
alias_name = fields.Char();
|
|
alias_tag_ids = fields.Many2many({ relation: "documents.tag" });
|
|
mail_alias_domain_count = fields.Integer();
|
|
create_activity_type_id = fields.Many2one({ relation: "mail.activity.type" });
|
|
create_activity_user_id = fields.Many2one({ relation: "res.users" });
|
|
description = fields.Char({ string: "Attachment description" });
|
|
last_access_date_group = fields.Selection({
|
|
string: "Last Accessed On",
|
|
selection: [
|
|
["0_older", "Older"],
|
|
["1_month", "This Month"],
|
|
["2_week", "This Week"],
|
|
["3_day", "Today"],
|
|
],
|
|
default: "3_day",
|
|
});
|
|
activity_user_id = fields.Many2one({ relation: "res.users" });
|
|
// added here for convenience, do not use in views if the field does not exist (as in "base" `documents`)
|
|
has_embedded_pdf = fields.Boolean({ string: "Has Embedded PDF" });
|
|
|
|
get_deletion_delay() {
|
|
return 30;
|
|
}
|
|
|
|
get_document_max_upload_limit() {
|
|
return 67000000;
|
|
}
|
|
|
|
get_details_panel_res_models() {
|
|
// Nine elements to match the number actually sent by the server when all apps are present.
|
|
return [
|
|
"res.partner",
|
|
"res.users",
|
|
"mail.activity",
|
|
"mail.activity.type",
|
|
"mail.channel",
|
|
"mail.channel.member",
|
|
"mail.channel.message",
|
|
"mail.message",
|
|
"documents.document",
|
|
];
|
|
}
|
|
|
|
action_create_shortcut() {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Override to implement _search_user_folder_id search method, and to hide
|
|
* the documents the user has no access to (as the record rules do).
|
|
*/
|
|
web_search_read() {
|
|
const kwargs = arguments[0];
|
|
const domain = kwargs?.domain;
|
|
if (domain) {
|
|
const folderLeafIdx = domain.findIndex((leaf) => leaf[0] === "user_folder_id");
|
|
if (folderLeafIdx !== -1) {
|
|
domain.splice(folderLeafIdx, 1, [
|
|
"user_folder_id",
|
|
domain[folderLeafIdx][1],
|
|
domain[folderLeafIdx][2].toString(),
|
|
]);
|
|
}
|
|
// maybe redundant but should never be incorrect
|
|
kwargs.domain = Domain.and([domain, [["user_permission", "!=", "none"]]]).toList();
|
|
} else {
|
|
kwargs.domain = [["user_permission", "!=", "none"]];
|
|
}
|
|
return super.web_search_read(...arguments);
|
|
}
|
|
|
|
action_move_folder(folder, target, before_folder_id = false) {
|
|
const record = this.filter((r) => folder.id === r.id);
|
|
record.folder_id = target;
|
|
}
|
|
|
|
/**
|
|
* @override to avoid super() not working for us.
|
|
* Folders the user has no access to are not returned, as on the server.
|
|
*/
|
|
async search_panel_select_range(fieldName) {
|
|
const result = { parent_field: "user_folder_id" };
|
|
result.values = await this._get_search_panel_specials();
|
|
for (const record of this.search_read(
|
|
[
|
|
["type", "=", "folder"],
|
|
["user_permission", "!=", "none"],
|
|
],
|
|
[
|
|
"access_internal",
|
|
"access_via_link",
|
|
"active",
|
|
"alias_domain_id",
|
|
"alias_name",
|
|
"alias_tag_ids",
|
|
"company_id",
|
|
"create_activity_type_id",
|
|
"description",
|
|
"display_name",
|
|
"user_folder_id",
|
|
"id",
|
|
"is_access_via_link_hidden",
|
|
"is_folder",
|
|
"mail_alias_domain_count",
|
|
"owner_id",
|
|
"partner_id",
|
|
"type",
|
|
"user_permission",
|
|
"access_token",
|
|
]
|
|
)) {
|
|
if (!isNaN(record.user_folder_id)) {
|
|
record.user_folder_id = Number(record.user_folder_id);
|
|
}
|
|
if (!record.active) {
|
|
record.user_folder_id = "TRASH";
|
|
}
|
|
if (record.alias_tag_ids) {
|
|
record.alias_tag_ids = record.alias_tag_ids.map((id) => {
|
|
const [tag] = this.env["documents.tag"].browse(id);
|
|
return { id, color: tag.color, display_name: tag.name };
|
|
});
|
|
}
|
|
result.values.push(record);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
async _get_search_panel_specials() {
|
|
if (!(await user.hasGroup("base.group_user"))) {
|
|
return [];
|
|
}
|
|
return [
|
|
{
|
|
bold: true,
|
|
childrenIds: [],
|
|
parentId: false,
|
|
user_permission: "view",
|
|
display_name: "Company",
|
|
id: "COMPANY",
|
|
description: "Common roots for all company users.",
|
|
},
|
|
{
|
|
bold: true,
|
|
childrenIds: [],
|
|
parentId: false,
|
|
user_permission: "edit",
|
|
display_name: "My Drive",
|
|
id: "MY",
|
|
description: "Your individual space.",
|
|
},
|
|
{
|
|
bold: true,
|
|
childrenIds: [],
|
|
parentId: false,
|
|
user_permission: "edit",
|
|
display_name: "Shared with me",
|
|
id: "SHARED",
|
|
description: "Additional documents you have access to.",
|
|
},
|
|
{
|
|
bold: true,
|
|
childrenIds: [],
|
|
parentId: false,
|
|
user_permission: "edit",
|
|
display_name: "Recent",
|
|
id: "RECENT",
|
|
description: "Recently accessed documents.",
|
|
},
|
|
{
|
|
bold: true,
|
|
childrenIds: [],
|
|
parentId: false,
|
|
user_permission: "edit",
|
|
display_name: "Trash",
|
|
id: "TRASH",
|
|
description: "Items in trash will be deleted forever after 30 days.",
|
|
},
|
|
];
|
|
}
|
|
|
|
toggle_lock(id) {
|
|
const record = this.browse(id)[0];
|
|
record.lock_uid = record.lock_uid ? false : serverState.odoobotId;
|
|
}
|
|
|
|
get_documents_actions(folder_id) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export class DocumentsOperation extends models.Model {
|
|
_name = "documents.operation";
|
|
|
|
operation = fields.Selection({
|
|
selection: [
|
|
["move", "Move"],
|
|
["shortcut", "Create shortcuts"],
|
|
["copy", "Duplicate to"],
|
|
["add", "Add attachment to Documents"],
|
|
],
|
|
});
|
|
document_ids = fields.Many2many({ relation: "documents.document" });
|
|
attachment_id = fields.Many2one({ relation: "ir.attachment" });
|
|
|
|
destination = fields.Char({ default: "MY" });
|
|
display_name = fields.Char({ default: "My Drive" });
|
|
|
|
user_permission = fields.Char({ string: "Destination User Permission", default: "edit" });
|
|
access_internal = fields.Char({ string: "Destination Access Internal", default: "edit" });
|
|
access_via_link = fields.Char({ string: "Destination Access Via Link", default: "edit" });
|
|
is_access_via_link_hidden = fields.Boolean({ string: "Destination Link Access Hidden" });
|
|
|
|
get_any_editor_destination() {
|
|
for (const record of this.env["documents.document"].search_read(
|
|
[["type", "=", "folder"]],
|
|
["shortcut_document_id", "type", "user_permission"]
|
|
)) {
|
|
if (
|
|
record.type === "folder" &&
|
|
!record.shortcut_document_id &&
|
|
record.user_permission === "edit"
|
|
) {
|
|
return [{ destination: record.id.toString(), display_name: record.display_name }];
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export class DocumentsTag extends models.Model {
|
|
_name = "documents.tag";
|
|
|
|
name = fields.Char({ string: "Tag Name" });
|
|
color = fields.Integer({ default: 1 });
|
|
sequence = fields.Integer();
|
|
}
|
|
|
|
export class DocumentsSharing extends models.Model {
|
|
_name = "documents.sharing";
|
|
|
|
access_internal = fields.Selection({
|
|
selection: [
|
|
["edit", "Editor"],
|
|
["write_edit", "Editor"],
|
|
["view", "Viewer"],
|
|
["write_view", "Viewer"],
|
|
["none", "None"],
|
|
["write_none", "None"],
|
|
["mixed", "Mixed rights"],
|
|
],
|
|
});
|
|
}
|
|
|
|
export class IrEmbeddedActions extends models.Model {
|
|
_name = "ir.embedded.actions";
|
|
|
|
name = fields.Char({ string: "Action Name" });
|
|
}
|
|
|
|
export class MailAlias extends models.Model {
|
|
_name = "mail.alias";
|
|
|
|
alias_name = fields.Char({ string: "Alias Name" });
|
|
}
|
|
|
|
export class MailAliasDomain extends models.Model {
|
|
_name = "mail.alias.domain";
|
|
|
|
name = fields.Char({ string: "Alias Domain Name" });
|
|
}
|
|
|
|
/**
|
|
* @param {Number} id
|
|
* @param {String} name
|
|
* @param {object?} data
|
|
* @return {{}}
|
|
*/
|
|
export function makeDocumentRecordData(id, name, data = {}) {
|
|
const strippedName = name.replace(/\s/g, "");
|
|
const defaultValues = {
|
|
available_embedded_actions_ids: [],
|
|
folder_id: false,
|
|
company_id: false,
|
|
owner_id: false,
|
|
partner_id: false,
|
|
type: "binary",
|
|
};
|
|
const documentType = data.type || defaultValues.type;
|
|
const user_folder_id =
|
|
data.user_folder_id ||
|
|
(data.folder_id
|
|
? data.folder_id.toString()
|
|
: data.owner_id
|
|
? data.owner_id === serverState.userId
|
|
? "MY"
|
|
: "SHARED"
|
|
: "COMPANY");
|
|
return {
|
|
...defaultValues,
|
|
id,
|
|
access_token: `accessToken${strippedName}`,
|
|
is_folder: documentType === "folder",
|
|
name,
|
|
type: documentType,
|
|
user_folder_id,
|
|
...data,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @returns {Object}
|
|
*/
|
|
export function getDocumentsTestServerModelsData(additionalRecords = []) {
|
|
return {
|
|
"res.users": [
|
|
{ name: "OdooBot", id: serverState.odoobotId },
|
|
{
|
|
name: serverState.partnerName,
|
|
id: serverState.userId,
|
|
active: true,
|
|
partner_id: serverState.partnerId,
|
|
},
|
|
],
|
|
"documents.document": [
|
|
makeDocumentRecordData(1, "Folder 1", { type: "folder", user_permission: "edit" }),
|
|
...additionalRecords,
|
|
],
|
|
"documents.tag": [
|
|
{
|
|
id: 1,
|
|
name: "Colorless",
|
|
color: 0,
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Colorful",
|
|
color: 1,
|
|
},
|
|
],
|
|
"mail.alias": [
|
|
{
|
|
id: 1,
|
|
alias_name: "alias",
|
|
},
|
|
],
|
|
|
|
"mail.alias.domain": [
|
|
{
|
|
id: 1,
|
|
name: "odoo.com",
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "runbot.odoo.com",
|
|
},
|
|
],
|
|
|
|
"res.company": serverState.companies,
|
|
};
|
|
}
|
|
|
|
export const DocumentsModels = {
|
|
...mailModels,
|
|
IrEmbeddedActions,
|
|
MailAlias,
|
|
MailAliasDomain,
|
|
ResCompany: webModels.ResCompany,
|
|
DocumentsDocument,
|
|
DocumentsOperation,
|
|
DocumentsTag,
|
|
DocumentsSharing,
|
|
};
|
|
|
|
export function getDocumentsModel(modelName) {
|
|
return Object.values(DocumentsModels).find((model) => model.getModelName() === modelName);
|
|
}
|
|
|
|
export const mimetypeExamplesBase64 = {
|
|
WEBP: "UklGRjoAAABXRUJQVlA4IC4AAAAwAQCdASoBAAEAAUAmJaAAA3AA/u/uY//8s//2W/7LeM///5Bj/dl/pJxGAAAA",
|
|
};
|