🎉 Initialize module repository
This commit is contained in:
65
views/menu_views.xml
Normal file
65
views/menu_views.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<menuitem
|
||||
id="mvd_tcg_mtg_scryfall_menu"
|
||||
name="Scryfall"
|
||||
parent="mvd_tcg_mtg.mvd_tcg_mtg_configuration_menu"
|
||||
sequence="20"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
id="mvd_tcg_mtg_scryfall_lookup_menu"
|
||||
name="Lookup Card"
|
||||
parent="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_menu"
|
||||
sequence="10"
|
||||
action="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_lookup_action"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
id="mvd_tcg_mtg_scryfall_import_menu"
|
||||
name="Import Cards"
|
||||
parent="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_menu"
|
||||
sequence="20"
|
||||
action="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_import_action"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
id="mvd_tcg_mtg_scryfall_import_runs_menu"
|
||||
name="Import Runs"
|
||||
parent="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_menu"
|
||||
sequence="30"
|
||||
action="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_import_run_action"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
/>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_menu" model="ir.ui.menu">
|
||||
<field
|
||||
name="group_ids"
|
||||
eval="[(6, 0, [ref('mvd_tcg_base.mvd_tcg_base_group_manager'), ref('base.group_system')])]"
|
||||
/>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_lookup_menu" model="ir.ui.menu">
|
||||
<field
|
||||
name="group_ids"
|
||||
eval="[(6, 0, [ref('mvd_tcg_base.mvd_tcg_base_group_manager'), ref('base.group_system')])]"
|
||||
/>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_import_menu" model="ir.ui.menu">
|
||||
<field
|
||||
name="group_ids"
|
||||
eval="[(6, 0, [ref('mvd_tcg_base.mvd_tcg_base_group_manager'), ref('base.group_system')])]"
|
||||
/>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_import_runs_menu" model="ir.ui.menu">
|
||||
<field
|
||||
name="group_ids"
|
||||
eval="[(6, 0, [ref('mvd_tcg_base.mvd_tcg_base_group_manager'), ref('base.group_system')])]"
|
||||
/>
|
||||
</record>
|
||||
</odoo>
|
||||
93
views/mvd_tcg_mtg_card_views.xml
Normal file
93
views/mvd_tcg_mtg_card_views.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mvd_tcg_mtg_card_view_form_scryfall" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.card.view.form.scryfall</field>
|
||||
<field name="model">mvd.tcg.card</field>
|
||||
<field name="inherit_id" ref="mvd_tcg_mtg.mvd_tcg_mtg_card_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header" position="inside">
|
||||
<button
|
||||
name="action_mtg_scryfall_refresh_card"
|
||||
string="Refresh from Scryfall"
|
||||
type="object"
|
||||
class="btn-secondary"
|
||||
invisible="not is_mtg_game"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='image_1920']" position="replace">
|
||||
<field
|
||||
name="image_1920"
|
||||
widget="image"
|
||||
class="oe_avatar"
|
||||
options="{'convert_to_webp': True, 'preview_image': 'image_512', 'zoom': true, 'zoom_delay': 0, 'size': [0, 260]}"
|
||||
readonly="state == 'validated'"
|
||||
invisible="state == 'validated'"
|
||||
/>
|
||||
<field
|
||||
name="mtg_display_image_1920"
|
||||
widget="image"
|
||||
class="oe_avatar"
|
||||
options="{'convert_to_webp': True, 'preview_image': 'mtg_display_image_512', 'zoom': true, 'zoom_delay': 0, 'size': [0, 260]}"
|
||||
readonly="1"
|
||||
invisible="state != 'validated'"
|
||||
/>
|
||||
</xpath>
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button
|
||||
name="action_open_mtg_scryfall_last_import_run"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-refresh"
|
||||
invisible="not mtg_scryfall_last_import_run_id"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
>
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_text">Last Import</span>
|
||||
<span class="o_stat_value">Open</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//notebook/page[@name='reference_information']" position="after">
|
||||
<page string="Scryfall" name="scryfall_connector" groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system">
|
||||
<group>
|
||||
<group name="scryfall_identity">
|
||||
<field name="mtg_scryfall_id"/>
|
||||
<field name="mtg_scryfall_uri" widget="url"/>
|
||||
</group>
|
||||
<group name="scryfall_sync">
|
||||
<field name="mtg_scryfall_last_synced_at"/>
|
||||
<field name="mtg_scryfall_last_import_run_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="mtg_scryfall_image_ids" readonly="1">
|
||||
<list string="Localized Images">
|
||||
<field name="language_code"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_card_view_kanban_scryfall" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.card.view.kanban.scryfall</field>
|
||||
<field name="model">mvd.tcg.card</field>
|
||||
<field name="inherit_id" ref="mvd_tcg_mtg.mvd_tcg_mtg_card_view_kanban"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//kanban/field[@name='image_512']" position="replace">
|
||||
<field name="mtg_display_image_512"/>
|
||||
</xpath>
|
||||
<xpath expr="//kanban//field[@name='image_512']" position="replace">
|
||||
<field
|
||||
name="mtg_display_image_512"
|
||||
widget="image"
|
||||
alt="Magic Card"
|
||||
options="{'img_class': 'w-100 object-fit-contain', 'preview_image': 'mtg_display_image_512'}"
|
||||
class="w-100"
|
||||
invisible="not mtg_display_image_512"
|
||||
/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
46
views/mvd_tcg_mtg_lookup_views.xml
Normal file
46
views/mvd_tcg_mtg_lookup_views.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mvd_tcg_mtg_scryfall_lookup_view_form" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.scryfall.lookup.view.form</field>
|
||||
<field name="model">mvd.tcg.mtg.lookup</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lookup Card">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field
|
||||
name="query"
|
||||
placeholder="e.g. Black Lotus or https://scryfall.com/card/lea/233/black-lotus"
|
||||
/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="lookup_mode" widget="radio"/>
|
||||
</group>
|
||||
</group>
|
||||
<div class="text-muted">
|
||||
The Scryfall connector imports or refreshes one MTG
|
||||
reference card together with its set metadata and
|
||||
translations.
|
||||
</div>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button
|
||||
name="action_lookup_card"
|
||||
string="Lookup Card"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_lookup_action" model="ir.actions.act_window">
|
||||
<field name="name">Lookup Card</field>
|
||||
<field name="res_model">mvd.tcg.mtg.lookup</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_lookup_view_form"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
118
views/mvd_tcg_mtg_scryfall_import_run_views.xml
Normal file
118
views/mvd_tcg_mtg_scryfall_import_run_views.xml
Normal file
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mvd_tcg_mtg_scryfall_import_run_view_list" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.scryfall.import.run.view.list</field>
|
||||
<field name="model">mvd.tcg.mtg.scryfall.import.run</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Scryfall Import Runs" default_order="id desc">
|
||||
<field name="name"/>
|
||||
<field name="import_mode"/>
|
||||
<field name="lookup_mode" optional="show"/>
|
||||
<field name="state"/>
|
||||
<field name="stage"/>
|
||||
<field name="requested_by_id" optional="show"/>
|
||||
<field name="progress_percent" optional="show"/>
|
||||
<field name="cards_created" optional="show"/>
|
||||
<field name="cards_updated" optional="show"/>
|
||||
<field name="started_at" optional="show"/>
|
||||
<field name="finished_at" optional="show"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_import_run_view_form" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.scryfall.import.run.view.form</field>
|
||||
<field name="model">mvd.tcg.mtg.scryfall.import.run</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Scryfall Import Run">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button
|
||||
name="action_open_cards"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-clone"
|
||||
>
|
||||
<field name="item_count" string="Cards" widget="statinfo"/>
|
||||
</button>
|
||||
<button
|
||||
name="action_open_sets"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-folder-open"
|
||||
>
|
||||
<field name="set_count" string="Sets" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
<widget name="web_ribbon" title="Failed" bg_color="text-bg-danger" invisible="state != 'failed'"/>
|
||||
<widget name="web_ribbon" title="Done" bg_color="text-bg-success" invisible="state != 'done'"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="import_mode"/>
|
||||
<field name="lookup_mode" invisible="import_mode != 'batch'"/>
|
||||
<field name="requested_by_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="state"/>
|
||||
<field name="stage"/>
|
||||
<field name="started_at"/>
|
||||
<field name="finished_at"/>
|
||||
<field name="progress_percent"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Counters">
|
||||
<group>
|
||||
<field name="set_count"/>
|
||||
<field name="item_count"/>
|
||||
<field name="cards_created"/>
|
||||
<field name="cards_updated"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="sets_created"/>
|
||||
<field name="sets_updated"/>
|
||||
<field name="progress_current"/>
|
||||
<field name="progress_total"/>
|
||||
</group>
|
||||
</group>
|
||||
<group
|
||||
string="Technical Options"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system"
|
||||
>
|
||||
<group>
|
||||
<field name="language_codes"/>
|
||||
<field name="max_cards_per_set" invisible="import_mode != 'set'"/>
|
||||
<field name="include_tokens" invisible="import_mode != 'set'"/>
|
||||
</group>
|
||||
</group>
|
||||
<group
|
||||
string="Input"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system"
|
||||
>
|
||||
<field name="input_text" nolabel="1"/>
|
||||
</group>
|
||||
<group
|
||||
string="Error"
|
||||
invisible="not error_message"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system"
|
||||
>
|
||||
<field name="error_message" nolabel="1"/>
|
||||
</group>
|
||||
<group
|
||||
string="Run Log"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system"
|
||||
>
|
||||
<field name="log_text" nolabel="1"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_import_run_action" model="ir.actions.act_window">
|
||||
<field name="name">Import Runs</field>
|
||||
<field name="res_model">mvd.tcg.mtg.scryfall.import.run</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_import_run_view_list"/>
|
||||
</record>
|
||||
</odoo>
|
||||
74
views/mvd_tcg_mtg_scryfall_import_views.xml
Normal file
74
views/mvd_tcg_mtg_scryfall_import_views.xml
Normal file
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mvd_tcg_mtg_scryfall_import_view_form" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.scryfall.import.view.form</field>
|
||||
<field name="model">mvd.tcg.mtg.scryfall.import</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Import Cards">
|
||||
<sheet>
|
||||
<div class="text-muted mb-3">
|
||||
Import one or more Magic cards from Scryfall. Choose set
|
||||
codes or a card list and start one controlled import run.
|
||||
</div>
|
||||
<group>
|
||||
<group string="Import Mode">
|
||||
<field name="import_mode" widget="radio"/>
|
||||
</group>
|
||||
<group string="Lookup Strategy" invisible="import_mode != 'batch'">
|
||||
<field name="lookup_mode" widget="radio" invisible="import_mode != 'batch'"/>
|
||||
</group>
|
||||
</group>
|
||||
<group invisible="import_mode != 'set'">
|
||||
<field
|
||||
name="set_codes_text"
|
||||
placeholder="One set code per line, for example: tdm ktk"
|
||||
nolabel="1"
|
||||
/>
|
||||
</group>
|
||||
<group invisible="import_mode != 'batch'">
|
||||
<field
|
||||
name="batch_input"
|
||||
placeholder="One card per line, for example: Black Lotus https://scryfall.com/card/tdm/209/narset-jeskai-waymaster"
|
||||
nolabel="1"
|
||||
/>
|
||||
</group>
|
||||
<div class="text-muted" invisible="import_mode != 'set'">
|
||||
Set imports fetch the selected sets from Scryfall with
|
||||
the defaults configured for this connector.
|
||||
</div>
|
||||
<div class="text-muted" invisible="import_mode != 'batch'">
|
||||
Card-list imports resolve each line with the selected
|
||||
lookup strategy before cards are created or refreshed.
|
||||
</div>
|
||||
<group
|
||||
string="Advanced Options"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system"
|
||||
>
|
||||
<group>
|
||||
<field name="language_codes"/>
|
||||
<field name="max_cards_per_set" invisible="import_mode != 'set'"/>
|
||||
<field name="include_tokens" invisible="import_mode != 'set'"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button
|
||||
name="action_import_cards"
|
||||
string="Import Cards"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mvd_tcg_mtg_scryfall_import_action" model="ir.actions.act_window">
|
||||
<field name="name">Import Cards</field>
|
||||
<field name="res_model">mvd.tcg.mtg.scryfall.import</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="mvd_tcg_mtg_scryfall.mvd_tcg_mtg_scryfall_import_view_form"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
48
views/mvd_tcg_mtg_set_views.xml
Normal file
48
views/mvd_tcg_mtg_set_views.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mvd_tcg_mtg_set_view_form_scryfall" model="ir.ui.view">
|
||||
<field name="name">mvd.tcg.mtg.set.view.form.scryfall</field>
|
||||
<field name="model">mvd.tcg.mtg.set</field>
|
||||
<field name="inherit_id" ref="mvd_tcg_mtg.mvd_tcg_mtg_set_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//sheet" position="before">
|
||||
<header>
|
||||
<button
|
||||
name="action_mtg_scryfall_refresh_set"
|
||||
string="Refresh from Scryfall"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
/>
|
||||
</header>
|
||||
</xpath>
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button
|
||||
name="action_open_mtg_scryfall_last_import_run"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-refresh"
|
||||
invisible="not mtg_scryfall_last_import_run_id"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_manager,base.group_system"
|
||||
>
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_text">Last Import</span>
|
||||
<span class="o_stat_value">Open</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//notebook/page[@name='general_information']" position="after">
|
||||
<page string="Scryfall" name="scryfall_connector" groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system">
|
||||
<group>
|
||||
<group>
|
||||
<field name="mtg_scryfall_last_synced_at"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="mtg_scryfall_last_import_run_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
60
views/res_config_settings_views.xml
Normal file
60
views/res_config_settings_views.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="res_config_settings_view_form_mvd_tcg_mtg_scryfall" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.mvd.tcg.mtg.scryfall</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="mvd_tcg_base.mvd_tcg_res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//app[@name='mvd_tcg']" position="inside">
|
||||
<block
|
||||
title="Scryfall Connector"
|
||||
name="mvd_tcg_scryfall_connector"
|
||||
groups="mvd_tcg_base.mvd_tcg_base_group_administrator,base.group_system"
|
||||
>
|
||||
<setting
|
||||
id="mvd_tcg_scryfall_import_languages"
|
||||
string="Default Import Languages"
|
||||
help="Comma-separated Scryfall language codes imported for each print group."
|
||||
>
|
||||
<field name="mtg_scryfall_import_language_codes" placeholder="en,de"/>
|
||||
</setting>
|
||||
<setting
|
||||
id="mvd_tcg_scryfall_import_limit"
|
||||
string="Default Set Card Limit"
|
||||
help="Optional per-set limit for controlled set imports. Use 0 for no limit."
|
||||
>
|
||||
<field name="mtg_scryfall_import_max_cards_per_set"/>
|
||||
</setting>
|
||||
<setting
|
||||
id="mvd_tcg_scryfall_import_tokens"
|
||||
string="Include Tokens"
|
||||
help="Include token cards by default for controlled set imports."
|
||||
>
|
||||
<field name="mtg_scryfall_import_include_tokens"/>
|
||||
</setting>
|
||||
<setting
|
||||
id="mvd_tcg_scryfall_api_base_url"
|
||||
string="API Base URL"
|
||||
help="Override the Scryfall API base URL only for special environments."
|
||||
>
|
||||
<field name="mtg_scryfall_api_base_url"/>
|
||||
</setting>
|
||||
<setting
|
||||
id="mvd_tcg_scryfall_timeout"
|
||||
string="Request Timeout"
|
||||
help="Timeout in seconds for Scryfall API requests and image downloads."
|
||||
>
|
||||
<field name="mtg_scryfall_timeout_seconds"/>
|
||||
</setting>
|
||||
<setting
|
||||
id="mvd_tcg_scryfall_user_agent"
|
||||
string="User Agent"
|
||||
help="HTTP user agent used for Scryfall API requests and image downloads."
|
||||
>
|
||||
<field name="mtg_scryfall_user_agent"/>
|
||||
</setting>
|
||||
</block>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user