Files
seo/otoolkit_seo_content/views/seo_content_views.xml
T

489 lines
27 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- SEO Content List View -->
<record id="otk_seo_content_view_tree" model="ir.ui.view">
<field name="name">otk.seo.content.list</field>
<field name="model">otk.seo.content</field>
<field name="arch" type="xml">
<list string="SEO Content" default_order="create_date desc" create="False"
decoration-info="state == 'draft'"
decoration-warning="state == 'images_pending' or is_stale"
decoration-success="state in ('approved', 'published') and not is_stale"
decoration-muted="state == 'archived'">
<field name="name"/>
<field name="content_type"/>
<field name="language_id" optional="show"/>
<field name="source_keywords"/>
<field name="seo_score" widget="progressbar"
options="{'max_value': 100}"/>
<field name="word_count" optional="show"/>
<field name="image_count" optional="hide"/>
<field name="is_stale" string="Stale" widget="boolean"/>
<field name="days_since_refresh" optional="hide"/>
<field name="state" widget="badge"
decoration-info="state == 'draft'"
decoration-warning="state in ('generating', 'images_pending')"
decoration-success="state in ('review', 'approved', 'published')"
decoration-danger="state == 'archived'"/>
<field name="create_date" optional="hide"/>
<field name="blog_post_id" optional="hide"/>
<field name="token_cost" optional="hide"/>
</list>
</field>
</record>
<!-- SEO Content Form View -->
<record id="otk_seo_content_view_form" model="ir.ui.view">
<field name="name">otk.seo.content.form</field>
<field name="model">otk.seo.content</field>
<field name="arch" type="xml">
<form string="SEO Content">
<header>
<button name="action_generate" type="object" string="Generate"
class="oe_highlight" invisible="state != 'draft'"/>
<button name="action_regenerate" type="object" string="Regenerate"
invisible="state not in ('review', 'approved')"
confirm="This will regenerate the content. A version will be saved. Continue?"/>
<button name="action_approve" type="object" string="Approve"
class="oe_highlight" invisible="state != 'review'"/>
<button name="action_create_blog_post" type="object"
string="Create Blog Post" class="oe_highlight"
invisible="state != 'approved' or blog_post_id"/>
<button name="action_apply_to_product" type="object"
string="Apply to Product" class="oe_highlight"
icon="fa-share"
invisible="state not in ('review', 'approved') or content_type != 'product_desc' or not source_product_id"/>
<button name="action_back_to_draft" type="object" string="Back to Draft"
invisible="state not in ('review', 'approved')"/>
<button name="action_insert_images" type="object"
string="Insert Images in Content" icon="fa-picture-o"
class="btn-secondary"
invisible="state not in ('review', 'approved') or not has_insertable_images"/>
<button name="action_mark_refreshed" type="object"
string="Mark as Refreshed" icon="fa-check"
invisible="not is_stale"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,generating,review,approved,published"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_blog_post" type="object"
class="oe_stat_button" icon="fa-newspaper-o"
invisible="not blog_post_id">
<span class="o_stat_text">Blog Post</span>
</button>
<button name="action_view_images" type="object"
class="oe_stat_button" icon="fa-image">
<field name="image_count" widget="statinfo" string="Images"/>
</button>
<button name="action_restore_version" type="object"
class="oe_stat_button" icon="fa-history"
invisible="current_version &lt;= 1">
<field name="current_version" widget="statinfo" string="Versions"/>
</button>
</div>
<widget name="web_ribbon" title="Needs Refresh"
bg_color="text-bg-info" invisible="not is_stale"/>
<widget name="web_ribbon" title="Images Pending"
bg_color="text-bg-warning" invisible="not images_pending or is_stale"/>
<widget name="web_ribbon" title="Error"
bg_color="text-bg-danger" invisible="not error_message or images_pending or is_stale"/>
<widget name="web_ribbon" title="Generating"
bg_color="text-bg-warning" invisible="state != 'generating'"/>
<div class="oe_title">
<h1>
<field name="name" placeholder="Content Title"/>
</h1>
</div>
<group>
<group string="Content Settings">
<field name="content_type"
readonly="state != 'draft'"/>
<field name="source_keywords" placeholder="keyword1, keyword2, ..."
readonly="state != 'draft'"/>
<field name="tone"
readonly="state != 'draft'"/>
<field name="target_word_count"
readonly="state != 'draft'"/>
<field name="language_id"
readonly="state != 'draft'"/>
<field name="template_id"
domain="[('content_type', '=', content_type)]"
readonly="state != 'draft'"/>
<field name="brand_voice_id"
readonly="state != 'draft'"/>
</group>
<group string="SEO Analysis">
<field name="seo_score" widget="progressbar"
options="{'max_value': 100}"/>
<field name="keyword_density"/>
<field name="word_count"/>
<field name="readability_score"/>
<field name="is_seo_optimized" widget="boolean_toggle"/>
</group>
</group>
<notebook>
<page string="Generated Content" name="content">
<group>
<group>
<field name="generated_title" placeholder="Generated title will appear here"/>
</group>
<group>
<field name="generated_subtitle" placeholder="Generated subtitle"/>
</group>
</group>
<field name="generated_content" placeholder="Generated content will appear here..."/>
<!-- Inline SEO Summary Panel -->
<div class="o_seo_inline_panel mt-3 p-3 border rounded bg-light"
invisible="not generated_content">
<div class="row align-items-center">
<div class="col-md-3">
<div class="d-flex align-items-center">
<i class="fa fa-line-chart me-2 text-primary" title="SEO Score"/>
<strong class="me-2">SEO Score</strong>
<field name="seo_score" widget="progressbar"
options="{'max_value': 100}" class="flex-grow-1"/>
</div>
</div>
<div class="col-md-3">
<div class="d-flex align-items-center">
<i class="fa fa-tag me-1"/>
<span class="me-1">Title:</span>
<field name="meta_title_length" class="me-1"/>
<span class="text-muted">/60</span>
<span class="o_meta_indicator ms-1"
invisible="meta_title_status != 'optimal'">
<i class="fa fa-check-circle text-success" title="Optimal length"/>
</span>
<span class="o_meta_indicator ms-1"
invisible="meta_title_status != 'short'">
<i class="fa fa-exclamation-circle text-warning" title="Too short"/>
</span>
<span class="o_meta_indicator ms-1"
invisible="meta_title_status != 'long'">
<i class="fa fa-exclamation-triangle text-danger" title="Too long"/>
</span>
</div>
</div>
<div class="col-md-3">
<div class="d-flex align-items-center">
<i class="fa fa-file-text-o me-1"/>
<span class="me-1">Desc:</span>
<field name="meta_desc_length" class="me-1"/>
<span class="text-muted">/155</span>
<span class="o_meta_indicator ms-1"
invisible="meta_desc_status != 'optimal'">
<i class="fa fa-check-circle text-success" title="Optimal length"/>
</span>
<span class="o_meta_indicator ms-1"
invisible="meta_desc_status != 'short'">
<i class="fa fa-exclamation-circle text-warning" title="Too short"/>
</span>
<span class="o_meta_indicator ms-1"
invisible="meta_desc_status != 'long'">
<i class="fa fa-exclamation-triangle text-danger" title="Too long"/>
</span>
</div>
</div>
<div class="col-md-3">
<div class="d-flex align-items-center">
<i class="fa fa-font me-1"/>
<span class="me-1">Words:</span>
<field name="word_count"/>
</div>
</div>
</div>
<div class="mt-2" invisible="not seo_improvements">
<small class="text-muted">
<i class="fa fa-lightbulb-o me-1" title="Suggestions"/>
<field name="seo_improvements" class="d-inline" widget="text" readonly="1"/>
</small>
</div>
</div>
<group string="Generated teaser/excerpt">
<field name="generated_teaser" nolabel="1" colspan="2" placeholder="Generated teaser/excerpt"/>
</group>
</page>
<page string="SEO Metadata" name="seo">
<group>
<group string="Meta Tags">
<field name="website_meta_title"
placeholder="Max 60 characters recommended"/>
<field name="website_meta_description"
placeholder="Max 155 characters recommended"/>
<field name="website_meta_keywords"/>
</group>
<group string="URL &amp; Keywords">
<field name="seo_name" placeholder="url-friendly-name"/>
<field name="generated_keywords"/>
</group>
</group>
</page>
<page string="SEO Analysis" name="seo_analysis">
<field name="seo_analysis_html" nolabel="1"/>
<group string="Quick Improvement List" invisible="not seo_improvements">
<div class="alert alert-light border" role="alert" colspan="2">
<strong><i class="fa fa-lightbulb-o"></i> Suggestions to improve your SEO score:</strong>
<field name="seo_improvements" nolabel="1" class="mt-2"
widget="text" readonly="1" style="white-space: pre-line;"/>
</div>
</group>
<group string="Raw Analysis Data (Debug)" invisible="1">
<field name="seo_analysis" readonly="True" widget="json_pretty" nolabel="1"/>
</group>
</page>
<page string="Images" name="images">
<group>
<group>
<field name="requested_image_count"
readonly="state != 'draft'"/>
<field name="image_style"
readonly="state != 'draft'"/>
</group>
<group>
<field name="images_pending" invisible="1"/>
</group>
</group>
<field name="image_ids">
<list editable="bottom">
<field name="sequence" widget="handle"/>
<field name="image" widget="image"
options="{'size': [120, 120]}"/>
<field name="name"/>
<field name="style"/>
<field name="state" widget="badge"
decoration-info="state == 'draft'"
decoration-warning="state in ('pending', 'processing')"
decoration-success="state == 'done'"
decoration-danger="state == 'error'"/>
<field name="is_cover" string="Cover"
widget="boolean_toggle"/>
<field name="is_og_image" string="OG"
widget="boolean_toggle"/>
<field name="alt_text"/>
<button name="action_generate" type="object"
string="Generate" icon="fa-magic"
invisible="state != 'draft'"/>
<button name="action_retry" type="object"
string="Retry" icon="fa-refresh"
invisible="state != 'error'"/>
</list>
</field>
</page>
<page string="Source" name="source">
<group>
<group string="Topic">
<field name="source_topic" placeholder="Describe what the content should be about..."
readonly="state != 'draft'"/>
</group>
<group string="Source">
<field name="source_product_id"
readonly="state != 'draft'"/>
<field name="source_text" placeholder="Paste existing content to optimize..."
readonly="state != 'draft'"/>
<field name="reference_ids" widget="many2many_tags"/>
</group>
</group>
</page>
<page string="Publishing" name="publishing">
<group>
<group string="Blog Settings">
<field name="blog_id"/>
<field name="blog_post_id" readonly="1"/>
</group>
<group string="Tracking">
<field name="token_cost"/>
<field name="generation_time"/>
<field name="api_task_id" readonly="1"/>
</group>
</group>
<group>
<group string="Content Freshness">
<field name="last_refreshed_date"/>
<field name="refresh_threshold_days"/>
<field name="days_since_refresh" readonly="1"/>
<field name="is_stale" readonly="1"/>
</group>
</group>
<group string="Error" invisible="not error_message">
<field name="error_message" readonly="1"/>
</group>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- SEO Content Search View -->
<record id="otk_seo_content_view_search" model="ir.ui.view">
<field name="name">otk.seo.content.search</field>
<field name="model">otk.seo.content</field>
<field name="arch" type="xml">
<search string="Search SEO Content">
<field name="name"/>
<field name="source_keywords"/>
<field name="generated_title"/>
<separator/>
<filter name="filter_draft" string="Draft"
domain="[('state', '=', 'draft')]"/>
<filter name="filter_review" string="In Review"
domain="[('state', '=', 'review')]"/>
<filter name="filter_approved" string="Approved"
domain="[('state', '=', 'approved')]"/>
<filter name="filter_published" string="Published"
domain="[('state', '=', 'published')]"/>
<separator/>
<filter name="filter_blog_post" string="Blog Posts"
domain="[('content_type', '=', 'blog_post')]"/>
<filter name="filter_product_desc" string="Product Descriptions"
domain="[('content_type', '=', 'product_desc')]"/>
<separator/>
<filter name="filter_high_seo" string="High SEO Score (70+)"
domain="[('seo_score', '>=', 70)]"/>
<filter name="filter_needs_work" string="Needs SEO Work (&lt;50)"
domain="[('seo_score', '&lt;', 50)]"/>
<separator/>
<filter name="filter_my_content" string="My Content"
domain="[('create_uid', '=', uid)]"/>
<filter name="filter_stale" string="Needs Refresh"
domain="[('is_stale', '=', True)]"/>
<group>
<filter name="group_state" string="Status"
context="{'group_by': 'state'}"/>
<filter name="group_type" string="Content Type"
context="{'group_by': 'content_type'}"/>
<filter name="group_language" string="Language"
context="{'group_by': 'language_id'}"/>
<filter name="group_template" string="Template"
context="{'group_by': 'template_id'}"/>
<filter name="group_create_date" string="Created"
context="{'group_by': 'create_date:month'}"/>
</group>
</search>
</field>
</record>
<!-- SEO Content Kanban View -->
<record id="otk_seo_content_view_kanban" model="ir.ui.view">
<field name="name">otk.seo.content.kanban</field>
<field name="model">otk.seo.content</field>
<field name="arch" type="xml">
<kanban default_group_by="state" class="o_kanban_small_column">
<field name="name"/>
<field name="content_type"/>
<field name="seo_score"/>
<field name="state"/>
<field name="image_count"/>
<templates>
<t t-name="card">
<div class="oe_kanban_card oe_kanban_global_click">
<div class="oe_kanban_content">
<div class="o_kanban_record_title">
<strong><field name="name"/></strong>
</div>
<div class="o_kanban_record_subtitle">
<field name="content_type"/>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<span title="SEO Score">
<i class="fa fa-line-chart"/> <field name="seo_score"/>%
</span>
</div>
<div class="oe_kanban_bottom_right">
<span title="Images">
<i class="fa fa-image"/> <field name="image_count"/>
</span>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Content Version List View -->
<record id="otk_seo_content_version_view_tree" model="ir.ui.view">
<field name="name">otk.seo.content.version.list</field>
<field name="model">otk.seo.content.version</field>
<field name="arch" type="xml">
<list string="Version History">
<field name="version_number"/>
<field name="note"/>
<field name="generated_title"/>
<field name="created_by"/>
<field name="created_at"/>
<button name="action_view_diff" type="object"
string="View Diff" icon="fa-exchange"
class="btn-link"/>
<button name="action_restore" type="object"
string="Restore" icon="fa-undo"
confirm="Restore this version? Current content will be saved as a new version."/>
</list>
</field>
</record>
<!-- Content Version Diff View (Dialog) -->
<record id="otk_seo_content_version_view_diff" model="ir.ui.view">
<field name="name">otk.seo.content.version.diff</field>
<field name="model">otk.seo.content.version</field>
<field name="arch" type="xml">
<form string="Version Diff">
<sheet>
<group>
<group>
<field name="version_number" readonly="1"/>
<field name="note" readonly="1"/>
</group>
<group>
<field name="created_by" readonly="1"/>
<field name="created_at" readonly="1"/>
</group>
</group>
<separator string="Changes from this version to current content"/>
<field name="diff_preview" nolabel="1" readonly="1"/>
</sheet>
<footer>
<button name="action_restore" type="object"
string="Restore This Version" class="btn-primary"
confirm="Restore this version? Current content will be saved as a new version."/>
<button string="Close" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- Action -->
<record id="action_otk_seo_content" model="ir.actions.act_window">
<field name="name">SEO Content</field>
<field name="res_model">otk.seo.content</field>
<field name="view_mode">list,kanban,form</field>
<field name="search_view_id" ref="otk_seo_content_view_search"/>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first SEO content!
</p>
<p>
Generate AI-powered blog posts, product descriptions, and more
with built-in SEO optimization and image generation.
</p>
</field>
</record>
</odoo>