Skip to content

feat: Enhance of UX/UI feat#3

Merged
Abdeali099 merged 10 commits into
developfrom
phase-2-enhancement
Jan 20, 2026
Merged

feat: Enhance of UX/UI feat#3
Abdeali099 merged 10 commits into
developfrom
phase-2-enhancement

Conversation

@Abdeali099

@Abdeali099 Abdeali099 commented Jan 20, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

Release Notes

  • New Features

    • Added publish/unpublish web view functionality with a custom button on localization records.
    • Introduced Tasks table for tracking localization milestones and project phases.
    • Added email notifications to developers and internal team when new applications are submitted.
  • Improvements

    • Replaced title field with subject field for better clarity.
    • Expanded progress status options with additional states (Submitted, Pending Review, In Progress).
    • Enhanced localization display to show company information.
  • Removals

    • Removed Frappe Partner doctype.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 20, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The pull request restructures the ERPNext Localization doctype by renaming the title field to subject, introducing a Tasks child table for milestone tracking, removing the Frappe Partner doctype, and adding notification templates for developer and internal team communications.

Changes

Cohort / File(s) Summary
ERPNext Localization Core
erpnext_localization.js, erpnext_localization.json, erpnext_localization.py
Schema refactoring: replaced title with subject as primary field, added tasks table (LocalizationTask), expanded progress_status options ("Submitted", "Pending Review", "In Progress"), removed partner field, updated field metadata (enable_webview now defaults to "0" and read-only), added refresh/publish-web-view button handlers in JS
Localization Task (New)
localization_task.json, localization_task.py
New child table doctype for task management; includes fields for task name, milestone (Phase 1–4), description, dates, status (Open/Closed/Cancelled), and priority (Low/Medium/High)
UI Templates
erpnext_localization.html, erpnext_localization_row.html
Updated header rendering to use doc.subject instead of title, added "Develop By" section with company name/website, redesigned row template card layout with metadata display and responsive styling, replaced documentation icon
Email Notifications (New)
notification/localization_requested_developer/...html, .json, .py
notification/localization_requested_internal_team/...html, .json, .py
Two new notification templates: one for developer applicant confirmation (sent to developer_mail), one for internal team review (sent to Localization Reviewer role); both include styled email layouts with application details, country flags, and CTAs
Frappe Partner Removal
frappe_partner.js, frappe_partner.json, frappe_partner.py, test_frappe_partner.py
Complete removal of Frappe Partner doctype and all associated files (schema, model class, tests)
Web Form & Workspace
localization_application.json, localization.json
Updated localization_application web form to use subject field instead of title, removed URL options from developer_github/company_website/repo/documentation_url fields; removed Frappe Partner shortcut from workspace
Migration & Configuration
patches.txt, set_subjects_from_title.py, set_default_progress_status.py
Two migration patches registered: one to copy title values to subject field, one to set progress_status to "Submitted" for records with null/empty values

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A subject emerges, no longer just a title,
Tasks now take center stage in this docile doctype's recital,
Partners depart whilst notifications take flight,
Fresh email templates bring developers to light,
The schema reshapes with a hop and a bound! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: Enhance of UX/UI feat' is vague and uses non-descriptive terms that don't convey specific information about the changeset. Revise the title to be more specific about the primary changes, such as 'feat: Replace title with subject field and add tasks management' or 'feat: Restructure localization form with subject field and task tracking'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Abdeali099
Abdeali099 merged commit 9a77169 into develop Jan 20, 2026
2 of 3 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
localization_management_system/localization_management_system/workspace/localization/localization.json (1)

3-3: Remove the stale "Frappe Partner" shortcut from the content field.

The content JSON contains a reference to "Frappe Partner" (id: AjtF543aTo), but this shortcut is not defined in the shortcuts array. This orphaned reference can cause the workspace to render a broken or missing shortcut in the UI.

localization_management_system/localization_management_system/doctype/erpnext_localization/templates/erpnext_localization.html (1)

228-228: Bug: Missing doc. prefix on documentation_url.

The template uses documentation_url instead of doc.documentation_url, which will cause an undefined variable error or render an empty/incorrect URL. All other fields consistently use the doc. prefix.

🐛 Proposed fix
-                            <a href="{{ documentation_url }}" target="_blank">Read Docs →</a>
+                            <a href="{{ doc.documentation_url }}" target="_blank">Read Docs →</a>
🤖 Fix all issues with AI agents
In
`@localization_management_system/localization_management_system/doctype/erpnext_localization/erpnext_localization.js`:
- Around line 11-19: The add_publish_web_view_button function is adding a custom
button on every refresh causing duplicates; update
add_publish_web_view_button(frm) to clear existing custom buttons first by
calling frm.clear_custom_buttons() (or another appropriate frm.page/btn-clear
API) before calling frm.add_custom_button so only a single Publish/Unpublish
button appears after save/refresh.

In
`@localization_management_system/localization_management_system/doctype/erpnext_localization/templates/erpnext_localization_row.html`:
- Around line 155-159: The closing </div> for .localization-card-header is
misplaced and is on the same line as the `{% if doc.description %}` block, which
breaks nesting; move the `</div>` so that `.localization-card-header` is closed
before starting `.localization-card-content`, ensure the `{% if doc.description
%}` conditional and the `<p class="localization-card-description">` live inside
`.localization-card-content` with correct indentation, and verify tags close in
proper order around the `doc.description` check.

In
`@localization_management_system/localization_management_system/notification/localization_requested_developer/localization_requested_developer.json`:
- Line 28: The JSON subject value contains an extraneous word "Inbox"; update
the "subject" value in localization_requested_developer.json (the "subject" key)
to remove "Inbox" and use a clearer phrase such as "Localization Application
Submitted" or "Localization Application Received" so the subject reads
correctly.
- Line 14: The notification HTML template is duplicated: the actual notification
is loaded from localization_requested_developer.json via the "message" field
(and "message_type": "HTML"), while localization_requested_developer.html is an
orphaned copy; either delete localization_requested_developer.html to remove
unused files, or if you want to keep it for reference, add a brief top-of-file
comment and document its purpose (e.g., "reference copy for editors; not used at
runtime") and add a note in the notifications README explaining that templates
are loaded from the JSON "message" field so maintainers know why the HTML file
exists.

In
`@localization_management_system/localization_management_system/notification/localization_requested_developer/localization_requested_developer.md`:
- Line 1: The placeholder text "Add your message here" in
localization_requested_developer.md is user-visible and must be replaced with
the final notification copy; open localization_requested_developer.md and
replace the placeholder with a concise, user-facing message that includes the
necessary dynamic fields (e.g., requester name, project/locale, required action,
and a CTA link) and removes any dummy text so the notification renders correctly
for developers.

In
`@localization_management_system/localization_management_system/notification/localization_requested_developer/localization_requested_developer.py`:
- Around line 4-6: get_context currently returns None; update the
get_context(context) function to always return a dictionary (the Jinja template
context) — for example merge/validate the incoming context parameter (if
dict-like) and return a dict with the required keys (or an empty dict) so
rendering never receives None; locate get_context in
localization_requested_developer.py and ensure it returns a dict containing
whatever template variables are needed (or an empty {}) instead of leaving the
function as pass.

In
`@localization_management_system/localization_management_system/notification/localization_requested_internal_team/localization_requested_internal_team.html`:
- Around line 49-57: The .info-row CSS uses display:flex which breaks in some
email clients (notably Outlook); replace the flex-based layout with a
table-based structure: change .info-row to use table/table-row/table-cell
semantics (e.g., make .info-row a table element or set display:table and wrap
each row's cells in elements with display:table-cell), preserve padding and
border-bottom styles, and keep the .info-row:last-child rule to remove the
border and padding; update the HTML where .info-row is used (the info-card rows)
to use <table>/<tr>/<td> or equivalent elements matching the new CSS so content
that relied on flex items becomes table cells.

In `@localization_management_system/patches/set_subjects_from_title.py`:
- Around line 4-6: The patch's execute() currently updates all rows via
frappe.qb.update(EL).set(EL.subject, EL.title).run(), which will overwrite
existing subject values; modify the update to add a WHERE clause so it only
updates records where subject is NULL/empty (e.g., using EL.subject IS NULL or
equivalent) before calling .run(), ensuring you reference the same EL DocType
binding and the same set(EL.subject, EL.title) call.
🧹 Nitpick comments (6)
localization_management_system/localization_management_system/notification/localization_requested_internal_team/localization_requested_internal_team.html (1)

125-133: External image dependency may be blocked by email clients.

Many email clients block external images by default. The flag from flagcdn.com may not display until the recipient enables image loading. The conditional check on doc.country_code is good, and the country name still renders as fallback text, so this degrades gracefully.

localization_management_system/localization_management_system/doctype/erpnext_localization/templates/erpnext_localization.html (1)

5-11: Duplicate .country-flag CSS definition.

The .country-flag class is defined identically at lines 5-11 and lines 117-123. Remove one of the duplicates to improve maintainability.

♻️ Suggested fix: Remove duplicate CSS block
-    .country-flag {
-        display: inline-block;
-        margin-right: 0.5rem;
-        vertical-align: middle;
-        border-radius: 2px;
-        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
-    }
-
     .localization-cta-card {

Remove lines 117-123 since the same styles are already defined at lines 5-11.

Also applies to: 117-123

localization_management_system/localization_management_system/doctype/erpnext_localization/templates/erpnext_localization_row.html (1)

15-16: Inconsistent indentation: mixing tabs and spaces.

Lines 15-16 use 4-space indentation while the rest of the file uses tabs. This can cause rendering inconsistencies and maintainability issues.

♻️ Suggested fix
-    border: 1px solid `#7a7c80`;
-}
+	border: 1px solid `#7a7c80`;
+}
localization_management_system/localization_management_system/notification/localization_requested_developer/localization_requested_developer.html (1)

154-157: Consider adding a fallback for empty applicable_for.

If doc.applicable_for is not set, this will render an empty value. Consider adding a fallback similar to the main template's "Not specified" pattern.

♻️ Suggested fix
                     <div class="info-row">
                         <div class="info-label">Type:</div>
-                        <div class="info-value">{{ doc.applicable_for }}</div>
+                        <div class="info-value">{{ doc.applicable_for or "Not specified" }}</div>
                     </div>
localization_management_system/localization_management_system/doctype/localization_task/localization_task.json (2)

68-74: Consider adding a default value for the status field.

The status field has no default value, so newly created tasks will have an empty status. Consider adding "default": "Open" to ensure new tasks start with a meaningful status.

Suggested fix
  {
+  "default": "Open",
   "fieldname": "status",
   "fieldtype": "Select",
   "in_list_view": 1,
   "label": "Status",
   "options": "Open\nClosed\nCancelled"
  },

50-63: Date range validation should be handled in the parent DocType.

The start_date and end_date fields lack validation to ensure end_date >= start_date. Since this is a child table, consider adding validation logic in the parent ERPNextLocalization.validate() method to check task date consistency.

@@ -0,0 +1 @@
Add your message here No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Replace placeholder notification copy.
This will be user-visible as-is.

🤖 Prompt for AI Agents
In
`@localization_management_system/localization_management_system/notification/localization_requested_developer/localization_requested_developer.md`
at line 1, The placeholder text "Add your message here" in
localization_requested_developer.md is user-visible and must be replaced with
the final notification copy; open localization_requested_developer.md and
replace the placeholder with a concise, user-facing message that includes the
necessary dynamic fields (e.g., requester name, project/locale, required action,
and a CTA link) and removes any dummy text so the notification renders correctly
for developers.

Comment on lines +4 to +6
def execute():
EL = frappe.qb.DocType("ERPNext Localization")
frappe.qb.update(EL).set(EL.subject, EL.title).run()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "set_subjects_from_title.py" -type f

Repository: resilient-tech/localization-management-system

Length of output: 234


🌐 Web query:

frappe.qb.update() ERPNext localization patch set_subjects_from_title

💡 Result:

You can write a patch that uses Frappe Query Builder's update to set the subjects field from the title (or any computed value) in bulk. Example patch (save as erpnext/.../patches/set_subjects_from_title.py and add to patches.txt):

import frappe
from frappe.qb import DocType
from frappe.qb import Field

def execute():
Doc = DocType("Your Doctype") # e.g. "Article" or "Web Page"
# assume title and subjects are columns in the table
# build an UPDATE ... SET subjects = WHERE subjects IS NULL
# here we copy title → subjects; adjust expression as needed (e.g. substring, split)
frappe.db.sql(
frappe.qb.update(Doc)
.set(Doc.subjects, Doc.title)
.where(Doc.subjects.isnull())
.get_sql()
)
frappe.db.commit()

Notes:

  • Replace "Your Doctype" and field names with your actual doctype/fields.
  • If you need string manipulation (e.g. split title into comma-separated subjects), use SQL functions in the set expression; you can use Field("...") to inject SQL functions. Example: .set(Doc.subjects, Field("SUBSTRING_INDEX(%s, ' - ', 1)" % Doc.title)) .
  • Test on a copy of your site before running on production and run bench migrate to apply the patch.

References:

  • Frappe Query Builder usage (get_query / qb docs). [1]
  • Example pattern for writing patches that update doctypes. [2]

Sources:
[1] https://docs.frappe.io/framework/get_query
[2] https://sabbirz.com/blog/update-doctypes-after-data-entry-using-frappe-patches


🌐 Web query:

frappe QueryBuilder update without WHERE clause data loss risk

💡 Result:

Short answer: very high risk — an update issued without a WHERE (or filters) will modify every row in the target table and can cause irreversible data loss unless you can restore from backup. See Frappe/SQL docs and general SQL guidance. [1][2][3]

Immediate safeguards and recommendations

  • Never run UPDATE without filters in production; always use QueryBuilder filters or frappe.db.set_value/frappe.db.update with an explicit name/filters. [1][2]
  • Preview the affected rows first: run an equivalent SELECT with the same filters before UPDATE. (If the SELECT returns all rows, your UPDATE will too.) [3]
  • Use transactions on migration scripts: wrap in a transaction and test rollback before commit, or run on a copy of the DB. Frappe bench migrate/actions should be tested on staging first. [2]
  • Take a backup before running any mass update (dump or snapshot) so you can restore quickly. (bench backup / DB-level snapshot.)
  • Add safety checks in code: assert rowcount > 0 and <= expected, or require an explicit flag to allow full-table updates; fail otherwise.
  • Use LIMIT (if supported) or filter by primary key batches and run small, tested batches rather than one huge UPDATE.
  • Log and test scripts on staging/dev and use a dry-run mode that shows SQL without executing it.
  • Consider row-level locking (FOR UPDATE/for_update) if concurrency matters. [1]

If you already ran an unsafe UPDATE

  • Stop further writes, take a DB dump immediately (even in broken state) to preserve ability to investigate.
  • Restore from the most recent good backup to recover; if none, you may need to reconstruct via logs or application-level exports.
  • Check binary/transaction logs (MySQL binlog, WAL) for point-in-time recovery if your DB has them enabled.

Relevant references

  • QueryBuilder / get_query docs (filters, for_update). [1]
  • frappe.db API (set_value / update behavior). [2]
  • General SQL behavior for UPDATE without WHERE (affects all rows). [3]

References
[1] Frappe Query/get_query docs — filters, for_update.
[2] Frappe DB API (frappe.db.set_value / update).
[3] SQL: UPDATE without WHERE — explanation and consequences.


Add a WHERE clause to prevent overwriting existing subject values.
This update currently runs unconditionally on all rows. Frappe's documentation for similar bulk update patches includes a guard (e.g., .where(subject IS NULL)) to prevent data loss. Without it, any pre-existing subject values will be overwritten.

Suggested fix
 def execute():
     EL = frappe.qb.DocType("ERPNext Localization")
-    frappe.qb.update(EL).set(EL.subject, EL.title).run()
+    frappe.qb.update(EL).set(EL.subject, EL.title).where(
+        (EL.subject.isnull()) | (EL.subject == "")
+    ).run()
🤖 Prompt for AI Agents
In `@localization_management_system/patches/set_subjects_from_title.py` around
lines 4 - 6, The patch's execute() currently updates all rows via
frappe.qb.update(EL).set(EL.subject, EL.title).run(), which will overwrite
existing subject values; modify the update to add a WHERE clause so it only
updates records where subject is NULL/empty (e.g., using EL.subject IS NULL or
equivalent) before calling .run(), ensuring you reference the same EL DocType
binding and the same set(EL.subject, EL.title) call.

@Abdeali099
Abdeali099 deleted the phase-2-enhancement branch January 20, 2026 13:18
@coderabbitai coderabbitai Bot mentioned this pull request Jan 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant