[IMP] mail, web: create FileModelMixin for FileViewer

Extract basic props needed by the `FileViewer` for `files` instances in a
reusable `Mixin`.

task-3172056

Part-of: odoo/odoo#127021
This commit is contained in:
abd-msyukyu-odoo
2023-10-13 07:33:52 +00:00
parent 31eeb6de6a
commit 62ca95f0fd
2 changed files with 135 additions and 121 deletions
@@ -4,9 +4,9 @@ import { Record } from "@mail/core/common/record";
import { assignDefined } from "@mail/utils/common/misc";
import { deserializeDateTime } from "@web/core/l10n/dates";
import { url } from "@web/core/utils/urls";
import { FileModelMixin } from "@web/core/file_viewer/file_model";
export class Attachment extends Record {
export class Attachment extends FileModelMixin(Record) {
static id = "id";
/** @type {Object.<number, import("models").Attachment>} */
static records = {};
@@ -61,22 +61,8 @@ export class Attachment extends Record {
}
}
accessToken;
checksum;
extension;
filename;
id;
mimetype;
name;
originThread = Record.one("Thread");
res_name;
type;
/** @type {string} */
tmpUrl;
/** @type {string} */
url;
/** @type {boolean} */
uploading;
message = Record.one("Message");
/** @type {string} */
create_date;
@@ -85,25 +71,6 @@ export class Attachment extends Record {
return true;
}
get displayName() {
return this.name || this.filename;
}
get isText() {
const textMimeType = [
"application/javascript",
"application/json",
"text/css",
"text/html",
"text/plain",
];
return textMimeType.includes(this.mimetype);
}
get isPdf() {
return this.mimetype && this.mimetype.startsWith("application/pdf");
}
get monthYear() {
if (!this.create_date) {
return undefined;
@@ -111,92 +78,6 @@ export class Attachment extends Record {
const datetime = deserializeDateTime(this.create_date);
return `${datetime.monthLong}, ${datetime.year}`;
}
get isImage() {
const imageMimetypes = [
"image/bmp",
"image/gif",
"image/jpeg",
"image/png",
"image/svg+xml",
"image/tiff",
"image/x-icon",
"image/webp",
];
return imageMimetypes.includes(this.mimetype);
}
get isUrl() {
return this.type === "url" && this.url;
}
get isUrlYoutube() {
return !!this.url && this.url.includes("youtu");
}
get isVideo() {
const videoMimeTypes = ["audio/mpeg", "video/x-matroska", "video/mp4", "video/webm"];
return videoMimeTypes.includes(this.mimetype);
}
get isViewable() {
return (
(this.isText || this.isImage || this.isVideo || this.isPdf || this.isUrlYoutube) &&
!this.uploading
);
}
get defaultSource() {
const route = url(this.urlRoute, this.urlQueryParams);
const encodedRoute = encodeURIComponent(route);
if (this.isPdf) {
return `/web/static/lib/pdfjs/web/viewer.html?file=${encodedRoute}#pagemode=none`;
}
if (this.isUrlYoutube) {
const urlArr = this.url.split("/");
let token = urlArr[urlArr.length - 1];
if (token.includes("watch")) {
token = token.split("v=")[1];
const amp = token.indexOf("&");
if (amp !== -1) {
token = token.substring(0, amp);
}
}
return `https://www.youtube.com/embed/${token}`;
}
return route;
}
get downloadUrl() {
return url(this.urlRoute, { ...this.urlQueryParams, download: true });
}
/**
* @returns {string}
*/
get urlRoute() {
if (this.uploading && this.tmpUrl) {
return this.tmpUrl;
}
return this.isImage ? `/web/image/${this.id}` : `/web/content/${this.id}`;
}
/**
* @returns {Object}
*/
get urlQueryParams() {
if (this.uploading && this.tmpUrl) {
return {};
}
return assignDefined(
{},
{
access_token: this.accessToken || undefined,
filename: this.name || undefined,
unique: this.checksum || undefined,
}
);
}
}
Attachment.register();
@@ -0,0 +1,133 @@
/* @odoo-module */
import { url } from "@web/core/utils/urls";
export const FileModelMixin = T => class extends T {
accessToken;
checksum;
extension;
filename;
id;
mimetype;
name;
type;
/** @type {string} */
tmpUrl;
/** @type {string} */
url;
/** @type {boolean} */
uploading;
get defaultSource() {
const route = url(this.urlRoute, this.urlQueryParams);
const encodedRoute = encodeURIComponent(route);
if (this.isPdf) {
return `/web/static/lib/pdfjs/web/viewer.html?file=${encodedRoute}#pagemode=none`;
}
if (this.isUrlYoutube) {
const urlArr = this.url.split("/");
let token = urlArr[urlArr.length - 1];
if (token.includes("watch")) {
token = token.split("v=")[1];
const amp = token.indexOf("&");
if (amp !== -1) {
token = token.substring(0, amp);
}
}
return `https://www.youtube.com/embed/${token}`;
}
return route;
}
get displayName() {
return this.name || this.filename;
}
get downloadUrl() {
return url(this.urlRoute, { ...this.urlQueryParams, download: true });
}
get isImage() {
const imageMimetypes = [
"image/bmp",
"image/gif",
"image/jpeg",
"image/png",
"image/svg+xml",
"image/tiff",
"image/x-icon",
"image/webp",
];
return imageMimetypes.includes(this.mimetype);
}
get isPdf() {
return this.mimetype && this.mimetype.startsWith("application/pdf");
}
get isText() {
const textMimeType = [
"application/javascript",
"application/json",
"text/css",
"text/html",
"text/plain",
];
return textMimeType.includes(this.mimetype);
}
get isUrl() {
return this.type === "url" && this.url;
}
get isUrlYoutube() {
return !!this.url && this.url.includes("youtu");
}
get isVideo() {
const videoMimeTypes = ["audio/mpeg", "video/x-matroska", "video/mp4", "video/webm"];
return videoMimeTypes.includes(this.mimetype);
}
get isViewable() {
return (
(this.isText || this.isImage || this.isVideo || this.isPdf || this.isUrlYoutube) &&
!this.uploading
);
}
/**
* @returns {Object}
*/
get urlQueryParams() {
if (this.uploading && this.tmpUrl) {
return {};
}
const params = {
access_token: this.accessToken,
filename: this.name,
unique: this.checksum,
};
for (const prop in params) {
if (!params[prop]) {
delete params[prop];
}
}
return params;
}
/**
* @returns {string}
*/
get urlRoute() {
if (this.isUrl) {
return this.url;
}
if (this.uploading && this.tmpUrl) {
return this.tmpUrl;
}
return this.isImage ? `/web/image/${this.id}` : `/web/content/${this.id}`;
}
}
export class FileModel extends FileModelMixin(Object) {}