CBV code updates: 28th May II
This commit is contained in:
@@ -167,11 +167,11 @@
|
||||
setTimeout(function () {
|
||||
var timer = $("#otp-timer");
|
||||
timer.removeClass("oh-opacity-0");
|
||||
|
||||
|
||||
let counter = 20;
|
||||
let $timeSpan = timer.find(".time");
|
||||
let resendUrl = "{% url 'send-otp' %}";
|
||||
|
||||
|
||||
let interval = setInterval(function () {
|
||||
counter--;
|
||||
if (counter <= 0) {
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
</div>
|
||||
<ul class="oh-dashboard__events-nav" id="birthdayDots">
|
||||
{% for birthday in birthdays %}
|
||||
<li onclick="moveSlider(event)"
|
||||
class="oh-dashboard__events-nav-item {% if forloop.first %}oh-dashboard__events-nav-item--active{% endif %}"
|
||||
<li onclick="moveSlider(event)"
|
||||
class="oh-dashboard__events-nav-item {% if forloop.first %}oh-dashboard__events-nav-item--active{% endif %}"
|
||||
data-target="{{ forloop.counter0 }}">
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -25,4 +25,4 @@
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{% for cat_id, category in catagories.items %}
|
||||
<div class="oh-accordion">
|
||||
<div class="oh-accordion-header">{{category}}</div>
|
||||
<div
|
||||
<div
|
||||
class="oh-accordion-body"
|
||||
style="
|
||||
max-height: 500px; overflow-y: auto;
|
||||
@@ -108,4 +108,4 @@
|
||||
$(".selectAll").click();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -367,15 +367,11 @@ class HorillaListView(ListView):
|
||||
).only("pk", field)
|
||||
|
||||
existing_values = existing_objects.values_list(field, flat=True)
|
||||
print(">>>>>>>>>>>>>>>>>>>")
|
||||
print(existing_values)
|
||||
to_create = [
|
||||
related_model(**{field: value})
|
||||
for value in values
|
||||
if value not in existing_values
|
||||
]
|
||||
print(to_create)
|
||||
print(">>>>>>>>>>>>>>>>>>>")
|
||||
|
||||
if to_create:
|
||||
related_model.objects.bulk_create(to_create)
|
||||
@@ -557,6 +553,7 @@ class HorillaListView(ListView):
|
||||
)
|
||||
bulk_base_fk_grouping = {}
|
||||
bulk_update_reverse_related_grouping = {}
|
||||
bulk_create_from_update_reverse_related_grouping = {}
|
||||
bulk_update_base_grouping = []
|
||||
|
||||
related_fields = list(self.reverse_model_relation_to_base_model.keys())
|
||||
@@ -600,6 +597,14 @@ class HorillaListView(ListView):
|
||||
bulk_update_reverse_related_grouping.get(relation, [])
|
||||
+ [related_instance]
|
||||
)
|
||||
else:
|
||||
bulk_create_from_update_reverse_related_grouping[
|
||||
relation
|
||||
] = bulk_update_reverse_related_grouping.get(
|
||||
relation, []
|
||||
) + [
|
||||
related_instance
|
||||
]
|
||||
|
||||
for fk_field in fk_fields:
|
||||
if fk_field not in self.fk_mapping:
|
||||
@@ -631,6 +636,10 @@ class HorillaListView(ListView):
|
||||
related_model.objects.bulk_update(
|
||||
bulk_update_reverse_related_grouping[field], update_fields
|
||||
)
|
||||
elif field in bulk_create_from_update_reverse_related_grouping:
|
||||
related_model.objects.bulk_create(
|
||||
bulk_create_from_update_reverse_related_grouping[field]
|
||||
)
|
||||
|
||||
status = "Success"
|
||||
if error_records:
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
table.import th,
|
||||
table.import td {
|
||||
border: 1px solid #cdd5df;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
table.import th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</form>
|
||||
<script>
|
||||
let htmxBusy = false
|
||||
|
||||
|
||||
document.body.addEventListener('htmx:configRequest', function (event) {
|
||||
if (htmxBusy) {
|
||||
event.preventDefault()
|
||||
@@ -66,11 +66,11 @@
|
||||
htmxBusy = true
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
document.body.addEventListener('htmx:afterRequest', function () {
|
||||
htmxBusy = false
|
||||
})
|
||||
|
||||
|
||||
document.body.addEventListener('htmx:responseError', function () {
|
||||
htmxBusy = false
|
||||
})
|
||||
|
||||
@@ -99,9 +99,9 @@
|
||||
$(document).ready(function () {
|
||||
// Define the viewId
|
||||
var viewId = '#{{view_id}}'
|
||||
|
||||
|
||||
let draggedCard = null
|
||||
|
||||
|
||||
// Initialize drag events for cards
|
||||
function initDragAndDrop() {
|
||||
// Drag start
|
||||
@@ -111,44 +111,44 @@
|
||||
draggedCard.addClass('dragging')
|
||||
}, 0)
|
||||
})
|
||||
|
||||
|
||||
// Drag end
|
||||
$(viewId + ' .kanban-card').on('dragend', function () {
|
||||
$(this).removeClass('dragging')
|
||||
draggedCard = null
|
||||
updateTaskCounts()
|
||||
})
|
||||
|
||||
|
||||
// Handle dragover to allow drops
|
||||
$(viewId + ' .cards-container').on('dragover', function (e) {
|
||||
e.preventDefault()
|
||||
$(this).addClass('drop-zone')
|
||||
})
|
||||
|
||||
|
||||
// Remove drop zone highlighting
|
||||
$(viewId + ' .cards-container').on('dragleave', function () {
|
||||
$(this).removeClass('drop-zone')
|
||||
})
|
||||
|
||||
|
||||
// Handle drops
|
||||
$(viewId + ' .cards-container').on('drop', function (e) {
|
||||
e.preventDefault()
|
||||
$(this).removeClass('drop-zone')
|
||||
|
||||
|
||||
if (draggedCard) {
|
||||
// Find the "Add task" button and insert before it
|
||||
const addTaskButton = $(this).find('.add-task')
|
||||
draggedCard.insertBefore(addTaskButton)
|
||||
|
||||
|
||||
const itemId = draggedCard.data('id')
|
||||
const column = $(this).closest('.kanban-column')
|
||||
const newStage = column.data('stage')
|
||||
|
||||
|
||||
console.log(`Item ${itemId} moved to ${newStage}`)
|
||||
|
||||
|
||||
// Update card styling based on new column
|
||||
updateCardStyling(draggedCard, newStage)
|
||||
|
||||
|
||||
// 🔁 Replace with AJAX to update backend
|
||||
/*
|
||||
$.ajax({
|
||||
@@ -167,28 +167,28 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Initialize profile dropdowns for cards
|
||||
function initProfileDropdowns() {
|
||||
// Avatar click to show dropdown
|
||||
$(viewId).on('click', '.avatar, .avatar-placeholder', function (e) {
|
||||
e.stopPropagation()
|
||||
const dropdown = $(this).siblings('.assignee-dropdown')
|
||||
|
||||
|
||||
// Close all other dropdowns first
|
||||
$(viewId + ' .assignee-dropdown.active')
|
||||
.not(dropdown)
|
||||
.removeClass('active')
|
||||
|
||||
|
||||
// Toggle this dropdown
|
||||
dropdown.toggleClass('active')
|
||||
})
|
||||
|
||||
|
||||
// Assignee selection
|
||||
$(viewId).on('click', '.assignee-option', function () {
|
||||
const profileContainer = $(this).closest('.profile-container')
|
||||
const initials = $(this).data('initials')
|
||||
|
||||
|
||||
if (initials === 'UN') {
|
||||
// Unassign
|
||||
profileContainer.find('.avatar, .avatar-placeholder').replaceWith($('<div class="avatar-placeholder" title="Unassigned">+</div>'))
|
||||
@@ -197,39 +197,39 @@
|
||||
const personName = $(this).find('span').text()
|
||||
const avatar = $(this).find('.avatar').clone()
|
||||
avatar.attr('title', personName)
|
||||
|
||||
|
||||
profileContainer.find('.avatar, .avatar-placeholder').replaceWith(avatar)
|
||||
}
|
||||
|
||||
|
||||
// Close dropdown
|
||||
profileContainer.find('.assignee-dropdown').removeClass('active')
|
||||
})
|
||||
|
||||
|
||||
// Close dropdowns when clicking elsewhere
|
||||
$(document).on('click', function () {
|
||||
$(viewId + ' .assignee-dropdown.active').removeClass('active')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Initialize column collapse/expand functionality
|
||||
function initColumnCollapse() {
|
||||
$(viewId + ' .column-header').on('click', function () {
|
||||
$(this).closest('.kanban-column').toggleClass('collapsed')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Handle adding new tasks
|
||||
function initAddTask() {
|
||||
$(viewId + ' .add-task').on('click', function () {
|
||||
const column = $(this).closest('.kanban-column')
|
||||
const stage = column.data('stage')
|
||||
|
||||
|
||||
// Create a new card
|
||||
const newCard = createNewTaskCard(stage)
|
||||
|
||||
|
||||
// Add it before the add button
|
||||
$(this).before(newCard)
|
||||
|
||||
|
||||
// Initialize drag events for the new card
|
||||
newCard
|
||||
.on('dragstart', function () {
|
||||
@@ -243,19 +243,19 @@
|
||||
draggedCard = null
|
||||
updateTaskCounts()
|
||||
})
|
||||
|
||||
|
||||
// Update counts
|
||||
updateTaskCounts()
|
||||
|
||||
|
||||
console.log(`New task created in ${stage}`)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Create a new task card
|
||||
function createNewTaskCard(stage) {
|
||||
// Create unique ID for the card
|
||||
const newId = Date.now()
|
||||
|
||||
|
||||
// Create the card with proper structure
|
||||
const newCard = $('<div class="kanban-card" draggable="true"></div>').attr('data-id', newId).append(`
|
||||
<div class="card-title">New Task</div>
|
||||
@@ -288,13 +288,13 @@
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
|
||||
|
||||
// Apply styling based on column
|
||||
updateCardStyling(newCard, stage)
|
||||
|
||||
|
||||
return newCard
|
||||
}
|
||||
|
||||
|
||||
// Update card styling based on column
|
||||
function updateCardStyling(card, stage) {
|
||||
if (stage === 'todo') {
|
||||
@@ -314,7 +314,7 @@
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update task counts for each column
|
||||
function updateTaskCounts() {
|
||||
$(viewId + ' .kanban-column').each(function () {
|
||||
@@ -322,7 +322,7 @@
|
||||
$(this).find('.task-count').text(cardCount)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Initialize everything
|
||||
function init() {
|
||||
initDragAndDrop()
|
||||
@@ -331,7 +331,7 @@
|
||||
initAddTask()
|
||||
updateTaskCounts()
|
||||
}
|
||||
|
||||
|
||||
// Run initialization
|
||||
init()
|
||||
})
|
||||
@@ -342,9 +342,9 @@
|
||||
const columns = document.querySelectorAll('.kanban-column')
|
||||
const cardsContainers = document.querySelectorAll('.cards-container')
|
||||
const addTaskButtons = document.querySelectorAll('.add-task')
|
||||
|
||||
|
||||
let draggedCard = null
|
||||
|
||||
|
||||
// Initialize card dragging
|
||||
cards.forEach((card) => {
|
||||
card.addEventListener('dragstart', () => {
|
||||
@@ -353,19 +353,19 @@
|
||||
card.classList.add('dragging')
|
||||
}, 0)
|
||||
})
|
||||
|
||||
|
||||
card.addEventListener('dragend', () => {
|
||||
draggedCard = null
|
||||
card.classList.remove('dragging')
|
||||
updateTaskCounts()
|
||||
})
|
||||
|
||||
|
||||
// Set up profile dropdown functionality
|
||||
const profileContainer = card.querySelector('.profile-container')
|
||||
if (profileContainer) {
|
||||
const avatar = profileContainer.querySelector('.avatar, .avatar-placeholder')
|
||||
const dropdown = profileContainer.querySelector('.assignee-dropdown')
|
||||
|
||||
|
||||
avatar.addEventListener('click', (e) => {
|
||||
e.stopPropagation()
|
||||
// Close all other dropdowns first
|
||||
@@ -376,14 +376,14 @@
|
||||
})
|
||||
dropdown.classList.toggle('active')
|
||||
})
|
||||
|
||||
|
||||
// Handle assignee selection
|
||||
const assigneeOptions = dropdown.querySelectorAll('.assignee-option')
|
||||
assigneeOptions.forEach((option) => {
|
||||
option.addEventListener('click', () => {
|
||||
const initials = option.getAttribute('data-initials')
|
||||
const currentAvatar = profileContainer.querySelector('.avatar, .avatar-placeholder')
|
||||
|
||||
|
||||
if (initials === 'UN') {
|
||||
// Unassign
|
||||
profileContainer.innerHTML = `
|
||||
@@ -403,16 +403,16 @@
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
// Reset event listeners for the new elements
|
||||
const newDropdown = profileContainer.querySelector('.assignee-dropdown')
|
||||
const newAvatar = profileContainer.querySelector('.avatar, .avatar-placeholder')
|
||||
|
||||
|
||||
newAvatar.addEventListener('click', (e) => {
|
||||
e.stopPropagation()
|
||||
newDropdown.classList.toggle('active')
|
||||
})
|
||||
|
||||
|
||||
// Reset assignee option event listeners
|
||||
const newOptions = newDropdown.querySelectorAll('.assignee-option')
|
||||
newOptions.forEach((newOpt) => {
|
||||
@@ -422,13 +422,13 @@
|
||||
this.click() // This is a simplified approach
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
dropdown.classList.remove('active')
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Handle column collapse
|
||||
document.querySelectorAll('.column-header').forEach((header) => {
|
||||
header.addEventListener('click', () => {
|
||||
@@ -436,43 +436,43 @@
|
||||
column.classList.toggle('collapsed')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// Close dropdowns when clicking outside
|
||||
document.addEventListener('click', () => {
|
||||
document.querySelectorAll('.assignee-dropdown.active').forEach((dropdown) => {
|
||||
dropdown.classList.remove('active')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// Handle drag and drop for columns
|
||||
cardsContainers.forEach((container) => {
|
||||
container.addEventListener('dragover', (e) => {
|
||||
e.preventDefault()
|
||||
container.classList.add('drop-zone')
|
||||
})
|
||||
|
||||
|
||||
container.addEventListener('dragleave', () => {
|
||||
container.classList.remove('drop-zone')
|
||||
})
|
||||
|
||||
|
||||
container.addEventListener('drop', (e) => {
|
||||
e.preventDefault()
|
||||
container.classList.remove('drop-zone')
|
||||
|
||||
|
||||
if (draggedCard) {
|
||||
// Find the "Add task" button and insert before it
|
||||
const addTaskButton = container.querySelector('.add-task')
|
||||
container.insertBefore(draggedCard, addTaskButton)
|
||||
|
||||
|
||||
const itemId = draggedCard.getAttribute('data-id')
|
||||
const column = container.closest('.kanban-column')
|
||||
const newStage = column.getAttribute('data-stage')
|
||||
|
||||
|
||||
console.log(`Item ${itemId} moved to ${newStage}`)
|
||||
|
||||
|
||||
// Update card styling based on new column
|
||||
updateCardStyling(draggedCard, newStage)
|
||||
|
||||
|
||||
// 🔁 Replace with AJAX to update backend
|
||||
/*
|
||||
fetch('/api/kanban/update-stage/', {
|
||||
@@ -490,21 +490,21 @@
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// Handle add task button clicks
|
||||
addTaskButtons.forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const column = button.closest('.kanban-column')
|
||||
const stage = column.getAttribute('data-stage')
|
||||
const container = column.querySelector('.cards-container')
|
||||
|
||||
|
||||
// Create a new card with a unique ID (this is just for demo purposes)
|
||||
const newId = Date.now()
|
||||
const newCard = document.createElement('div')
|
||||
newCard.className = 'kanban-card'
|
||||
newCard.setAttribute('draggable', 'true')
|
||||
newCard.setAttribute('data-id', newId)
|
||||
|
||||
|
||||
// Set the default content for the new card
|
||||
newCard.innerHTML = `
|
||||
<div class="card-title">New Task</div>
|
||||
@@ -514,13 +514,13 @@
|
||||
<span>Today</span>
|
||||
</div>
|
||||
`
|
||||
|
||||
|
||||
// Apply styling based on the column
|
||||
updateCardStyling(newCard, stage)
|
||||
|
||||
|
||||
// Add the new card before the add task button
|
||||
container.insertBefore(newCard, button)
|
||||
|
||||
|
||||
// Set up drag events for the new card
|
||||
newCard.addEventListener('dragstart', () => {
|
||||
draggedCard = newCard
|
||||
@@ -528,26 +528,26 @@
|
||||
newCard.classList.add('dragging')
|
||||
}, 0)
|
||||
})
|
||||
|
||||
|
||||
newCard.addEventListener('dragend', () => {
|
||||
draggedCard = null
|
||||
newCard.classList.remove('dragging')
|
||||
updateTaskCounts()
|
||||
})
|
||||
|
||||
|
||||
// Update counts
|
||||
updateTaskCounts()
|
||||
|
||||
|
||||
console.log(`New task created in ${stage}`)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// Function to update card styling based on column
|
||||
function updateCardStyling(card, stage) {
|
||||
// Remove all potential styling classes first
|
||||
card.style.borderLeftColor = ''
|
||||
card.style.background = ''
|
||||
|
||||
|
||||
// Apply styling based on stage
|
||||
if (stage === 'todo') {
|
||||
card.style.borderLeftColor = '#f43f5e'
|
||||
@@ -560,7 +560,7 @@
|
||||
card.style.background = '#ecfdf5'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Function to update task counts
|
||||
function updateTaskCounts() {
|
||||
columns.forEach((column) => {
|
||||
@@ -569,7 +569,7 @@
|
||||
countSpan.textContent = cards
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Initial count update
|
||||
updateTaskCounts()
|
||||
</script>
|
||||
|
||||
@@ -81,4 +81,4 @@
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
<h1 class="oh-empty__title">{% trans "No Records found." %}</h1>
|
||||
<p class="oh-empty__subtitle">{% trans "No employees have taken leave today." %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -80,4 +80,4 @@
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user