chore: import enterprise addons 19.0 bulk snapshot

This commit is contained in:
1b-agent committed 2026-09-16 10:13:08 +00:00
commit ca4af030d3
39951 files changed
+15570005

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1 @@
<svg width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><path d="M25.01 4.318c-8.636 0-11.161.009-11.652.05-1.772.147-2.875.426-4.077 1.024a8.257 8.257 0 0 0-2.376 1.74c-1.313 1.362-2.108 3.039-2.396 5.031-.14.967-.181 1.165-.19 6.105-.002 1.647 0 3.814 0 6.721 0 8.63.01 11.152.052 11.642.143 1.725.413 2.81.986 3.997 1.095 2.271 3.185 3.977 5.648 4.613.852.22 1.794.34 3.003.398.512.022 5.734.038 10.958.038s10.449-.006 10.948-.032c1.4-.066 2.213-.175 3.112-.407a8.66 8.66 0 0 0 5.648-4.623c.561-1.158.846-2.285.975-3.919.028-.356.04-6.038.04-11.712 0-5.675-.013-11.346-.041-11.702-.13-1.661-.415-2.778-.995-3.958a8.2 8.2 0 0 0-1.77-2.426c-1.37-1.307-3.043-2.103-5.037-2.39-.966-.14-1.159-.181-6.103-.19H25.01Z" fill="url(#o_icon_social_instagram__a)"/><path d="M25.01 4.318c-8.636 0-11.161.009-11.652.05-1.772.147-2.875.426-4.077 1.024a8.257 8.257 0 0 0-2.376 1.74c-1.313 1.362-2.108 3.039-2.396 5.031-.14.967-.181 1.165-.19 6.105-.002 1.647 0 3.814 0 6.721 0 8.63.01 11.152.052 11.642.143 1.725.413 2.81.986 3.997 1.095 2.271 3.185 3.977 5.648 4.613.852.22 1.794.34 3.003.398.512.022 5.734.038 10.958.038s10.449-.006 10.948-.032c1.4-.066 2.213-.175 3.112-.407a8.66 8.66 0 0 0 5.648-4.623c.561-1.158.846-2.285.975-3.919.028-.356.04-6.038.04-11.712 0-5.675-.013-11.346-.041-11.702-.13-1.661-.415-2.778-.995-3.958a8.2 8.2 0 0 0-1.77-2.426c-1.37-1.307-3.043-2.103-5.037-2.39-.966-.14-1.159-.181-6.103-.19H25.01Z" fill="url(#o_icon_social_instagram__b)"/><path d="M25 9.727c-4.147 0-4.668.018-6.297.092-1.625.075-2.735.332-3.706.71a7.479 7.479 0 0 0-2.706 1.76 7.499 7.499 0 0 0-1.763 2.706c-.378.971-.636 2.082-.709 3.707-.073 1.629-.092 2.15-.092 6.297 0 4.148.019 4.667.092 6.296.075 1.626.332 2.736.71 3.707a7.483 7.483 0 0 0 1.761 2.705 7.48 7.48 0 0 0 2.705 1.763c.971.377 2.082.635 3.707.71 1.63.073 2.15.092 6.297.092 4.148 0 4.667-.019 6.296-.093 1.625-.074 2.737-.332 3.708-.71a7.473 7.473 0 0 0 2.704-1.762 7.498 7.498 0 0 0 1.762-2.705c.376-.971.634-2.082.71-3.707.073-1.629.092-2.148.092-6.296 0-4.147-.019-4.668-.092-6.297-.076-1.626-.334-2.736-.71-3.707a7.497 7.497 0 0 0-1.762-2.705 7.464 7.464 0 0 0-2.705-1.761c-.973-.378-2.084-.635-3.71-.71-1.629-.074-2.147-.092-6.296-.092H25Zm-1.37 2.752H25c4.078 0 4.562.015 6.172.088 1.489.068 2.297.317 2.835.526a4.727 4.727 0 0 1 1.755 1.142 4.739 4.739 0 0 1 1.143 1.757c.21.537.459 1.345.526 2.834.073 1.61.09 2.094.09 6.17 0 4.076-.017 4.56-.09 6.17-.068 1.488-.317 2.296-.526 2.834a4.721 4.721 0 0 1-1.143 1.755 4.723 4.723 0 0 1-1.755 1.142c-.537.21-1.346.458-2.835.526-1.61.073-2.094.09-6.171.09-4.078 0-4.562-.017-6.172-.09-1.489-.069-2.297-.318-2.836-.527a4.73 4.73 0 0 1-1.756-1.142A4.734 4.734 0 0 1 13.094 34c-.209-.538-.458-1.346-.526-2.835-.073-1.61-.088-2.094-.088-6.172 0-4.078.015-4.56.088-6.17.068-1.488.317-2.297.526-2.835a4.732 4.732 0 0 1 1.143-1.756 4.738 4.738 0 0 1 1.756-1.143c.539-.21 1.347-.458 2.836-.527 1.41-.063 1.955-.082 4.802-.086v.004Zm9.523 2.536a1.832 1.832 0 1 0 0 3.666 1.832 1.832 0 0 0 0-3.667v.001ZM25 17.156a7.843 7.843 0 1 0 0 15.687 7.843 7.843 0 0 0 0-15.687Zm0 2.753a5.09 5.09 0 1 1 0 10.18 5.09 5.09 0 0 1 0-10.18Z" fill="#fff"/><defs><radialGradient id="o_icon_social_instagram__a" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -40.9897 38.134 0 15.307 48.862)"><stop stop-color="#FD5"/><stop offset=".1" stop-color="#FD5"/><stop offset=".5" stop-color="#FF543E"/><stop offset="1" stop-color="#C837AB"/></radialGradient><radialGradient id="o_icon_social_instagram__b" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(3.59718 17.96623 -74.07602 14.83143 -2.61 7.297)"><stop stop-color="#3771C8"/><stop offset=".128" stop-color="#3771C8"/><stop offset="1" stop-color="#60F" stop-opacity="0"/></radialGradient></defs></svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" ?><svg style="enable-background:new 0 0 64 64;" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css">
.st0{fill:#4267B2;}
.st1{fill:url(#SVGID_1_);}
.st2{fill:#FFFFFF;}
.st3{fill:#C2191E;}
.st4{fill:#1DA1F3;}
.st5{fill:#FEFE00;}
.st6{fill:#25D366;stroke:#FFFFFF;stroke-width:5;stroke-miterlimit:10;}
.st7{fill:#CB2027;}
.st8{fill:#0077B5;}
.st9{fill:url(#SVGID_2_);}
.st10{fill:url(#SVGID_3_);}
.st11{fill:#FF004F;}
.st12{fill:#00F7EF;}
.st13{fill:#5181B8;}
.st14{fill:#395976;}
.st15{fill:#F58220;}
.st16{fill:#E6162D;}
.st17{fill:#FF9933;}
</style><g id="guidlines"/><g id="ig"><radialGradient cx="6.5" cy="62.5" fx="3.1684" fy="60.7807" gradientTransform="matrix(0.9116 -0.411 0.3329 0.7384 -20.233 19.0203)" gradientUnits="userSpaceOnUse" id="SVGID_1_" r="93.512"><stop offset="0" style="stop-color:#F9ED32"/><stop offset="0.2555" style="stop-color:#F59F4F"/><stop offset="0.6535" style="stop-color:#EE2A7B"/><stop offset="0.6848" style="stop-color:#E32A81"/><stop offset="0.7394" style="stop-color:#C72A91"/><stop offset="0.8107" style="stop-color:#982AAB"/><stop offset="0.896" style="stop-color:#582ACE"/><stop offset="0.9922" style="stop-color:#072AFB"/><stop offset="1" style="stop-color:#002AFF"/></radialGradient><path class="st1" d="M50,62H14C7.4,62,2,56.6,2,50V14C2,7.4,7.4,2,14,2h36c6.6,0,12,5.4,12,12v36C62,56.6,56.6,62,50,62z"/><g><path class="st2" d="M40,53H24c-7.2,0-13-5.8-13-13V24c0-7.2,5.8-13,13-13h16c7.2,0,13,5.8,13,13v16C53,47.2,47.2,53,40,53z M24,13c-6.1,0-11,4.9-11,11v16c0,6.1,4.9,11,11,11h16c6.1,0,11-4.9,11-11V24c0-6.1-4.9-11-11-11H24z"/></g><g><path class="st2" d="M32,43c-6.1,0-11-4.9-11-11s4.9-11,11-11s11,4.9,11,11S38.1,43,32,43z M32,23c-5,0-9,4-9,9s4,9,9,9s9-4,9-9 S37,23,32,23z"/></g><g><path class="st2" d="M44,23c-1.7,0-3-1.3-3-3s1.3-3,3-3s3,1.3,3,3S45.7,23,44,23z M44,19c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1 S44.6,19,44,19z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

@@ -0,0 +1,46 @@
import { markup } from "@odoo/owl";
import {
SocialPostFormatterMixinBase,
SocialPostFormatterRegex,
} from "@social/js/social_post_formatter_mixin";
import { htmlReplace } from "@web/core/utils/html";
import { patch } from "@web/core/utils/patch";
/*
* Add Instagram #hashtag and @mention support.
* Replace all occurrences of `#hashtag` and `@mention` by a HTML link to a
* search of the hashtag/mention on the media website
*/
patch(SocialPostFormatterMixinBase, {
_formatPost(value) {
value = super._formatPost(...arguments);
if (this._getMediaType() === "instagram") {
value = htmlReplace(
value,
SocialPostFormatterRegex.REGEX_HASHTAG,
(_, before, hashtag) => {
/**
* markup: value is a Markup object (either escaped inside htmlReplace or
* flagged safe), `before` and `hashtag` are directly coming from this value,
* and the regex doesn't do anything crazy to unescape them.
*/
before = markup(before);
hashtag = markup(hashtag);
return markup`${before}<a href='https://www.instagram.com/explore/tags/${hashtag}' target='_blank'>#${hashtag}</a>`;
}
);
value = htmlReplace(value, SocialPostFormatterRegex.REGEX_AT, (_, name) => {
/**
* markup: value is a Markup object (either escaped inside htmlReplace or flagged
* safe), `name` is directly coming from this value, and the regex doesn't do
* anything crazy to unescape it.
*/
name = markup(name);
return markup`<a href='https://www.instagram.com/${name}' target='_blank'>@${name}</a>`;
});
}
return value;
},
});
@@ -0,0 +1,50 @@
import { StreamPostComment } from '@social/js/stream_post_comment';
import { StreamPostCommentsReplyInstagram } from './stream_post_comments_reply';
export class StreamPostCommentInstagram extends StreamPostComment {
//--------
// Getters
//--------
get authorPictureSrc() {
return `https://graph.facebook.com/v17.0/${encodeURIComponent(this.originalPost.instagram_facebook_author_id.raw_value)}/picture`;
}
get link() {
return `https://www.instagram.com/${encodeURIComponent(this.comment.from.name)}`;
}
get authorLink() {
return this.originalPost.post_link.raw_value;
}
get isAuthor() {
return this.comment.from.id === this.props.mediaSpecificProps.instagramAccountId;
}
get commentReplyComponent() {
return StreamPostCommentsReplyInstagram;
}
get deleteCommentEndpoint() {
return '/social_instagram/delete_comment';
}
get likesClass() {
return 'fa-heart';
}
get isLikable() {
return false;
}
get isDeletable() {
return true;
}
get isEditable() {
return false;
}
}
@@ -0,0 +1,10 @@
import { StreamPostCommentList } from '@social/js/stream_post_comment_list';
import { StreamPostCommentInstagram } from './stream_post_comment';
export class StreamPostCommentListInstagram extends StreamPostCommentList {
get commentComponent() {
return StreamPostCommentInstagram;
}
}
@@ -0,0 +1,52 @@
import { rpc } from "@web/core/network/rpc";
import { StreamPostComments } from '@social/js/stream_post_comments';
import { StreamPostCommentListInstagram } from './stream_post_comment_list';
import { StreamPostCommentsReplyInstagram } from './stream_post_comments_reply';
import { onWillStart } from "@odoo/owl";
export class StreamPostCommentsInstagram extends StreamPostComments {
setup() {
super.setup();
this.commentsCount = this.props.commentsCount;
this.totalLoadedComments = this.props.comments.length;
this.state.showLoadMoreComments = !!this.props.nextRecordsToken;
this.nextRecordsToken = this.props.nextRecordsToken;
onWillStart(async () => {
const instagramInfo = await this.orm.read(
'social.account', [this.props.accountId], ['name', 'instagram_account_id']);
this.mediaSpecificProps = Object.assign(this.mediaSpecificProps, {
accountId: this.props.accountId,
accountName: instagramInfo[0].name,
instagramAccountId: instagramInfo[0].instagram_account_id,
});
});
}
async loadMoreComments() {
const nextComments = await rpc('/social_instagram/get_comments', {
stream_post_id: this.originalPost.id.raw_value,
next_records_token: this.nextRecordsToken,
comments_count: this.commentsCount
});
this.state.showLoadMoreComments = !!nextComments.nextRecordsToken;
this.comments.push(...nextComments.comments);
this.nextRecordsToken = nextComments.nextRecordsToken;
}
get commentListComponent() {
return StreamPostCommentListInstagram;
}
get commentReplyComponent() {
return StreamPostCommentsReplyInstagram;
}
get commentsDisabled() {
return this.props.commentsDisabled;
}
}
@@ -0,0 +1,17 @@
import { StreamPostCommentsReply } from '@social/js/stream_post_comments_reply';
export class StreamPostCommentsReplyInstagram extends StreamPostCommentsReply {
get authorPictureSrc() {
return '/social_instagram/static/src/img/instagram_user.png';
}
get canAddImage() {
return false;
}
get addCommentEndpoint() {
return '/social_instagram/comment';
}
}
@@ -0,0 +1,16 @@
import { StreamPostDashboard } from '@social/js/stream_post_kanban_dashboard';
import { patch } from "@web/core/utils/patch";
patch(StreamPostDashboard.prototype, {
/**
* Instagram doesn't provide any information on stories.
*
* @override
*/
_hasStories(account) {
return account.media_type !== 'instagram' && super._hasStories(...arguments);
},
});
@@ -0,0 +1,44 @@
import { rpc } from "@web/core/network/rpc";
import { _t } from "@web/core/l10n/translation";
import { StreamPostKanbanRecord } from '@social/js/stream_post_kanban_record';
import { StreamPostCommentsInstagram } from './stream_post_comments';
import { debounce } from "@web/core/utils/timing";
import { patch } from "@web/core/utils/patch";
import { useEffect } from "@odoo/owl";
patch(StreamPostKanbanRecord.prototype, {
setup() {
super.setup(...arguments);
useEffect((commentEl) => {
if (commentEl) {
const onInstagramCommentsClick = debounce(this._onInstagramCommentsClick.bind(this), 300, true);
commentEl.addEventListener('click', onInstagramCommentsClick);
return () => {
commentEl.removeEventListener('click', onInstagramCommentsClick);
};
}
}, () => [this.rootRef.el.querySelector('.o_social_instagram_comments')]);
},
_onInstagramCommentsClick(ev) {
ev.stopPropagation();
const postId = this.record.id.raw_value;
rpc('/social_instagram/get_comments', {
stream_post_id: postId,
comments_count: this.commentsCount,
}).then((result) => {
this.dialog.add(StreamPostCommentsInstagram, {
title: _t('Instagram Comments'),
commentCount: this.commentCount,
originalPost: this.record,
accountId: this.record.account_id.raw_value,
postId: postId,
comments: result.comments,
nextRecordsToken: result.nextRecordsToken,
commentsDisabled: this.record.instagram_comments_disabled.raw_value,
});
});
},
});
@@ -0,0 +1,32 @@
.o_social_subtle_btn_readonly {
color: lighten($o-main-text-color, 10%);
}
.o_social_instagram_preview {
.o_social_preview_author {
line-height: 2em;
}
.fa-instagram {
color: #E1306C;
}
.o_social_instagram_font_size {
font-size: 1rem;
&.small {
font-size: .8rem;
}
}
}
.o_social_comments_modal_instagram {
--social-instagram-color: #0094f6;
a:not(.btn-outline-secondary):not(.o_social_comment_published_date):not(.o_social_post_published_date):not(.dropdown-item) {
color: var(--social-instagram-color);
&:hover, &:focus {
color: var(--social-instagram-color);
text-decoration: underline;
}
}
}
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-inherit="social.StreamPostCommentsOriginalPost" t-inherit-mode="extension">
<xpath expr="//span[hasclass('o_social_original_post_author_image')]" position="inside">
<img t-if="originalPost.instagram_facebook_author_id.raw_value" t-attf-src="https://graph.facebook.com/v17.0/{{ originalPost.instagram_facebook_author_id.raw_value }}/picture" alt="Author Image" class="rounded"/>
</xpath>
<xpath expr="//div[hasclass('o_social_comments_modal_original_post_content')]" position="inside">
<div t-if="originalPost.media_type.raw_value === 'instagram'"
class="o_social_original_post_instagram_stats d-flex justify-content-around pt-2">
<div class="o_social_instagram_likes ps-2 pe-3"
t-att-data-post-id="originalPost.id.raw_value">
<t t-if="originalPost.instagram_likes_count.raw_value !== 0">
<i class="fa fa-heart me-1" title="Likes"/>
<b class="o_social_likes_count" t-esc="originalPost.instagram_likes_count.value"/>
</t>
</div>
<div class="flex-grow-1" />
</div>
</xpath>
</t>
</templates>