From 7d7037dd500e2625f069144d03dd387046661105 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Thu, 20 Mar 2025 10:49:54 +0530 Subject: [PATCH 01/14] feat: scrollable list view --- .../list_view_settings.json | 4 +-- .../list_view_settings/list_view_settings.py | 2 +- frappe/public/js/frappe/list/base_list.js | 7 +++- frappe/public/js/frappe/list/list_settings.js | 20 ++++++++++-- frappe/public/js/frappe/list/list_view.js | 2 +- frappe/public/scss/desk/page.scss | 32 +++++++++++++++++-- 6 files changed, 58 insertions(+), 9 deletions(-) diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.json b/frappe/desk/doctype/list_view_settings/list_view_settings.json index ddadffb2f7..09326d82f0 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.json +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.json @@ -39,7 +39,7 @@ "fieldname": "total_fields", "fieldtype": "Select", "label": "Maximum Number of Fields", - "options": "\n4\n5\n6\n7\n8\n9\n10" + "options": "\n4\n5\n6\n7\n8\n9\n10\n20\n25" }, { "fieldname": "fields_html", @@ -75,7 +75,7 @@ ], "grid_page_length": 50, "links": [], - "modified": "2025-03-12 16:28:46.073808", + "modified": "2025-03-13 19:55:21.695027", "modified_by": "Administrator", "module": "Desk", "name": "List View Settings", diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.py b/frappe/desk/doctype/list_view_settings/list_view_settings.py index 5d1d4e153d..ded63e59c2 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.py @@ -21,7 +21,7 @@ class ListViewSettings(Document): disable_count: DF.Check disable_sidebar_stats: DF.Check fields: DF.Code | None - total_fields: DF.Literal["", "4", "5", "6", "7", "8", "9", "10"] + total_fields: DF.Literal["", "4", "5", "6", "7", "8", "9", "10", "20", "25"] # end: auto-generated types pass diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index 4265cd0ddd..ed1d13ab94 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -309,6 +309,7 @@ frappe.views.BaseList = class BaseList { this.show_or_hide_sidebar, this.setup_filter_area, this.setup_sort_selector, + this.setup_result_container_area, this.setup_result_area, this.setup_no_result_area, this.setup_freeze_area, @@ -349,9 +350,13 @@ frappe.views.BaseList = class BaseList { this.refresh(); } + setup_result_container_area() { + this.$frappe_list.append($(`
`)); + } + setup_result_area() { this.$result = $(`
`); - this.$frappe_list.append(this.$result); + this.$frappe_list.find(".result-container").append(this.$result); } setup_no_result_area() { diff --git a/frappe/public/js/frappe/list/list_settings.js b/frappe/public/js/frappe/list/list_settings.js index 1950edeff2..59533dc0a2 100644 --- a/frappe/public/js/frappe/list/list_settings.js +++ b/frappe/public/js/frappe/list/list_settings.js @@ -35,6 +35,7 @@ export default class ListSettings { me.dialog.set_values(me.settings); me.dialog.set_primary_action(__("Save"), () => { let values = me.dialog.get_values(); + console.log(values, "values"); frappe.show_alert({ message: __("Saving"), @@ -114,15 +115,23 @@ export default class ListSettings { fields += `
+ data-label="${me.fields[idx].label}" data-type="${me.fields[idx].type}" data-col-width="${ + me.fields[idx].columns + }">
${frappe.utils.icon("drag", "xs", "", "", "sortable-handle " + show_sortable_handle)}
-
+
${__(me.fields[idx].label, null, me.doctype)}
+
+ +
${frappe.utils.icon("delete", "xs")} @@ -210,9 +219,12 @@ export default class ListSettings { me.fields = []; for (let idx = 0; idx < fields_order.length; idx++) { + // console.log(fields_order.item(idx)); + me.fields.push({ fieldname: fields_order.item(idx).getAttribute("data-fieldname"), label: __(fields_order.item(idx).getAttribute("data-label")), + // col_width: __(fields_order.item(idx).getAttribute("data-col-width")), }); } @@ -301,6 +313,8 @@ export default class ListSettings { get_listview_fields(meta) { let me = this; + // console.log(me, "list"); + if (!me.settings.fields) { me.set_list_view_fields(meta); } else { @@ -317,6 +331,8 @@ export default class ListSettings { me.set_status_field(); meta.fields.forEach((field) => { + console.log(field, "field"); + if ( field.in_list_view && !frappe.model.no_value_type.includes(field.fieldtype) && diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 903f91ed12..e8925e4812 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -768,7 +768,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { return `
-
+
${left}
diff --git a/frappe/public/scss/desk/page.scss b/frappe/public/scss/desk/page.scss index 044148534f..ca53cb10ed 100644 --- a/frappe/public/scss/desk/page.scss +++ b/frappe/public/scss/desk/page.scss @@ -93,7 +93,8 @@ } .layout-main-section-wrapper { - width: 100%; + flex: 1 0 80%; + width: 80%; } .layout-main-section.frappe-card { @@ -179,12 +180,33 @@ .layout-main-section { scroll-margin-top: var(--navbar-height); + .frappe-list { + .result-container { + overflow-x: auto; + .result { + width: fit-content; + min-width: 100%; + .list-row-container:first-child { + position: sticky; + top: 0; + z-index: 2; + } + .list-row-container .level-left { + .list-row-col { + flex: 1 0 150px; + width: 150px; + } + } + } + } + } + .frappe-list, .report-wrapper { .result, .no-result, .freeze { - min-height: "200px"; + min-height: 200px; } .result { @@ -221,3 +243,9 @@ margin-top: var(--margin-xs); text-align: center; } + +.frappe-control { + .form-control.fields_order { + padding-top: 1.5px; + } +} From 72d3575397e7b58f5c69fc139e840bf0fb45e286 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 21 Mar 2025 11:57:48 +0530 Subject: [PATCH 02/14] refactor: [wip] stick activity section to right --- frappe/public/scss/desk/list.scss | 10 +++++++--- frappe/public/scss/desk/page.scss | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index 9d97bafc33..c32e77243c 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -101,9 +101,13 @@ min-width: 80%; } .level-right { - flex: 1; - overflow: visible; - align-items: center; + // flex: 1; + // overflow: visible; + // align-items: center; + position: sticky; + right: 0; + background-color: #fff; + padding-right: 10px; } .tag-col { diff --git a/frappe/public/scss/desk/page.scss b/frappe/public/scss/desk/page.scss index ca53cb10ed..709f59c793 100644 --- a/frappe/public/scss/desk/page.scss +++ b/frappe/public/scss/desk/page.scss @@ -186,6 +186,10 @@ .result { width: fit-content; min-width: 100%; + width: auto; + .list-row-container { + width: fit-content; + } .list-row-container:first-child { position: sticky; top: 0; From eb9d0be8c427957b78c1950b07635a9fca3f0433 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Mon, 24 Mar 2025 13:29:03 +0530 Subject: [PATCH 03/14] feat: calculate columns width automatically --- frappe/public/js/frappe/list/list_view.js | 26 ++++++++++++++++++++++- frappe/public/scss/desk/list.scss | 16 ++++++++++---- frappe/public/scss/desk/page.scss | 12 ++++++----- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index e8925e4812..0a94333d5a 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -33,6 +33,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { ); this.count_upper_bound = 1001; this._element_factory = new ElementFactory(this.doctype); + this.column_max_widths = {}; } has_permissions() { @@ -641,6 +642,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { this.$result.append(this.get_list_row_html(doc)); } } + this.apply_column_widths(); } render_count() { @@ -697,6 +699,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { col.type == "Subject" ? "list-subject level" : "hidden-xs", col.type == "Tag" ? "tag-col hide" : "", frappe.model.is_numeric_field(col.df) ? "text-right" : "", + col.df?.fieldname, ].join(" "); let html = ""; @@ -768,7 +771,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { return `
-
+
${left}
@@ -893,6 +896,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { "list-row-col ellipsis", class_map[col.type], frappe.model.is_numeric_field(df) ? "text-right" : "", + fieldname, ].join(" "); let column_html; @@ -909,6 +913,17 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { }[col.type]; } + let textLength = $(column_html).text()?.trim()?.length || 22.5; + let calculatedWidth = (textLength * 10) / 1.3; + + // store the max width for this column + if ( + !this.column_max_widths[fieldname] || + calculatedWidth > this.column_max_widths[fieldname] + ) { + this.column_max_widths[fieldname] = calculatedWidth; + } + return `
${column_html} @@ -916,6 +931,15 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { `; } + apply_column_widths() { + Object.entries(this.column_max_widths).forEach(([fieldname, width]) => { + $(`.${fieldname}`).css({ + width: width, + flex: `1 0 ${width}px`, + }); + }); + } + get_tags_html(user_tags, limit, colored = false) { let get_tag_html = (tag) => { let color = "", diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index c32e77243c..70685d1294 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -80,7 +80,7 @@ } .list-row { - padding-right: 15px; + // padding-right: 15px; height: var(--list-row-height); border-radius: var(--border-radius); cursor: pointer; @@ -92,6 +92,10 @@ background-color: var(--highlight-color); } + &:hover .level-right { + background-color: var(--highlight-color); + } + &:last-child { border-bottom: 0px; } @@ -101,13 +105,12 @@ min-width: 80%; } .level-right { - // flex: 1; - // overflow: visible; - // align-items: center; position: sticky; right: 0; background-color: #fff; padding-right: 10px; + flex: 0 0 180px; + width: 180px; } .tag-col { @@ -184,6 +187,11 @@ .checkbox-actions { display: none; } + .level-right { + background-color: var(--subtle-fg); + border-radius: var(--border-radius); + height: var(--list-row-height); + } } .list-row-col { diff --git a/frappe/public/scss/desk/page.scss b/frappe/public/scss/desk/page.scss index 709f59c793..bd86a517e8 100644 --- a/frappe/public/scss/desk/page.scss +++ b/frappe/public/scss/desk/page.scss @@ -184,21 +184,23 @@ .result-container { overflow-x: auto; .result { - width: fit-content; min-width: 100%; width: auto; .list-row-container { width: fit-content; + min-width: 100%; } .list-row-container:first-child { position: sticky; top: 0; z-index: 2; } - .list-row-container .level-left { - .list-row-col { - flex: 1 0 150px; - width: 150px; + .list-row-container { + .level-left { + .list-row-col { + min-width: 150px; + max-width: 400px; + } } } } From 6d88b6c88b8d757950650670e369b5bf8fd451d6 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 28 Mar 2025 14:57:02 +0530 Subject: [PATCH 04/14] fix: wired scroll behaviour and laggy scroll --- frappe/public/scss/desk/list.scss | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index 70685d1294..c58b8c7715 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -60,7 +60,6 @@ .list-row-container { display: flex; flex-direction: column; - padding: var(--padding-xs) var(--padding-md); border-bottom: 1px solid $border-color; &:focus { @@ -73,15 +72,9 @@ padding-top: 0; border-bottom: none; } - - &:last-child { - border-bottom: none; - } } .list-row { - // padding-right: 15px; - height: var(--list-row-height); border-radius: var(--border-radius); cursor: pointer; transition: color 0.2s; @@ -103,6 +96,7 @@ .level-left { flex: 4; min-width: 80%; + padding: var(--padding-xs) var(--padding-md); } .level-right { position: sticky; @@ -111,6 +105,8 @@ padding-right: 10px; flex: 0 0 180px; width: 180px; + box-shadow: -5px 0px 5px rgb(255, 255, 255); + padding: 8px 10px; } .tag-col { @@ -320,7 +316,6 @@ input.list-header-checkbox { align-items: center; cursor: pointer; - height: var(--list-row-height); padding-left: 15px; @include get_textstyle("base", "regular"); From e17fdaeba0702b37b298a72ef91902c1257f8c4d Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 28 Mar 2025 15:00:04 +0530 Subject: [PATCH 05/14] refactor: add more options in no of fields --- .../desk/doctype/list_view_settings/list_view_settings.json | 4 ++-- frappe/desk/doctype/list_view_settings/list_view_settings.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.json b/frappe/desk/doctype/list_view_settings/list_view_settings.json index 09326d82f0..fb8b2c6998 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.json +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.json @@ -39,7 +39,7 @@ "fieldname": "total_fields", "fieldtype": "Select", "label": "Maximum Number of Fields", - "options": "\n4\n5\n6\n7\n8\n9\n10\n20\n25" + "options": "\n4\n5\n6\n7\n8\n9\n10\n15\n20\n25\n30" }, { "fieldname": "fields_html", @@ -75,7 +75,7 @@ ], "grid_page_length": 50, "links": [], - "modified": "2025-03-13 19:55:21.695027", + "modified": "2025-03-24 14:17:39.888956", "modified_by": "Administrator", "module": "Desk", "name": "List View Settings", diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.py b/frappe/desk/doctype/list_view_settings/list_view_settings.py index ded63e59c2..975d2807cd 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.py @@ -21,7 +21,7 @@ class ListViewSettings(Document): disable_count: DF.Check disable_sidebar_stats: DF.Check fields: DF.Code | None - total_fields: DF.Literal["", "4", "5", "6", "7", "8", "9", "10", "20", "25"] + total_fields: DF.Literal["", "4", "5", "6", "7", "8", "9", "10", "15", "20", "25", "30"] # end: auto-generated types pass From f2d48e95baf4a619494e46c6c5ae89e466e86e0f Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Sun, 30 Mar 2025 05:59:26 +0530 Subject: [PATCH 06/14] fix: assign to unwanted width and shadow --- frappe/public/js/frappe/list/list_view.js | 12 +++++++++ frappe/public/scss/desk/list.scss | 31 +++++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 0a94333d5a..4f65cef208 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -634,15 +634,27 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { this.$result.find(".list-row-container").remove(); this.render_header(); + let has_assignto = false; + if (this.data.length > 0) { // append rows let idx = 0; for (let doc of this.data) { doc._idx = idx++; this.$result.append(this.get_list_row_html(doc)); + if (!has_assignto && doc._assign) { + has_assignto = true; + } } } this.apply_column_widths(); + + // add class to result to indetify that it has assignto + if (has_assignto) { + this.$result.addClass("has-assign-to"); + } else { + this.$result.addClass("no-assign-to"); + } } render_count() { diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index c58b8c7715..aea6c5657e 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -74,6 +74,20 @@ } } +.result.has-assign-to { + .list-row .level-right { + flex: 0 0 180px; + width: 180px; + } +} + +.result.no-assign-to { + .list-row .level-right { + flex: 0 0 130px; + width: 130px; + } +} + .list-row { border-radius: var(--border-radius); cursor: pointer; @@ -83,6 +97,9 @@ &:hover:not(.list-row-head) { background-color: var(--highlight-color); + .level-right { + box-shadow: -5px 0px 5px var(--highlight-color); + } } &:hover .level-right { @@ -101,12 +118,9 @@ .level-right { position: sticky; right: 0; - background-color: #fff; - padding-right: 10px; - flex: 0 0 180px; - width: 180px; + background-color: var(--bg-color); box-shadow: -5px 0px 5px rgb(255, 255, 255); - padding: 8px 10px; + padding: 6px 10px; } .tag-col { @@ -187,6 +201,13 @@ background-color: var(--subtle-fg); border-radius: var(--border-radius); height: var(--list-row-height); + box-shadow: none; + &:hover { + background-color: var(--subtle-fg); + } + } + &:hover .level-right { + background-color: var(--subtle-fg); } } From 43f23ee0a1ee25bd20c90306f3952689187a957b Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Sun, 30 Mar 2025 12:48:13 +0530 Subject: [PATCH 07/14] test: fix failing test case --- cypress/integration/list_view_settings.js | 2 +- frappe/public/js/frappe/list/list_settings.js | 20 ++----------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/cypress/integration/list_view_settings.js b/cypress/integration/list_view_settings.js index 9c66edb5d5..5dafb7a04a 100644 --- a/cypress/integration/list_view_settings.js +++ b/cypress/integration/list_view_settings.js @@ -15,7 +15,7 @@ context("List View Settings", () => { cy.clear_filters(); cy.wait(300); cy.get(".list-count").should("contain", "20 of"); - cy.get("[href='#es-line-chat-alt']").should("be.visible"); + cy.get(".frappe-list svg.es-icon.es-line").should("be.visible"); cy.get(".menu-btn-group button").click(); cy.get(".dropdown-menu li").filter(":visible").contains("List Settings").click(); cy.get(".modal-dialog").should("contain", "DocType Settings"); diff --git a/frappe/public/js/frappe/list/list_settings.js b/frappe/public/js/frappe/list/list_settings.js index 59533dc0a2..1950edeff2 100644 --- a/frappe/public/js/frappe/list/list_settings.js +++ b/frappe/public/js/frappe/list/list_settings.js @@ -35,7 +35,6 @@ export default class ListSettings { me.dialog.set_values(me.settings); me.dialog.set_primary_action(__("Save"), () => { let values = me.dialog.get_values(); - console.log(values, "values"); frappe.show_alert({ message: __("Saving"), @@ -115,23 +114,15 @@ export default class ListSettings { fields += `
+ data-label="${me.fields[idx].label}" data-type="${me.fields[idx].type}">
${frappe.utils.icon("drag", "xs", "", "", "sortable-handle " + show_sortable_handle)}
-
+
${__(me.fields[idx].label, null, me.doctype)}
-
- -
${frappe.utils.icon("delete", "xs")} @@ -219,12 +210,9 @@ export default class ListSettings { me.fields = []; for (let idx = 0; idx < fields_order.length; idx++) { - // console.log(fields_order.item(idx)); - me.fields.push({ fieldname: fields_order.item(idx).getAttribute("data-fieldname"), label: __(fields_order.item(idx).getAttribute("data-label")), - // col_width: __(fields_order.item(idx).getAttribute("data-col-width")), }); } @@ -313,8 +301,6 @@ export default class ListSettings { get_listview_fields(meta) { let me = this; - // console.log(me, "list"); - if (!me.settings.fields) { me.set_list_view_fields(meta); } else { @@ -331,8 +317,6 @@ export default class ListSettings { me.set_status_field(); meta.fields.forEach((field) => { - console.log(field, "field"); - if ( field.in_list_view && !frappe.model.no_value_type.includes(field.fieldtype) && From 128508ed24b87700feaf2c25f8d7868110e3b922 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Sun, 30 Mar 2025 13:38:21 +0530 Subject: [PATCH 08/14] chore: add jsDocs to new function --- frappe/public/js/frappe/list/list_view.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 4f65cef208..429be4a032 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -925,6 +925,10 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { }[col.type]; } + /** + * Calculates the width of a text element based on its length. + * If the length of the text is not available, it defaults to a length of 22.5. + */ let textLength = $(column_html).text()?.trim()?.length || 22.5; let calculatedWidth = (textLength * 10) / 1.3; @@ -943,6 +947,11 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { `; } + /** + * Applies dynamically calculated widths to elements based on their respective class names. + * Iterates through `column_max_widths` and sets the `width` and `flex` styles for each column. + * The width for each column is applied as both a fixed `width` and a flexible `flex` property. + */ apply_column_widths() { Object.entries(this.column_max_widths).forEach(([fieldname, width]) => { $(`.${fieldname}`).css({ From e271227dd045302618f321effcd5e8a28dbf3c29 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Sun, 30 Mar 2025 13:41:57 +0530 Subject: [PATCH 09/14] chore: add jsDocs to new function of base_list --- frappe/public/js/frappe/list/base_list.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/public/js/frappe/list/base_list.js b/frappe/public/js/frappe/list/base_list.js index ed1d13ab94..ef1e219918 100644 --- a/frappe/public/js/frappe/list/base_list.js +++ b/frappe/public/js/frappe/list/base_list.js @@ -350,6 +350,10 @@ frappe.views.BaseList = class BaseList { this.refresh(); } + /** + * Sets up a result container area by appending a new `
` element with the class `result-container` + * to the `frappe_list` container. This container is used to create a scrollable area for the result content. + */ setup_result_container_area() { this.$frappe_list.append($(`
`)); } From 5e7a9b0087e9876aed9c7430978b2f4c9dc99ac1 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Sun, 30 Mar 2025 13:46:24 +0530 Subject: [PATCH 10/14] chore: add jsDocs to new store width --- frappe/public/js/frappe/list/list_view.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 429be4a032..843749c598 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -932,7 +932,10 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { let textLength = $(column_html).text()?.trim()?.length || 22.5; let calculatedWidth = (textLength * 10) / 1.3; - // store the max width for this column + /** + * Updates the `column_max_widths` object by setting the maximum width for a specific column (fieldname). + * If no width is set for the column, or the newly calculated width exceeds the current width, the width is updated. + */ if ( !this.column_max_widths[fieldname] || calculatedWidth > this.column_max_widths[fieldname] From d601990a1980dce0733ad153c894ae7145efac42 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 8 Aug 2025 10:44:01 +0530 Subject: [PATCH 11/14] feat: new mobile list view --- frappe/public/js/frappe/list/list_view.js | 32 ++++++-- frappe/public/scss/desk/list.scss | 89 ++++++++++++++++++++--- 2 files changed, 105 insertions(+), 16 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 627cc5b21f..34670c787f 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -779,7 +779,22 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { } get_left_html(doc) { - let left_html = this.columns.map((col) => this.get_column_html(col, doc)).join(""); + // let left_html = this.columns.map((col) => this.get_column_html(col, doc)).join(""); + + let left_html = ""; + for (let i = 0; i < this.columns.length; i++) { + let col = this.columns[i]; + + if (frappe.is_mobile() && col.type == "Field" && [3, 4].includes(i)) { + left_html += `
${this.get_column_html( + col, + doc, + true + )}
`; + } else { + left_html += this.get_column_html(col, doc, false); + } + } left_html += this.generate_button_html(doc); left_html += this.generate_dropdown_html(doc); @@ -810,7 +825,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { `; } - get_column_html(col, doc) { + get_column_html(col, doc, show_in_mobile) { if (col.type === "Status" || col.df?.options == "Workflow State") { let show_workflow_state = col.df?.options == "Workflow State"; return ` @@ -918,9 +933,9 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { const class_map = { Subject: "list-subject level", - Field: "hidden-xs", + Field: !show_in_mobile ? "hidden-xs" : "", }; - const css_class = [ + let css_class = [ "list-row-col ellipsis", class_map[col.type], frappe.model.is_numeric_field(df) ? "text-right" : "", @@ -941,6 +956,10 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { }[col.type]; } + if (frappe.is_mobile() && col.type == "Subject") { + css_class += " bold"; + } + /** * Calculates the width of a text element based on its length. * If the length of the text is not available, it defaults to a length of 22.5. @@ -953,8 +972,9 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { * If no width is set for the column, or the newly calculated width exceeds the current width, the width is updated. */ if ( - !this.column_max_widths[fieldname] || - calculatedWidth > this.column_max_widths[fieldname] + (!this.column_max_widths[fieldname] || + calculatedWidth > this.column_max_widths[fieldname]) && + !frappe.is_mobile() ) { this.column_max_widths[fieldname] = calculatedWidth; } diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index 39f4a8d816..8b19e5ca52 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -74,17 +74,20 @@ } } -.result.has-assign-to { - .list-row .level-right { - flex: 0 0 180px; - width: 180px; +.frappe-list { + margin: var(--margin-xs) var(--margin-md); + .result.has-assign-to { + .list-row .level-right { + flex: 0 0 180px; + width: 180px; + } } -} -.result.no-assign-to { - .list-row .level-right { - flex: 0 0 130px; - width: 130px; + .result.no-assign-to { + .list-row .level-right { + flex: 0 0 130px; + width: 130px; + } } } @@ -97,6 +100,7 @@ &:hover:not(.list-row-head) { background-color: var(--highlight-color); + border-radius: unset; .level-right { box-shadow: -5px 0px 5px var(--highlight-color); } @@ -113,7 +117,7 @@ .level-left { flex: 4; min-width: 80%; - padding: var(--padding-xs) var(--padding-md); + padding: var(--padding-xs) 0; } .level-right { position: sticky; @@ -527,3 +531,68 @@ input.list-header-checkbox { height: calc(100vh - 284px); z-index: 0; } + +@media (max-width: map-get($grid-breakpoints, "lg")) { + .layout-main-section-wrapper { + width: 100%; + } + .frappe-list { + .list-row { + .level-right { + flex: 0 0 auto; + width: auto; + } + } + } +} + +@media (max-width: map-get($grid-breakpoints, "sm")) { + .layout-main-section .frappe-list .result-container { + .result { + overflow: hidden; + input.list-row-checkbox, + input.list-header-checkbox { + width: 15px !important; + height: 15px; + } + } + .list-row-container:not(:has(.list-row-head)) { + .list-row { + &.level { + align-items: flex-start; + } + .level-left { + min-width: auto; + display: block; + .mobile-layout { + display: inline-block; + z-index: 1; + position: relative; + padding-left: 10px; + .list-row-col { + margin-right: 0px; + } + } + .mobile-layout:not(.mobile-layout ~ .mobile-layout) { + padding-left: 30px; + margin-right: 6px; + + &::after { + content: "\2022"; + position: absolute; + right: 0; + top: 50%; + transform: translate(50%, -50%); + padding-left: 15px; + } + } + } + .level-right { + .level-item.visible-xs { + margin-top: 5px; + } + } + } + } + } +} From 891a568d257d432febef6b914352a6e2848283ee Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 8 Aug 2025 12:25:05 +0530 Subject: [PATCH 12/14] test: fix click todo button test --- cypress/integration/list_view.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cypress/integration/list_view.js b/cypress/integration/list_view.js index d6cc16fef1..397c91215b 100644 --- a/cypress/integration/list_view.js +++ b/cypress/integration/list_view.js @@ -65,10 +65,9 @@ context("List View", () => { cy.go_to_list("ToDo"); // Check if the 'Open' button is present in the ToDo list view - cy.get(".btn-default[data-name='" + todo_name + "']") - .should((el) => { - expect(el).to.exist; - }) + cy.get(`.btn-default[data-name="${todo_name}"]`) + .scrollIntoView({ inline: "center", block: "nearest" }) + .should("be.visible") .click(); cy.window() From bd77e9ccf736cf3245bbc59aa5ce32bcbbd0cdae Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 8 Aug 2025 12:29:03 +0530 Subject: [PATCH 13/14] fix: minor spacing issue --- frappe/public/scss/desk/list.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index 8b19e5ca52..1a1010f701 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -574,7 +574,7 @@ input.list-header-checkbox { } } .mobile-layout:not(.mobile-layout ~ .mobile-layout) { - padding-left: 30px; + padding-left: 27px; margin-right: 6px; &::after { From e38b85518cf0607d9ba7adb0239a6427fb491ae9 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Fri, 8 Aug 2025 12:41:29 +0530 Subject: [PATCH 14/14] fix: allow right content to take dynamic width --- frappe/public/scss/desk/list.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/public/scss/desk/list.scss b/frappe/public/scss/desk/list.scss index 1a1010f701..77c04cec33 100644 --- a/frappe/public/scss/desk/list.scss +++ b/frappe/public/scss/desk/list.scss @@ -588,6 +588,8 @@ input.list-header-checkbox { } } .level-right { + flex: 0 0 auto; + width: auto; .level-item.visible-xs { margin-top: 5px; }