Initial commit
This commit is contained in:
259
assets/js/admin.js
Normal file
259
assets/js/admin.js
Normal file
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* Door Status Voting - Admin JavaScript
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
initSettingsForm();
|
||||
initResetButtons();
|
||||
initResetByTypeButtons();
|
||||
initMismatchFilter();
|
||||
initMetaStatusButtons();
|
||||
});
|
||||
|
||||
/**
|
||||
* Settings Form Handler
|
||||
*/
|
||||
function initSettingsForm() {
|
||||
$('#dsv-settings-form').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $form = $(this);
|
||||
var $btn = $form.find('.button-primary');
|
||||
var $status = $form.find('.dsv-save-status');
|
||||
|
||||
$btn.prop('disabled', true).text('Speichern...');
|
||||
$status.text('');
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: dsvAdmin.ajaxUrl,
|
||||
data: {
|
||||
action: 'dsv_save_settings',
|
||||
nonce: dsvAdmin.nonce,
|
||||
disabled_posts: $('#dsv-disabled-posts').val()
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$status.text('✓ Gespeichert').css('color', '#00a32a');
|
||||
} else {
|
||||
$status.text('✗ Fehler: ' + (response.data?.message || 'Unbekannt')).css('color', '#d63638');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$status.text('✗ Verbindungsfehler').css('color', '#d63638');
|
||||
},
|
||||
complete: function() {
|
||||
$btn.prop('disabled', false).text('Einstellungen speichern');
|
||||
|
||||
setTimeout(function() {
|
||||
$status.fadeOut(300, function() {
|
||||
$(this).text('').show();
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset All Buttons Handler
|
||||
*/
|
||||
function initResetButtons() {
|
||||
$(document).on('click', '.dsv-reset-btn', function() {
|
||||
var $btn = $(this);
|
||||
var $row = $btn.closest('tr');
|
||||
var postId = $btn.data('post-id');
|
||||
|
||||
if (!confirm('Alle Votes für diesen Beitrag wirklich zurücksetzen?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.prop('disabled', true).text('Löschen...');
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: dsvAdmin.ajaxUrl,
|
||||
data: {
|
||||
action: 'dsv_reset_votes',
|
||||
nonce: dsvAdmin.nonce,
|
||||
post_id: postId
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$row.fadeOut(300, function() {
|
||||
$(this).remove();
|
||||
checkEmptyTable();
|
||||
});
|
||||
} else {
|
||||
alert('Fehler: ' + (response.data?.message || 'Unbekannt'));
|
||||
$btn.prop('disabled', false).text('Alle löschen');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('Verbindungsfehler');
|
||||
$btn.prop('disabled', false).text('Alle löschen');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset By Type Buttons Handler
|
||||
*/
|
||||
function initResetByTypeButtons() {
|
||||
$(document).on('click', '.dsv-reset-type-btn', function() {
|
||||
var $btn = $(this);
|
||||
var $row = $btn.closest('tr');
|
||||
var postId = $btn.data('post-id');
|
||||
var type = $btn.data('type');
|
||||
var typeLabel = type === 'open' ? 'Geöffnet' : 'Geschlossen';
|
||||
|
||||
if (!confirm('Alle "' + typeLabel + '" Stimmen für diesen Beitrag löschen?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var originalText = $btn.text();
|
||||
$btn.prop('disabled', true).text('...');
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: dsvAdmin.ajaxUrl,
|
||||
data: {
|
||||
action: 'dsv_reset_votes_by_type',
|
||||
nonce: dsvAdmin.nonce,
|
||||
post_id: postId,
|
||||
type: type
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
// Zähler aktualisieren
|
||||
$row.find('.dsv-count-open').text(response.data.votes.open);
|
||||
$row.find('.dsv-count-closed').text(response.data.votes.closed);
|
||||
$row.find('.dsv-count-total').text(response.data.votes.open + response.data.votes.closed);
|
||||
|
||||
// Status Badge aktualisieren
|
||||
var $badge = $row.find('.dsv-badge');
|
||||
$badge.removeClass('dsv-badge-open dsv-badge-closed dsv-badge-tied');
|
||||
|
||||
if (response.data.votes.open > response.data.votes.closed) {
|
||||
$badge.addClass('dsv-badge-open').text('Geöffnet');
|
||||
} else if (response.data.votes.closed > response.data.votes.open) {
|
||||
$badge.addClass('dsv-badge-closed').text('Geschlossen');
|
||||
} else {
|
||||
$badge.addClass('dsv-badge-tied').text('Unklar');
|
||||
}
|
||||
|
||||
// Wenn keine Votes mehr, Zeile entfernen
|
||||
if (response.data.votes.open === 0 && response.data.votes.closed === 0) {
|
||||
$row.fadeOut(300, function() {
|
||||
$(this).remove();
|
||||
checkEmptyTable();
|
||||
});
|
||||
} else {
|
||||
// Kurzes Feedback
|
||||
$btn.text('✓').css('color', '#00a32a');
|
||||
setTimeout(function() {
|
||||
$btn.prop('disabled', false).text(originalText).css('color', '');
|
||||
}, 1000);
|
||||
}
|
||||
} else {
|
||||
alert('Fehler: ' + (response.data?.message || 'Unbekannt'));
|
||||
$btn.prop('disabled', false).text(originalText);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('Verbindungsfehler');
|
||||
$btn.prop('disabled', false).text(originalText);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter: Nur Abweichungen anzeigen
|
||||
*/
|
||||
function initMismatchFilter() {
|
||||
var $btn = $('#dsv-filter-mismatch');
|
||||
var active = false;
|
||||
|
||||
$btn.on('click', function() {
|
||||
active = !active;
|
||||
var $table = $('#dsv-votes-table');
|
||||
|
||||
if (active) {
|
||||
$table.find('tbody tr').not('.dsv-mismatch').hide();
|
||||
$btn.addClass('button-primary').text('Alle anzeigen');
|
||||
} else {
|
||||
$table.find('tbody tr').show();
|
||||
$btn.removeClass('button-primary').text('Nur Abweichungen anzeigen');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Meta-Status per Knopfdruck ändern
|
||||
*/
|
||||
function initMetaStatusButtons() {
|
||||
$(document).on('click', '.dsv-meta-set-btn', function() {
|
||||
var $btn = $(this);
|
||||
var $cell = $btn.closest('.dsv-meta-status-cell');
|
||||
var postId = $btn.data('post-id');
|
||||
var status = $btn.data('status');
|
||||
|
||||
$cell.find('.dsv-meta-set-btn').prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: dsvAdmin.ajaxUrl,
|
||||
data: {
|
||||
action: 'dsv_update_meta_status',
|
||||
nonce: dsvAdmin.nonce,
|
||||
post_id: postId,
|
||||
status: status
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
// Badge aktualisieren
|
||||
var badgeClass = 'dsv-badge-tied';
|
||||
var lower = status.toLowerCase();
|
||||
if (lower === 'geöffnet') badgeClass = 'dsv-badge-open';
|
||||
else if (lower === 'geschlossen') badgeClass = 'dsv-badge-closed';
|
||||
|
||||
var $badge = $cell.find('.dsv-badge, .dsv-meta-empty');
|
||||
if ($badge.hasClass('dsv-meta-empty')) {
|
||||
$badge.removeClass('dsv-meta-empty').addClass('dsv-badge');
|
||||
}
|
||||
$badge.removeClass('dsv-badge-open dsv-badge-closed dsv-badge-tied')
|
||||
.addClass(badgeClass)
|
||||
.text(status);
|
||||
|
||||
// Active-State der Buttons
|
||||
$cell.find('.dsv-meta-set-btn').removeClass('active');
|
||||
$btn.addClass('active');
|
||||
} else {
|
||||
alert('Fehler: ' + (response.data?.message || 'Unbekannt'));
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('Verbindungsfehler');
|
||||
},
|
||||
complete: function() {
|
||||
$cell.find('.dsv-meta-set-btn').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüfen ob Tabelle leer ist
|
||||
*/
|
||||
function checkEmptyTable() {
|
||||
if ($('tbody tr').length === 0) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
257
assets/js/frontend.js
Normal file
257
assets/js/frontend.js
Normal file
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* Door Status Voting - Frontend JavaScript
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initDoorVoting();
|
||||
});
|
||||
|
||||
function initDoorVoting() {
|
||||
const widgets = document.querySelectorAll('.dsv-widget');
|
||||
|
||||
widgets.forEach(function(widget) {
|
||||
// Vote Buttons
|
||||
const buttons = widget.querySelectorAll('.dsv-btn');
|
||||
buttons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
handleVote(widget, btn.dataset.vote);
|
||||
});
|
||||
});
|
||||
|
||||
// Remove Vote Button
|
||||
const removeBtn = widget.querySelector('.dsv-remove-vote');
|
||||
if (removeBtn) {
|
||||
removeBtn.addEventListener('click', function() {
|
||||
handleRemoveVote(widget);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleVote(widget, vote) {
|
||||
const postId = widget.dataset.postId;
|
||||
const hasVoted = widget.dataset.hasVoted === 'true';
|
||||
|
||||
if (hasVoted) return;
|
||||
|
||||
// Buttons deaktivieren
|
||||
const buttons = widget.querySelectorAll('.dsv-btn');
|
||||
buttons.forEach(function(btn) {
|
||||
btn.disabled = true;
|
||||
});
|
||||
|
||||
// Animation starten
|
||||
widget.classList.add('dsv-animating');
|
||||
|
||||
// AJAX Request
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'dsv_vote');
|
||||
formData.append('post_id', postId);
|
||||
formData.append('vote', vote);
|
||||
formData.append('nonce', dsvConfig.nonce);
|
||||
|
||||
fetch(dsvConfig.ajaxUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'same-origin'
|
||||
})
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
if (data.success) {
|
||||
updateWidget(widget, data.data, vote);
|
||||
} else {
|
||||
console.error('Vote error:', data.data?.message);
|
||||
buttons.forEach(function(btn) {
|
||||
btn.disabled = false;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Network error:', error);
|
||||
buttons.forEach(function(btn) {
|
||||
btn.disabled = false;
|
||||
});
|
||||
})
|
||||
.finally(function() {
|
||||
widget.classList.remove('dsv-animating');
|
||||
});
|
||||
}
|
||||
|
||||
function handleRemoveVote(widget) {
|
||||
const postId = widget.dataset.postId;
|
||||
|
||||
// Button deaktivieren
|
||||
const removeBtn = widget.querySelector('.dsv-remove-vote');
|
||||
if (removeBtn) {
|
||||
removeBtn.disabled = true;
|
||||
removeBtn.textContent = '...';
|
||||
}
|
||||
|
||||
widget.classList.add('dsv-animating');
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'dsv_remove_vote');
|
||||
formData.append('post_id', postId);
|
||||
formData.append('nonce', dsvConfig.nonce);
|
||||
|
||||
fetch(dsvConfig.ajaxUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'same-origin'
|
||||
})
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
if (data.success) {
|
||||
resetWidgetToVoting(widget, data.data);
|
||||
} else {
|
||||
console.error('Remove vote error:', data.data?.message);
|
||||
if (removeBtn) {
|
||||
removeBtn.disabled = false;
|
||||
removeBtn.textContent = '✕';
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Network error:', error);
|
||||
if (removeBtn) {
|
||||
removeBtn.disabled = false;
|
||||
removeBtn.textContent = '✕';
|
||||
}
|
||||
})
|
||||
.finally(function() {
|
||||
widget.classList.remove('dsv-animating');
|
||||
});
|
||||
}
|
||||
|
||||
function updateWidget(widget, data, userVote) {
|
||||
// Status aktualisieren
|
||||
widget.dataset.status = data.status;
|
||||
widget.dataset.hasVoted = 'true';
|
||||
widget.dataset.userVote = userVote;
|
||||
|
||||
// Badge aktualisieren
|
||||
const badge = widget.querySelector('.dsv-status-badge');
|
||||
badge.className = 'dsv-status-badge dsv-status-' + data.status;
|
||||
|
||||
if (data.status === 'open') {
|
||||
badge.innerHTML = '🟢 GEÖFFNET';
|
||||
} else if (data.status === 'closed') {
|
||||
badge.innerHTML = '🔴 GESCHLOSSEN';
|
||||
} else {
|
||||
badge.innerHTML = '🟡 UNKLAR';
|
||||
}
|
||||
|
||||
// Fortschrittsbalken aktualisieren
|
||||
updateProgressBar(widget, data);
|
||||
|
||||
// Buttons durch Bestätigung ersetzen
|
||||
const buttonsContainer = widget.querySelector('.dsv-buttons');
|
||||
buttonsContainer.classList.add('dsv-voted');
|
||||
|
||||
const voteClass = userVote === 'open' ? 'dsv-voted-open' : 'dsv-voted-closed';
|
||||
const voteIcon = userVote === 'open' ? '✓' : '✗';
|
||||
const voteText = userVote === 'open' ? 'Geöffnet' : 'Geschlossen';
|
||||
|
||||
buttonsContainer.innerHTML =
|
||||
'<div class="dsv-voted-message ' + voteClass + '">' +
|
||||
'<span class="dsv-voted-icon">' + voteIcon + '</span>' +
|
||||
'<span class="dsv-voted-text">Du hast für "' + voteText + '" gestimmt</span>' +
|
||||
'<button type="button" class="dsv-remove-vote" title="Stimme zurücknehmen">✕</button>' +
|
||||
'</div>';
|
||||
|
||||
// Event Listener für neuen Remove Button
|
||||
const newRemoveBtn = buttonsContainer.querySelector('.dsv-remove-vote');
|
||||
newRemoveBtn.addEventListener('click', function() {
|
||||
handleRemoveVote(widget);
|
||||
});
|
||||
|
||||
// Total aktualisieren
|
||||
widget.querySelector('.dsv-total').textContent = data.total;
|
||||
|
||||
// Pulse Animation
|
||||
widget.classList.add('dsv-just-voted');
|
||||
setTimeout(function() {
|
||||
widget.classList.remove('dsv-just-voted');
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function resetWidgetToVoting(widget, data) {
|
||||
// Status aktualisieren
|
||||
widget.dataset.status = data.status;
|
||||
widget.dataset.hasVoted = 'false';
|
||||
widget.dataset.userVote = '';
|
||||
|
||||
// Badge aktualisieren
|
||||
const badge = widget.querySelector('.dsv-status-badge');
|
||||
badge.className = 'dsv-status-badge dsv-status-' + data.status;
|
||||
|
||||
if (data.status === 'open') {
|
||||
badge.innerHTML = '🟢 GEÖFFNET';
|
||||
} else if (data.status === 'closed') {
|
||||
badge.innerHTML = '🔴 GESCHLOSSEN';
|
||||
} else {
|
||||
badge.innerHTML = '🟡 UNKLAR';
|
||||
}
|
||||
|
||||
// Fortschrittsbalken aktualisieren
|
||||
updateProgressBar(widget, data);
|
||||
|
||||
// Voting Buttons wieder anzeigen
|
||||
const buttonsContainer = widget.querySelector('.dsv-buttons');
|
||||
buttonsContainer.classList.remove('dsv-voted');
|
||||
|
||||
buttonsContainer.innerHTML =
|
||||
'<button type="button" class="dsv-btn dsv-btn-open" data-vote="open">' +
|
||||
'<span class="dsv-btn-icon">✓</span>' +
|
||||
'<span class="dsv-btn-text">Geöffnet</span>' +
|
||||
'</button>' +
|
||||
'<button type="button" class="dsv-btn dsv-btn-closed" data-vote="closed">' +
|
||||
'<span class="dsv-btn-icon">✗</span>' +
|
||||
'<span class="dsv-btn-text">Geschlossen</span>' +
|
||||
'</button>';
|
||||
|
||||
// Event Listener für neue Buttons
|
||||
const newButtons = buttonsContainer.querySelectorAll('.dsv-btn');
|
||||
newButtons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
handleVote(widget, btn.dataset.vote);
|
||||
});
|
||||
});
|
||||
|
||||
// Total aktualisieren
|
||||
widget.querySelector('.dsv-total').textContent = data.total;
|
||||
}
|
||||
|
||||
function updateProgressBar(widget, data) {
|
||||
const progressOpen = widget.querySelector('.dsv-progress-open');
|
||||
const progressClosed = widget.querySelector('.dsv-progress-closed');
|
||||
|
||||
progressOpen.style.width = data.openPercent + '%';
|
||||
progressClosed.style.width = (100 - data.openPercent) + '%';
|
||||
|
||||
// Zähler
|
||||
if (data.openPercent > 15) {
|
||||
progressOpen.innerHTML = '<span class="dsv-progress-count">' + data.votes.open + '</span>';
|
||||
} else {
|
||||
progressOpen.innerHTML = '';
|
||||
}
|
||||
|
||||
if ((100 - data.openPercent) > 15) {
|
||||
progressClosed.innerHTML = '<span class="dsv-progress-count">' + data.votes.closed + '</span>';
|
||||
} else {
|
||||
progressClosed.innerHTML = '';
|
||||
}
|
||||
|
||||
// Labels
|
||||
widget.querySelector('.dsv-label-open').textContent = 'Geöffnet (' + data.openPercent + '%)';
|
||||
widget.querySelector('.dsv-label-closed').textContent = 'Geschlossen (' + (100 - data.openPercent) + '%)';
|
||||
}
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user