diff --git a/jey_theme/public/css/shared.css b/jey_theme/public/css/shared.css
index bf8e49e..2fe8c13 100644
--- a/jey_theme/public/css/shared.css
+++ b/jey_theme/public/css/shared.css
@@ -13,7 +13,8 @@
}
/* Hide Organization desktop icon by default */
-.desktop-icon[data-id="Organization"] {
+.desktop-icon[data-id="Organization"],
+.desktop-icon[data-id="ERPNext"] {
display: none !important;
}
@@ -1375,3 +1376,34 @@ textarea.form-control:focus,
border-color: transparent !important;
box-shadow: none !important;
}
+
+/* List view — period (Between) filter sized to fit "DD/MM/YYYY to DD/MM/YYYY". */
+.standard-filter-section .frappe-control.jey-period-filter {
+ flex: 0 0 auto;
+ min-width: 200px;
+}
+.standard-filter-section .frappe-control.jey-period-filter input {
+ min-width: 200px;
+}
+
+/* Grid "Configure Columns" dialog — let rows grow when label wraps.
+ Frappe hardcodes height:32px inline on each .fields_order row in
+ grid_row.js, which clips long translated labels (eg. Azerbaijani
+ "Əsas Tarif (Anbar Ölçü Vahidinə görə)") so the wrapped portion
+ overflows into the next row and into the help text below. Switch
+ to flex centering with min-height so rows grow with content. */
+.control-input.fields_order {
+ height: auto !important;
+ min-height: 32px;
+ display: flex;
+ align-items: center;
+}
+.control-input.fields_order > .row {
+ width: 100%;
+ align-items: center;
+ margin: 0;
+}
+.control-input.fields_order > .row > [class*="col-"] {
+ padding-top: 0 !important;
+ margin-top: 0 !important;
+}
diff --git a/jey_theme/public/js/jey_theme.js b/jey_theme/public/js/jey_theme.js
index c43a0cd..eaab694 100644
--- a/jey_theme/public/js/jey_theme.js
+++ b/jey_theme/public/js/jey_theme.js
@@ -1921,6 +1921,215 @@
}
})();
+/* ==========================================================================
+ List View — Period filter (Between) for date fields like posting_date
+ Replaces the single-date "=" standard filter with a DateRange "Between"
+ control, or injects one after the ID filter if it's not in standard_filter.
+ ========================================================================== */
+
+(function () {
+ "use strict";
+
+ /* Trigger fields: if doctype has any of these as Date/Datetime, we upgrade.
+ Order matters — first match wins. Extend freely. */
+ var TRIGGER_FIELDS = ["posting_date"];
+
+ function findTriggerDf(listview) {
+ if (!listview || !listview.meta || !Array.isArray(listview.meta.fields)) return null;
+ var fields = listview.meta.fields;
+ for (var i = 0; i < TRIGGER_FIELDS.length; i++) {
+ var name = TRIGGER_FIELDS[i];
+ for (var j = 0; j < fields.length; j++) {
+ var f = fields[j];
+ if (f.fieldname === name && (f.fieldtype === "Date" || f.fieldtype === "Datetime")) {
+ return f;
+ }
+ }
+ }
+ return null;
+ }
+
+ function patchFilterAreaProto(filter_area) {
+ var proto = Object.getPrototypeOf(filter_area);
+ if (!proto || proto.__jeyBetweenPatched) return;
+ proto.__jeyBetweenPatched = true;
+
+ var origSetStandard = proto.set_standard_filter;
+ proto.set_standard_filter = function (filters) {
+ if (!filters || filters.length === 0) return origSetStandard.call(this, filters);
+
+ var fields_dict = this.list_view.page.fields_dict || {};
+ var handled = [];
+ var passthrough = [];
+
+ filters.forEach(function (filter) {
+ var fieldname = filter[1];
+ var condition = filter[2];
+ var value = filter[3];
+ var ctrl = fields_dict[fieldname];
+ if (
+ condition === "Between" &&
+ ctrl &&
+ ctrl.df &&
+ ctrl.df.fieldtype === "DateRange"
+ ) {
+ handled.push({ ctrl: ctrl, value: value });
+ } else {
+ passthrough.push(filter);
+ }
+ });
+
+ var result = origSetStandard.call(this, passthrough);
+
+ if (handled.length) {
+ result.promise = (result.promise || Promise.resolve()).then(function () {
+ handled.forEach(function (h) {
+ h.ctrl.df.match_type = "Between";
+ h.ctrl.df.condition = "Between";
+ return h.ctrl.set_value(h.value);
+ });
+ });
+ }
+ return result;
+ };
+ }
+
+ function buildDateRangeField(listview, df) {
+ var page = listview.page;
+ var $section = page.page_form.find(".standard-filter-section");
+ if (!$section.length) $section = page.page_form;
+
+ var existing = page.fields_dict[df.fieldname];
+ var $placeholder = null;
+
+ if (existing && existing.$wrapper) {
+ var $existingWrap = $(existing.$wrapper);
+ if ($existingWrap.parent().length) {
+ $placeholder = $('');
+ $existingWrap.before($placeholder);
+ }
+ $existingWrap.remove();
+ delete page.fields_dict[df.fieldname];
+ }
+
+ var newField = page.add_field(
+ {
+ fieldtype: "DateRange",
+ label: df.label || "Posting Date",
+ fieldname: df.fieldname,
+ condition: "Between",
+ is_filter: 1,
+ onchange: function () {
+ if (
+ listview &&
+ listview.filter_area &&
+ typeof listview.filter_area.refresh_list_view === "function"
+ ) {
+ listview.filter_area.trigger_refresh = true;
+ listview.filter_area.refresh_list_view();
+ }
+ },
+ },
+ $section
+ );
+
+ if (!newField) return null;
+
+ newField.df.match_type = "Between";
+ newField.df.condition = "Between";
+
+ var $newWrap = $(newField.$wrapper || newField.wrapper);
+ $newWrap.addClass("jey-period-filter");
+
+ if ($placeholder && $placeholder.length) {
+ $placeholder.replaceWith($newWrap);
+ } else {
+ var $idWrap = $section.find('[data-fieldname="name"]').closest(".frappe-control");
+ if ($idWrap.length) {
+ $idWrap.after($newWrap);
+ } else {
+ $section.prepend($newWrap);
+ }
+ }
+
+ return newField;
+ }
+
+ function reflectExistingFilter(listview, df, field) {
+ try {
+ if (
+ !listview.filter_area ||
+ !listview.filter_area.filter_list ||
+ typeof listview.filter_area.filter_list.get_filters !== "function"
+ ) {
+ return;
+ }
+ var filters = listview.filter_area.filter_list.get_filters() || [];
+ var match = null;
+ for (var i = 0; i < filters.length; i++) {
+ var f = filters[i];
+ if (f[1] === df.fieldname && f[2] === "Between") {
+ match = f;
+ break;
+ }
+ }
+ if (!match) return;
+
+ var sidebarFilter = listview.filter_area.filter_list.get_filter(df.fieldname);
+ if (sidebarFilter && typeof sidebarFilter.remove === "function") {
+ sidebarFilter.remove();
+ }
+
+ field.df.match_type = "Between";
+ field.df.condition = "Between";
+ field.set_value(match[3]);
+ } catch (e) {
+ /* noop */
+ }
+ }
+
+ function setup(listview) {
+ if (!listview || listview.view_name !== "List") return;
+ if (listview.__jeyPeriodSet) return;
+ if (!listview.page || !listview.page.page_form) return;
+
+ var df = findTriggerDf(listview);
+ if (!df) return;
+
+ if (listview.filter_area) patchFilterAreaProto(listview.filter_area);
+
+ var field = buildDateRangeField(listview, df);
+ if (!field) return;
+
+ reflectExistingFilter(listview, df, field);
+
+ listview.__jeyPeriodSet = true;
+ }
+
+ function wrapRenderList() {
+ if (!window.frappe || !frappe.views || !frappe.views.ListView) return false;
+ var proto = frappe.views.ListView.prototype;
+ if (proto.__jeyPeriodWrapped) return true;
+ proto.__jeyPeriodWrapped = true;
+
+ var originalRender = proto.render_list;
+ proto.render_list = function () {
+ var result = originalRender.apply(this, arguments);
+ try { setup(this); } catch (e) { /* noop */ }
+ return result;
+ };
+ return true;
+ }
+
+ if (!wrapRenderList()) {
+ var attempts = 0;
+ var iv = setInterval(function () {
+ attempts++;
+ if (wrapRenderList() || attempts > 100) clearInterval(iv);
+ }, 200);
+ }
+})();
+
/* ==========================================================================
List View — Override SVG sprite icons
Replaces content in Frappe's SVG sprite sheets so every