Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14bd0bfc68 | |||
| 47543ed98d | |||
| aa58ae479c | |||
| a815fe7c7b | |||
| 525616391a | |||
| 8f82a72ea3 | |||
| 2318594ea9 | |||
| b934c94765 | |||
| 023a2818cb | |||
| b67644318e | |||
| 35c89990f3 | |||
| 415d717c78 | |||
| da9a6af766 | |||
| 7beed53f66 | |||
| a799012952 | |||
| 193119cc2d |
103
README.md
103
README.md
@@ -1,23 +1,100 @@
|
||||
# WP Multi Team-Card
|
||||
|
||||
## Einstellungen im Backend
|
||||
**Erstellt Teamkarten mit Name, Funktion, Zuständigkeit, Bild und Kategorie. Ausgabe per Shortcode `[teamcards]`.**
|
||||
|
||||
Im WordPress-Adminbereich kannst du Teammitglieder hinzufügen, bearbeiten und löschen. Jedes Teammitglied besteht aus den folgenden Feldern:
|
||||
[](https://git.viper.ipv64.net/M_Viper/wp-multi-teamcard/releases)
|
||||
[Telegram Support](https://t.me/M_Viper04)
|
||||
|
||||
- **Name**
|
||||
- **Funktion**
|
||||
- **Zuständigkeit**
|
||||
- **Bild**
|
||||
- **Kategorie**
|
||||
---
|
||||
|
||||
## Entwickeln
|
||||
## Features
|
||||
|
||||
Wenn du Änderungen am Plugin vornehmen möchtest, kannst du das Plugin nach Belieben anpassen. Achte darauf, dass du die richtigen Hooks und Filter verwendest, um deine Anpassungen mit zukünftigen Versionen kompatibel zu halten.
|
||||
- Verwaltung von Teammitgliedern im WordPress-Backend
|
||||
- Teamkarten mit Name, Funktion, Zuständigkeit, Bild und Kategorie
|
||||
- Drag & Drop Sortierung und Inline-Bearbeitung im Backend
|
||||
- Responsive Darstellung im Frontend
|
||||
- Ausgabe per Shortcode `[teamcards]`
|
||||
- Kategorien für Teammitglieder
|
||||
- Bild-Upload und Vorschau
|
||||
- Automatische Update-Benachrichtigung bei neuen Releases
|
||||
|
||||
## Changelog
|
||||
---
|
||||
|
||||
### Version 1.0
|
||||
- Erste Veröffentlichung des Plugins.
|
||||
## Installation
|
||||
|
||||
1. Lade das Plugin herunter oder klone das Repository: git clone https://git.viper.ipv64.net/M_Viper/wp-multi-teamcard.git
|
||||
2. Kopiere den Ordner `wp-multi-teamcard` in dein WordPress-Plugin-Verzeichnis (`/wp-content/plugins/`).
|
||||
3. Aktiviere das Plugin im WordPress-Backend unter „Plugins“.
|
||||
|
||||
**Mindestanforderungen:**
|
||||
- WordPress 6.7.2 oder neuer
|
||||
- PHP 7.2 oder neuer
|
||||
|
||||
---
|
||||
|
||||
## Nutzung
|
||||
|
||||
### Teammitglieder verwalten
|
||||
|
||||
Im WordPress-Backend erscheint ein Menüpunkt **Teamkarten**. Dort kannst du:
|
||||
|
||||
- Neue Teammitglieder hinzufügen (Name, Funktion, Zuständigkeit, Bild, Kategorie)
|
||||
- Bestehende Teammitglieder bearbeiten (per Klick auf das jeweilige Feld)
|
||||
- Reihenfolge per Drag & Drop ändern
|
||||
- Teammitglieder löschen
|
||||
- Bilder per Medienauswahl zuweisen oder ändern
|
||||
|
||||
### Shortcode
|
||||
|
||||
Gib den Shortcode überall im Editor ein, wo die Teamkarten angezeigt werden sollen: `[teamcards]`
|
||||
|
||||
**Optional:** Nach Kategorie filtern: `[teamcards kategorie="support"]`
|
||||
Ersetze `"support"` durch den Slug der gewünschten Kategorie.
|
||||
|
||||
---
|
||||
|
||||
## Beispielausgabe (Frontend)
|
||||
|
||||
Die Teamkarten werden als responsive Grid angezeigt, z.B.:
|
||||
|
||||
+-------------------+----------------------------------+ </br>
|
||||
| [Bild] | Name: Max Mustermann | </br>
|
||||
| | Funktion: Support | </br>
|
||||
| | Zuständigkeit: Kundenservice | </br>
|
||||
+-------------------+----------------------------------+ </br>
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Entwickler-Infos
|
||||
|
||||
- **Custom Post Type:** `teamcard`
|
||||
- **Taxonomie:** `teamcard_kategorie`
|
||||
- **Shortcode:** `[teamcards]`
|
||||
- **AJAX-Handler:** Hinzufügen, Bearbeiten, Löschen, Sortieren, Bild-Upload
|
||||
- **Styles & Scripts:** Werden nur im Admin geladen
|
||||
|
||||
---
|
||||
|
||||
## Update-Hinweis
|
||||
|
||||
Das Plugin prüft automatisch, ob eine neue Version auf Gitea verfügbar ist, und zeigt einen Hinweis im Admin-Bereich an.
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
- [Telegram Support](https://t.me/M_Viper04)
|
||||
|
||||
---
|
||||
|
||||
## Lizenz
|
||||
|
||||
Dieses Plugin wird unter der GPL2-Lizenz veröffentlicht. Weitere Informationen findest du unter [GPL2 Lizenz](https://www.gnu.org/licenses/gpl-2.0.html).
|
||||
GPLv2 – siehe [LICENSE](https://www.gnu.org/licenses/gpl-2.0.html)
|
||||
|
||||
---
|
||||
|
||||
## Autor
|
||||
|
||||
- **M_Viper**
|
||||
- [m-viper.de](https://m-viper.de)
|
||||
|
||||
102
assets/css/teamcard-admin.css
Normal file
102
assets/css/teamcard-admin.css
Normal file
@@ -0,0 +1,102 @@
|
||||
/* Allgemeine Admin-Stile */
|
||||
.teamcard-admin .nav-tab-wrapper {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.teamcard-admin .tab-content {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccd0d4;
|
||||
box-shadow: 0 1px 1px rgba(0,0,0,.04);
|
||||
}
|
||||
|
||||
.teamcard-add-new-form {
|
||||
background: #f9f9f9;
|
||||
border: 1px solid #e5e5e5;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-fields {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.form-field label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.form-field input[type="text"],
|
||||
.form-field select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.teamcard-table .column-thumbnail {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.teamcard-table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.image-preview-container {
|
||||
margin-bottom: 10px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.teamcard-bild-vorschau {
|
||||
max-width: 80px;
|
||||
max-height: 80px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.editable {
|
||||
padding: 8px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
min-height: 18px; /* Verhindert Sprünge */
|
||||
}
|
||||
|
||||
.editable:hover {
|
||||
border-color: #0073aa;
|
||||
background-color: #f3f3f3;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inline-edit {
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ui-sortable-helper {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.ui-state-highlight {
|
||||
height: 80px;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px dashed #ccc;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
.ui-state-highlight::before {
|
||||
content: "Hier ablegen";
|
||||
}
|
||||
|
||||
#teamcard-message {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
right: 20px;
|
||||
z-index: 9999;
|
||||
max-width: 300px;
|
||||
}
|
||||
233
assets/css/teamcard-frontend.css
Normal file
233
assets/css/teamcard-frontend.css
Normal file
@@ -0,0 +1,233 @@
|
||||
/* Grid-Container für die Teamkarten */
|
||||
.teamcard-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
justify-content: flex-start;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
/* Basis-Stile für alle Teamkarten */
|
||||
.teamcard {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
overflow: hidden; /* Verhindert, dass abgerundete Ecken vom Bild abgeschnitten werden */
|
||||
}
|
||||
|
||||
.teamcard:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.teamcard-image {
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.teamcard-image img {
|
||||
max-width: 120px;
|
||||
height: 120px;
|
||||
object-fit: cover; /* Schneidet Bilder zu, ohne sie zu verzerren */
|
||||
border-radius: 50%;
|
||||
border: 3px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.teamcard-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.teamcard-name {
|
||||
font-size: 1.2em;
|
||||
font-weight: 600;
|
||||
margin: 0 0 10px 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.teamcard-function {
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
color: #0073aa;
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
|
||||
.teamcard-responsibility {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Spezifische Stile für die Card-Typen */
|
||||
|
||||
/* Standard Card */
|
||||
.teamcard-standard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Compact Card */
|
||||
.teamcard-compact {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
}
|
||||
.teamcard-compact .teamcard-image {
|
||||
margin-bottom: 0;
|
||||
margin-right: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.teamcard-compact .teamcard-image img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.teamcard-compact .teamcard-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* Featured Card */
|
||||
.teamcard-featured {
|
||||
border: 2px solid #0073aa;
|
||||
background: linear-gradient(145deg, #ffffff, #f9fbff);
|
||||
}
|
||||
.teamcard-featured .teamcard-image img {
|
||||
border-color: #0073aa;
|
||||
}
|
||||
.teamcard-featured .teamcard-name {
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
/* --- NEUE STILE FÜR DIE KARTENTYPEN --- */
|
||||
|
||||
/* Flip Card */
|
||||
.teamcard-flip-container {
|
||||
perspective: 1000px; /* Entfernung zum 3D-Effekt */
|
||||
}
|
||||
|
||||
.teamcard-flipper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 320px; /* Feste Höhe, wichtig für den Flip-Effekt */
|
||||
transition: transform 0.8s;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.teamcard-flip-container:hover .teamcard-flipper {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
.teamcard-flip {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backface-visibility: hidden; /* Rückseite der Elemente verbergen */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.teamcard-front {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.teamcard-back {
|
||||
background-color: #f8f9fa;
|
||||
color: #333;
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
.teamcard-back .teamcard-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.teamcard-back .teamcard-responsibility {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.6;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Profile Card */
|
||||
.teamcard-profile {
|
||||
border-radius: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.teamcard-profile-header {
|
||||
height: 180px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.teamcard-profile-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, rgba(0,0,0,0.7), rgba(0,0,0,0.1));
|
||||
}
|
||||
|
||||
.teamcard-profile-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.teamcard-profile .teamcard-name {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.teamcard-profile .teamcard-function {
|
||||
margin: 5px 0 0 0;
|
||||
color: #f0f0f0;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.teamcard-profile-body {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.teamcard-profile-body .teamcard-responsibility {
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Responsive Anpassungen */
|
||||
@media (max-width: 768px) {
|
||||
.teamcard-grid {
|
||||
justify-content: center;
|
||||
}
|
||||
.teamcard {
|
||||
flex-basis: 100% !important;
|
||||
max-width: 320px;
|
||||
}
|
||||
/* Anpassung der Höhe für Flip-Cards auf kleinen Bildschirmen */
|
||||
.teamcard-flipper {
|
||||
height: 280px;
|
||||
}
|
||||
}
|
||||
171
assets/js/teamcard-admin.js
Normal file
171
assets/js/teamcard-admin.js
Normal file
@@ -0,0 +1,171 @@
|
||||
jQuery(document).ready(function($) {
|
||||
var newTeamcardFrame;
|
||||
var teamcardFrame;
|
||||
|
||||
// Medienbibliothek für neues Teammitglied
|
||||
$('#new-teamcard-bild-button').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (newTeamcardFrame) { newTeamcardFrame.open(); return; }
|
||||
|
||||
newTeamcardFrame = wp.media({ title: 'Bild auswählen', button: { text: 'Verwenden' }, multiple: false });
|
||||
newTeamcardFrame.on('select', function() {
|
||||
var attachment = newTeamcardFrame.state().get('selection').first().toJSON();
|
||||
$('#new-teamcard-bild-id').val(attachment.id);
|
||||
$('#new-teamcard-bild-vorschau').attr('src', attachment.url).show();
|
||||
});
|
||||
newTeamcardFrame.open();
|
||||
});
|
||||
|
||||
// Medienbibliothek für vorhandene Teammitglieder
|
||||
$(document).on('click', '.teamcard-bild-button', function(e) {
|
||||
e.preventDefault();
|
||||
var button = $(this);
|
||||
var teamcardId = button.data('id');
|
||||
|
||||
if (teamcardFrame) { teamcardFrame.open(); return; }
|
||||
|
||||
teamcardFrame = wp.media({ title: 'Bild ändern', button: { text: 'Verwenden' }, multiple: false });
|
||||
teamcardFrame.on('select', function() {
|
||||
var attachment = teamcardFrame.state().get('selection').first().toJSON();
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: { action: 'update_teamcard_image', id: teamcardId, bild_id: attachment.id, nonce: teamcard_data.nonce },
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var container = button.siblings('.image-preview-container');
|
||||
container.html('<img src="' + response.data.bild_url + '" class="teamcard-bild-vorschau">');
|
||||
showMessage('Bild erfolgreich aktualisiert.', 'success');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
teamcardFrame.open();
|
||||
});
|
||||
|
||||
// Neues Teammitglied hinzufügen
|
||||
$('#add-teamcard-button').on('click', function() {
|
||||
var name = $('#new-teamcard-name').val();
|
||||
if (!name) { showMessage('Bitte gib einen Namen ein.', 'error'); return; }
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'add_teamcard',
|
||||
name: name,
|
||||
funktion: $('#new-teamcard-funktion').val(),
|
||||
zustaendigkeit: $('#new-teamcard-zustaendigkeit').val(),
|
||||
card_type: $('#new-teamcard-card-type').val(),
|
||||
bild_id: $('#new-teamcard-bild-id').val(),
|
||||
nonce: teamcard_data.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var bildHtml = response.data.bild_url ? '<img src="' + response.data.bild_url + '" class="teamcard-bild-vorschau">' : '';
|
||||
var newRow = `
|
||||
<tr data-id="${response.data.id}" class="teamcard-item">
|
||||
<td class="teamcard-bild-column"><div class="image-preview-container">${bildHtml}</div><button type="button" class="button teamcard-bild-button" data-id="${response.data.id}">Ändern</button></td>
|
||||
<td><div class="editable" data-field="title" data-id="${response.data.id}">${name}</div></td>
|
||||
<td><div class="editable" data-field="funktion" data-id="${response.data.id}">${$('#new-teamcard-funktion').val()}</div></td>
|
||||
<td><div class="editable" data-field="zustaendigkeit" data-id="${response.data.id}">${$('#new-teamcard-zustaendigkeit').val()}</div></td>
|
||||
<td>${$('#new-teamcard-card-type option:selected').text()}</td>
|
||||
<td><button type="button" class="button button-small teamcard-delete" data-id="${response.data.id}">Löschen</button></td>
|
||||
</tr>`;
|
||||
$('#teamcard-list').append(newRow);
|
||||
|
||||
// Formular zurücksetzen
|
||||
$('#new-teamcard-name, #new-teamcard-funktion, #new-teamcard-zustaendigkeit, #new-teamcard-bild-id').val('');
|
||||
$('#new-teamcard-bild-vorschau').hide();
|
||||
$('#new-teamcard-card-type').prop('selectedIndex',0);
|
||||
|
||||
showMessage('Teammitglied erfolgreich hinzugefügt.', 'success');
|
||||
} else {
|
||||
showMessage(response.data.message || 'Ein unbekannter Fehler ist aufgetreten.', 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Inline-Bearbeitung
|
||||
$(document).on('click', '.editable', function() {
|
||||
var element = $(this);
|
||||
var currentText = element.text().trim();
|
||||
element.html('<input type="text" class="inline-edit" value="' + currentText + '">');
|
||||
element.find('input').focus().select();
|
||||
});
|
||||
|
||||
$(document).on('blur keypress', '.inline-edit', function(e) {
|
||||
if (e.type === 'keypress' && e.which !== 13) return;
|
||||
if (e.type === 'keypress') { e.preventDefault(); }
|
||||
|
||||
var input = $(this);
|
||||
var element = input.parent();
|
||||
var newValue = input.val().trim();
|
||||
var field = element.data('field');
|
||||
var id = element.data('id');
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: { action: 'update_teamcard', id: id, field: field, value: newValue, nonce: teamcard_data.nonce },
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
element.text(newValue);
|
||||
showMessage('Erfolgreich aktualisiert.', 'success');
|
||||
} else {
|
||||
element.text(newValue); // Text trotzdem aktualisieren, auch wenn der Request fehlschlägt
|
||||
showMessage('Fehler beim Speichern.', 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Teammitglied löschen
|
||||
$(document).on('click', '.teamcard-delete', function() {
|
||||
if (!confirm('Möchtest du dieses Teammitglied wirklich löschen?')) { return; }
|
||||
|
||||
var button = $(this);
|
||||
var id = button.data('id');
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: { action: 'delete_teamcard', id: id, nonce: teamcard_data.nonce },
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
button.closest('tr').fadeOut(400, function() { $(this).remove(); });
|
||||
showMessage('Teammitglied erfolgreich gelöscht.', 'success');
|
||||
} else {
|
||||
showMessage('Fehler beim Löschen.', 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Drag & Drop Sortierung
|
||||
$('#teamcard-list').sortable({
|
||||
handle: 'td:first', // Nur die erste Spalte als Handle
|
||||
placeholder: 'ui-state-highlight',
|
||||
tolerance: 'pointer',
|
||||
update: function(event, ui) {
|
||||
var order = $(this).sortable('toArray', {attribute: 'data-id'});
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: { action: 'update_teamcard_order', order: order, nonce: teamcard_data.nonce },
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
showMessage('Reihenfolge aktualisiert.', 'success');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function showMessage(message, type) {
|
||||
var messageElement = $('#teamcard-message');
|
||||
messageElement.removeClass('notice-success notice-error').addClass('notice-' + type);
|
||||
messageElement.html('<p>' + message + '</p>').show().delay(3000).fadeOut();
|
||||
}
|
||||
});
|
||||
40
includes/help-tab.php
Normal file
40
includes/help-tab.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// Diese Datei wird in der Haupt-Admin-Datei included.
|
||||
?>
|
||||
<div class="teamcard-tab-content">
|
||||
<h2>Hilfe & Dokumentation</h2>
|
||||
<div class="help-section">
|
||||
<h3>Shortcode verwenden</h3>
|
||||
<p>Um alle Teammitglieder anzuzeigen, verwenden Sie:</p>
|
||||
<code>[teamcards]</code>
|
||||
|
||||
<p>Um nur eine bestimmte Kategorie anzuzeigen:</p>
|
||||
<code>[teamcards kategorie="management"]</code>
|
||||
|
||||
<p>Um einen bestimmten Card-Typ zu erzwingen (überschreibt die Einstellung des Mitglieds):</p>
|
||||
<code>[teamcards type="featured"]</code>
|
||||
|
||||
<p>Um die Anzahl der Spalten zu ändern (überschreibt die globale Einstellung):</p>
|
||||
<code>[teamcards columns="3"]</code>
|
||||
</div>
|
||||
|
||||
<div class="help-section">
|
||||
<h3>Card-Typen</h3>
|
||||
<ul>
|
||||
<li><strong>Standard Card:</strong> Die klassische Card mit Bild oben und Text darunter.</li>
|
||||
<li><strong>Compact Card:</strong> Eine platzsparende Version, ideal für lange Listen.</li>
|
||||
<li><strong>Featured Card:</strong> Eine hervorgehobene Card mit zentriertem Layout und besonderem Styling.</li>
|
||||
<li><strong>Flip Card:</strong> Eine interaktive Card, die beim Hover gedreht wird, um zusätzliche Informationen (z.B. "Über mich") auf der Rückseite zu zeigen.</li>
|
||||
<li><strong>Profile Card:</strong> Eine Card mit dem Bild als Hintergrund, ideal für ein modernes, visuelles Profil.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="help-section">
|
||||
<h3>Support</h3>
|
||||
<p>Für Support und Fragen kontaktieren Sie uns bitte über:</p>
|
||||
<ul>
|
||||
<li><a href="https://discord.com/invite/FdRs4BRd8D" target="_blank">Discord Support</a></li>
|
||||
<li><a href="https://t.me/M_Viper04" target="_blank">Telegram Support</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
12
includes/settings-tab.php
Normal file
12
includes/settings-tab.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
// Diese Datei wird in der Haupt-Admin-Datei included.
|
||||
?>
|
||||
<div class="teamcard-tab-content">
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
settings_fields('teamcard_settings_group');
|
||||
do_settings_sections('teamcard_settings');
|
||||
submit_button('Einstellungen speichern');
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
93
includes/team-members-tab.php
Normal file
93
includes/team-members-tab.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
// Diese Datei wird in der Haupt-Admin-Datei included.
|
||||
?>
|
||||
<div class="teamcard-tab-content">
|
||||
<p><strong>Hinweis:</strong> Beim Löschen des Plugins werden alle Teammitglieder und zugehörigen Daten unwiderruflich aus der Datenbank entfernt. Bitte erstellen Sie ein Backup, falls Sie die Daten behalten möchten.</p>
|
||||
|
||||
<div class="teamcard-add-new-form">
|
||||
<h2>Neues Teammitglied hinzufügen</h2>
|
||||
<div class="form-fields">
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-name">Name:</label>
|
||||
<input type="text" id="new-teamcard-name" placeholder="Name eingeben" required>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-funktion">Funktion:</label>
|
||||
<input type="text" id="new-teamcard-funktion" placeholder="Funktion eingeben">
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-zustaendigkeit">Zuständigkeit / Über mich:</label>
|
||||
<textarea id="new-teamcard-zustaendigkeit" placeholder="Zuständigkeit oder Text für die Rückseite der Flip-Card eingeben"></textarea>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-card-type">Card-Typ:</label>
|
||||
<select id="new-teamcard-card-type">
|
||||
<option value="standard">Standard Card</option>
|
||||
<option value="compact">Compact Card</option>
|
||||
<option value="featured">Featured Card</option>
|
||||
<!-- NEUE OPTIONEN -->
|
||||
<option value="flip">Flip Card</option>
|
||||
<option value="profile">Profile Card</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>Bild:</label>
|
||||
<div class="image-preview-container">
|
||||
<img id="new-teamcard-bild-vorschau" src="" style="display:none; max-width:100px;">
|
||||
</div>
|
||||
<input type="hidden" id="new-teamcard-bild-id" value="">
|
||||
<button type="button" class="button" id="new-teamcard-bild-button">Bild auswählen</button>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button type="button" id="add-teamcard-button" class="button button-primary">Teammitglied hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Vorhandene Teammitglieder</h2>
|
||||
<p>Ziehe die Zeilen, um die Reihenfolge zu ändern. Klicke auf die Felder, um sie zu bearbeiten.</p>
|
||||
|
||||
<table class="wp-list-table widefat fixed striped teamcard-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="column-thumbnail">Bild</th>
|
||||
<th>Name</th>
|
||||
<th>Funktion</th>
|
||||
<th>Zuständigkeit</th>
|
||||
<th>Typ</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="teamcard-list">
|
||||
<?php
|
||||
$teamcards = get_posts(['post_type' => 'teamcard', 'posts_per_page' => -1, 'orderby' => 'menu_order', 'order' => 'ASC']);
|
||||
foreach ($teamcards as $teamcard) {
|
||||
$funktion = get_post_meta($teamcard->ID, '_teamcard_funktion', true);
|
||||
$zustaendigkeit = get_post_meta($teamcard->ID, '_teamcard_zustaendigkeit', true);
|
||||
$bild_id = get_post_meta($teamcard->ID, '_teamcard_bild_id', true);
|
||||
$card_type = get_post_meta($teamcard->ID, '_teamcard_card_type', true);
|
||||
$bild_url = $bild_id ? wp_get_attachment_image_url($bild_id, 'thumbnail') : '';
|
||||
?>
|
||||
<tr data-id="<?php echo $teamcard->ID; ?>" class="teamcard-item">
|
||||
<td class="teamcard-bild-column">
|
||||
<div class="image-preview-container">
|
||||
<?php if ($bild_url): ?>
|
||||
<img src="<?php echo esc_url($bild_url); ?>" class="teamcard-bild-vorschau">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<button type="button" class="button teamcard-bild-button" data-id="<?php echo $teamcard->ID; ?>">Ändern</button>
|
||||
</td>
|
||||
<td><div class="editable" data-field="title" data-id="<?php echo $teamcard->ID; ?>"><?php echo esc_html($teamcard->post_title); ?></div></td>
|
||||
<td><div class="editable" data-field="funktion" data-id="<?php echo $teamcard->ID; ?>"><?php echo esc_html($funktion); ?></div></td>
|
||||
<td><div class="editable" data-field="zustaendigkeit" data-id="<?php echo $teamcard->ID; ?>"><?php echo esc_html($zustaendigkeit); ?></div></td>
|
||||
<td><?php echo esc_html(ucfirst($card_type ?: 'standard')); ?></td>
|
||||
<td><button type="button" class="button button-small teamcard-delete" data-id="<?php echo $teamcard->ID; ?>">Löschen</button></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="teamcard-message" class="notice" style="display:none;"></div>
|
||||
</div>
|
||||
376
multi-team-card.php
Normal file
376
multi-team-card.php
Normal file
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Multi Team-Card
|
||||
* Plugin URI: https://git.viper.ipv64.net/M_Viper/wp-multi-teamcard
|
||||
* Description: Erstellt Teamkarten mit Name, Funktion, Zuständigkeit, Bild und Kategorie. Ausgabe per Shortcode [teamcards].
|
||||
* Version: 2.0
|
||||
* Author: M_Viper
|
||||
* Author URI: https://m-viper.de
|
||||
* Requires at least: 6.8
|
||||
* Tested up to: 6.8
|
||||
* PHP Version: 7.4
|
||||
* License: GPL2
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
* Text Domain: multi-team-card
|
||||
* Tags: team, card, shortcodes, team-management, customizable, responsive
|
||||
* Support: [Discord Support](https://discord.com/invite/FdRs4BRd8D)
|
||||
* Support: [Telegram Support](https://t.me/M_Viper04)
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
// Check if the PHP version is sufficient
|
||||
if (version_compare(PHP_VERSION, '7.2', '<')) {
|
||||
die('This plugin requires PHP 7.2 or higher.');
|
||||
}
|
||||
|
||||
// Get the current version of the plugin from the plugin header dynamically
|
||||
function get_current_plugin_version() {
|
||||
if (!function_exists('get_plugin_data')) {
|
||||
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||
}
|
||||
$plugin_data = get_plugin_data(__FILE__);
|
||||
return $plugin_data['Version'];
|
||||
}
|
||||
|
||||
$gitea_api_url = 'https://git.viper.ipv64.net/api/v1/repos/M_Viper/wp-multi-teamcard/releases/latest';
|
||||
|
||||
function check_for_new_release() {
|
||||
global $gitea_api_url;
|
||||
$current_version = get_current_plugin_version();
|
||||
$response = wp_remote_get($gitea_api_url);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$release_data = json_decode($body);
|
||||
|
||||
if (isset($release_data->tag_name)) {
|
||||
$latest_version = ltrim($release_data->tag_name, 'v'); // Entfernt 'v' falls vorhanden
|
||||
if (version_compare($latest_version, $current_version, '>')) {
|
||||
add_action('admin_notices', function() use ($latest_version) {
|
||||
echo '<div class="notice notice-info is-dismissible">
|
||||
<p><strong>⚠️ Neue Version von WP Multi Teamcard verfügbar:</strong> Version ' . esc_html($latest_version) . ' ist jetzt auf Gitea verfügbar. <a href="https://git.viper.ipv64.net/M_Viper/wp-multi-teamcard/releases" target="_blank">Hier klicken, um die neue Version herunterzuladen. ⚠️</a></p>
|
||||
</div>';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('admin_init', 'check_for_new_release');
|
||||
|
||||
|
||||
// CPT registrieren
|
||||
function teamcard_register_post_type() {
|
||||
register_post_type('teamcard', [
|
||||
'labels' => [
|
||||
'name' => 'Teammitglieder',
|
||||
'singular_name' => 'Teammitglied',
|
||||
'add_new' => 'Neues Teammitglied',
|
||||
'add_new_item' => 'Teammitglied hinzufügen',
|
||||
'edit_item' => 'Teammitglied bearbeiten',
|
||||
],
|
||||
'public' => true,
|
||||
'show_ui' => false, // Wir nutzen eine eigene Admin-Seite
|
||||
'show_in_menu' => false,
|
||||
'menu_icon' => 'dashicons-groups',
|
||||
'supports' => ['title'],
|
||||
'has_archive' => false,
|
||||
'show_in_admin_bar' => false,
|
||||
]);
|
||||
|
||||
register_taxonomy('teamcard_kategorie', 'teamcard', [
|
||||
'labels' => [
|
||||
'name' => 'Kategorien',
|
||||
'singular_name' => 'Kategorie',
|
||||
],
|
||||
'hierarchical' => true,
|
||||
'public' => true,
|
||||
'show_admin_column' => true,
|
||||
'show_ui' => true, // Kategorien im Admin-Menü anzeigen
|
||||
]);
|
||||
}
|
||||
add_action('init', 'teamcard_register_post_type');
|
||||
|
||||
// Admin-Menü hinzufügen
|
||||
function teamcard_add_admin_menu() {
|
||||
add_menu_page(
|
||||
'Team-Cards verwalten',
|
||||
'Team-Cards',
|
||||
'manage_options',
|
||||
'teamcard_management',
|
||||
'teamcard_render_admin_page',
|
||||
'dashicons-groups',
|
||||
30
|
||||
);
|
||||
}
|
||||
add_action('admin_menu', 'teamcard_add_admin_menu');
|
||||
|
||||
// Die Hauptverwaltungsseite mit Tabs
|
||||
function teamcard_render_admin_page() {
|
||||
$active_tab = isset($_GET['tab']) ? sanitize_key($_GET['tab']) : 'team_members';
|
||||
?>
|
||||
<div class="wrap teamcard-admin">
|
||||
<h1>Team-Cards verwalten</h1>
|
||||
|
||||
<nav class="nav-tab-wrapper">
|
||||
<a href="?page=teamcard_management&tab=team_members" class="nav-tab <?php echo $active_tab === 'team_members' ? 'nav-tab-active' : ''; ?>">Teammitglieder</a>
|
||||
<a href="?page=teamcard_management&tab=settings" class="nav-tab <?php echo $active_tab === 'settings' ? 'nav-tab-active' : ''; ?>">Einstellungen</a>
|
||||
<a href="?page=teamcard_management&tab=help" class="nav-tab <?php echo $active_tab === 'help' ? 'nav-tab-active' : ''; ?>">Hilfe</a>
|
||||
</nav>
|
||||
|
||||
<div class="tab-content">
|
||||
<?php
|
||||
switch ($active_tab) {
|
||||
case 'team_members':
|
||||
require_once plugin_dir_path(__FILE__) . 'includes/team-members-tab.php';
|
||||
break;
|
||||
case 'settings':
|
||||
require_once plugin_dir_path(__FILE__) . 'includes/settings-tab.php';
|
||||
break;
|
||||
case 'help':
|
||||
require_once plugin_dir_path(__FILE__) . 'includes/help-tab.php';
|
||||
break;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
// AJAX-Handler zum Speichern der Teammitglieder
|
||||
function teamcard_ajax_handlers() {
|
||||
add_action('wp_ajax_add_teamcard', function() {
|
||||
check_ajax_referer('teamcard_nonce', 'nonce');
|
||||
|
||||
$name = sanitize_text_field($_POST['name']);
|
||||
$funktion = sanitize_text_field($_POST['funktion']);
|
||||
$zustaendigkeit = sanitize_textarea_field($_POST['zustaendigkeit']); // Textarea erlauben
|
||||
$bild_id = intval($_POST['bild_id']);
|
||||
$card_type = sanitize_text_field($_POST['card_type']);
|
||||
|
||||
if (empty($name)) {
|
||||
wp_send_json_error(['message' => 'Bitte gib einen Namen ein.']);
|
||||
}
|
||||
|
||||
$max_order = 0;
|
||||
$posts = get_posts(['post_type' => 'teamcard', 'posts_per_page' => 1, 'orderby' => 'menu_order', 'order' => 'DESC']);
|
||||
if (!empty($posts)) {
|
||||
$max_order = $posts[0]->menu_order;
|
||||
}
|
||||
|
||||
$post_id = wp_insert_post([
|
||||
'post_type' => 'teamcard',
|
||||
'post_title' => $name,
|
||||
'post_status' => 'publish',
|
||||
'menu_order' => $max_order + 1
|
||||
]);
|
||||
|
||||
if ($post_id) {
|
||||
update_post_meta($post_id, '_teamcard_funktion', $funktion);
|
||||
update_post_meta($post_id, '_teamcard_zustaendigkeit', $zustaendigkeit);
|
||||
update_post_meta($post_id, '_teamcard_card_type', $card_type);
|
||||
if ($bild_id > 0) {
|
||||
update_post_meta($post_id, '_teamcard_bild_id', $bild_id);
|
||||
}
|
||||
$bild_url = $bild_id ? wp_get_attachment_image_url($bild_id, 'thumbnail') : '';
|
||||
wp_send_json_success(['id' => $post_id, 'bild_url' => $bild_url]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Fehler beim Erstellen des Teammitglieds.']);
|
||||
}
|
||||
});
|
||||
|
||||
add_action('wp_ajax_update_teamcard', function() {
|
||||
check_ajax_referer('teamcard_nonce', 'nonce');
|
||||
$post_id = intval($_POST['id']);
|
||||
$field = sanitize_text_field($_POST['field']);
|
||||
$value = sanitize_textarea_field($_POST['value']); // Textarea erlauben
|
||||
|
||||
if ($field === 'title') {
|
||||
wp_update_post(['ID' => $post_id, 'post_title' => $value]);
|
||||
} else {
|
||||
update_post_meta($post_id, '_teamcard_' . $field, $value);
|
||||
}
|
||||
wp_send_json_success();
|
||||
});
|
||||
|
||||
add_action('wp_ajax_delete_teamcard', function() {
|
||||
check_ajax_referer('teamcard_nonce', 'nonce');
|
||||
$post_id = intval($_POST['id']);
|
||||
if (wp_delete_post($post_id, true)) {
|
||||
wp_send_json_success();
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Fehler beim Löschen.']);
|
||||
}
|
||||
});
|
||||
|
||||
add_action('wp_ajax_update_teamcard_image', function() {
|
||||
check_ajax_referer('teamcard_nonce', 'nonce');
|
||||
$post_id = intval($_POST['id']);
|
||||
$bild_id = intval($_POST['bild_id']);
|
||||
update_post_meta($post_id, '_teamcard_bild_id', $bild_id);
|
||||
$bild_url = wp_get_attachment_image_url($bild_id, 'thumbnail');
|
||||
wp_send_json_success(['bild_url' => $bild_url]);
|
||||
});
|
||||
|
||||
add_action('wp_ajax_update_teamcard_order', function() {
|
||||
check_ajax_referer('teamcard_nonce', 'nonce');
|
||||
$order = $_POST['order']; // This is an array of IDs
|
||||
foreach ($order as $position => $post_id) {
|
||||
wp_update_post(['ID' => intval($post_id), 'menu_order' => $position]);
|
||||
}
|
||||
wp_send_json_success();
|
||||
});
|
||||
}
|
||||
add_action('init', 'teamcard_ajax_handlers');
|
||||
|
||||
// Admin-Skripte und Styles laden
|
||||
function teamcard_admin_scripts($hook) {
|
||||
if ($hook !== 'toplevel_page_teamcard_management') return;
|
||||
|
||||
wp_enqueue_media();
|
||||
wp_enqueue_script('jquery-ui-sortable');
|
||||
|
||||
wp_enqueue_style('teamcard-admin-style', plugin_dir_url(__FILE__) . 'assets/css/teamcard-admin.css', [], '2.1');
|
||||
wp_enqueue_script('teamcard-admin-script', plugin_dir_url(__FILE__) . 'assets/js/teamcard-admin.js', ['jquery', 'jquery-ui-sortable'], '2.1', true);
|
||||
|
||||
wp_localize_script('teamcard-admin-script', 'teamcard_data', [
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('teamcard_nonce')
|
||||
]);
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'teamcard_admin_scripts');
|
||||
|
||||
// Frontend-Styles laden
|
||||
function teamcard_frontend_styles() {
|
||||
// Nur laden, wenn der Shortcode auf der Seite ist
|
||||
global $post;
|
||||
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'teamcards')) {
|
||||
wp_enqueue_style('teamcard-frontend-style', plugin_dir_url(__FILE__) . 'assets/css/teamcard-frontend.css', [], '2.1');
|
||||
}
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'teamcard_frontend_styles');
|
||||
|
||||
|
||||
// Shortcode für die Frontend-Anzeige
|
||||
function teamcard_shortcode($atts) {
|
||||
$atts = shortcode_atts([
|
||||
'kategorie' => '',
|
||||
'type' => get_option('teamcard_default_card_type', 'standard'),
|
||||
'columns' => get_option('teamcard_columns', 2),
|
||||
], $atts, 'teamcards');
|
||||
|
||||
$args = [
|
||||
'post_type' => 'teamcard',
|
||||
'posts_per_page' => -1,
|
||||
'orderby' => 'menu_order',
|
||||
'order' => 'ASC',
|
||||
];
|
||||
|
||||
if (!empty($atts['kategorie'])) {
|
||||
$args['tax_query'] = [[
|
||||
'taxonomy' => 'teamcard_kategorie',
|
||||
'field' => 'slug',
|
||||
'terms' => sanitize_text_field($atts['kategorie']),
|
||||
]];
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
return '<p>Keine Teammitglieder gefunden.</p>';
|
||||
}
|
||||
|
||||
// Spaltenbreite für das Grid berechnen
|
||||
$column_style = '';
|
||||
if ($atts['columns'] > 1) {
|
||||
$column_width = (100 / $atts['columns']) - 2; // 2% für den gap
|
||||
$column_style = "style='flex-basis: calc({$column_width}% - 20px);'";
|
||||
} else {
|
||||
$column_style = "style='flex-basis: 100%;'";
|
||||
}
|
||||
|
||||
|
||||
ob_start();
|
||||
echo '<div class="teamcard-grid teamcard-grid-' . esc_attr($atts['columns']) . '-cols">';
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$post_id = get_the_ID();
|
||||
$meta = [
|
||||
'funktion' => get_post_meta($post_id, '_teamcard_funktion', true),
|
||||
'zustaendigkeit' => get_post_meta($post_id, '_teamcard_zustaendigkeit', true),
|
||||
'bild_id' => get_post_meta($post_id, '_teamcard_bild_id', true),
|
||||
'card_type' => get_post_meta($post_id, '_teamcard_card_type', true),
|
||||
];
|
||||
$meta['bild_url'] = $meta['bild_id'] ? wp_get_attachment_url($meta['bild_id']) : '';
|
||||
|
||||
// Card-Typ aus dem Meta-Feld verwenden, falls vorhanden, sonst den aus dem Shortcode
|
||||
$card_type_to_render = !empty($meta['card_type']) ? $meta['card_type'] : $atts['type'];
|
||||
|
||||
// Sicherstellen, dass die Template-Datei existiert
|
||||
$template_file = plugin_dir_path(__FILE__) . "templates/card-{$card_type_to_render}.php";
|
||||
if (file_exists($template_file)) {
|
||||
include $template_file;
|
||||
} else {
|
||||
// Fallback auf Standard-Template, falls spezifisches nicht existiert
|
||||
include plugin_dir_path(__FILE__) . 'templates/card-standard.php';
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
wp_reset_postdata();
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('teamcards', 'teamcard_shortcode');
|
||||
|
||||
// Einstellungs-API registrieren
|
||||
function teamcard_register_settings() {
|
||||
register_setting('teamcard_settings_group', 'teamcard_default_card_type', ['sanitize_callback' => 'sanitize_text_field']);
|
||||
register_setting('teamcard_settings_group', 'teamcard_columns', ['sanitize_callback' => 'absint']);
|
||||
|
||||
add_settings_section(
|
||||
'teamcard_settings_section',
|
||||
'Anzeige-Einstellungen',
|
||||
'__return_false', // Keine Beschreibung nötig
|
||||
'teamcard_settings'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'teamcard_default_card_type',
|
||||
'Standard Card-Typ',
|
||||
'teamcard_default_card_type_callback',
|
||||
'teamcard_settings',
|
||||
'teamcard_settings_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'teamcard_columns',
|
||||
'Anzahl der Spalten',
|
||||
'teamcard_columns_callback',
|
||||
'teamcard_settings',
|
||||
'teamcard_settings_section'
|
||||
);
|
||||
}
|
||||
add_action('admin_init', 'teamcard_register_settings');
|
||||
|
||||
function teamcard_default_card_type_callback() {
|
||||
$default_card_type = get_option('teamcard_default_card_type', 'standard');
|
||||
?>
|
||||
<select name="teamcard_default_card_type">
|
||||
<option value="standard" <?php selected($default_card_type, 'standard'); ?>>Standard Card</option>
|
||||
<option value="compact" <?php selected($default_card_type, 'compact'); ?>>Compact Card</option>
|
||||
<option value="featured" <?php selected($default_card_type, 'featured'); ?>>Featured Card</option>
|
||||
<!-- NEUE OPTIONEN -->
|
||||
<option value="flip" <?php selected($default_card_type, 'flip'); ?>>Flip Card</option>
|
||||
<option value="profile" <?php selected($default_card_type, 'profile'); ?>>Profile Card</option>
|
||||
</select>
|
||||
<p class="description">Dieser Typ wird verwendet, wenn für ein Mitglied kein spezifischer Typ festgelegt ist.</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
function teamcard_columns_callback() {
|
||||
$columns = get_option('teamcard_columns', 2);
|
||||
?>
|
||||
<input type="number" name="teamcard_columns" value="<?php echo esc_attr($columns); ?>" min="1" max="4" step="1">
|
||||
<p class="description">Anzahl der Spalten für die Teammitglieder-Anzeige (1-4).</p>
|
||||
<?php
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
.teamcard-admin {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.teamcard-add-new-form {
|
||||
background: #fff;
|
||||
border: 1px solid #ccd0d4;
|
||||
box-shadow: 0 1px 1px rgba(0,0,0,.04);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-fields {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
flex: 1 0 200px;
|
||||
}
|
||||
|
||||
.form-field label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.form-field input[type="text"] {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.teamcard-item td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.teamcard-bild {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.image-preview-container {
|
||||
margin-bottom: 10px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.teamcard-bild-vorschau {
|
||||
max-width: 80px;
|
||||
max-height: 80px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.editable {
|
||||
padding: 8px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.editable:hover {
|
||||
border-color: #ddd;
|
||||
background-color: #f9f9f9;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inline-edit {
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.ui-state-highlight {
|
||||
height: 80px;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px dashed #ccc;
|
||||
}
|
||||
|
||||
#teamcard-message {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
right: 20px;
|
||||
z-index: 9999;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
/* Container für das Teamkarten-Grid */
|
||||
.teamcard-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
/* Stil für jedes Teammitglied */
|
||||
.teamcard {
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
width: 280px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
background-color: #fff;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
/* Hover-Effekte */
|
||||
.teamcard:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Bild des Teammitglieds */
|
||||
.teamcard img {
|
||||
max-width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 15px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* Hover-Effekt für das Bild */
|
||||
.teamcard:hover img {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Name des Teammitglieds */
|
||||
.teamcard h3 {
|
||||
font-size: 1.2em;
|
||||
font-weight: 600;
|
||||
margin: 10px 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Funktion und Zuständigkeit des Teammitglieds */
|
||||
.teamcard p {
|
||||
font-size: 0.95em;
|
||||
color: #666;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Stil für den Hover-Effekt beim Teammitglied */
|
||||
.teamcard:hover h3,
|
||||
.teamcard:hover p {
|
||||
color: #0073e6;
|
||||
}
|
||||
|
||||
/* Stil für den Container der Teamkarten auf mobilen Geräten */
|
||||
@media (max-width: 768px) {
|
||||
.teamcard-grid {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.teamcard {
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
}
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
jQuery(document).ready(function($) {
|
||||
// Medienbibliothek für neues Teammitglied
|
||||
var newTeamcardFrame;
|
||||
|
||||
$('#new-teamcard-bild-button').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (newTeamcardFrame) {
|
||||
newTeamcardFrame.open();
|
||||
return;
|
||||
}
|
||||
|
||||
newTeamcardFrame = wp.media({
|
||||
title: 'Bild auswählen',
|
||||
button: { text: 'Verwenden' },
|
||||
multiple: false
|
||||
});
|
||||
|
||||
newTeamcardFrame.on('select', function() {
|
||||
var attachment = newTeamcardFrame.state().get('selection').first().toJSON();
|
||||
$('#new-teamcard-bild-id').val(attachment.id);
|
||||
$('#new-teamcard-bild-vorschau').attr('src', attachment.url).show();
|
||||
});
|
||||
|
||||
newTeamcardFrame.open();
|
||||
});
|
||||
|
||||
// Medienbibliothek für vorhandene Teammitglieder
|
||||
var teamcardFrame;
|
||||
|
||||
$(document).on('click', '.teamcard-bild-button', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var button = $(this);
|
||||
var teamcardId = button.data('id');
|
||||
|
||||
if (teamcardFrame) {
|
||||
teamcardFrame.open();
|
||||
return;
|
||||
}
|
||||
|
||||
teamcardFrame = wp.media({
|
||||
title: 'Bild auswählen',
|
||||
button: { text: 'Verwenden' },
|
||||
multiple: false
|
||||
});
|
||||
|
||||
teamcardFrame.on('select', function() {
|
||||
var attachment = teamcardFrame.state().get('selection').first().toJSON();
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'update_teamcard_image',
|
||||
id: teamcardId,
|
||||
bild_id: attachment.id,
|
||||
nonce: teamcard_data.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var container = button.siblings('.image-preview-container');
|
||||
container.html('<img src="' + response.data.bild_url + '" class="teamcard-bild-vorschau">');
|
||||
showMessage('Bild erfolgreich aktualisiert', 'success');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teamcardFrame.open();
|
||||
});
|
||||
|
||||
// Neues Teammitglied hinzufügen
|
||||
$('#add-teamcard-button').on('click', function() {
|
||||
var name = $('#new-teamcard-name').val();
|
||||
var funktion = $('#new-teamcard-funktion').val();
|
||||
var zustaendigkeit = $('#new-teamcard-zustaendigkeit').val();
|
||||
var bildId = $('#new-teamcard-bild-id').val();
|
||||
|
||||
if (!name) {
|
||||
showMessage('Bitte gib einen Namen ein', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'add_teamcard',
|
||||
name: name,
|
||||
funktion: funktion,
|
||||
zustaendigkeit: zustaendigkeit,
|
||||
bild_id: bildId,
|
||||
nonce: teamcard_data.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var bildHtml = '';
|
||||
if (response.data.bild_url) {
|
||||
bildHtml = '<img src="' + response.data.bild_url + '" class="teamcard-bild-vorschau">';
|
||||
}
|
||||
|
||||
var newRow = '<tr data-id="' + response.data.id + '" class="teamcard-item">' +
|
||||
'<td class="teamcard-bild">' +
|
||||
'<div class="image-preview-container">' + bildHtml + '</div>' +
|
||||
'<button type="button" class="button teamcard-bild-button" data-id="' + response.data.id + '">Bild ändern</button>' +
|
||||
'</td>' +
|
||||
'<td><div class="editable" data-field="title" data-id="' + response.data.id + '">' + name + '</div></td>' +
|
||||
'<td><div class="editable" data-field="funktion" data-id="' + response.data.id + '">' + funktion + '</div></td>' +
|
||||
'<td><div class="editable" data-field="zustaendigkeit" data-id="' + response.data.id + '">' + zustaendigkeit + '</div></td>' +
|
||||
'<td><button type="button" class="button button-small teamcard-delete" data-id="' + response.data.id + '">Löschen</button></td>' +
|
||||
'</tr>';
|
||||
|
||||
$('#teamcard-list').append(newRow);
|
||||
|
||||
// Formular zurücksetzen
|
||||
$('#new-teamcard-name').val('');
|
||||
$('#new-teamcard-funktion').val('');
|
||||
$('#new-teamcard-zustaendigkeit').val('');
|
||||
$('#new-teamcard-bild-id').val('');
|
||||
$('#new-teamcard-bild-vorschau').attr('src', '').hide();
|
||||
|
||||
showMessage('Teammitglied erfolgreich hinzugefügt', 'success');
|
||||
} else {
|
||||
showMessage(response.data.message, 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Inline-Bearbeitung
|
||||
$(document).on('click', '.editable', function() {
|
||||
var element = $(this);
|
||||
var currentText = element.text();
|
||||
|
||||
element.html('<input type="text" class="inline-edit" value="' + currentText + '">');
|
||||
element.find('input').focus().select();
|
||||
});
|
||||
|
||||
$(document).on('blur', '.inline-edit', function() {
|
||||
var input = $(this);
|
||||
var element = input.parent();
|
||||
var newValue = input.val();
|
||||
var field = element.data('field');
|
||||
var id = element.data('id');
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'update_teamcard',
|
||||
id: id,
|
||||
field: field,
|
||||
value: newValue,
|
||||
nonce: teamcard_data.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
element.text(newValue);
|
||||
showMessage('Erfolgreich aktualisiert', 'success');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('keypress', '.inline-edit', function(e) {
|
||||
if (e.which === 13) {
|
||||
$(this).blur();
|
||||
}
|
||||
});
|
||||
|
||||
// Teammitglied löschen
|
||||
$(document).on('click', '.teamcard-delete', function() {
|
||||
if (!confirm('Möchtest du dieses Teammitglied wirklich löschen?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var button = $(this);
|
||||
var id = button.data('id');
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'delete_teamcard',
|
||||
id: id,
|
||||
nonce: teamcard_data.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
button.closest('tr').remove();
|
||||
showMessage('Teammitglied erfolgreich gelöscht', 'success');
|
||||
} else {
|
||||
showMessage(response.data.message, 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Drag & Drop Sortierung
|
||||
$('#teamcard-list').sortable({
|
||||
handle: 'td:first',
|
||||
placeholder: 'ui-state-highlight',
|
||||
update: function(event, ui) {
|
||||
var order = [];
|
||||
$('.teamcard-item').each(function() {
|
||||
order.push($(this).data('id'));
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: teamcard_data.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'update_teamcard_order',
|
||||
order: order,
|
||||
nonce: teamcard_data.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
showMessage('Reihenfolge erfolgreich aktualisiert', 'success');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Hilfsfunktion für Nachrichten
|
||||
function showMessage(message, type) {
|
||||
var messageElement = $('#teamcard-message');
|
||||
messageElement.removeClass('notice-success notice-error').addClass('notice-' + type);
|
||||
messageElement.html('<p>' + message + '</p>').show();
|
||||
|
||||
setTimeout(function() {
|
||||
messageElement.fadeOut();
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
18
templates/card-compact.php
Normal file
18
templates/card-compact.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* @var array $meta Enthält alle Metadaten des Teammitglieds
|
||||
* @var string $column_style Der Inline-Style für die Spaltenbreite
|
||||
*/
|
||||
?>
|
||||
<div class="teamcard teamcard-compact" <?php echo $column_style; ?>>
|
||||
<?php if ($meta['bild_url']): ?>
|
||||
<div class="teamcard-image">
|
||||
<img src="<?php echo esc_url($meta['bild_url']); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="teamcard-content">
|
||||
<h3 class="teamcard-name"><?php the_title(); ?></h3>
|
||||
<p class="teamcard-function"><?php echo esc_html($meta['funktion']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
19
templates/card-featured.php
Normal file
19
templates/card-featured.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @var array $meta Enthält alle Metadaten des Teammitglieds
|
||||
* @var string $column_style Der Inline-Style für die Spaltenbreite
|
||||
*/
|
||||
?>
|
||||
<div class="teamcard teamcard-featured" <?php echo $column_style; ?>>
|
||||
<?php if ($meta['bild_url']): ?>
|
||||
<div class="teamcard-image">
|
||||
<img src="<?php echo esc_url($meta['bild_url']); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="teamcard-content">
|
||||
<h3 class="teamcard-name"><?php the_title(); ?></h3>
|
||||
<p class="teamcard-function"><?php echo esc_html($meta['funktion']); ?></p>
|
||||
<p class="teamcard-responsibility"><?php echo esc_html($meta['zustaendigkeit']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
35
templates/card-flip.php
Normal file
35
templates/card-flip.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* @var array $meta Enthält alle Metadaten des Teammitglieds
|
||||
* @var string $column_style Der Inline-Style für die Spaltenbreite
|
||||
*/
|
||||
?>
|
||||
<div class="teamcard-flip-container" <?php echo $column_style; ?>>
|
||||
<div class="teamcard-flipper">
|
||||
<!-- Vorderseite der Karte -->
|
||||
<div class="teamcard teamcard-flip teamcard-front">
|
||||
<?php if ($meta['bild_url']): ?>
|
||||
<div class="teamcard-image">
|
||||
<img src="<?php echo esc_url($meta['bild_url']); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="teamcard-content">
|
||||
<h3 class="teamcard-name"><?php the_title(); ?></h3>
|
||||
<p class="teamcard-function"><?php echo esc_html($meta['funktion']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rückseite der Karte -->
|
||||
<div class="teamcard teamcard-flip teamcard-back">
|
||||
<div class="teamcard-content">
|
||||
<h3 class="teamcard-name"><?php the_title(); ?></h3>
|
||||
<div class="teamcard-responsibility">
|
||||
<?php
|
||||
// nl2br() wandelt Zeilenumbrüche in <br>-Tags um
|
||||
echo wp_kses_post(nl2br($meta['zustaendigkeit']));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
17
templates/card-profile.php
Normal file
17
templates/card-profile.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* @var array $meta Enthält alle Metadaten des Teammitglieds
|
||||
* @var string $column_style Der Inline-Style für die Spaltenbreite
|
||||
*/
|
||||
?>
|
||||
<div class="teamcard teamcard-profile" <?php echo $column_style; ?>>
|
||||
<div class="teamcard-profile-header" <?php echo $meta['bild_url'] ? 'style="background-image: url(' . esc_url($meta['bild_url']) . ');"' : ''; ?>>
|
||||
<div class="teamcard-profile-content">
|
||||
<h3 class="teamcard-name"><?php the_title(); ?></h3>
|
||||
<p class="teamcard-function"><?php echo esc_html($meta['funktion']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="teamcard-profile-body">
|
||||
<p class="teamcard-responsibility"><?php echo esc_html($meta['zustaendigkeit']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
19
templates/card-standard.php
Normal file
19
templates/card-standard.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @var array $meta Enthält alle Metadaten des Teammitglieds
|
||||
* @var string $column_style Der Inline-Style für die Spaltenbreite
|
||||
*/
|
||||
?>
|
||||
<div class="teamcard teamcard-standard" <?php echo $column_style; ?>>
|
||||
<?php if ($meta['bild_url']): ?>
|
||||
<div class="teamcard-image">
|
||||
<img src="<?php echo esc_url($meta['bild_url']); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="teamcard-content">
|
||||
<h3 class="teamcard-name"><?php the_title(); ?></h3>
|
||||
<p class="teamcard-function"><?php echo esc_html($meta['funktion']); ?></p>
|
||||
<p class="teamcard-responsibility"><?php echo esc_html($meta['zustaendigkeit']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
48
uninstall.php
Normal file
48
uninstall.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
// Sicherstellen, dass die Datei nur bei Plugin-Deinstallation direkt von WordPress aufgerufen wird
|
||||
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Funktion zum Löschen aller Plugin-Daten
|
||||
function delete_teamcard_data() {
|
||||
// Alle Teamcard-Posts abrufen
|
||||
$teamcards = get_posts([
|
||||
'post_type' => 'teamcard',
|
||||
'posts_per_page' => -1,
|
||||
'post_status' => 'any',
|
||||
]);
|
||||
|
||||
// Jeden Post und zugehörige Bilder löschen
|
||||
foreach ($teamcards as $teamcard) {
|
||||
// Bild aus der Mediathek löschen, falls vorhanden
|
||||
$bild_id = get_post_meta($teamcard->ID, '_teamcard_bild_id', true);
|
||||
if ($bild_id) {
|
||||
wp_delete_attachment($bild_id, true);
|
||||
}
|
||||
// Post und Metadaten löschen
|
||||
wp_delete_post($teamcard->ID, true);
|
||||
}
|
||||
|
||||
// Taxonomie 'teamcard_kategorie' und ihre Begriffe löschen
|
||||
$terms = get_terms([
|
||||
'taxonomy' => 'teamcard_kategorie',
|
||||
'hide_empty' => false,
|
||||
]);
|
||||
|
||||
if (!is_wp_error($terms)) {
|
||||
foreach ($terms as $term) {
|
||||
wp_delete_term($term->term_id, 'teamcard_kategorie');
|
||||
}
|
||||
}
|
||||
|
||||
// Alle Metadaten löschen, die mit dem Plugin verknüpft sind
|
||||
global $wpdb;
|
||||
$wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key LIKE '_teamcard_%'");
|
||||
|
||||
// Rewrite Rules zurücksetzen
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
// Funktion ausführen
|
||||
delete_teamcard_data();
|
||||
@@ -1,359 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WP Multi Team-Card
|
||||
* Plugin URI: https://git.viper.ipv64.net/M_Viper/wp-multi
|
||||
* Description: Erstellt Teamkarten mit Name, Funktion, Zuständigkeit, Bild und Kategorie. Ausgabe per Shortcode [teamcards].
|
||||
* Version: 1.0
|
||||
* Author: M_Viper
|
||||
* Author URI: https://m-viper.de
|
||||
* Requires at least: 6.7.2
|
||||
* Tested up to: 6.7.2
|
||||
* PHP Version: 7.2
|
||||
* License: GPL2
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
* Text Domain: wp-multi-team-card
|
||||
* Tags: team, card, shortcodes, team-management, customizable, responsive
|
||||
* Support: [Microsoft Teams Support](https://teams.live.com/l/community/FEAzokphpZTJ2u6OgI)
|
||||
* Support: [Telegram Support](https://t.me/M_Viper04)
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
// Check if the PHP version is sufficient
|
||||
if (version_compare(PHP_VERSION, '7.2', '<')) {
|
||||
die('This plugin requires PHP 7.2 or higher.');
|
||||
}
|
||||
|
||||
// CPT registrieren
|
||||
function teamcard_register_post_type() {
|
||||
register_post_type('teamcard', [
|
||||
'labels' => [
|
||||
'name' => 'Teammitglieder',
|
||||
'singular_name' => 'Teammitglied',
|
||||
'add_new' => 'Neues Teammitglied',
|
||||
'add_new_item' => 'Teammitglied hinzufügen',
|
||||
'edit_item' => 'Teammitglied bearbeiten',
|
||||
],
|
||||
'public' => true,
|
||||
'show_ui' => false, // Standard-UI ausblenden
|
||||
'show_in_menu' => false, // Nicht im Hauptmenü anzeigen
|
||||
'menu_icon' => 'dashicons-groups',
|
||||
'supports' => ['title'],
|
||||
'has_archive' => false,
|
||||
'show_in_admin_bar' => false,
|
||||
]);
|
||||
|
||||
register_taxonomy('teamcard_kategorie', 'teamcard', [
|
||||
'labels' => [
|
||||
'name' => 'Kategorien',
|
||||
'singular_name' => 'Kategorie',
|
||||
],
|
||||
'hierarchical' => true,
|
||||
'public' => true,
|
||||
'show_admin_column' => true,
|
||||
]);
|
||||
}
|
||||
add_action('init', 'teamcard_register_post_type');
|
||||
|
||||
// Admin-Menü hinzufügen
|
||||
function teamcard_add_admin_menu() {
|
||||
add_menu_page(
|
||||
'Teammitglieder verwalten',
|
||||
'Teamkarten',
|
||||
'manage_options',
|
||||
'teamcard_management',
|
||||
'teamcard_admin_page',
|
||||
'dashicons-groups',
|
||||
30
|
||||
);
|
||||
}
|
||||
add_action('admin_menu', 'teamcard_add_admin_menu');
|
||||
|
||||
// Die Hauptverwaltungsseite
|
||||
function teamcard_admin_page() {
|
||||
?>
|
||||
<div class="wrap teamcard-admin">
|
||||
<h1>Teammitglieder verwalten</h1>
|
||||
|
||||
<!-- Formular zum Hinzufügen neuer Teammitglieder -->
|
||||
<div class="teamcard-add-new-form">
|
||||
<h2>Neues Teammitglied hinzufügen</h2>
|
||||
<div class="form-fields">
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-name">Name:</label>
|
||||
<input type="text" id="new-teamcard-name" placeholder="Name eingeben">
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-funktion">Funktion:</label>
|
||||
<input type="text" id="new-teamcard-funktion" placeholder="Funktion eingeben">
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="new-teamcard-zustaendigkeit">Zuständigkeit:</label>
|
||||
<input type="text" id="new-teamcard-zustaendigkeit" placeholder="Zuständigkeit eingeben">
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>Bild:</label>
|
||||
<div class="image-preview-container">
|
||||
<img id="new-teamcard-bild-vorschau" src="" style="display:none; max-width:100px;">
|
||||
</div>
|
||||
<input type="hidden" id="new-teamcard-bild-id" value="">
|
||||
<button type="button" class="button" id="new-teamcard-bild-button">Bild auswählen</button>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button type="button" id="add-teamcard-button" class="button button-primary">Teammitglied hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Vorhandene Teammitglieder</h2>
|
||||
<p>Ziehe die Zeilen, um die Reihenfolge zu ändern. Klicke auf die Felder, um sie zu bearbeiten.</p>
|
||||
|
||||
<!-- Liste der vorhandenen Teammitglieder -->
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="10%">Bild</th>
|
||||
<th width="20%">Name</th>
|
||||
<th width="20%">Funktion</th>
|
||||
<th width="30%">Zuständigkeit</th>
|
||||
<th width="20%">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="teamcard-list">
|
||||
<?php
|
||||
$teamcards = get_posts([
|
||||
'post_type' => 'teamcard',
|
||||
'posts_per_page' => -1,
|
||||
'orderby' => 'menu_order',
|
||||
'order' => 'ASC'
|
||||
]);
|
||||
|
||||
foreach ($teamcards as $teamcard) {
|
||||
$funktion = get_post_meta($teamcard->ID, '_teamcard_funktion', true);
|
||||
$zustaendigkeit = get_post_meta($teamcard->ID, '_teamcard_zustaendigkeit', true);
|
||||
$bild_id = get_post_meta($teamcard->ID, '_teamcard_bild_id', true);
|
||||
$bild_url = $bild_id ? wp_get_attachment_image_url($bild_id, 'thumbnail') : '';
|
||||
?>
|
||||
<tr data-id="<?php echo $teamcard->ID; ?>" class="teamcard-item">
|
||||
<td class="teamcard-bild">
|
||||
<div class="image-preview-container">
|
||||
<?php if ($bild_url): ?>
|
||||
<img src="<?php echo esc_url($bild_url); ?>" class="teamcard-bild-vorschau">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<button type="button" class="button teamcard-bild-button" data-id="<?php echo $teamcard->ID; ?>">Bild ändern</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="editable" data-field="title" data-id="<?php echo $teamcard->ID; ?>"><?php echo esc_html($teamcard->post_title); ?></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="editable" data-field="funktion" data-id="<?php echo $teamcard->ID; ?>"><?php echo esc_html($funktion); ?></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="editable" data-field="zustaendigkeit" data-id="<?php echo $teamcard->ID; ?>"><?php echo esc_html($zustaendigkeit); ?></div>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="button button-small teamcard-delete" data-id="<?php echo $teamcard->ID; ?>">Löschen</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="teamcard-message" class="notice" style="display:none;"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
// AJAX-Handler zum Speichern der Teammitglieder
|
||||
function teamcard_ajax_handlers() {
|
||||
// Neues Teammitglied hinzufügen
|
||||
add_action('wp_ajax_add_teamcard', function() {
|
||||
$name = sanitize_text_field($_POST['name']);
|
||||
$funktion = sanitize_text_field($_POST['funktion']);
|
||||
$zustaendigkeit = sanitize_text_field($_POST['zustaendigkeit']);
|
||||
$bild_id = intval($_POST['bild_id']);
|
||||
|
||||
// Höchste menu_order finden
|
||||
$max_order = 0;
|
||||
$posts = get_posts([
|
||||
'post_type' => 'teamcard',
|
||||
'posts_per_page' => 1,
|
||||
'orderby' => 'menu_order',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
|
||||
if (!empty($posts)) {
|
||||
$max_order = $posts[0]->menu_order;
|
||||
}
|
||||
|
||||
// Neuen Post erstellen
|
||||
$post_id = wp_insert_post([
|
||||
'post_type' => 'teamcard',
|
||||
'post_title' => $name,
|
||||
'post_status' => 'publish',
|
||||
'menu_order' => $max_order + 1
|
||||
]);
|
||||
|
||||
if ($post_id) {
|
||||
update_post_meta($post_id, '_teamcard_funktion', $funktion);
|
||||
update_post_meta($post_id, '_teamcard_zustaendigkeit', $zustaendigkeit);
|
||||
|
||||
if ($bild_id > 0) {
|
||||
update_post_meta($post_id, '_teamcard_bild_id', $bild_id);
|
||||
}
|
||||
|
||||
$bild_url = $bild_id ? wp_get_attachment_image_url($bild_id, 'thumbnail') : '';
|
||||
|
||||
wp_send_json_success([
|
||||
'id' => $post_id,
|
||||
'bild_url' => $bild_url
|
||||
]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Fehler beim Erstellen des Teammitglieds']);
|
||||
}
|
||||
});
|
||||
|
||||
// Teammitglied aktualisieren
|
||||
add_action('wp_ajax_update_teamcard', function() {
|
||||
$post_id = intval($_POST['id']);
|
||||
$field = sanitize_text_field($_POST['field']);
|
||||
$value = sanitize_text_field($_POST['value']);
|
||||
|
||||
if ($field === 'title') {
|
||||
wp_update_post([
|
||||
'ID' => $post_id,
|
||||
'post_title' => $value
|
||||
]);
|
||||
} else {
|
||||
update_post_meta($post_id, '_teamcard_' . $field, $value);
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
});
|
||||
|
||||
// Teammitglied löschen
|
||||
add_action('wp_ajax_delete_teamcard', function() {
|
||||
$post_id = intval($_POST['id']);
|
||||
|
||||
if (wp_delete_post($post_id, true)) {
|
||||
wp_send_json_success();
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Fehler beim Löschen des Teammitglieds']);
|
||||
}
|
||||
});
|
||||
|
||||
// Bild aktualisieren
|
||||
add_action('wp_ajax_update_teamcard_image', function() {
|
||||
$post_id = intval($_POST['id']);
|
||||
$bild_id = intval($_POST['bild_id']);
|
||||
|
||||
update_post_meta($post_id, '_teamcard_bild_id', $bild_id);
|
||||
$bild_url = wp_get_attachment_image_url($bild_id, 'thumbnail');
|
||||
|
||||
wp_send_json_success(['bild_url' => $bild_url]);
|
||||
});
|
||||
|
||||
// Reihenfolge aktualisieren
|
||||
add_action('wp_ajax_update_teamcard_order', function() {
|
||||
$order = $_POST['order'];
|
||||
|
||||
foreach ($order as $position => $post_id) {
|
||||
wp_update_post([
|
||||
'ID' => intval($post_id),
|
||||
'menu_order' => $position
|
||||
]);
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
});
|
||||
}
|
||||
add_action('init', 'teamcard_ajax_handlers');
|
||||
|
||||
// Admin-Skripte und Styles laden
|
||||
function teamcard_admin_scripts($hook) {
|
||||
if ($hook !== 'toplevel_page_teamcard_management') return;
|
||||
|
||||
wp_enqueue_media();
|
||||
wp_enqueue_script('jquery-ui-sortable');
|
||||
|
||||
wp_enqueue_style(
|
||||
'teamcard-admin-style',
|
||||
plugin_dir_url(__FILE__) . 'teamcard-admin.css',
|
||||
[],
|
||||
'1.0'
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'teamcard-admin-script',
|
||||
plugin_dir_url(__FILE__) . 'teamcard-admin.js',
|
||||
['jquery', 'jquery-ui-sortable'],
|
||||
'1.0',
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script('teamcard-admin-script', 'teamcard_data', [
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('teamcard_nonce')
|
||||
]);
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'teamcard_admin_scripts');
|
||||
|
||||
// Shortcode für die Frontend-Anzeige
|
||||
function teamcard_shortcode($atts) {
|
||||
$atts = shortcode_atts([
|
||||
'kategorie' => '',
|
||||
], $atts);
|
||||
|
||||
$args = [
|
||||
'post_type' => 'teamcard',
|
||||
'posts_per_page' => -1,
|
||||
'orderby' => 'menu_order',
|
||||
'order' => 'ASC',
|
||||
];
|
||||
|
||||
if ($atts['kategorie']) {
|
||||
$args['tax_query'] = [[
|
||||
'taxonomy' => 'teamcard_kategorie',
|
||||
'field' => 'slug',
|
||||
'terms' => $atts['kategorie'],
|
||||
]];
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) return '<p>Keine Teammitglieder gefunden.</p>';
|
||||
|
||||
ob_start();
|
||||
echo '<div class="teamcard-grid" style="display: flex; flex-wrap: wrap; gap: 20px;">';
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$funktion = get_post_meta(get_the_ID(), '_teamcard_funktion', true);
|
||||
$zustaendigkeit = get_post_meta(get_the_ID(), '_teamcard_zustaendigkeit', true);
|
||||
$bild_id = get_post_meta(get_the_ID(), '_teamcard_bild_id', true);
|
||||
$bild_url = $bild_id ? wp_get_attachment_url($bild_id) : '';
|
||||
echo '<div class="teamcard" style="display: flex; flex-wrap: wrap; border:1px solid #ccc; border-radius:10px; padding:15px; width:48%; align-items: center;">';
|
||||
|
||||
// Bild links
|
||||
if ($bild_url) {
|
||||
echo '<div style="flex: 1; text-align: center; display: flex; justify-content: center; align-items: center; margin-right: 10px;">';
|
||||
echo '<img src="' . esc_url($bild_url) . '" style="max-width:100px; border-radius:50%; margin-bottom:0;">';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
// Text rechts
|
||||
echo '<div style="flex: 2; padding-left: 10px;">';
|
||||
echo '<h3>' . get_the_title() . '</h3>';
|
||||
echo '<p><strong>' . esc_html($funktion) . '</strong></p>';
|
||||
echo '<p>' . esc_html($zustaendigkeit) . '</p>';
|
||||
echo '</div>';
|
||||
|
||||
echo '</div>'; // Schließt die Teamcard-Div
|
||||
}
|
||||
echo '</div>'; // Schließt die Teamcard-Grid-Div
|
||||
|
||||
wp_reset_postdata();
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('teamcards', 'teamcard_shortcode');
|
||||
Reference in New Issue
Block a user