[IMP] website, *: use "auto" widget for font customization
* theme_bootswatch, theme_default, website_theme_install This commit makes use of the new 'auto' widget for font selection: instead of enabling a template which will enable a scss file which sets a font variable to a specific value... we directly allow to do a scss custo which sets that value. The code in charge of resetting font customizations on theme switching is also moved and refactored here in website (instead of being specific to each theme). Part of https://github.com/odoo/odoo/pull/33442 task-1974659 Co-authored-by: qsm-odoo <qsm@odoo.com>
This commit is contained in:
committed by
qsm-odoo
co-authored by
qsm-odoo
parent
15bae2920c
commit
7deceae18c
@@ -1,5 +1,6 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ThemeBootswatch(models.AbstractModel):
|
||||
_inherit = 'theme.utils'
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ThemeDefault(models.AbstractModel):
|
||||
_inherit = 'theme.utils'
|
||||
|
||||
|
||||
@@ -369,10 +369,6 @@ class Website(Home):
|
||||
@http.route(['/website/make_scss_custo'], type='json', auth='user', website=True)
|
||||
def make_scss_custo(self, url, values):
|
||||
"""
|
||||
Makes a scss customization of the given file. That file must
|
||||
contain a scss map including a line comment containing the word 'hook',
|
||||
to indicate the location where to write the new key,value pairs.
|
||||
|
||||
Params:
|
||||
url (str):
|
||||
the URL of the scss file to customize (supposed to be a variable
|
||||
@@ -382,24 +378,11 @@ class Website(Home):
|
||||
key,value mapping to integrate in the file's map (containing the
|
||||
word hook). If a key is already in the file's map, its value is
|
||||
overridden.
|
||||
|
||||
Returns:
|
||||
boolean
|
||||
"""
|
||||
AssetsUtils = request.env['web_editor.assets']
|
||||
|
||||
custom_url = AssetsUtils.make_custom_asset_file_url(url, 'web.assets_common')
|
||||
updatedFileContent = AssetsUtils.get_asset_content(custom_url) or AssetsUtils.get_asset_content(url)
|
||||
updatedFileContent = updatedFileContent.decode('utf-8')
|
||||
for name, value in values.items():
|
||||
pattern = "'%s': %%s,\n" % name
|
||||
regex = re.compile(pattern % ".+")
|
||||
replacement = pattern % value
|
||||
if regex.search(updatedFileContent):
|
||||
updatedFileContent = re.sub(regex, replacement, updatedFileContent)
|
||||
else:
|
||||
updatedFileContent = re.sub(r'( *)(.*hook.*)', r'\1%s\1\2' % replacement, updatedFileContent)
|
||||
|
||||
# Bundle is 'assets_common' as this route is only meant to update
|
||||
# variables scss files
|
||||
AssetsUtils.save_asset(url, 'web.assets_common', updatedFileContent, 'scss')
|
||||
request.env['web_editor.assets'].make_scss_customization(url, values)
|
||||
return True
|
||||
|
||||
@http.route(['/website/multi_render'], type='json', auth="public", website=True)
|
||||
|
||||
@@ -1,12 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import re
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class Assets(models.AbstractModel):
|
||||
_inherit = 'web_editor.assets'
|
||||
|
||||
def make_scss_customization(self, url, values):
|
||||
"""
|
||||
Makes a scss customization of the given file. That file must
|
||||
contain a scss map including a line comment containing the word 'hook',
|
||||
to indicate the location where to write the new key,value pairs.
|
||||
|
||||
Params:
|
||||
url (str):
|
||||
the URL of the scss file to customize (supposed to be a variable
|
||||
file which will appear in the assets_common bundle)
|
||||
|
||||
values (dict):
|
||||
key,value mapping to integrate in the file's map (containing the
|
||||
word hook). If a key is already in the file's map, its value is
|
||||
overridden.
|
||||
"""
|
||||
custom_url = self.make_custom_asset_file_url(url, 'web.assets_common')
|
||||
updatedFileContent = self.get_asset_content(custom_url) or self.get_asset_content(url)
|
||||
updatedFileContent = updatedFileContent.decode('utf-8')
|
||||
for name, value in values.items():
|
||||
pattern = "'%s': %%s,\n" % name
|
||||
regex = re.compile(pattern % ".+")
|
||||
replacement = pattern % value
|
||||
if regex.search(updatedFileContent):
|
||||
updatedFileContent = re.sub(regex, replacement, updatedFileContent)
|
||||
else:
|
||||
updatedFileContent = re.sub(r'( *)(.*hook.*)', r'\1%s\1\2' % replacement, updatedFileContent)
|
||||
|
||||
# Bundle is 'assets_common' as this route is only meant to update
|
||||
# variables scss files
|
||||
self.save_asset(url, 'web.assets_common', updatedFileContent, 'scss')
|
||||
|
||||
def _get_custom_attachment(self, custom_url, op='='):
|
||||
"""
|
||||
See web_editor.Assets._get_custom_attachment
|
||||
|
||||
@@ -25,9 +25,9 @@ $body-color: palette-color('text') !default;
|
||||
//
|
||||
// Font, line-height, and color for body text, headings, and more.
|
||||
|
||||
$font-family-sans-serif: nth($o-theme-fonts, $o-theme-font-number) !default;
|
||||
$font-family-sans-serif: $o-theme-font !default;
|
||||
|
||||
$headings-font-family: nth($o-theme-fonts, $o-theme-headings-font-number) !default;
|
||||
$headings-font-family: $o-theme-headings-font !default;
|
||||
$headings-color: palette-color('h1') !default;
|
||||
|
||||
// Jumbotron
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-font-number: 2;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-font-number: 3;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-font-number: 4;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-font-number: 5;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-font-number: 6;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-buttons-font-number: 2;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-buttons-font-number: 3;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-buttons-font-number: 4;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-buttons-font-number: 5;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-buttons-font-number: 6;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-navbar-font-number: 2;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-navbar-font-number: 3;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-navbar-font-number: 4;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-navbar-font-number: 5;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-navbar-font-number: 6;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-headings-font-number: 2;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-headings-font-number: 3;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-headings-font-number: 4;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-headings-font-number: 5;
|
||||
@@ -1 +0,0 @@
|
||||
$o-theme-headings-font-number: 6;
|
||||
@@ -51,6 +51,10 @@ $o-website-values-palettes: (
|
||||
(
|
||||
'logo-height': null, // Default to navbar height (see portal)
|
||||
'header-font-size': null, // Default to BS (normal font-size)
|
||||
'font-number': 1,
|
||||
'headings-font-number': 1,
|
||||
'navbar-font-number': 1,
|
||||
'buttons-font-number': 1,
|
||||
),
|
||||
) !default;
|
||||
$o-website-values-palette-number: 1 !default;
|
||||
@@ -87,7 +91,3 @@ $o-theme-font-names: (
|
||||
'Noto Serif',
|
||||
'Arvo',
|
||||
) !default;
|
||||
$o-theme-font-number: 1 !default;
|
||||
$o-theme-headings-font-number: 1 !default;
|
||||
$o-theme-buttons-font-number: 1 !default;
|
||||
$o-theme-navbar-font-number: 1 !default;
|
||||
|
||||
@@ -51,3 +51,7 @@ $o-website-values-palette-number: length($o-website-values-palettes);
|
||||
}
|
||||
|
||||
$o-theme-navbar-logo-height: o-website-value('logo-height') !default;
|
||||
$o-theme-font: nth($o-theme-fonts, o-website-value('font-number')) !default;
|
||||
$o-theme-headings-font: nth($o-theme-fonts, o-website-value('headings-font-number')) !default;
|
||||
$o-theme-navbar-font: nth($o-theme-fonts, o-website-value('navbar-font-number')) !default;
|
||||
$o-theme-buttons-font: nth($o-theme-fonts, o-website-value('buttons-font-number')) !default;
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
$-seen: ();
|
||||
$-font-numbers: (
|
||||
$o-theme-font-number,
|
||||
$o-theme-headings-font-number,
|
||||
$o-theme-buttons-font-number,
|
||||
$o-theme-navbar-font-number
|
||||
o-website-value('font-number'),
|
||||
o-website-value('headings-font-number'),
|
||||
o-website-value('navbar-font-number'),
|
||||
o-website-value('buttons-font-number'),
|
||||
);
|
||||
@each $-number in $-font-numbers {
|
||||
@if index($-seen, $-number) == null {
|
||||
@@ -75,8 +75,8 @@ $-font-numbers: (
|
||||
}
|
||||
|
||||
.navbar {
|
||||
@if ($o-theme-navbar-font-number != $o-theme-font-number) {
|
||||
font-family: nth($o-theme-fonts, $o-theme-navbar-font-number);
|
||||
@if ($o-theme-navbar-font != $o-theme-font) {
|
||||
font-family: $o-theme-navbar-font;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
@@ -154,8 +154,8 @@ h6 {
|
||||
color: color('h6');
|
||||
}
|
||||
.btn {
|
||||
@if ($o-theme-buttons-font-number != $o-theme-font-number) {
|
||||
font-family: nth($o-theme-fonts, $o-theme-buttons-font-number);
|
||||
@if ($o-theme-buttons-font != $o-theme-font) {
|
||||
font-family: $o-theme-buttons-font;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -552,42 +552,42 @@
|
||||
<content id="theme_customize_content_fonts" string="Fonts" title="Choose your fonts">
|
||||
<list string="Title">
|
||||
<selection id="theme_customize_content_fonts_title">
|
||||
<opt data-xmlid="" data-font="1"/>
|
||||
<opt data-xmlid="website.option_font_title_02_variables" data-font="2"/>
|
||||
<opt data-xmlid="website.option_font_title_03_variables" data-font="3"/>
|
||||
<opt data-xmlid="website.option_font_title_04_variables" data-font="4"/>
|
||||
<opt data-xmlid="website.option_font_title_05_variables" data-font="5"/>
|
||||
<opt data-xmlid="website.option_font_title_06_variables" data-font="6"/>
|
||||
<opt data-widget="auto" data-variable="headings-font-number" data-value="1" data-font="1"/>
|
||||
<opt data-widget="auto" data-variable="headings-font-number" data-value="2" data-font="2"/>
|
||||
<opt data-widget="auto" data-variable="headings-font-number" data-value="3" data-font="3"/>
|
||||
<opt data-widget="auto" data-variable="headings-font-number" data-value="4" data-font="4"/>
|
||||
<opt data-widget="auto" data-variable="headings-font-number" data-value="5" data-font="5"/>
|
||||
<opt data-widget="auto" data-variable="headings-font-number" data-value="6" data-font="6"/>
|
||||
</selection>
|
||||
</list>
|
||||
<list string="Body">
|
||||
<selection id="theme_customize_content_fonts_body">
|
||||
<opt data-xmlid="" data-font="1"/>
|
||||
<opt data-xmlid="website.option_font_body_02_variables" data-font="2"/>
|
||||
<opt data-xmlid="website.option_font_body_03_variables" data-font="3"/>
|
||||
<opt data-xmlid="website.option_font_body_04_variables" data-font="4"/>
|
||||
<opt data-xmlid="website.option_font_body_05_variables" data-font="5"/>
|
||||
<opt data-xmlid="website.option_font_body_06_variables" data-font="6"/>
|
||||
<opt data-widget="auto" data-variable="font-number" data-value="1" data-font="1"/>
|
||||
<opt data-widget="auto" data-variable="font-number" data-value="2" data-font="2"/>
|
||||
<opt data-widget="auto" data-variable="font-number" data-value="3" data-font="3"/>
|
||||
<opt data-widget="auto" data-variable="font-number" data-value="4" data-font="4"/>
|
||||
<opt data-widget="auto" data-variable="font-number" data-value="5" data-font="5"/>
|
||||
<opt data-widget="auto" data-variable="font-number" data-value="6" data-font="6"/>
|
||||
</selection>
|
||||
</list>
|
||||
<list string="Button">
|
||||
<selection id="theme_customize_content_fonts_button">
|
||||
<opt data-xmlid="" data-font="1"/>
|
||||
<opt data-xmlid="website.option_font_button_02_variables" data-font="2"/>
|
||||
<opt data-xmlid="website.option_font_button_03_variables" data-font="3"/>
|
||||
<opt data-xmlid="website.option_font_button_04_variables" data-font="4"/>
|
||||
<opt data-xmlid="website.option_font_button_05_variables" data-font="5"/>
|
||||
<opt data-xmlid="website.option_font_button_06_variables" data-font="6"/>
|
||||
<opt data-widget="auto" data-variable="buttons-font-number" data-value="1" data-font="1"/>
|
||||
<opt data-widget="auto" data-variable="buttons-font-number" data-value="2" data-font="2"/>
|
||||
<opt data-widget="auto" data-variable="buttons-font-number" data-value="3" data-font="3"/>
|
||||
<opt data-widget="auto" data-variable="buttons-font-number" data-value="4" data-font="4"/>
|
||||
<opt data-widget="auto" data-variable="buttons-font-number" data-value="5" data-font="5"/>
|
||||
<opt data-widget="auto" data-variable="buttons-font-number" data-value="6" data-font="6"/>
|
||||
</selection>
|
||||
</list>
|
||||
<list string="Navbar">
|
||||
<selection id="theme_customize_content_fonts_navbar">
|
||||
<opt data-xmlid="" data-font="1"/>
|
||||
<opt data-xmlid="website.option_font_navbar_02_variables" data-font="2"/>
|
||||
<opt data-xmlid="website.option_font_navbar_03_variables" data-font="3"/>
|
||||
<opt data-xmlid="website.option_font_navbar_04_variables" data-font="4"/>
|
||||
<opt data-xmlid="website.option_font_navbar_05_variables" data-font="5"/>
|
||||
<opt data-xmlid="website.option_font_navbar_06_variables" data-font="6"/>
|
||||
<opt data-widget="auto" data-variable="navbar-font-number" data-value="1" data-font="1"/>
|
||||
<opt data-widget="auto" data-variable="navbar-font-number" data-value="2" data-font="2"/>
|
||||
<opt data-widget="auto" data-variable="navbar-font-number" data-value="3" data-font="3"/>
|
||||
<opt data-widget="auto" data-variable="navbar-font-number" data-value="4" data-font="4"/>
|
||||
<opt data-widget="auto" data-variable="navbar-font-number" data-value="5" data-font="5"/>
|
||||
<opt data-widget="auto" data-variable="navbar-font-number" data-value="6" data-font="6"/>
|
||||
</selection>
|
||||
</list>
|
||||
</content>
|
||||
@@ -615,116 +615,6 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- TODO use scss customization for fonts instead (like for user colors) -->
|
||||
|
||||
<!-- Title font options -->
|
||||
<template id="option_font_title_02_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_title_02_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_title_03_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_title_03_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_title_04_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_title_04_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_title_05_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_title_05_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_title_06_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_title_06_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Body font options -->
|
||||
<template id="option_font_body_02_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_body_02_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_body_03_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_body_03_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_body_04_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_body_04_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_body_05_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_body_05_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_body_06_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_body_06_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Button font options -->
|
||||
<template id="option_font_button_02_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_button_02_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_button_03_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_button_03_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_button_04_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_button_04_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_button_05_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_button_05_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_button_06_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_button_06_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Navbar font options -->
|
||||
<template id="option_font_navbar_02_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_navbar_02_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_navbar_03_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_navbar_03_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_navbar_04_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_navbar_04_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_navbar_05_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_navbar_05_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template id="option_font_navbar_06_variables" inherit_id="website._assets_primary_variables" active="False">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/scss/options/fonts/option_font_navbar_06_variables.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="kanban">
|
||||
<t t-set="step"><t t-esc="step or 0"/></t>
|
||||
<t t-set="scope"><t t-esc="scope or 0"/></t>
|
||||
|
||||
@@ -147,6 +147,18 @@ class Theme(models.AbstractModel):
|
||||
if not website: # remove optional website in master
|
||||
website = self.env['website'].get_current_website()
|
||||
|
||||
# Reinitialize font customizations
|
||||
self.env['web_editor.assets'].make_scss_customization(
|
||||
'/website/static/src/scss/options/user_values.scss',
|
||||
{
|
||||
'font-number': 'null',
|
||||
'headings-font-number': 'null',
|
||||
'navbar-font-number': 'null',
|
||||
'buttons-font-number': 'null',
|
||||
}
|
||||
)
|
||||
|
||||
# Call specific theme post copy
|
||||
theme_post_copy = '_%s_post_copy' % mod.name
|
||||
if hasattr(self, theme_post_copy):
|
||||
_logger.info('Executing method %s' % theme_post_copy)
|
||||
|
||||
Reference in New Issue
Block a user