fix(e-taxes): make document-load dialogs fit the screen
The "select records to import" dialogs (VAT operations, sales/purchase invoices, AMAS employees) wasted vertical space: a fixed 500px table plus a context alert pinned to the bottom forced scrolling to reach the content and the buttons. Rework them to the journal_entry pattern: the records table is now the single scroll area sized to the viewport (max-height: calc(100vh - 360px)) with a sticky header, and the top count alert + bottom context alert are merged into one compact header row. Affects journal_entry, sales_order, purchase_order, sales_invoice and employee (AMAS) selection dialogs. No logic/handler changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
610b98ca69
commit
c6e2101c26
|
|
@ -529,17 +529,19 @@ function show_employee_selection(listview, asan_login_name, organization_name, e
|
|||
const existing_count = employees.length - new_count;
|
||||
|
||||
// Build table (e-taxes style)
|
||||
let invoiceTable = '<div style="max-height: 500px; overflow-y: auto;">' +
|
||||
'<table class="table table-bordered amas-employees-table" style="width: 100%; table-layout: fixed;">' +
|
||||
'<thead><tr>' +
|
||||
'<th style="width: 4%;"><input type="checkbox" class="select-all-employees"></th>' +
|
||||
'<th style="width: 20%;">' + __('Full Name') + '</th>' +
|
||||
'<th style="width: 10%;">' + __('FIN') + '</th>' +
|
||||
'<th style="width: 20%;">' + __('Position') + '</th>' +
|
||||
'<th style="width: 8%;">' + __('Salary') + '</th>' +
|
||||
'<th style="width: 12%;">' + __('Status') + '</th>' +
|
||||
'<th style="width: 10%;">' + __('Begin Date') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('In System') + '</th>' +
|
||||
// Таблица сотрудников — единственная прокручиваемая область. Высота привязана
|
||||
// к вьюпорту (calc), чтобы модал целиком помещался в экран. Шапка «липкая».
|
||||
let invoiceTable = '<div class="amas-employees-scroll" style="max-height: calc(100vh - 360px); min-height: 220px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 6px;">' +
|
||||
'<table class="table table-bordered amas-employees-table" style="width: 100%; table-layout: fixed; margin-bottom: 0;">' +
|
||||
'<thead style="position: sticky; top: 0; z-index: 1;"><tr>' +
|
||||
'<th style="width: 4%; background: var(--control-bg, var(--bg-color));"><input type="checkbox" class="select-all-employees"></th>' +
|
||||
'<th style="width: 20%; background: var(--control-bg, var(--bg-color));">' + __('Full Name') + '</th>' +
|
||||
'<th style="width: 10%; background: var(--control-bg, var(--bg-color));">' + __('FIN') + '</th>' +
|
||||
'<th style="width: 20%; background: var(--control-bg, var(--bg-color));">' + __('Position') + '</th>' +
|
||||
'<th style="width: 8%; background: var(--control-bg, var(--bg-color));">' + __('Salary') + '</th>' +
|
||||
'<th style="width: 12%; background: var(--control-bg, var(--bg-color));">' + __('Status') + '</th>' +
|
||||
'<th style="width: 10%; background: var(--control-bg, var(--bg-color));">' + __('Begin Date') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('In System') + '</th>' +
|
||||
'</tr></thead><tbody>';
|
||||
|
||||
employees.forEach(function(emp, idx) {
|
||||
|
|
@ -563,9 +565,19 @@ function show_employee_selection(listview, asan_login_name, organization_name, e
|
|||
|
||||
invoiceTable += '</tbody></table></div>';
|
||||
|
||||
const infoMessage = '<div class="alert alert-info">' +
|
||||
__('Employees found: ') + employees.length +
|
||||
' (' + __('New') + ': ' + new_count + ', ' + __('Already in system') + ': ' + existing_count + ')' +
|
||||
// Компактная шапка: счётчик сотрудников слева + организация справа в одну
|
||||
// строку. Заменяет alert со счётчиком и убирает пустые Section Break-лейблы.
|
||||
const headerHtml =
|
||||
'<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:8px;">' +
|
||||
'<span class="indicator-pill blue" style="font-size:13px;">' +
|
||||
__('Employees found: ') + '<strong>' + employees.length + '</strong>' +
|
||||
' (' + __('New') + ': ' + new_count + ', ' + __('Already in system') + ': ' + existing_count + ')' +
|
||||
'</span>' +
|
||||
(organization_name
|
||||
? '<span style="color: var(--text-muted);">' +
|
||||
__('Organization: ') + '<strong>' + frappe.utils.escape_html(organization_name) + '</strong>' +
|
||||
'</span>'
|
||||
: '') +
|
||||
'</div>';
|
||||
|
||||
const default_company = frappe.defaults.get_user_default('Company') || frappe.defaults.get_global_default('company');
|
||||
|
|
@ -575,9 +587,9 @@ function show_employee_selection(listview, asan_login_name, organization_name, e
|
|||
size: 'large',
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'settings_section',
|
||||
fieldtype: 'Section Break',
|
||||
label: __('Settings')
|
||||
fieldname: 'header_html',
|
||||
fieldtype: 'HTML',
|
||||
options: headerHtml
|
||||
},
|
||||
{
|
||||
fieldname: 'create_designation',
|
||||
|
|
@ -585,16 +597,6 @@ function show_employee_selection(listview, asan_login_name, organization_name, e
|
|||
label: __('Create Designation if not found'),
|
||||
default: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'employees_section',
|
||||
fieldtype: 'Section Break',
|
||||
label: __('Employees')
|
||||
},
|
||||
{
|
||||
fieldname: 'info_html',
|
||||
fieldtype: 'HTML',
|
||||
options: infoMessage
|
||||
},
|
||||
{
|
||||
fieldname: 'employees_html',
|
||||
fieldtype: 'HTML',
|
||||
|
|
|
|||
|
|
@ -1142,17 +1142,21 @@ VATETaxes.import = {
|
|||
// Показать диалог выбора операций
|
||||
showOperationSelection: function(operations, token, company, createAsDraft = 0) {
|
||||
VATETaxes.dialogs.hide();
|
||||
let operationTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered vat-operations-table" style="width: 100%; table-layout: fixed;">';
|
||||
operationTable += '<thead><tr>' +
|
||||
'<th style="width: 3%;"><input type="checkbox" class="select-all-operations"></th>' +
|
||||
'<th style="width: 8%;">' + __('Date') + '</th>' +
|
||||
'<th style="width: 9%;">' + __('TIN') + '</th>' +
|
||||
'<th style="width: 15%;">' + __('Name') + '</th>' +
|
||||
'<th style="width: 15%;">' + __('Operation Type') + '</th>' +
|
||||
'<th style="width: 9%;">' + __('Classification Code') + '</th>' +
|
||||
'<th style="width: 17%;">' + __('Explanation') + '</th>' +
|
||||
'<th style="width: 12%;">' + __('Income') + '</th>' +
|
||||
'<th style="width: 12%;">' + __('Expense') + '</th>' +
|
||||
// Таблица операций — единственная прокручиваемая область. Высота привязана к
|
||||
// вьюпорту (calc), чтобы модал целиком помещался в экран без внешнего скролла.
|
||||
// Шапка таблицы «липкая» (sticky), чтобы заголовки колонок оставались видны
|
||||
// при прокрутке списка.
|
||||
let operationTable = '<div class="vat-operations-scroll" style="max-height: calc(100vh - 360px); min-height: 220px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 6px;"><table class="table table-bordered vat-operations-table" style="width: 100%; table-layout: fixed; margin-bottom: 0;">';
|
||||
operationTable += '<thead style="position: sticky; top: 0; z-index: 1;"><tr style="background: var(--control-bg, var(--bg-color));">' +
|
||||
'<th style="width: 3%; background: var(--control-bg, var(--bg-color));"><input type="checkbox" class="select-all-operations"></th>' +
|
||||
'<th style="width: 8%; background: var(--control-bg, var(--bg-color));">' + __('Date') + '</th>' +
|
||||
'<th style="width: 9%; background: var(--control-bg, var(--bg-color));">' + __('TIN') + '</th>' +
|
||||
'<th style="width: 15%; background: var(--control-bg, var(--bg-color));">' + __('Name') + '</th>' +
|
||||
'<th style="width: 15%; background: var(--control-bg, var(--bg-color));">' + __('Operation Type') + '</th>' +
|
||||
'<th style="width: 9%; background: var(--control-bg, var(--bg-color));">' + __('Classification Code') + '</th>' +
|
||||
'<th style="width: 17%; background: var(--control-bg, var(--bg-color));">' + __('Explanation') + '</th>' +
|
||||
'<th style="width: 12%; background: var(--control-bg, var(--bg-color));">' + __('Income') + '</th>' +
|
||||
'<th style="width: 12%; background: var(--control-bg, var(--bg-color));">' + __('Expense') + '</th>' +
|
||||
'</tr></thead><tbody>';
|
||||
|
||||
operations.forEach(function(operation) {
|
||||
|
|
@ -1188,23 +1192,27 @@ VATETaxes.import = {
|
|||
|
||||
operationTable += '</tbody></table></div>';
|
||||
|
||||
const infoMessage = '<div class="alert alert-info">' +
|
||||
__('New VAT operations found: ') + operations.length +
|
||||
'</div>';
|
||||
// Компактная шапка: количество операций + компания в одной строке.
|
||||
// Заменяет два отдельных alert'а (верхний со счётчиком и нижний с компанией,
|
||||
// который раньше уезжал под таблицу и требовал скролла).
|
||||
const headerHtml =
|
||||
'<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:8px;">' +
|
||||
'<span class="indicator-pill blue" style="font-size:13px;">' +
|
||||
__('New VAT operations found: ') + '<strong>' + operations.length + '</strong>' +
|
||||
'</span>' +
|
||||
'<span style="color: var(--text-muted);">' +
|
||||
__('Company: ') + '<strong>' + frappe.utils.escape_html(company) + '</strong>' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Select VAT Operations'),
|
||||
size: 'large',
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'info_html',
|
||||
fieldname: 'header_html',
|
||||
fieldtype: 'HTML',
|
||||
options: infoMessage
|
||||
},
|
||||
{
|
||||
fieldname: 'settings_section',
|
||||
fieldtype: 'Section Break',
|
||||
label: __('Import Settings')
|
||||
options: headerHtml
|
||||
},
|
||||
{
|
||||
fieldname: 'create_as_draft',
|
||||
|
|
@ -1213,6 +1221,10 @@ VATETaxes.import = {
|
|||
default: createAsDraft,
|
||||
description: __('If checked, Journal Entries will be created in Draft status instead of being submitted automatically')
|
||||
},
|
||||
{
|
||||
fieldname: 'settings_col_break',
|
||||
fieldtype: 'Column Break'
|
||||
},
|
||||
{
|
||||
fieldname: 'auto_create_customers',
|
||||
fieldtype: 'Check',
|
||||
|
|
@ -1222,19 +1234,12 @@ VATETaxes.import = {
|
|||
},
|
||||
{
|
||||
fieldname: 'operations_section',
|
||||
fieldtype: 'Section Break',
|
||||
label: __('Operations')
|
||||
fieldtype: 'Section Break'
|
||||
},
|
||||
{
|
||||
fieldname: 'operations_html',
|
||||
fieldtype: 'HTML',
|
||||
options: operationTable
|
||||
},
|
||||
{
|
||||
fieldname: 'company_display',
|
||||
fieldtype: 'HTML',
|
||||
options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
|
||||
__('Selected company: ') + '<strong>' + company + '</strong></div></div></div>'
|
||||
}
|
||||
],
|
||||
primary_action_label: __('Load Selected'),
|
||||
|
|
|
|||
|
|
@ -1094,13 +1094,13 @@ ETaxes.import = {
|
|||
|
||||
// Показать диалог выбора инвойсов
|
||||
showInvoiceSelection: function(invoices, token, warehouse) {
|
||||
let invoiceTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered etaxes-invoices-table" style="width: 100%; table-layout: fixed;">';
|
||||
invoiceTable += '<thead><tr>' +
|
||||
'<th style="width: 6%;"><input type="checkbox" class="select-all-invoices"></th>' +
|
||||
'<th style="width: 24%;">' + __('Number') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('Date') + '</th>' +
|
||||
'<th style="width: 38%;">' + __('Supplier') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('Amount') + '</th>' +
|
||||
let invoiceTable = '<div class="etaxes-purchase-scroll" style="max-height: calc(100vh - 360px); min-height: 220px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 6px;"><table class="table table-bordered etaxes-invoices-table" style="width: 100%; table-layout: fixed; margin-bottom: 0;">';
|
||||
invoiceTable += '<thead style="position: sticky; top: 0; z-index: 1;"><tr>' +
|
||||
'<th style="width: 6%; background: var(--control-bg, var(--bg-color));"><input type="checkbox" class="select-all-invoices"></th>' +
|
||||
'<th style="width: 24%; background: var(--control-bg, var(--bg-color));">' + __('Number') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('Date') + '</th>' +
|
||||
'<th style="width: 38%; background: var(--control-bg, var(--bg-color));">' + __('Supplier') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('Amount') + '</th>' +
|
||||
'</tr></thead><tbody>';
|
||||
|
||||
invoices.forEach(function(invoice) {
|
||||
|
|
@ -1127,9 +1127,15 @@ ETaxes.import = {
|
|||
|
||||
invoiceTable += '</tbody></table></div>';
|
||||
|
||||
const infoMessage = '<div class="alert alert-info">' +
|
||||
__('New invoices found: ') + invoices.length +
|
||||
'</div>';
|
||||
const infoMessage =
|
||||
'<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:8px;">' +
|
||||
'<span class="indicator-pill blue" style="font-size:13px;">' +
|
||||
__('New invoices found: ') + '<strong>' + invoices.length + '</strong>' +
|
||||
'</span>' +
|
||||
'<span style="color: var(--text-muted);">' +
|
||||
__('Selected warehouse: ') + '<strong>' + frappe.utils.escape_html(warehouse) + '</strong>' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Select invoice'),
|
||||
|
|
@ -1144,12 +1150,6 @@ ETaxes.import = {
|
|||
fieldname: 'invoices_html',
|
||||
fieldtype: 'HTML',
|
||||
options: invoiceTable
|
||||
},
|
||||
{
|
||||
fieldname: 'warehouse_display',
|
||||
fieldtype: 'HTML',
|
||||
options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
|
||||
__('Selected warehouse: ') + '<strong>' + warehouse + '</strong></div></div></div>'
|
||||
}
|
||||
],
|
||||
primary_action_label: __('Load selected'),
|
||||
|
|
|
|||
|
|
@ -1113,13 +1113,13 @@ ETaxes.import = {
|
|||
|
||||
// Показать диалог выбора инвойсов
|
||||
showInvoiceSelection: function(invoices, token, warehouse) {
|
||||
let invoiceTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered etaxes-invoices-table" style="width: 100%; table-layout: fixed;">';
|
||||
invoiceTable += '<thead><tr>' +
|
||||
'<th style="width: 6%;"><input type="checkbox" class="select-all-invoices"></th>' +
|
||||
'<th style="width: 24%;">' + __('Number') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('Date') + '</th>' +
|
||||
'<th style="width: 38%;">' + __('Supplier') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('Amount') + '</th>' +
|
||||
let invoiceTable = '<div class="etaxes-sales-inv-scroll" style="max-height: calc(100vh - 360px); min-height: 220px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 6px;"><table class="table table-bordered etaxes-invoices-table" style="width: 100%; table-layout: fixed; margin-bottom: 0;">';
|
||||
invoiceTable += '<thead style="position: sticky; top: 0; z-index: 1;"><tr>' +
|
||||
'<th style="width: 6%; background: var(--control-bg, var(--bg-color));"><input type="checkbox" class="select-all-invoices"></th>' +
|
||||
'<th style="width: 24%; background: var(--control-bg, var(--bg-color));">' + __('Number') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('Date') + '</th>' +
|
||||
'<th style="width: 38%; background: var(--control-bg, var(--bg-color));">' + __('Supplier') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('Amount') + '</th>' +
|
||||
'</tr></thead><tbody>';
|
||||
|
||||
invoices.forEach(function(invoice) {
|
||||
|
|
@ -1146,29 +1146,29 @@ ETaxes.import = {
|
|||
|
||||
invoiceTable += '</tbody></table></div>';
|
||||
|
||||
const infoMessage = '<div class="alert alert-info">' +
|
||||
__('New invoices found: ') + invoices.length +
|
||||
'</div>';
|
||||
const headerHtml =
|
||||
'<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:8px;">' +
|
||||
'<span class="indicator-pill blue" style="font-size:13px;">' +
|
||||
__('New invoices found: ') + '<strong>' + invoices.length + '</strong>' +
|
||||
'</span>' +
|
||||
'<span style="color: var(--text-muted);">' +
|
||||
__('Selected warehouse: ') + '<strong>' + frappe.utils.escape_html(warehouse) + '</strong>' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Select invoice'),
|
||||
size: 'large',
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'info_html',
|
||||
fieldname: 'header_html',
|
||||
fieldtype: 'HTML',
|
||||
options: infoMessage
|
||||
options: headerHtml
|
||||
},
|
||||
{
|
||||
fieldname: 'invoices_html',
|
||||
fieldtype: 'HTML',
|
||||
options: invoiceTable
|
||||
},
|
||||
{
|
||||
fieldname: 'warehouse_display',
|
||||
fieldtype: 'HTML',
|
||||
options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
|
||||
__('Selected warehouse: ') + '<strong>' + warehouse + '</strong></div></div></div>'
|
||||
}
|
||||
],
|
||||
primary_action_label: __('Load selected'),
|
||||
|
|
|
|||
|
|
@ -1111,13 +1111,13 @@ SalesETaxes.import = {
|
|||
// Показать диалог выбора инвойсов
|
||||
showInvoiceSelection: function(invoices, token, warehouse) {
|
||||
SalesETaxes.dialogs.hide();
|
||||
let invoiceTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered etaxes-sales-invoices-table" style="width: 100%; table-layout: fixed;">';
|
||||
invoiceTable += '<thead><tr>' +
|
||||
'<th style="width: 6%;"><input type="checkbox" class="select-all-sales-invoices"></th>' +
|
||||
'<th style="width: 24%;">' + __('Number') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('Date') + '</th>' +
|
||||
'<th style="width: 38%;">' + __('Customer') + '</th>' +
|
||||
'<th style="width: 16%;">' + __('Amount') + '</th>' +
|
||||
let invoiceTable = '<div class="etaxes-sales-scroll" style="max-height: calc(100vh - 360px); min-height: 220px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 6px;"><table class="table table-bordered etaxes-sales-invoices-table" style="width: 100%; table-layout: fixed; margin-bottom: 0;">';
|
||||
invoiceTable += '<thead style="position: sticky; top: 0; z-index: 1;"><tr>' +
|
||||
'<th style="width: 6%; background: var(--control-bg, var(--bg-color));"><input type="checkbox" class="select-all-sales-invoices"></th>' +
|
||||
'<th style="width: 24%; background: var(--control-bg, var(--bg-color));">' + __('Number') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('Date') + '</th>' +
|
||||
'<th style="width: 38%; background: var(--control-bg, var(--bg-color));">' + __('Customer') + '</th>' +
|
||||
'<th style="width: 16%; background: var(--control-bg, var(--bg-color));">' + __('Amount') + '</th>' +
|
||||
'</tr></thead><tbody>';
|
||||
|
||||
invoices.forEach(function(invoice) {
|
||||
|
|
@ -1144,29 +1144,32 @@ SalesETaxes.import = {
|
|||
|
||||
invoiceTable += '</tbody></table></div>';
|
||||
|
||||
const infoMessage = '<div class="alert alert-info">' +
|
||||
__('Sales invoices found: ') + invoices.length +
|
||||
'</div>';
|
||||
// Компактная шапка: количество инвойсов + склад в одной строке.
|
||||
// Заменяет два отдельных alert'а (верхний со счётчиком и нижний со складом,
|
||||
// который раньше уезжал под таблицу и требовал скролла).
|
||||
const headerHtml =
|
||||
'<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:8px;">' +
|
||||
'<span class="indicator-pill blue" style="font-size:13px;">' +
|
||||
__('Sales invoices found: ') + '<strong>' + invoices.length + '</strong>' +
|
||||
'</span>' +
|
||||
'<span style="color: var(--text-muted);">' +
|
||||
__('Selected delivery warehouse: ') + '<strong>' + frappe.utils.escape_html(warehouse) + '</strong>' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Select sales invoice'),
|
||||
size: 'large',
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'info_html',
|
||||
fieldname: 'header_html',
|
||||
fieldtype: 'HTML',
|
||||
options: infoMessage
|
||||
options: headerHtml
|
||||
},
|
||||
{
|
||||
fieldname: 'invoices_html',
|
||||
fieldtype: 'HTML',
|
||||
options: invoiceTable
|
||||
},
|
||||
{
|
||||
fieldname: 'warehouse_display',
|
||||
fieldtype: 'HTML',
|
||||
options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
|
||||
__('Selected delivery warehouse: ') + '<strong>' + warehouse + '</strong></div></div></div>'
|
||||
}
|
||||
],
|
||||
primary_action_label: __('Load selected'),
|
||||
|
|
|
|||
Loading…
Reference in New Issue