diff --git a/addons/website_forum/__manifest__.py b/addons/website_forum/__manifest__.py index 80019e925d1..25c5828edd0 100644 --- a/addons/website_forum/__manifest__.py +++ b/addons/website_forum/__manifest__.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. + { 'name': 'Forum', 'category': 'Website/Website', @@ -41,6 +42,7 @@ Ask questions, get answers, no distractions 'views/forum_forum_templates_moderation.xml', 'views/forum_forum_templates_post.xml', 'views/forum_forum_templates_tools.xml', + 'views/forum_templates_mail.xml', 'views/website_profile_templates.xml', 'views/snippets/snippets.xml', diff --git a/addons/website_forum/controllers/website_forum.py b/addons/website_forum/controllers/website_forum.py index 8a5ffe4086d..20c01b85043 100644 --- a/addons/website_forum/controllers/website_forum.py +++ b/addons/website_forum/controllers/website_forum.py @@ -501,6 +501,23 @@ class WebsiteForum(WebsiteProfile): return request.render("website_forum.moderation_queue", values) + @http.route('/forum//closed_posts', type='http', auth="user", website=True) + def closed_posts(self, forum, **kwargs): + if request.env.user.karma < forum.karma_moderate: + raise werkzeug.exceptions.NotFound() + + closed_posts_ids = request.env['forum.post'].search( + [('forum_id', '=', forum.id), ('state', '=', 'close')], + order='write_date DESC, id DESC', + ) + values = self._prepare_user_values(forum=forum) + values.update({ + 'posts_ids': closed_posts_ids, + 'queue_type': 'close', + }) + + return request.render("website_forum.moderation_queue", values) + @http.route('/forum//post//validate', type='http', auth="user", website=True) def post_accept(self, forum, post, **kwargs): url = "/forum/%s/validation_queue" % (slug(forum)) @@ -508,6 +525,8 @@ class WebsiteForum(WebsiteProfile): url = "/forum/%s/flagged_queue" % (slug(forum)) elif post.state == 'offensive': url = "/forum/%s/offensive_posts" % (slug(forum)) + elif post.state == 'close': + url = "/forum/%s/closed_posts" % (slug(forum)) post.validate() return request.redirect(url) diff --git a/addons/website_forum/data/forum_forum_data.xml b/addons/website_forum/data/forum_forum_data.xml index 00866b0f7d7..9bdc46a9a11 100644 --- a/addons/website_forum/data/forum_forum_data.xml +++ b/addons/website_forum/data/forum_forum_data.xml @@ -3,6 +3,7 @@ Help + This community is for professionals and enthusiasts of our products and services. Share and discuss the best content and new marketing ideas, build your professional profile and become a better marketer together. diff --git a/addons/website_forum/data/forum_forum_template_faq.xml b/addons/website_forum/data/forum_forum_template_faq.xml index d6b936d4f56..77a3fbdca8b 100644 --- a/addons/website_forum/data/forum_forum_template_faq.xml +++ b/addons/website_forum/data/forum_forum_template_faq.xml @@ -5,15 +5,19 @@ qweb website_forum.faq_accordion -
+ + Guidelines +
-
-
- -
-
+
+
+

+ +

+
+

This community is for professional and enthusiast users, partners and programmers. You can ask questions about:

  • how to install Odoo on a specific infrastructure,
  • @@ -27,12 +31,14 @@
-
- -
-
+
+

+ +

+
+

You should only ask practical, answerable questions based on actual problems that you face. Chatty, open-ended questions diminish the usefulness of this site and push other questions off the front page.

To prevent your question from being flagged and possibly removed, avoid asking subjective questions where …

    @@ -54,28 +60,32 @@
-
- -
-
+
+

+ +

+
+

Answers should not add or expand questions. Instead, either edit the question or add a comment.

Answers should not comment other answers. Instead add a comment on the other answers.

Answers shouldn't just point to other questions.Instead add a comment indicating "Possible duplicate of...". However, it's fine to include links to other questions or answers providing relevant additional information.

-

Answers shouldn't just provide a link a solution. Instead provide the solution description text in your answer, even if it's just a copy/paste. Links are welcome, but should be complementary to answer, referring sources or additional reading.

+

Answers shouldn't just provide a link a solution. Instead provide the solution description text in your answer, even if it's just a copy/paste. Links are welcome, but should be complementary to answer, referring sources or additional reading.

Answers should not start debates This community Q&A is not a discussion group. Please avoid holding debates in your answers as they tend to dilute the essence of questions and answers. For brief discussions please use commenting facility.

When a question or answer is upvoted, the user who posted them will gain some points, which are called "karma points". These points serve as a rough measure of the community trust to him/her. Various moderation tasks are gradually assigned to the users based on those points.

For example, if you ask an interesting question or give a helpful answer, your input will be upvoted. On the other hand if the answer is misleading - it will be downvoted. Each vote in favor will generate 10 points, each vote against will subtract 2 points. There is a limit of 200 points that can be accumulated for a question or answer per day. The table given at the end explains reputation point requirements for each type of moderation task.

-
- -
-
+
+

+ +

+
+

The goal of this site is create a relevant knowledge base that would answer questions related to Odoo.

Therefore questions and answers can be edited like wiki pages by experienced users of this site in order to improve the overall quality of the knowledge base content. Such privileges are granted based on user karma level: you will be able to do the same once your karma gets high enough.

If this approach is not for you, please respect the community.

@@ -89,4 +99,4 @@ - \ No newline at end of file + diff --git a/addons/website_forum/models/forum_forum.py b/addons/website_forum/models/forum_forum.py index 0f1fe1a1a51..f1306d2d8ba 100644 --- a/addons/website_forum/models/forum_forum.py +++ b/addons/website_forum/models/forum_forum.py @@ -3,6 +3,8 @@ import textwrap +from markupsafe import Markup + from odoo import _, api, fields, models from odoo.tools.translate import html_translate from odoo.addons.http_routing.models.ir_http import slug @@ -21,25 +23,26 @@ class Forum(models.Model): _order = "sequence" def _get_default_welcome_message(self): - return """ -
-
-
-
-

Welcome!

-

%(message_intro)s
%(message_post)s

-
- -
-
-
""" % { - 'message_intro': _("This community is for professionals and enthusiasts of our products and services."), - 'message_post': _("Share and discuss the best content and new marketing ideas, build your professional profile and become a better marketer together."), - 'hide_text': _('Hide Intro'), - 'register_text': _('Register')} + return Markup(""" +

%(message_intro)s

+
+

%(message_post)s

+

+ %(register_text)s + +

+
+ """) % { + 'message_intro': _("Welcome!"), + 'message_post': _( + "Share and discuss the best content and new marketing ideas, build your professional profile and become" + " a better marketer together." + ), + 'hide_text': _('Dismiss'), + 'register_text': _('Sign up'), + } # description and use name = fields.Char('Forum Name', required=True, translate=True) @@ -131,6 +134,7 @@ class Forum(models.Model): karma_post = fields.Integer(string='Ask questions without validation', default=100) karma_moderate = fields.Integer(string='Moderate posts', default=1000) has_pending_post = fields.Boolean(string='Has pending post', compute='_compute_has_pending_post') + can_moderate = fields.Boolean(string="Is a moderator", compute="_compute_can_moderate") @api.depends_context('uid') def _compute_has_pending_post(self): @@ -146,6 +150,12 @@ class Forum(models.Model): pending_forums.has_pending_post = True (self - pending_forums).has_pending_post = False + @api.depends_context('uid') + @api.depends('karma_moderate') + def _compute_can_moderate(self): + for forum in self: + forum.can_moderate = self.env.user.karma >= forum.karma_moderate + @api.depends('description') def _compute_teaser(self): for forum in self: diff --git a/addons/website_forum/static/src/img/empty.svg b/addons/website_forum/static/src/img/empty.svg new file mode 100644 index 00000000000..6e371b2ff02 --- /dev/null +++ b/addons/website_forum/static/src/img/empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/website_forum/static/src/img/help.jpg b/addons/website_forum/static/src/img/help.jpg new file mode 100644 index 00000000000..8827620cb2e Binary files /dev/null and b/addons/website_forum/static/src/img/help.jpg differ diff --git a/addons/website_forum/static/src/img/tasks.svg b/addons/website_forum/static/src/img/tasks.svg new file mode 100644 index 00000000000..4f5d810c102 --- /dev/null +++ b/addons/website_forum/static/src/img/tasks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/website_forum/static/src/js/tours/website_forum.js b/addons/website_forum/static/src/js/tours/website_forum.js index 3c1a396de3d..d09371d0690 100644 --- a/addons/website_forum/static/src/js/tours/website_forum.js +++ b/addons/website_forum/static/src/js/tours/website_forum.js @@ -9,7 +9,7 @@ wTourUtils.registerBackendAndFrontendTour("question", { url: '/forum/1', }, [{ - trigger: ".o_forum_ask_btn", + trigger: ".o_wforum_ask_btn", position: "left", content: _t("Create a new post in this forum by clicking on the button."), }, { diff --git a/addons/website_forum/static/src/js/website_forum.js b/addons/website_forum/static/src/js/website_forum.js index 6153f1c6d8b..e78f3f0f86c 100644 --- a/addons/website_forum/static/src/js/website_forum.js +++ b/addons/website_forum/static/src/js/website_forum.js @@ -26,11 +26,12 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ 'click .o_wforum_flag_validator': '_onFlagValidatorClick', 'click .o_wforum_flag_mark_as_offensive': '_onFlagMarkAsOffensiveClick', 'click .vote_up:not(.karma_required), .vote_down:not(.karma_required)': '_onVotePostClick', - 'click .o_js_validation_queue a[href*="/validate"]': '_onValidationQueueClick', + 'click .o_wforum_validation_queue a[href*="/validate"]': '_onValidationQueueClick', 'click .o_wforum_validate_toggler:not(.karma_required)': '_onAcceptAnswerClick', 'click .o_wforum_favourite_toggle': '_onFavoriteQuestionClick', 'click .comment_delete': '_onDeleteCommentClick', 'click .js_close_intro': '_onCloseIntroClick', + 'click .answer_collapse': '_onExpandAnswerClick', 'submit .js_wforum_submit_form:has(:not(.karma_required).o_wforum_submit_post)': '_onSubmitForm', }, @@ -225,6 +226,21 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ }, 0); } }, + /** + * @private + * @param {Event} ev + */ + _onExpandAnswerClick: function (ev) { + const expandableWindow = ev.currentTarget; + if (ev.target.matches('.o_wforum_expand_toggle')) { + expandableWindow.classList.toggle('o_expand') + expandableWindow.classList.toggle('min-vh-100'); + expandableWindow.classList.toggle('w-lg-50'); + } else if (ev.target.matches('.o_wforum_discard_btn')){ + expandableWindow.classList.remove('o_expand', 'min-vh-100'); + expandableWindow.classList.add('w-lg-50'); + } + }, /** * @private * @param {Event} ev @@ -243,7 +259,8 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ }; if (session.is_website_user) { notifOptions.title = _t("Access Denied"); - notifOptions.message = _t("Sorry you must be logged in to perform this action"); + notifOptions.message = Markup` +

Oh no! Please sign in to vote

`; } else { notifOptions.title = _t("Karma Error"); // FIXME this translation is bad, the number should be part of the @@ -327,6 +344,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ elem.prepend(child); if (countFlaggedPosts) { countFlaggedPosts.classList.remove('bg-light'); + countFlaggedPosts.classList.remove('d-none'); countFlaggedPosts.classList.add('bg-danger'); countFlaggedPosts.innerText = parseInt(countFlaggedPosts.innerText, 10) + 1; } @@ -356,7 +374,8 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ if (data.error === 'own_post') { message = _t('Sorry, you cannot vote for your own posts'); } else if (data.error === 'anonymous_user') { - message = _t('Sorry you must be logged to vote'); + message = Markup` +

Oh no! Please sign in to vote

`; } this.displayNotification({ message: message, @@ -401,62 +420,96 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ }); }, /** + * Call the route to moderate/validate the post, then hide the validated post + * and decrement the count in the appropriate queue badge of the sidebar on success. + * * @private * @param {Event} ev */ - _onValidationQueueClick: function (ev) { + _onValidationQueueClick: async function (ev) { ev.preventDefault(); - var $link = $(ev.currentTarget); - $link.parents('.post_to_validate').hide(); - $.get($link.attr('href')).then(() => { - var left = $('.o_js_validation_queue:visible').length; - var type = $('h2.o_page_header a.active').data('type'); - $('#count_post').text(left); - $('#moderation_tools a[href*="/' + type + '_"]').find('strong').text(left); - if (!left) { - this.$('.o_caught_up_alert').removeClass('d-none'); - } - }, function () { - $link.parents('.o_js_validation_queue > div').addClass('bg-danger text-white').css('background-color', '#FAA'); - $link.parents('.post_to_validate').show(); - }); + const approvalLink = ev.currentTarget; + const postBeingValidated = this._findParent(approvalLink, '.post_to_validate'); + if (!postBeingValidated) { + return; + } + postBeingValidated.classList.add('d-none'); + let ok; + try { + ok = (await fetch(approvalLink.href)).ok; + } catch { + // Calling the endpoint like this returns an HTML page. As we can't + // extract the error message from that, we disregard it and simply + // restore the post's visibility. This __should__ be improved. + } + if (!ok) { + postBeingValidated.classList.remove('d-none'); + return; + } + const nbLeftInQueue = Array.from(document.querySelectorAll('.post_to_validate')) + .filter(e => window.getComputedStyle(e).display !== 'none') + .length; + const queueType = document.querySelector('#queue_type').dataset.queueType; + const queueCountBadge = document.querySelector(`#count_posts_queue_${queueType}`); + queueCountBadge.innerText = nbLeftInQueue; + if (!nbLeftInQueue) { + document.querySelector('.o_caught_up_alert').classList.remove('d-none'); + queueCountBadge.classList.add('d-none'); + } + }, + _findParent: function (el, selector) { + while (el.parentElement && !el.matches(selector)) { + el = el.parentElement; + } + return el.matches(selector) ? el : null; }, /** * @private * @param {Event} ev */ - _onAcceptAnswerClick: function (ev) { + _onAcceptAnswerClick: async function (ev) { ev.preventDefault(); - var $link = $(ev.currentTarget); - var target = $link.data('target'); + const $link = $(ev.currentTarget); + const target = $link.data('target'); - this._rpc({ - route: $link.data('href'), - }).then(data => { - if (data.error) { - if (data.error === 'anonymous_user') { - var message = _t("Sorry, anonymous users cannot choose correct answer."); - } - this.displayNotification({ - message: message, - title: _t("Access Denied"), - sticky: false, - type: "warning", - }); - } else { - this.$('.forum_answer').toArray().forEach((answer) => { - var $answer = $(answer); - var isCorrect = $answer.is(target) ? data : false; - var $toggler = $answer.find('.o_wforum_validate_toggler'); - var newHelper = isCorrect ? $toggler.data('helper-decline') : $toggler.data('helper-accept'); - - $answer.toggleClass('o_wforum_answer_correct', isCorrect); - $toggler.tooltip('dispose') - .attr('data-bs-original-title', newHelper) - .tooltip({delay: 0}); - }); + const data = await this._rpc({route: $link.data('href')}); + if (data.error) { + let message; + if (data.error === 'anonymous_user') { + message = _t('Sorry, anonymous users cannot choose correct answer.'); + } else if (data.error === 'own_post') { + message = _t('Sorry, you cannot vote for your own posts'); } - }); + this.displayNotification({ + message: message || data.error, + title: _t('Access Denied'), + sticky: false, + type: 'warning', + }); + } else { + this.$('.o_wforum_answer').toArray().forEach((answer) => { + const $answer = $(answer); + const isCorrect = $answer.is(target) ? data : false; + const $toggler = $answer.find('.o_wforum_validate_toggler'); + const $togglerIcon = $toggler.find('.fa'); + const $correctBadge = $answer.find('.o_wforum_answer_correct_badge'); + const newHelper = isCorrect ? $toggler.data('helper-decline') : $toggler.data('helper-accept'); + $answer.toggleClass( + "o_wforum_answer_correct my-2 mx-n3 mx-lg-n2 mx-xl-n3 py-3 px-3 px-lg-2 px-xl-3", + isCorrect + ); + $answer.find('div .border-start') + .toggleClass('border-success', isCorrect); + $toggler.tooltip('dispose') + .attr('data-bs-original-title', newHelper) + .tooltip({delay: 0}) + .toggleClass('opacity-50', !isCorrect); + $togglerIcon + .toggleClass('fa-check-circle text-success', isCorrect) + .toggleClass('fa-check-circle-o', !isCorrect); + $correctBadge.toggleClass('d-inline', isCorrect).toggleClass('d-none', !isCorrect); + }); + } }, /** * @private @@ -465,11 +518,13 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ _onFavoriteQuestionClick: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); + var $link_icon = $link.find('.fa'); this._rpc({ route: $link.data('href'), }).then(function (data) { - $link.toggleClass('o_wforum_gold fa-star', data) - .toggleClass('fa-star-o text-muted', !data); + $link.toggleClass('opacity-50 opacity-100-hover', !data); + $link_icon.toggleClass('o_wforum_gold fa-star', data) + .toggleClass('fa-star-o', !data); }); }, /** @@ -516,16 +571,16 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ method: currentTarget.dataset.action, args: [parseInt(currentTarget.dataset.postId)], }); - currentTarget.parentElement.querySelectorAll('.flag_validator').forEach((element) => element.classList.toggle('d-none')); + this._findParent(currentTarget, '.o_wforum_flag_alert')?.classList.toggle('d-none'); const flaggedButton = currentTarget.parentElement.firstElementChild, child = flaggedButton.firstElementChild, - countFlaggedPosts = this.el.querySelector('#count_flagged_posts'), + countFlaggedPosts = this.el.querySelector('#count_posts_queue_flagged'), count = parseInt(countFlaggedPosts.innerText, 10) - 1; flaggedButton.innerText = _t(' Flag'); flaggedButton.prepend(child); if (count === 0) { - countFlaggedPosts.classList.add("bg-light"); + countFlaggedPosts.classList.add('bg-light'); } countFlaggedPosts.innerText = count; }, @@ -545,7 +600,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ renderFooter: false, }).open(); dialog.opened().then(() => { - dialog.$(".btn-light:contains('Discard')").click((ev) => { + dialog.$(".btn-link:contains('Discard')").click((ev) => { ev.preventDefault(); dialog.close(); }); diff --git a/addons/website_forum/static/src/scss/website_forum.scss b/addons/website_forum/static/src/scss/website_forum.scss index 5b9639e17b8..124de84a628 100644 --- a/addons/website_forum/static/src/scss/website_forum.scss +++ b/addons/website_forum/static/src/scss/website_forum.scss @@ -1,42 +1,103 @@ $gold: #eca801; -$silver: #cccccc; -$bronze: #eea91e; +$silver: #acacac; +$bronze: #ba651f; +$-forum-sidebar-width: map-get($container-max-widths, sm) / 2; +.website_forum, .o_wprofile_body { + --o-avatar-height: 1.875rem; + + .o_wforum_avatar { + width: var(--o-avatar-height); + height: var(--o-avatar-height); + } + + .o_wforum_author_box { + &.o_show_info { + line-height: 1.2; + } + + &.o_compact { + --o-avatar-height: 1.4rem; + line-height: 1; + } + } +} .website_forum { - .o_forum_ask_btn { - @include media-breakpoint-up(md) { - box-shadow: $box-shadow; - width: 200px; + --o-post-header-height: var(--o-avatar-height); + + .o_wforum_wrapper { + @include media-breakpoint-up(xl) { + grid-template-columns: $-forum-sidebar-width minmax(0, auto); + } + + @include media-breakpoint-up(xxl) { + max-width: 100%; } } - .o_wforum_nav .nav-link { - @include o-hover-text-color($body-color, $link-color); - line-height: 1; + .o_wforum_content_wrapper { + @include media-breakpoint-up(xxl) { + margin-left: -$-forum-sidebar-width; - .fa { - opacity: 0.5; - } - - &:hover, &.active { - .fa { - opacity: 1; + > div { + max-width: map-get($grid-breakpoints, xl) - $-forum-sidebar-width - 100px; + @include make-container(); } } + } - &.active { - background-color: rgba(map-get($theme-colors, 'info'), 0.1); - color: darken(map-get($theme-colors, 'info'), 15%)!important; + aside.o_wforum_sidebar { + min-width: $-forum-sidebar-width; + + .btn.w-100:hover { + background-color: darken(map-get($o-color-palette, 'o-color-3'), 4%); + } + } + + .o_wforum_table { + --o-avatar-height: 2.25rem; + + img.o_wforum_avatar { + border: 2px solid var(--o-color-4); } - img.o_forum_avatar { - width: 30px; - height: 30px; + .o_wforum_reply_count, .o_wforum_view_count, .o_wforum_last_activity { + width: 100px; } + + &> :not(caption) > * > * { + @include media-breakpoint-down(lg) { + padding-left: 0; + padding-right: $table-cell-padding-x-sm; + } + + } + + tbody { + @include media-breakpoint-down(lg) { + border-top: 0; + } + + tr:hover { + @if ($body-bg and color-contrast($body-bg) != $color-contrast-dark) { + background-color: lighten($body-bg, 10%); + } @else { + background-color: darken($body-bg, 2%); + } + } + } + } + + .o_wforum_index_entry_title a:visited span { + color: lighten($body-color, 50%); + } + + .btn[aria-expanded="true"] { + opacity: 1 !important; } // Single Post - .o_wforum_post, .note-editable.panel-body { + .o_wforum_post, .note-editable { word-wrap: break-word; pre { @@ -49,22 +110,61 @@ $bronze: #eea91e; blockquote { position: relative; - padding-left: 1em; border-left: .25em solid map-get($grays, '500'); + padding-left: 1em; color: map-get($grays, '600'); } + } - #post_reply { - img.o_forum_avatar { - width: 24px; - height: 24px; + #post_reply { + z-index: $zindex-modal; + min-height: 0; + max-height: 0; + border-radius: $border-radius $border-radius 0 0; + transition: max-#{$transition-collapse}, min-#{$transition-collapse}, #{$transition-collapse}, #{$transition-collapse-width}; + + &.show { + max-height: 100%; + + &.o_expand { + .o_wforum_expand_toggle { + content:'\f066'; + } + + .odoo-editor-editable { + transition: $transition-collapse; + flex-grow: 1; + } + + form.js_website_submit_form { + height: calc(100vh - 100px); + } + } + + .o_wysiwyg_textarea_wrapper { + display: flex; + flex-flow: column; + flex-grow: 1; + + .odoo-editor { + height: 200px !important; + display: flex; + flex-grow: 1; + flex-flow: column; + + .note-editable { + flex-grow: 1; + } + } } } } - .o_wforum_readable { - max-width: 700px; + .o_wforum_post_header, .o_wforum_answer_header { + min-height: var(--o-post-header-height); + } + .o_wforum_readable { p { margin-bottom: 0.5rem; } @@ -99,61 +199,25 @@ $bronze: #eea91e; } } - .o_wforum_author_box { - &.o_show_info { - line-height: 1.2; - img { - width: 2em; - height: 2em; - } - } - - &.o_compact { - line-height: 1; - - img { - width: 1.4em; - height: 1.4em; - } - } - - } - - .forum_answer { - .o_wforum_answer_correct_badge { - display: none; - } - - .o_wforum_author_box_check { - width: 1em; - height: 1em; - display: none; - top: 0; - right: -3px; - box-shadow: 0 0 0 2px white; - line-height: .8; - } - - .o_wforum_validate_toggler { - @include o-hover-text-color(map-get($grays, '400'), lighten(map-get($theme-colors, 'success'), 20%)); - } + .o_wforum_answer { + transition: $transition-base; &.o_wforum_answer_correct { - .o_wforum_answer_correct_badge, .o_wforum_author_box .o_wforum_author_box_check { - display: inline; + // This hack is to have either a light or dark success color + // depending on the background color's contrast + $-cc1-bg: o-color(map-get($o-color-palette, o-cc1-bg)); + $-isBright: color-contrast($-cc1-bg) == $color-contrast-dark; + + @if ($-isBright) { + background-color: mix($color-contrast-light, $success, 90%); + } @else { + $-success-light: lighten(saturate($success, 70), 30); + border: 1px solid $-success-light; + background-color: mix($color-contrast-dark, $-success-light, 80%); } - .o_wforum_validate_toggler { - @include o-hover-text-color(map-get($theme-colors, 'success'), map-get($theme-colors, 'warning')); - - &:hover .fa.fa-check:before { - content: '\f00d'; - } - } - - .o_wforum_answer_header .o_wforum_author_pic { - border: 2px solid $success; - padding: 3px; + .o_wforum_author_pic img { + box-shadow: 0 0 0 2px $success; } } } @@ -177,7 +241,6 @@ $bronze: #eea91e; .website_forum, .o_wforum_profile_tab { .vote { .vote_count { - line-height: 1; animation-play-state: paused; &.o_forum_vote_animate { @@ -185,62 +248,13 @@ $bronze: #eea91e; } } - .vote_down, .vote_up { - line-height: 0.5; - font-size: 1.1em; - @include o-hover-text-color(rgba($text-muted, 0.5), map-get($theme-colors, 'success')); + .vote_up { + @include o-hover-text-color(inherit, $success); } .vote_down { - @include o-hover-text-color(rgba($text-muted, 0.5), map-get($theme-colors, 'danger')); + @include o-hover-text-color(inherit, $danger); } - - &.o_wforum_vote_vertical { - @include media-breakpoint-up(sm) { - font-size: 1.2em; - } - } - } -} - -.o_js_forum_tag_follow { - position: relative; - - .badge { - font-size: 100%; - } - - .o_forum_tag_follow_box { - @include o-position-absolute(100%, auto, auto, 0); - display: none; - z-index: 1; - - .card { - padding: ($grid-gutter-width*0.5) - 1px; - } - } -} - -.o_profile_main { - overflow: hidden; -} - -img.o_forum_avatar { - width: 40px; - height: 40px; - object-fit: cover; -} - -img.o_forum_avatar_big { - width: 75px; - height: 75px; - object-fit: cover; -} - -.o_wprofile_email_validation_container { - img.o_forum_avatar { - width: 16px; - height: 16px; } } @@ -250,6 +264,7 @@ img.o_forum_avatar_big { display: flex; align-items: center; } + span[data-oe-model="res.country"] { margin-left: 10px; } @@ -258,31 +273,37 @@ img.o_forum_avatar_big { .o_wforum_bio_popover_info .css_editable_mode_hidden > div:last-child > .o_forum_tooltip_line { margin-top: -0.5rem; // compensate parent 'mt-2' class } - - .o_wforum_bio_popover_bio p { - margin-top: 8px; - margin-bottom: 0; - } -} - -.o_wforum_elearning_navtabs_container { - @include media-breakpoint-up(md) { - background-color: map-get($theme-colors, 'secondary'); - } -} - -.website_forum { - margin-bottom: $spacer; } .popover.o_wforum_bio_popover_container { + box-shadow: 0 2px 5px $gray-400; + + .popover-header { + background-color: tint-color($primary, 80%); + border-bottom: 0; + color: $primary; + } + max-width: 552px; -} -.o_wforum_forum_card_bg { - background-image: linear-gradient(99deg, map-get($theme-colors, 'secondary') 10%, darken(map-get($theme-colors, 'secondary'), 10%) 90%); + .o-text-gold { + color: $gold; + } - #o_wforum_forums_index_list & { - min-height: 100px; + .o-text-silver { + color: $silver; + } + + .o-text-bronze { + color: $bronze; + } +} + +#o_wforum_forums_index_list .card { + border-radius: .75rem; + + &:hover { + transform: translateY(-5px); + box-shadow: $box-shadow !important; } } diff --git a/addons/website_forum/static/src/xml/public_templates.xml b/addons/website_forum/static/src/xml/public_templates.xml index 95458e9a303..31843da2ffa 100644 --- a/addons/website_forum/static/src/xml/public_templates.xml +++ b/addons/website_forum/static/src/xml/public_templates.xml @@ -3,7 +3,7 @@