[MOV] mail, mrp, mail, web: move attachment_viewer from mail to web
The `mail` module's `attachment_viewer` is useful for more than `mail` alone. In order to be able to use it in the `web_editor` module (which doesn't depend on `mail`), we move it to the `web` module. task-3109331 Part-of: odoo/odoo#119625
This commit is contained in:
@@ -5,7 +5,7 @@ import { Component } from "@odoo/owl";
|
||||
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { useAttachmentViewer } from "./attachment_viewer_hook";
|
||||
import { useAttachmentViewer } from "@web/core/attachment_viewer/attachment_viewer_hook";
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { url } from "@web/core/utils/urls";
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
.arrow {
|
||||
width: 5%;
|
||||
@include o-position-absolute(50%, 0);
|
||||
@include o-mail-AttachmentViewer-arrow;
|
||||
@include o-AttachmentViewer-arrow;
|
||||
transition: width 0.3s;
|
||||
padding-top: 30px;
|
||||
height: 75px;
|
||||
|
||||
@@ -15,7 +15,7 @@ $o-mail-Chatter-minWidth: 530px !default;
|
||||
$o-mail-Discuss-inspector: 250px !default;
|
||||
$o-mail-Discuss-headerHeight: 48px !default;
|
||||
|
||||
@mixin o-mail-AttachmentViewer-arrow {
|
||||
@mixin o-AttachmentViewer-arrow {
|
||||
background-color: rgba(black, 0.4);
|
||||
color: rgba(map-get($theme-colors, 'light'), 0.7);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
@include o-position-absolute(50%, $grid-gutter-width*0.5);
|
||||
border-radius: 100%;
|
||||
padding: 12px 16px 11px 18px;
|
||||
@include o-mail-AttachmentViewer-arrow;
|
||||
@include o-AttachmentViewer-arrow;
|
||||
}
|
||||
|
||||
.arrow-left {
|
||||
|
||||
@@ -115,7 +115,7 @@ QUnit.test("view attachment", async (assert) => {
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-AttachmentImage img");
|
||||
await click(".o-mail-AttachmentImage");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer");
|
||||
assert.containsOnce($, ".o-AttachmentViewer");
|
||||
});
|
||||
|
||||
QUnit.test("close attachment viewer", async (assert) => {
|
||||
@@ -140,10 +140,10 @@ QUnit.test("close attachment viewer", async (assert) => {
|
||||
assert.containsOnce($, ".o-mail-AttachmentImage img");
|
||||
|
||||
await click(".o-mail-AttachmentImage");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer");
|
||||
assert.containsOnce($, ".o-AttachmentViewer");
|
||||
|
||||
await click(".o-mail-AttachmentViewer div[aria-label='Close']");
|
||||
assert.containsNone($, ".o-mail-AttachmentViewer");
|
||||
await click(".o-AttachmentViewer div[aria-label='Close']");
|
||||
assert.containsNone($, ".o-AttachmentViewer");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -177,8 +177,8 @@ QUnit.test(
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await click(".o-mail-AttachmentImage");
|
||||
const image = $(".o-mail-AttachmentViewer-viewImage")[0];
|
||||
await click(".o-mail-AttachmentViewer div[aria-label='Close']");
|
||||
const image = $(".o-AttachmentViewer-viewImage")[0];
|
||||
await click(".o-AttachmentViewer div[aria-label='Close']");
|
||||
// Simulate image becoming loaded.
|
||||
let successfulLoad;
|
||||
try {
|
||||
@@ -314,10 +314,10 @@ QUnit.test(
|
||||
|
||||
click(".o-mail-AttachmentCard:contains(test.odt)").catch(() => {});
|
||||
await nextTick();
|
||||
assert.containsNone($, ".o-mail-AttachmentViewer");
|
||||
assert.containsNone($, ".o-AttachmentViewer");
|
||||
|
||||
await click(".o-mail-AttachmentImage[title='test.png']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer");
|
||||
assert.containsOnce($, ".o-AttachmentViewer");
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -136,16 +136,16 @@ QUnit.test("view attachments", async (assert) => {
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click('.o-mail-AttachmentCard[aria-label="Blah.txt"] .o-mail-AttachmentCard-image');
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer-header:contains(Blah.txt)");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-AttachmentViewer");
|
||||
assert.containsOnce($, ".o-AttachmentViewer-header:contains(Blah.txt)");
|
||||
assert.containsOnce($, ".o-AttachmentViewer div[aria-label='Next']");
|
||||
|
||||
await click(".o-mail-AttachmentViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer-header:contains(Blu.txt)");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer div[aria-label='Next']");
|
||||
await click(".o-AttachmentViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-AttachmentViewer-header:contains(Blu.txt)");
|
||||
assert.containsOnce($, ".o-AttachmentViewer div[aria-label='Next']");
|
||||
|
||||
await click(".o-mail-AttachmentViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentViewer-header:contains(Blah.txt)");
|
||||
await click(".o-AttachmentViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-AttachmentViewer-header:contains(Blah.txt)");
|
||||
});
|
||||
|
||||
QUnit.test("scroll to attachment box when toggling on", async (assert) => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { CANCEL_GLOBAL_CLICK, KanbanRecord } from "@web/views/kanban/kanban_record";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { useAttachmentViewer } from "@mail/attachments/attachment_viewer_hook";
|
||||
import { useAttachmentViewer } from "@web/core/attachment_viewer/attachment_viewer_hook";
|
||||
|
||||
export class MrpDocumentsKanbanRecord extends KanbanRecord {
|
||||
setup() {
|
||||
|
||||
@@ -231,12 +231,12 @@ QUnit.module('MrpDocumentsKanbanView', {
|
||||
assert.containsOnce(target, ".o_kanban_previewer");
|
||||
|
||||
await click(target.querySelector(".o_kanban_previewer"));
|
||||
await waitUntil('.o-mail-AttachmentViewer');
|
||||
assert.containsOnce(target, '.o-mail-AttachmentViewer');
|
||||
assert.containsOnce(target, '.o-mail-AttachmentViewer-headerButton .fa-times');
|
||||
await waitUntil('.o-AttachmentViewer');
|
||||
assert.containsOnce(target, '.o-AttachmentViewer');
|
||||
assert.containsOnce(target, '.o-AttachmentViewer-headerButton .fa-times');
|
||||
|
||||
await click(target, '.o-mail-AttachmentViewer-headerButton .fa-times');
|
||||
assert.containsNone(target, '.o-mail-AttachmentViewer');
|
||||
await click(target, '.o-AttachmentViewer-headerButton .fa-times');
|
||||
assert.containsNone(target, '.o-AttachmentViewer');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ This module provides the core of the Odoo Web Client.
|
||||
('remove', 'web/static/src/webclient/navbar/navbar.scss'), # already in assets_common
|
||||
('remove', 'web/static/src/webclient/clickbot/clickbot.js'), # lazy loaded
|
||||
('remove', 'web/static/src/views/form/button_box/*.scss'),
|
||||
('remove', 'web/static/src/core/attachment_viewer/attachment_viewer.dark.scss'),
|
||||
|
||||
# remove the report code and whitelist only what's needed
|
||||
('remove', 'web/static/src/webclient/actions/reports/**/*'),
|
||||
@@ -399,6 +400,7 @@ This module provides the core of the Odoo Web Client.
|
||||
'web/static/src/core/**/*',
|
||||
('remove', 'web/static/src/core/commands/**/*'),
|
||||
('remove', 'web/static/src/core/debug/debug_menu.js'),
|
||||
('remove', 'web/static/src/core/attachment_viewer/attachment_viewer.dark.scss'),
|
||||
'web/static/src/public/error_notifications.js',
|
||||
|
||||
'web/static/src/legacy/utils.js',
|
||||
@@ -481,6 +483,7 @@ This module provides the core of the Odoo Web Client.
|
||||
# ---------------------------------------------------------------------
|
||||
"web.dark_mode_assets_common": [
|
||||
('include', 'web.assets_common'),
|
||||
'web/static/src/core/attachment_viewer/attachment_viewer.dark.scss',
|
||||
],
|
||||
"web.dark_mode_assets_backend": [
|
||||
('include', 'web.assets_backend'),
|
||||
|
||||
+2
-2
@@ -2,6 +2,6 @@
|
||||
// ============================================================================
|
||||
// No CSS hacks, variables overrides only
|
||||
|
||||
.o-mail-AttachmentViewer-toolbarButton {
|
||||
--mail-attachment-viewer-toolbarButton-background-color: #{$o-gray-200};
|
||||
.o-AttachmentViewer-toolbarButton {
|
||||
--web-attachment-viewer-toolbarButton-background-color: #{$o-gray-200};
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { useService } from "@web/core/utils/hooks";
|
||||
* @extends {Component<Props, Env>}
|
||||
*/
|
||||
export class AttachmentViewer extends Component {
|
||||
static template = "mail.AttachmentViewer";
|
||||
static template = "web.AttachmentViewer";
|
||||
static components = {};
|
||||
static props = ["attachments", "startIndex", "close", "modal?"];
|
||||
static defaultProps = {
|
||||
+9
-9
@@ -1,33 +1,33 @@
|
||||
.o-mail-AttachmentViewer {
|
||||
.o-AttachmentViewer {
|
||||
z-index: -1;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-navigation {
|
||||
.o-AttachmentViewer-navigation {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-header {
|
||||
.o-AttachmentViewer-header {
|
||||
height: $o-navbar-height;
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-main {
|
||||
.o-AttachmentViewer-main {
|
||||
z-index: -1;
|
||||
padding: ($o-navbar-height * 1.125) 0;
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-zoomer {
|
||||
.o-AttachmentViewer-zoomer {
|
||||
padding: ($o-navbar-height * 1.125) 0;
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-headerButton:hover {
|
||||
.o-AttachmentViewer-headerButton:hover {
|
||||
background-color: rgba($white, 0.1);
|
||||
color: lighten($gray-400, 15%);
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-toolbarButton {
|
||||
background-color: var(--mail-attachment-viewer-toolbarButton-background-color, #{$o-gray-800});
|
||||
.o-AttachmentViewer-toolbarButton {
|
||||
background-color: var(--web-attachment-viewer-toolbarButton-background-color, #{$o-gray-800});
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
@@ -35,7 +35,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.o-mail-AttachmentViewer-view {
|
||||
.o-AttachmentViewer-view {
|
||||
background-color: #000000;
|
||||
box-shadow: 0 0 40px #000000;
|
||||
outline: none;
|
||||
+20
-20
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="mail.AttachmentViewer" owl="1">
|
||||
<t t-name="web.AttachmentViewer" owl="1">
|
||||
<div class="d-flex justify-content-center" t-att-class="{ 'modal fixed-top bottom-0': props.modal }">
|
||||
<div class="o-mail-AttachmentViewer flex-column align-items-center d-flex w-100 h-100" tabindex="0">
|
||||
<div class="o-mail-AttachmentViewer-header position-absolute top-0 d-flex w-100 bg-black-75 text-400">
|
||||
<div class="o-AttachmentViewer flex-column align-items-center d-flex w-100 h-100" tabindex="0">
|
||||
<div class="o-AttachmentViewer-header position-absolute top-0 d-flex w-100 bg-black-75 text-400">
|
||||
<div t-if="isViewable" class="d-flex align-items-center ms-4 me-2">
|
||||
<i t-if="state.attachment.isImage" class="fa fa-picture-o" role="img" title="Image"/>
|
||||
<i t-if="state.attachment.isPdf" class="fa fa-file-text" role="img" title="PDF file"/>
|
||||
@@ -15,58 +15,58 @@
|
||||
<span class="text-truncate" t-out="state.attachment.displayName"/>
|
||||
</div>
|
||||
<div class="flex-grow-1"/>
|
||||
<div class="o-mail-AttachmentViewer-download o-mail-AttachmentViewer-headerButton d-flex align-items-center px-3 cursor-pointer" role="button" title="Download">
|
||||
<div class="o-AttachmentViewer-download o-AttachmentViewer-headerButton d-flex align-items-center px-3 cursor-pointer" role="button" title="Download">
|
||||
<a t-att-href="state.attachment.downloadUrl" class="text-reset" download="">
|
||||
<i class="fa fa-download fa-fw" role="img"/>
|
||||
<span>Download</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div t-on-click.stop="close" class="o-mail-AttachmentViewer-headerButton d-flex align-items-center mb-0 px-3 h4 text-reset cursor-pointer" role="button" title="Close (Esc)" aria-label="Close">
|
||||
<div t-on-click.stop="close" class="o-AttachmentViewer-headerButton d-flex align-items-center mb-0 px-3 h4 text-reset cursor-pointer" role="button" title="Close (Esc)" aria-label="Close">
|
||||
<i class="fa fa-fw fa-times" role="img"/>
|
||||
</div>
|
||||
</div>
|
||||
<div t-on-click.stop="close" t-on-mousemove="onMousemoveView" class="o-mail-AttachmentViewer-main position-absolute top-0 bottom-0 start-0 end-0 align-items-center justify-content-center d-flex" t-att-class="{ 'o_with_img overflow-hidden': state.attachment.isImage }">
|
||||
<div t-if="state.attachment.isImage" class="o-mail-AttachmentViewer-zoomer position-absolute align-items-center justify-content-center d-flex w-100 h-100" t-ref="zoomer">
|
||||
<div t-on-click.stop="close" t-on-mousemove="onMousemoveView" class="o-AttachmentViewer-main position-absolute top-0 bottom-0 start-0 end-0 align-items-center justify-content-center d-flex" t-att-class="{ 'o_with_img overflow-hidden': state.attachment.isImage }">
|
||||
<div t-if="state.attachment.isImage" class="o-AttachmentViewer-zoomer position-absolute align-items-center justify-content-center d-flex w-100 h-100" t-ref="zoomer">
|
||||
<div t-if="!state.imageLoaded" class="position-absolute">
|
||||
<i class="fa fa-3x fa-circle-o-notch fa-fw fa-spin text-white" role="img" title="Loading"/>
|
||||
</div>
|
||||
<img t-on-click.stop="" t-on-load="onImageLoaded" t-on-wheel="onWheelImage" t-on-mousedown.stop="onMousedownImage" t-on-mouseup.stop="onMouseupImage" class="o-mail-AttachmentViewer-view o-mail-AttachmentViewer-viewImage mw-100 mh-100 transition-base" t-att-src="state.attachment.defaultSource" t-att-style="imageStyle" draggable="false" alt="Viewer" t-ref="image"/>
|
||||
<img t-on-click.stop="" t-on-load="onImageLoaded" t-on-wheel="onWheelImage" t-on-mousedown.stop="onMousedownImage" t-on-mouseup.stop="onMouseupImage" class="o-AttachmentViewer-view o-AttachmentViewer-viewImage mw-100 mh-100 transition-base" t-att-src="state.attachment.defaultSource" t-att-style="imageStyle" draggable="false" alt="Viewer" t-ref="image"/>
|
||||
</div>
|
||||
<iframe t-if="state.attachment.isPdf" class="o-mail-AttachmentViewer-view w-75 h-100 border-0" t-ref="iframeViewerPdf" t-att-class="{ 'w-100': ui.isSmall }" t-att-src="state.attachment.defaultSource"/>
|
||||
<iframe t-if="state.attachment.isText" class="o-mail-AttachmentViewer-view o-isText o_text w-75 h-100 border-0" t-att-src="state.attachment.defaultSource"/>
|
||||
<iframe t-if="state.attachment.isUrlYoutube" allow="autoplay; encrypted-media" class="o-mail-AttachmentViewer-view w-75 h-100 border-0" t-att-src="state.attachment.defaultSource" height="315" width="560"/>
|
||||
<video t-if="state.attachment.isVideo" class="o-mail-AttachmentViewer-view w-75 h-75" t-att-class="{ 'w-100 h-100': ui.isSmall }" t-on-click.stop="" controls="controls">
|
||||
<iframe t-if="state.attachment.isPdf" class="o-AttachmentViewer-view w-75 h-100 border-0" t-ref="iframeViewerPdf" t-att-class="{ 'w-100': ui.isSmall }" t-att-src="state.attachment.defaultSource"/>
|
||||
<iframe t-if="state.attachment.isText" class="o-AttachmentViewer-view o-isText o_text w-75 h-100 border-0" t-att-src="state.attachment.defaultSource"/>
|
||||
<iframe t-if="state.attachment.isUrlYoutube" allow="autoplay; encrypted-media" class="o-AttachmentViewer-view w-75 h-100 border-0" t-att-src="state.attachment.defaultSource" height="315" width="560"/>
|
||||
<video t-if="state.attachment.isVideo" class="o-AttachmentViewer-view w-75 h-75" t-att-class="{ 'w-100 h-100': ui.isSmall }" t-on-click.stop="" controls="controls">
|
||||
<source t-att-data-type="state.attachment.mimetype" t-att-src="state.attachment.defaultSource"/>
|
||||
</video>
|
||||
</div>
|
||||
<div t-if="state.attachment.isImage" class="position-absolute bottom-0 d-flex" role="toolbar">
|
||||
<div class="o-mail-AttachmentViewer-toolbarButton p-3 rounded-0" t-on-click="zoomIn" title="Zoom In (+)" role="button">
|
||||
<div class="o-AttachmentViewer-toolbarButton p-3 rounded-0" t-on-click="zoomIn" title="Zoom In (+)" role="button">
|
||||
<i class="fa fa-fw fa-plus" role="img"/>
|
||||
</div>
|
||||
<div class="o-mail-AttachmentViewer-toolbarButton p-3 rounded-0" t-att-class="{ 'o_disabled opacity-50': state.scale === 1 }" t-on-click="resetZoom" role="button" title="Reset Zoom (0)">
|
||||
<div class="o-AttachmentViewer-toolbarButton p-3 rounded-0" t-att-class="{ 'o_disabled opacity-50': state.scale === 1 }" t-on-click="resetZoom" role="button" title="Reset Zoom (0)">
|
||||
<i class="fa fa-fw fa-search" role="img"/>
|
||||
</div>
|
||||
<div class="o-mail-AttachmentViewer-toolbarButton p-3 rounded-0" t-att-class="{ 'o_disabled opacity-50': state.scale === minScale }" t-on-click="zoomOut" title="Zoom Out (-)" role="button">
|
||||
<div class="o-AttachmentViewer-toolbarButton p-3 rounded-0" t-att-class="{ 'o_disabled opacity-50': state.scale === minScale }" t-on-click="zoomOut" title="Zoom Out (-)" role="button">
|
||||
<i class="fa fa-fw fa-minus" role="img"/>
|
||||
</div>
|
||||
<div class="o-mail-AttachmentViewer-toolbarButton p-3 rounded-0" t-on-click="rotate" title="Rotate (r)" role="button">
|
||||
<div class="o-AttachmentViewer-toolbarButton p-3 rounded-0" t-on-click="rotate" title="Rotate (r)" role="button">
|
||||
<i class="fa fa-fw fa-repeat" role="img"/>
|
||||
</div>
|
||||
<div class="o-mail-AttachmentViewer-toolbarButton p-3 rounded-0" t-on-click="onClickPrint" title="Print" role="button">
|
||||
<div class="o-AttachmentViewer-toolbarButton p-3 rounded-0" t-on-click="onClickPrint" title="Print" role="button">
|
||||
<i class="fa fa-fw fa-print" role="img"/>
|
||||
</div>
|
||||
<div class="o-mail-AttachmentViewer-download o-mail-AttachmentViewer-toolbarButton p-3 rounded-0 cursor-pointer" title="Download" role="button">
|
||||
<div class="o-AttachmentViewer-download o-AttachmentViewer-toolbarButton p-3 rounded-0 cursor-pointer" title="Download" role="button">
|
||||
<a t-att-href="state.attachment.downloadUrl" class="text-reset" download="">
|
||||
<i class="fa fa-download fa-fw" role="img"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="props.attachments.length > 1">
|
||||
<div class="o-mail-AttachmentViewer-navigation position-absolute top-0 bottom-0 start-0 align-items-center justify-content-center d-flex my-auto ms-3 rounded-circle" t-on-click="previous" title="Previous (Left-Arrow)" aria-label="Previous" role="button">
|
||||
<div class="o-AttachmentViewer-navigation position-absolute top-0 bottom-0 start-0 align-items-center justify-content-center d-flex my-auto ms-3 rounded-circle" t-on-click="previous" title="Previous (Left-Arrow)" aria-label="Previous" role="button">
|
||||
<span class="oi oi-chevron-left" role="img"/>
|
||||
</div>
|
||||
<div class="o-mail-AttachmentViewer-navigation position-absolute top-0 bottom-0 end-0 align-items-center justify-content-center d-flex my-auto me-3 rounded-circle" t-on-click="next" title="Next (Right-Arrow)" aria-label="Next" role="button">
|
||||
<div class="o-AttachmentViewer-navigation position-absolute top-0 bottom-0 end-0 align-items-center justify-content-center d-flex my-auto me-3 rounded-circle" t-on-click="next" title="Next (Right-Arrow)" aria-label="Next" role="button">
|
||||
<span class="oi oi-chevron-right" role="img"/>
|
||||
</div>
|
||||
</t>
|
||||
+1
-1
@@ -7,7 +7,7 @@ import { AttachmentViewer } from "./attachment_viewer";
|
||||
let id = 1;
|
||||
|
||||
export function useAttachmentViewer() {
|
||||
const attachmentViewerId = `mail.attachment_viewer${id++}`;
|
||||
const attachmentViewerId = `web.attachment_viewer${id++}`;
|
||||
/**
|
||||
* @param {import("@mail/attachments/attachment_model").Attachment} attachment
|
||||
* @param {import("@mail/attachments/attachment_model").Attachment[]} attachments
|
||||
Reference in New Issue
Block a user