diff --git a/static/css/custom_v2.css b/static/css/custom_v2.css index fd7c0a9..3c70ab4 100644 --- a/static/css/custom_v2.css +++ b/static/css/custom_v2.css @@ -20,6 +20,34 @@ h1, h2, h3, h4, h5, h6 { font-weight: 700; } +/* --- Masar Date Filter Row (Dynamic Wrapper) --- */ +.masar-date-filter-row { + display: flex !important; + flex-direction: row !important; + align-items: center !important; + gap: 3px !important; + width: 100% !important; +} + +.masar-date-filter-row select { + width: 32% !important; + min-width: 50px !important; + font-size: 11px !important; + padding: 2px !important; + height: 30px !important; +} + +.masar-date-filter-row input { + width: 33% !important; + min-width: 50px !important; + font-size: 11px !important; + padding: 2px !important; + height: 30px !important; + margin: 0 !important; +} + + +/* --- Other Admin Tweaks --- */ .hero-section { background: linear-gradient(135deg, var(--primary-dark) 0%, #2D2D30 100%); padding: 100px 0; @@ -28,18 +56,6 @@ h1, h2, h3, h4, h5, h6 { overflow: hidden; } -.hero-section::before { - content: ''; - position: absolute; - top: -50px; - right: -50px; - width: 200px; - height: 200px; - background: var(--accent-orange); - filter: blur(80px); - opacity: 0.2; -} - .glass-card { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(15px); @@ -65,46 +81,6 @@ h1, h2, h3, h4, h5, h6 { color: white; } -.tracking-input { - background: rgba(255, 255, 255, 0.1); - border: 1px solid rgba(255, 255, 255, 0.2); - color: white; - border-radius: 12px 0 0 12px; - padding: 15px 20px; -} - -.tracking-input:focus { - background: rgba(255, 255, 255, 0.15); - border-color: var(--accent-orange); - box-shadow: none; - color: white; -} - -.feature-icon { - width: 60px; - height: 60px; - background: var(--accent-orange); - border-radius: 15px; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 20px; - color: white; - font-size: 24px; -} - -.parcel-status-badge { - padding: 8px 16px; - border-radius: 50px; - font-size: 14px; - font-weight: 600; -} - -.status-pending { background: #FFE8CC; color: #D9480F; } -.status-picked_up { background: #E3FAFC; color: #0B7285; } -.status-in_transit { background: #E7F5FF; color: #1864AB; } -.status-delivered { background: #EBFBEE; color: #2B8A3E; } - /* Chat Widget */ #masar-chat-widget { position: fixed; @@ -132,10 +108,6 @@ h1, h2, h3, h4, h5, h6 { transition: transform 0.2s; } -#masar-chat-toggle:hover { - transform: scale(1.05); -} - /* RTL Support for Chat */ [dir="rtl"] #masar-chat-widget { right: auto; @@ -146,163 +118,14 @@ h1, h2, h3, h4, h5, h6 { left: 20px; } -.typing-dots span { - display: inline-block; - width: 8px; - height: 8px; - background-color: #adb5bd; - border-radius: 50%; - margin: 0 2px; - animation: typing 1s infinite; -} -.typing-dots span:nth-child(2) { animation-delay: 0.2s; } -.typing-dots span:nth-child(3) { animation-delay: 0.4s; } - -@keyframes typing { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-5px); } -} - -/* --- Admin Panel Customizations --- */ - -/* Fix: Prevent accidental file dialog open when clicking labels for logos/favicons */ -body.model-platformprofile label[for="id_logo"], -body.model-platformprofile label[for="id_favicon"], -body.model-platformprofile label[for="id_admin_panel_logo"] { - pointer-events: none; - cursor: default; -} - -/* Improve Admin Form Spacing */ -.form-row { - padding: 15px 10px; - border-bottom: 1px solid #f0f0f0; -} - -/* --- Fix Admin Search Box & Filter Layout --- */ - -/* Target the search form container in Jazzmin/AdminLTE */ -#changelist-search .input-group { - display: flex !important; - flex-wrap: nowrap !important; - max-width: 300px !important; -} - -/* Make the input field take available space */ -#changelist-search input[type="text"] { - flex-grow: 1 !important; - width: auto !important; -} - -/* Ensure the button stays inline */ -#changelist-search button[type="submit"], -#changelist-search .btn { - white-space: nowrap !important; -} - -/* Force filters to sit nicely in a row */ -.filter-wrapper .form-group, -.filter-wrapper select, -.filter-wrapper .select2-container { - margin-bottom: 0 !important; - display: inline-block !important; - width: auto !important; -} - -/* --- Date Range Filter Styling (Compact & Horizontal) --- */ - -/* - We want the [Select] [Start] [End] to all appear on ONE line in the sidebar. - This requires aggressive flex styling and width control. -*/ - -/* 1. Flex Container */ -.admindatefilter .controls.date-filter-controls { - display: flex !important; - flex-direction: row !important; - align-items: center !important; - flex-wrap: nowrap !important; - gap: 2px !important; - width: 100% !important; - padding: 0 !important; - border: none !important; - font-size: 0 !important; /* Hide text nodes (dashes/spaces) between inputs */ -} - -/* 2. Dropdown (Quick Select) */ -.admindatefilter select.admin-date-dropdown { - width: 32% !important; - min-width: 0 !important; - height: 30px !important; - padding: 0px 4px !important; - font-size: 11px !important; - margin: 0 !important; - display: inline-block !important; - flex-shrink: 0 !important; -} - -/* 3. Inputs (From / To) */ -.admindatefilter .date-input { - width: 33% !important; - min-width: 0 !important; - height: 30px !important; - padding: 4px !important; - font-size: 11px !important; - margin: 0 !important; - display: inline-block !important; - flex-shrink: 1 !important; -} - -/* Hide any
tags injected by admin templates */ -.admindatefilter br { - display: none !important; -} - -/* Ensure the wrapper allows full width */ -.admindatefilter { - width: 100% !important; - display: block !important; - box-sizing: border-box !important; -} - -/* --- Search Box RTL/LTR Border Radius Handling --- */ - -/* LTR (Default) */ -.masar-search-input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.masar-search-btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -/* RTL Override for Search Box */ -[dir="rtl"] .masar-search-input { - border-top-right-radius: 0.25rem !important; - border-bottom-right-radius: 0.25rem !important; - border-top-left-radius: 0 !important; - border-bottom-left-radius: 0 !important; -} -[dir="rtl"] .masar-search-btn { - border-top-left-radius: 0.25rem !important; - border-bottom-left-radius: 0.25rem !important; - border-top-right-radius: 0 !important; - border-bottom-right-radius: 0 !important; -} - /* --- Admin Panel RTL Sidebar Override (Agresive) --- */ - @media (min-width: 992px) { - /* Main Sidebar */ [dir="rtl"] .main-sidebar { left: auto !important; right: 0 !important; border-right: none !important; border-left: 1px solid rgba(0,0,0,0.1) !important; } - - /* Content Wrapper & Headers */ [dir="rtl"] .content-wrapper, [dir="rtl"] .main-header, [dir="rtl"] .main-footer { @@ -310,22 +133,17 @@ body.model-platformprofile label[for="id_admin_panel_logo"] { margin-right: 250px !important; transition: margin-right .3s ease-in-out !important; } - - /* Collapsed Sidebar State */ [dir="rtl"].sidebar-collapse .main-sidebar { margin-left: 0 !important; margin-right: 0 !important; width: 4.6rem !important; } - [dir="rtl"].sidebar-collapse .content-wrapper, [dir="rtl"].sidebar-collapse .main-header, [dir="rtl"].sidebar-collapse .main-footer { margin-left: 0 !important; margin-right: 4.6rem !important; } - - /* Fix Brand Logo Area */ [dir="rtl"] .brand-link { float: right !important; width: 100% !important; @@ -336,53 +154,41 @@ body.model-platformprofile label[for="id_admin_panel_logo"] { margin-right: 0.8rem !important; margin-left: 0.5rem !important; } - - /* Navbar alignment */ [dir="rtl"] .navbar-nav { flex-direction: row; } [dir="rtl"] .navbar-nav .nav-item { float: right; } - [dir="rtl"] .ml-auto { margin-left: 0 !important; margin-right: auto !important; } - [dir="rtl"] .mr-auto { margin-right: 0 !important; margin-left: auto !important; } } - -/* Sidebar Navigation Items RTL */ [dir="rtl"] .nav-sidebar .nav-item > .nav-link { display: flex !important; flex-direction: row !important; align-items: center !important; } - [dir="rtl"] .nav-sidebar .nav-icon { margin-left: 0.5rem !important; margin-right: 0 !important; } - [dir="rtl"] .nav-sidebar .nav-link p { display: inline-block !important; margin-right: 0 !important; text-align: right !important; width: 100% !important; } - -/* Fix sidebar angle icon */ [dir="rtl"] .nav-sidebar .nav-icon.fa-angle-left { transform: rotate(180deg); margin-left: 0 !important; margin-right: auto !important; } - -/* General Utils */ [dir="rtl"] .float-right { float: left !important; } @@ -394,4 +200,4 @@ body.model-platformprofile label[for="id_admin_panel_logo"] { } [dir="rtl"] .text-left { text-align: right !important; -} \ No newline at end of file +} diff --git a/static/js/admin_date_range_dropdown.js b/static/js/admin_date_range_dropdown.js index 0c94f30..d8ff9fb 100644 --- a/static/js/admin_date_range_dropdown.js +++ b/static/js/admin_date_range_dropdown.js @@ -1,121 +1,158 @@ (function($) { - $(document).ready(function() { - // Helper to format date as YYYY-MM-DD - function formatDate(d) { - var year = d.getFullYear(); - var month = ('0' + (d.getMonth() + 1)).slice(-2); - var day = ('0' + d.getDate()).slice(-2); - return year + '-' + month + '-' + day; + // Masar Date Range Filter Layout Fix v3 + // Forces a horizontal layout for the Date Range Filter in Django Admin Sidebar + + function initDateRangeDropdown() { + console.log("Masar Date Filter: Initializing v3..."); + + // Find all "Greater Than or Equal" inputs (the start date of the range) + var $gteInputs = $('input[name$="__gte"]'); + + if ($gteInputs.length === 0) { + return; // Not found yet } - function initDateRangeDropdown() { - var $gteInputs = $('input[name$="__gte"]'); + $gteInputs.each(function() { + var $gte = $(this); + if ($gte.data('masar-processed')) return; + $gte.data('masar-processed', true); - $gteInputs.each(function() { - var $gte = $(this); - // Prevent double init - if ($gte.data('dropdown-processed')) return; - $gte.data('dropdown-processed', true); + var name = $gte.attr('name'); + var prefix = name.substring(0, name.lastIndexOf('__gte')); + var $lte = $('input[name="' + prefix + '__lte"]'); - var name = $gte.attr('name'); - var prefix = name.substring(0, name.lastIndexOf('__gte')); - var $lte = $('input[name="' + prefix + '__lte"]'); + if ($lte.length === 0) return; - if ($lte.length === 0) return; + // Locate the container in the sidebar. + // Usually it's inside a
  • or similar. + // We want to find the direct parent that holds these inputs. + var $parent = $gte.parent(); - var $container = $gte.closest('.admindatefilter'); - if ($container.length === 0) { - $container = $gte.closest('div[data-filter-name], li, .form-row, .card-body, .filter-wrapper'); - } - if ($container.length === 0) $container = $gte.parent(); + // Create our custom flex wrapper + var $wrapper = $('
    '); + $wrapper.css({ + 'display': 'flex', + 'flex-direction': 'row', + 'align-items': 'center', + 'gap': '3px', + 'width': '100%', + 'margin-bottom': '10px' + }); - // Find the direct wrapper of the inputs (usually .controls) - var $controls = $gte.closest('.controls'); - if ($controls.length === 0) { - $controls = $gte.parent(); - } - $controls.addClass('date-filter-controls'); // Hook for CSS - - // --- Dropdown --- - var $select = $(''); + // Create the Quick Select Dropdown + var $select = $(''); + + $select.css({ + 'width': '34%', + 'min-width': '60px', + 'height': '30px', + 'padding': '0 4px', + 'font-size': '11px' + }); - // --- Inputs Styling --- - $gte.addClass('form-control form-control-sm date-input'); - $lte.addClass('form-control form-control-sm date-input'); - $gte.attr('placeholder', 'Start'); // Short placeholder - $lte.attr('placeholder', 'End'); + // Style inputs + var inputStyle = { + 'width': '33%', + 'min-width': '0', + 'height': '30px', + 'padding': '4px', + 'font-size': '11px' + }; + $gte.css(inputStyle).attr('placeholder', 'Start'); + $lte.css(inputStyle).attr('placeholder', 'End'); - // Insert Dropdown INSIDE the flex container (at start) - if ($controls.length) { - $controls.prepend($select); + // --- RESTRUCTURING DOM --- + // 1. Insert wrapper before the start input + $gte.before($wrapper); + + // 2. Move elements into wrapper + $wrapper.append($select); + $wrapper.append($gte); + $wrapper.append($lte); + + // 3. Cleanup: Hide any left-over text nodes (like "-", "From", "To") or
    in the parent + $parent.contents().filter(function() { + return (this.nodeType === 3 && $.trim($(this).text()) !== '') || this.tagName === 'BR'; + }).remove(); + + // Logic for Dropdown Changes + // Helper to format date as YYYY-MM-DD + function formatDate(d) { + var year = d.getFullYear(); + var month = ('0' + (d.getMonth() + 1)).slice(-2); + var day = ('0' + d.getDate()).slice(-2); + return year + '-' + month + '-' + day; + } + + var gteVal = $gte.val(); + var lteVal = $lte.val(); + if (gteVal || lteVal) { + $select.val('custom'); + } else { + $select.val('any'); + } + + $select.on('change', function() { + var val = $(this).val(); + var today = new Date(); + + if (val === 'custom') { + // Do nothing, let user edit } else { - $gte.before($select); - } - - // Initial State - var gteVal = $gte.val(); - var lteVal = $lte.val(); - - if (gteVal || lteVal) { - $select.val('custom'); - } else { - $select.val('any'); - } - - // Event Listener - $select.on('change', function() { - var val = $(this).val(); - var today = new Date(); - - if (val === 'custom') { - // Inputs are always visible in our new layout, just ensure they are enabled/cleared if needed + if (val === 'any') { + $gte.val(''); + $lte.val(''); } else { - if (val === 'any') { - $gte.val(''); - $lte.val(''); - } else { - var startStr = ''; - var endStr = formatDate(today); + var startStr = ''; + var endStr = formatDate(today); - if (val === 'today') { - startStr = formatDate(today); - } else if (val === '7days') { - var past = new Date(); - past.setDate(today.getDate() - 7); - startStr = formatDate(past); - } else if (val === 'month') { - var firstDay = new Date(today.getFullYear(), today.getMonth(), 1); - startStr = formatDate(firstDay); - } else if (val === 'year') { - var firstDay = new Date(today.getFullYear(), 0, 1); - startStr = formatDate(firstDay); - } - - $gte.val(startStr); - $lte.val(endStr); + if (val === 'today') { + startStr = formatDate(today); + } else if (val === '7days') { + var past = new Date(); + past.setDate(today.getDate() - 7); + startStr = formatDate(past); + } else if (val === 'month') { + var firstDay = new Date(today.getFullYear(), today.getMonth(), 1); + startStr = formatDate(firstDay); } - - // Auto-submit - var $form = $gte.closest('form'); - if ($form.length) { - $form.submit(); + $gte.val(startStr); + $lte.val(endStr); + } + // Trigger Form Submit (Changes URL) + // Try to find the filter form + var $form = $gte.closest('form'); // Usually #changelist-search + if ($form.length) { + $form.submit(); + } else { + // Sometimes filters are links, but date range usually has a button or relies on form + // If there is an "Apply" button nearby? + var $applyBtn = $parent.closest('.admindatefilter').find('input[type="submit"], button'); + if ($applyBtn.length) { + $applyBtn.click(); } else { - var $btn = $container.find('input[type="submit"], button[type="submit"]'); - if ($btn.length) $btn.click(); + // Fallback: reload page with query params (complex, skip for now, rely on standard form) } } - }); + } }); - } + }); + } + $(document).ready(function() { + // Run immediately initDateRangeDropdown(); - // Re-run safely for dynamic content + + // And retry a few times to catch slow rendering + setTimeout(initDateRangeDropdown, 200); setTimeout(initDateRangeDropdown, 500); + setTimeout(initDateRangeDropdown, 1000); }); -})(django.jQuery); \ No newline at end of file + +})(django.jQuery);