[UPDT] HORILLA_THEME: horilla-tab view style updation
This commit is contained in:
@@ -1877,14 +1877,71 @@ select.oh-select--lg {
|
||||
color: hsl(0, 0%, 11%);
|
||||
}
|
||||
|
||||
.oh-tabs__content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.oh-tabs__content--active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.no-after::after {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
.oh-kanban-card__subtitle {
|
||||
font-size: 0.85rem;
|
||||
color: hsl(0, 0%, 45%);
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
@media (max-width: 575.98px) {
|
||||
.oh-kanban-card__subtitle {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
|
||||
.oh-dot {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.oh-dot--small {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.oh-timeoff-modal__stat-count {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.oh-password-input--toggle {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
height: 100%;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
ul.errorlist {
|
||||
color: #d9534f;
|
||||
background-color: #f0d8d8;
|
||||
border: 1px solid #d6e9c6;
|
||||
font-size: 0.875rem;
|
||||
list-style-type: disc;
|
||||
padding: 1rem 1rem 1rem 2rem;
|
||||
border-radius: 4px;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
ul.errorlist li {
|
||||
margin-bottom: 0.25rem;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
ul.errorlist ul.errorlist {
|
||||
list-style-type: none;
|
||||
margin-left: 1rem;
|
||||
margin-top: 0.25rem;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul.errorlist ul.errorlist li {
|
||||
margin-bottom: 0.125rem;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
172
horilla_theme/templates/generic/horilla_tabs.html
Normal file
172
horilla_theme/templates/generic/horilla_tabs.html
Normal file
@@ -0,0 +1,172 @@
|
||||
{% load i18n generic_template_filters %}
|
||||
<div id="{{view_id}}" x-data="tabsComponent('{{view_id}}')" x-init="init()">
|
||||
{% if show_filter_tags %}
|
||||
{% include "generic/filter_tags.html" %}
|
||||
{% endif %}
|
||||
|
||||
<div class="bg-white p-3 rounded-md shadow-card">
|
||||
<div class="flex flex-wrap gap-2 justify-between mb-3">
|
||||
<div class="flex gap-1 flex-wrap">
|
||||
{% for tab in tabs %}
|
||||
<div class="relative inline-block dropdown-wrapper" x-data="{ open: false }">
|
||||
<button
|
||||
:class="{
|
||||
'oh-tabs__tab--active': activeIndex === {{ forloop.counter0 }},
|
||||
'bg-primary-300 text-primary-600 border border-primary-600': activeIndex === {{ forloop.counter0 }},
|
||||
'border border-dark-50 text-gray-800': activeIndex !== {{ forloop.counter0 }}
|
||||
}"
|
||||
class="px-2 py-1 oh-tabs__tab rounded-md text-xs flex items-center gap-2 transition duration-300"
|
||||
data-tab-index="{{ forloop.counter0 }}"
|
||||
hx-get="{{ tab.url }}?{{ request.GET.urlencode }}"
|
||||
hx-target="#{{ view_id }}{{ forloop.counter }}"
|
||||
hx-trigger="click"
|
||||
hx-swap="innerHTML"
|
||||
@click="setActive({{ forloop.counter0 }})"
|
||||
>
|
||||
|
||||
<span class="w-6 h-6 bg-primary-600 rounded-full text-white flex items-center justify-center"
|
||||
id="badge-{{view_id}}{{forloop.counter}}"
|
||||
{% if tab.badge_label %}
|
||||
data-badge-label="{{tab.badge_label}}"
|
||||
title="0 {{tab.badge_label}}"
|
||||
{% else %}
|
||||
title="0 {% trans 'Records' %}"
|
||||
{% endif %}
|
||||
onclick="event.stopPropagation()">
|
||||
0
|
||||
</span>
|
||||
{{ tab.title }}
|
||||
|
||||
{% if tab.actions %}
|
||||
<span class="ps-3 cursor-pointer" onclick=actionClick(event)>
|
||||
<i class="fa-solid fa-ellipsis-vertical text-black" title="Actions"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
</button>
|
||||
|
||||
{% if tab.actions %}
|
||||
<div
|
||||
class="dropdown-menu absolute right-0 min-w-[100px] bg-white rounded-lg shadow-card py-2 z-50 transition-all duration-200"
|
||||
x-show="open"
|
||||
x-cloak
|
||||
>
|
||||
<ul class="text-xs">
|
||||
{% for action in tab.actions %}
|
||||
{% if instance %}
|
||||
{% if action.accessibility|accessibility:instance %}
|
||||
<li>
|
||||
<a {{ action.attrs|safe }} class="block w-full text-left px-3 py-1 hover:text-primary-600 transition duration-300">
|
||||
{{ action.action }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<li>
|
||||
<a {{ action.attrs|safe }} class="block w-full text-left px-3 py-1 hover:text-primary-600 transition duration-300">
|
||||
{{ action.action }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="oh-tabs__contents">
|
||||
{% for tab in tabs %}
|
||||
<div
|
||||
x-show="activeIndex === {{ forloop.counter0 }}"
|
||||
x-cloak
|
||||
class="oh-tabs__content"
|
||||
id="{{view_id}}{{forloop.counter}}"
|
||||
>
|
||||
<div class="animated-background"></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleHighlight(checkbox) {
|
||||
const row = checkbox.closest("tr");
|
||||
if (checkbox.checked) {
|
||||
row.classList.add("highlight");
|
||||
} else {
|
||||
row.classList.remove("highlight");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.body.addEventListener("htmx:afterSettle", function (event) {
|
||||
const target = event.target;
|
||||
if (window.Alpine && Alpine.initTree) {
|
||||
Alpine.initTree(target);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function tabsComponent(viewId) {
|
||||
return {
|
||||
activeIndex: 0,
|
||||
|
||||
init() {
|
||||
const savedIndex = localStorage.getItem(`${viewId}_activeIndex`);
|
||||
this.activeIndex = savedIndex !== null ? Number(savedIndex) : 0;
|
||||
|
||||
const tabBtn = document.querySelector(`[data-tab-index="${this.activeIndex}"]`);
|
||||
const targetId = tabBtn?.getAttribute("hx-target")?.replace("#", "");
|
||||
const url = tabBtn?.getAttribute("hx-get");
|
||||
|
||||
if (url && targetId) {
|
||||
const target = document.getElementById(targetId);
|
||||
if (target) {
|
||||
target.innerHTML = '<div class="animated-background"></div>';
|
||||
htmx.ajax('GET', url, { target: `#${targetId}`, swap: 'innerHTML' });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setActive(index) {
|
||||
this.activeIndex = index;
|
||||
localStorage.setItem(`${viewId}_activeIndex`, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
function actionClick(event) {
|
||||
event.stopPropagation(); // Prevents closing when clicking inside
|
||||
const icon = event.currentTarget;
|
||||
const dropdownMenu = $(icon).closest('.dropdown-wrapper').find('.dropdown-menu');
|
||||
|
||||
const isOpen = dropdownMenu.is(":visible");
|
||||
|
||||
// Close all other dropdowns
|
||||
$(".dropdown-menu").not(dropdownMenu).hide();
|
||||
|
||||
if (isOpen) {
|
||||
dropdownMenu.hide();
|
||||
} else {
|
||||
dropdownMenu.show();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
const $clickedWrapper = $(e.target).closest(".dropdown-wrapper");
|
||||
|
||||
$(".dropdown-wrapper").each(function () {
|
||||
const $wrapper = $(this);
|
||||
if (!$wrapper.is($clickedWrapper)) {
|
||||
$wrapper.find(".dropdown-menu").hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
<script src="{% static '/build/js/orgChart.js' %}"></script>
|
||||
<script src="{% static 'build/js/driver.js' %}"></script>
|
||||
<script src="{% static 'build/js/clearFilter.js' %}"></script>
|
||||
<script src="{% static '/jquery/alpine.min.js' %}"></script>
|
||||
{% block header_scripts %}
|
||||
{% endblock header_scripts %}
|
||||
|
||||
5
static/jquery/alpine.min.js
vendored
Normal file
5
static/jquery/alpine.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user