diff --git a/class_post_it_colors.php b/class_post_it_colors.php new file mode 100644 index 0000000..1ca30e7 --- /dev/null +++ b/class_post_it_colors.php @@ -0,0 +1,71 @@ +get_post_it_color($post_id); + } + function generate_post_it_colors() { + // Überprüfe, ob die Farben bereits in der wp_options gespeichert sind + $colors = get_option('post_it_colors'); + + // Wenn noch keine Farben vorhanden sind, generiere 12 Farben + if (!$colors) { + $colors = []; + for ($i = 0; $i < 12; $i++) { + $colors[] = $this->generate_contrast_color(); + } + // Speichere die generierten Farben in wp_options + update_option('post_it_colors', $colors); + } + + return $colors; + } + + function generate_contrast_color() { + // Helligkeit der Farben für gute Lesbarkeit mit schwarzer Schrift + $min_brightness = 130; + + do { + // Generiere eine zufällige Farbe + $color = sprintf('#%02X%02X%02X', mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); + // Berechne die Helligkeit der Farbe + $brightness = $this->calculate_brightness($color); + } while ($brightness < $min_brightness); + + return $color; + } + + function calculate_brightness($hex) { + // Entferne das "#" Zeichen, wenn vorhanden + $hex = str_replace('#', '', $hex); + + // Wandle HEX in RGB um + $r = hexdec(substr($hex, 0, 2)); + $g = hexdec(substr($hex, 2, 2)); + $b = hexdec(substr($hex, 4, 2)); + + // Berechne die Helligkeit (simplifiziert) + return ($r * 299 + $g * 587 + $b * 114) / 1000; + } + + function get_post_it_color($post_id) { + // Überprüfe, ob die Farbe bereits als Meta-Information gespeichert ist + $color = get_post_meta($post_id, '_post_it_color', true); + + if (!$color) { + // Hol die Liste der 12 Farben + $colors = $this->generate_post_it_colors(); + + // Wähle eine zufällige Farbe aus + $color = $colors[array_rand($colors)]; + + // Speichere die Farbe als Post-Meta + update_post_meta($post_id, '_post_it_color', $color); + } + + return $color; + } + +} diff --git a/css/colors.css b/css/colors.css new file mode 100644 index 0000000..e8ab7be --- /dev/null +++ b/css/colors.css @@ -0,0 +1,17 @@ +:root{ + --textcolor: var(--theme-palette-color-3); + --background: var(--theme-palette-color-7); + --buttoncolor: var(--theme-palette-color-1); + --buttontext: var(--theme-palette-color-6); + --inverse: var(--theme-palette-color-4); + --akcent: var(--theme-palette-color-2); + --akcent2: var(--theme-palette-color-5); + --background1: var(--theme-palette-color-6); + --background2: var(--theme-palette-color-8); + --modal-background: rgba(0,0,0,0.4); + --bordercolor: var(--theme-palette-color-2); + --bordercolor2: var(--theme-palette-color-9); + --gray: #d3d3d3; + +} + diff --git a/css/group-builder.css b/css/group-builder.css new file mode 100644 index 0000000..81b1da8 --- /dev/null +++ b/css/group-builder.css @@ -0,0 +1,573 @@ +.single-group_post .page-title { + background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.76) 10%, rgba(162, 162, 162, 0) 80%); + padding-left: 10px; + margin-left: -10px; +} +.entry-card.card-content.group_post, .entry-card.card-content.pinwall_post { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: minmax(20px,1fr); +} + +.attendees { + margin-top: 0px; + border-top: 4px solid #ddd; + +} +.attendees-wrapper { + position: relative; +} +.single-group_post .attendees-wrapper { + position: relative; + z-index: 50; + max-width: 500px; + margin: -75px auto 20px; +} +@media screen and (max-width: 1200px) { + .single-group_post .attendees-wrapper { + position: relative; + z-index: 50; + margin-top: -22px; + margin-bottom: -52px; + } +} +.attendees-wrapper p{ + color: var(--inverse); +} +.attendees-label { + color: var(--inverse); + text-align: center; +} +.group_post .attendees-wrapper { + margin-top: 10px; +} + + +.pinwall_post .attendees-label { + text-align: right; +} +.assoziated-groups { + list-style: none; +} +.assoziated-group-link a span { + background-color: var(--buttoncolor); + color: var(--inverse); + border-radius: 50%; + font-size: 32px; + height: fit-content; + width: fit-content; + padding: 2px; + margin-right: 7px; + margin-top: -5px; + margin-left: -3px; +} +.assoziated-group-link a:hover span { + border-radius: 50%; + font-size: 33px; + height: fit-content; + width: fit-content; + padding: 3px; + margin-top: -7px; + box-shadow: 2px 2px 5px 3px rgba(0,0,0,0.3); +} + +.assoziated-groups a{ + background-color: var(--buttoncolor); + color: var(--inverse); + border: none; + border-radius: 10px; + padding: 5px 10px; + cursor: pointer; + padding-left:0; + +} +.assoziated-groups a:hover{ + background-color: var(--inverse); + color: var(--buttoncolor) +} +.avatar-list { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + min-height: 50px; +} +.pinwall_post .avatar-list { + justify-content: right; +} +.avatar-wrapper { + display: inline-block; + margin-right: 5px; + position: relative; +} + +.avatar-wrapper img { + border-radius: 50%; + width: 50px; + height: 50px; +} +.avatar-wrapper img:hover { + border: 2px solid var(--buttoncolor); + scale: 1.3; +} + +.avatar-wrapper:hover::after { + content: attr(title); + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + background-color: var(--background1, #dddddd); + color: var(--textcolor, #000000); + padding: 5px; + border-radius: 3px; + font-size: 12px; + white-space: nowrap; +} +.single-group_post .avatar-list a { + display: inline-block; + opacity: 0; + transform: translateY(-100px); + animation: dropIn 0.5s forwards; +} + +.single-group_post .avatar-list a:nth-child(1) { + animation-delay: 0.2s; +} + +.single-group_post .avatar-list a:nth-child(2) { + animation-delay: 0.4s; +} + +.single-group_post .avatar-list a:nth-child(3) { + animation-delay: 0.6s; +} + +@keyframes dropIn { + to { + opacity: 1; + transform: translateY(0); + } +} + +.show-interest, +.create-group, +.leave-group { + padding: 5px 10px; + background-color: var(--background1); + color: var(--inverse); + border: none; + border-radius: 3px; + cursor: pointer; +} + +.show-interest:hover, +.create-group:hover, +.leave-group:hover { + /*background-color: var(--buttoncolor);*/ +} + + +/** Group Form **/ +.edit-group, .toggle-join-option, .generate-invite-link { + margin-top: 10px; + padding: 5px 10px; + background-color: var(--gray); + color: var(--inverse); + border: none; + cursor: pointer; +} + +.edit-group:hover, .toggle-join-option:hover, .generate-invite-link:hover { + background-color: var(--akcent); +} + +/* Modal Styles */ +.modal { + display: none; + position: fixed; + z-index: 99; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: var(--modal-background); +} + +.modal-content { + background-color: var(--background1); + margin: 15% auto; + padding: 20px; + border: var(--buttoncolor); + width: 80%; + max-width: 780px; + box-shadow: 3px 3px 5px rgba(0,0,0,0.3); + border-radius: 5px; +} + +.modal-close { + color: var(--textcolor); + float: right; + font-size: 28px; + font-weight: bold; + cursor: pointer; +} + +.modal-close:hover, +.modal-close:focus { + color: var(--akcent); + text-decoration: none; + cursor: pointer; +} + +/* Form Styles */ +.edit-group-form, +.edit-comment-form { + margin-top: 20px; +} + +.edit-group-form input[type="text"], +.edit-group-form textarea, +.edit-comment-form textarea { + width: 100%; + padding: 8px; + margin-bottom: 10px; +} + +.edit-group-form input[type="submit"], +.edit-comment-form button[type="submit"] { + background-color: var(--buttoncolor); + color: var(--inverse); + padding: 10px 15px; + border: none; + cursor: pointer; +} + +.edit-group-form input[type="submit"]:hover, +.edit-comment-form button[type="submit"]:hover { + background-color: var(--akcent); +} + +/* Button Styles */ +.edit-group, +.toggle-join-option, +.generate-invite-link, +.edit-comment { + margin-top: 10px; + padding: 5px 10px; + background-color: var(--buttoncolor); + color: var(--inverse); + border: none; + cursor: pointer; +} + +.edit-group:hover, +.toggle-join-option:hover, +.generate-invite-link:hover, +.edit-comment:hover { + background-color: var(--akcent); +} +.edit-button-wrapper { + display: inline; + justify-content: right; + position: relative; +} +.edit-button-wrapper button{ + /*position: absolute; + top:20px*/ +} +/* Invite Link Styles */ +#invite-link-modal input[type="text"] { + width: 100%; + padding: 8px; + margin-bottom: 10px; +} + +.copy-link { + background-color: var(--buttoncolor); + color: var(--background2); + padding: 5px 10px; + border: none; + cursor: pointer; +} + +.copy-link:hover { + background-color: var(--akcent); +} + +/** Editor styles **/ +.edit-thumbnail div.image-wrap { + max-width: 100%!important; + max-height: 200px; + overflow: hidden; + width: 100%; +} +.edit-thumbnail div.image-wrap img{ + max-width: 100%!important; + max-height: unset!important; + width: 100%; +} + +/** Action Buttons **/ + +.group-builder-button-container { + overflow: hidden; + border-radius: 25px; + transition: width 0.3s ease; + width: 45px; /* Anfangsbreite */ + text-align: center; + display: flex; + justify-content: left; + position: relative; + +} +.group-builder-create-button-container { + position: absolute; + top: 2px; +} +.group-builder-create-button-container button { + background-color: var(--buttoncolor); +} +.group-builder-button-container:hover { + width: auto; /* Breite bei Hover */ + position: absolute; +} +.group-builder-button-container button { + padding: 8px 11px; + border: none; + background-color: var(--gray); + color: var(--inverse); + border-radius: 25px; + cursor: pointer; + white-space: nowrap; + align-items: center; + justify-content: center; +} +.group-builder-button-container button svg { + top: 9px; + position: absolute; +} +.group-builder-button-container button span { + margin-left: 30px; + opacity: 0; + transition: opacity 0.3s ease; +} +.group-builder-button-container:hover button span { + opacity: 1; +} +.group-builder-join-button-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} +.group-builder-join-button-container button{ + grid-column: 2; + background-color: var(--buttoncolor); + color: var(--background2); + padding: 5px 20px 7px; + border-radius: 3px; +} + +.group-builder-join-button-container button:hover { + background-color: var(--akcent); +} +div.clearfix { + clear: both; + width: 100%; + display: block; +} + +/** Toggle-join design für die Beitrittsoption von Gruppen **/ +.toggle-join-option { + padding: 5px 10px; + background-color: var(--buttoncolor); + color: var(--inverse); + border: none; + cursor: pointer; + border-radius: 3px; +} + +.toggle-join-option:hover::after { + content: attr(title); + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + background-color: var(--buttoncolor, #dddddd); + color: var(--inverse, #000000); + padding: 5px 20px; + border-radius: 3px; + max-width: 300px; + font-size: 15px; + /*white-space: nowrap;*/ +} +.copy-invite-link-wrapper, .leave-btn-wrapper { + display: grid; + grid-template-columns: auto 200px; + border: 1px solid var(--akcent); + border-radius: 3px; + padding: 5px; +} +.leave-btn-wrapper { + margin-top: 10px; + border-color: var(--gray); +} +.leave-btn-wrapper span { + padding: 5px; +} +.leave-btn-wrapper button:hover { + background-color: var(--akcent); + color: var(--background2); +} +.copy-invite-link-label { + padding: 5px; +} + + + +/** Adminbar **/ + +.custom-modal, .custom-mega-menu { + z-index: 99!important; +} +.custom-modal-close, .custom-mega-menu-close { + color: var(--textcolor)!important; +} +.custom-modal-close:hover, .custom-modal-close:focus, +.custom-mega-menu-close:hover, .custom-mega-menu-close:focus { + color: var(--buttoncolor)!important; +} +.custom-modal-content, .custom-mega-menu-content { + background-color: var(--background)!important; + color: var(--textcolor)!important; + border: 3px solid var(--textcolor) !important; +} +.custom-modal-content > div, .custom-mega-menu-content > div { + overflow: auto; + max-height: calc(100vh - 50px); +} +#wpadminbar #wp-admin-bar-my-account.with-avatar #wp-admin-bar-user-actions > li { + margin-left: 20px; +} +#wp-admin-bar-root-default .custom a.ab-item { + color: var(--akcent); +} +/*schrift in der mobilen adminbar sichtbar machen */ +@media screen and (max-width: 782px) { + #wpadminbar .ab-label { + border: 0; + clip: unset; + clip-path: unset; + height: unset; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 200px; + word-wrap: normal !important; + } + +} +/** Formularfelder in modals**/ +.custom-modal .acf-field[data-name="group_title"] input { + font-size: 30px; + font-weight: bold; +} +.custom-modal .acf-field[data-name="group_exerpt"] textarea { + font-size: 20px; + font-weight: bold; + height: 80px; +} +.custom-modal .acf-fields > .acf-field { + border-top: 0; +} +.custom-modal .acf-label{ + font-size: 12px!important; + color: #444; +} +.custom-modal .acf-label label{ + font-size: 16px!important; + color: #444; +} +/** Comments **/ + +.single-group_post article > .ct-comments { + margin-top: 30px; + padding-top:0px; +} +.ct-comments-title, #reply-title { + display: none; +} +.ct-comment-inner { + padding-block: 10px; + position: relative; +} +.ct-comment-inner .cld-prevent{ + color: var(--buttoncolor); +} +.ct-comment-meta{ + background: rgba(22, 127, 168, 0.15); + border-radius: 25px 0 0 0; + +} +.cld-like-dislike-wrap { + position: absolute; + left: 15px; + top: 61px; +} +.cld-count-wrap { + margin-left: 5px; + font-weight: bold; +} + + +/** FEP Notificationbar **/ +#fep-notification-bar { + background-color: var(--akcent); + border-radius: 5px; + border: 1px solid var(--inverse); + box-sizing: border-box; + color: var(--inverse); + font-size: 15px; + font-weight: bold; + padding: 12px; + position: relative; + text-align: center; + width: 100%; + z-index: 999999; +} +#fep-notification-bar a { + color: var(--buttontext)!important; + text-decoration: underline; +} +#fep-notification-bar button{ + margin-top: -10px; +} + +/** HEADER MENU **/ +a.ct-menu-link { + background-position: center center; +} +#offcanvas a.ct-menu-link { + /*background-position: center left!important;*/ +} +@media screen and (max-width: 782px) { + li.menu-item:hover, li.menu-item:hover:active { + background-color: var(--menu-indicator-hover-color, var(--theme-palette-color-2)) + } +} + +/** Realtime Comment Notification Button **/ + +#realtime-comment-notification { + width: 100%; + display: grid; + background-color: var(--buttontext); + color: var(--background2); + padding: 5px; + border-radius: 3px; + border: 1px solid var(--buttoncolor); + animation:slide 3s ease-in-out infinite alternate; + background-image: linear-gradient(-60deg, var(--background2) 50%, var(--akcent)); + +} diff --git a/group-builder.php b/group-builder.php index 9db5e1c..e4ab276 100644 --- a/group-builder.php +++ b/group-builder.php @@ -7,12 +7,14 @@ */ if (!defined('ABSPATH')) exit; +require_once 'class_post_it_colors.php'; /** * Plugin-Klasse zur Verwaltung der Interessenbekundung und Gruppenerstellung */ class GroupBuilder { private static $instance = null; + private static $adminbar; /** * Gibt eine Instanz der Klasse zurück @@ -31,23 +33,268 @@ public static function get_instance() { private function __construct() { $this->setup_actions(); } + /** + * Aktualisiert den Zeitstempel der letzten Änderung + * + * @param int $post_id ID des Beitrags + */ + private function update_change_timestamp($post_id) { + update_post_meta($post_id, '_avatar_list_updated', time()); + } + /** * Initialisiert die Action Hooks für das Plugins */ private function setup_actions() { - add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); + + add_action('admin_bar_menu', array($this, 'set_adminbar'),10000); + add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'),800); + + + // AJAX-Aktionen add_action('wp_ajax_show_interest', array($this, 'ajax_show_interest')); add_action('wp_ajax_create_group', array($this, 'ajax_create_group')); - add_filter('the_content', array($this, 'display_interest_button')); + add_action('wp_ajax_leave_group', array($this, 'ajax_leave_group')); + add_action('wp_ajax_get_avatar_list', array($this, 'ajax_get_avatar_list')); + add_action('wp_ajax_withdraw_interest', array($this, 'ajax_withdraw_interest')); + add_action('wp_ajax_join_group', array($this, 'ajax_join_group')); + add_action('wp_ajax_toggle_join_option', array($this, 'ajax_toggle_join_option')); + add_action('wp_ajax_generate_invite_link', array($this, 'ajax_generate_invite_link')); + + // Kommentar-Aktionen + add_action('pre_get_comments', array($this, 'restrict_group_comments')); + add_filter('comment_form_defaults', array($this, 'customize_comment_form')); + add_filter('comments_template', array($this, 'customize_comments_template')); + + add_shortcode('group_members', array($this, 'group_members_shortcode')); + add_shortcode('group_edit_form', array($this, 'group_edit_form_shortcode')); + + // Integration in das Blocksy-Theme + add_action('blocksy:loop:card:end' , array($this, 'get_avatar_list')); + add_action('blocksy:comments:before' , array($this, 'get_pinnwall_post_avatar_list')); + add_action('blocksy:header:after' , array($this, 'get_group_post_avatar_list')); + add_action('blocksy:single:content:top' , array($this, 'join_group_button')); + add_action('blocksy:single:content:top' , array($this, 'group_goal')); + add_action('blocksy:comments:top' , array($this, 'comments_header')); + + + #add_action('blocksy:header:after' , array($this, 'invite_link_copy_button')); + + // Add Heartbeat API support + add_filter('heartbeat_received', array($this, 'heartbeat_received'), 10, 2); + add_filter('heartbeat_nopriv_received', array($this, 'heartbeat_received'), 10, 2); + + + // Integration in Ultimate Member + add_filter( 'um_profile_tabs', array( $this, 'ultimate_member_integration_tab' ), 1000 ); + add_filter( 'um_user_profile_tabs', array( $this, 'ultimate_member_integration_tab' ), 1000 ); + add_action('um_profile_content_group-builder', array( $this, 'ultimate_member_integration_content' ) ); + add_filter( 'um_profile_query_make_posts', [$this,'ultimate_member_integration_profile_query_make_posts'], 10, 1 ); + + + // Tägliche Bereinigung der Daten + if (!wp_next_scheduled('group_builder_cleanup')) { + wp_schedule_event(time(), 'daily', 'group_builder_cleanup'); + } + add_action('group_builder_cleanup', array($this, 'cleanup_orphaned_data')); + } + + public function heartbeat_received($response, $data) { + if (empty($data['group_builder_request'])) { + return $response; + } + + $updated_lists = array(); + + foreach ($data['group_builder_request'] as $request) { + $post_id = intval($request['post_id']); + $client_timestamp = intval($request['timestamp']); + + $server_timestamp = get_post_meta($post_id, '_avatar_list_updated', true); + + if (!$server_timestamp) { + $server_timestamp = time(); + update_post_meta($post_id, '_avatar_list_updated', $server_timestamp); + } + + if ($client_timestamp < $server_timestamp) { + $avatar_list = $this->get_avatar_list($post_id); + if ($avatar_list !== null) { + $updated_lists[] = array( + 'post_id' => $post_id, + 'updated' => true, + 'avatar_list' => $avatar_list, + 'timestamp' => $server_timestamp + ); + } + } else { + $updated_lists[] = array( + 'post_id' => $post_id, + 'updated' => false + ); + } + } + + $response['group_builder_response'] = $updated_lists; + + return $response; + } + + /** + * Integriert das Plugin Custom WP Adminbar von Joachim Happel + * @see https://github.com/johappel/custom_wp_adminbar + * @param $customized_wordpress_adminbar Custom_AdminBar Class + * stellt eine angepasste Adminbar auch für Abonnenten bereit und stellt eine Modal-Fenster Funktionalität zur Verfügung. + */ + public function set_adminbar(){ + if(is_admin()){ + return; + } + global $customized_wordpress_adminbar; + + $user = wp_get_current_user(); + $adminbar = $customized_wordpress_adminbar;; + $adminbar->remove('search'); + $adminbar->remove('logout'); + $adminbar->remove('user-info'); + + $adminbar->edit('my-account',null,'/user/'); + $adminbar->add('top-secondary','','#', ' '); + $adminbar->add('user-actions','Profil ansehen','/user/', 'dashicons-admin-users'); + $adminbar->add('user-actions','Profil bearbeiten','/user?um_action=edit', 'dashicons-edit'); + $adminbar->add('user-actions','Meine Gruppen','/user/wpadmin/?profiletab=group-builder', 'dashicons-admin-groups'); + $adminbar->add('user-actions','Nachricht schreiben','/account/fep-um/', 'dashicons-email-alt'); + + $adminbar->add('user-actions','Konto Einstellungen','/account/', 'dashicons-admin-settings'); + $adminbar->add('user-actions','Abmelden',wp_logout_url(), 'dashicons-exit'); + $parent =''; + $parent_home = $adminbar->add('',get_bloginfo('name'),home_url(), 'dashicons-admin-home'); + if(is_user_logged_in()){ + $adminbar->add($parent_home,'Leute', '/netwerk/'); + $adminbar->add($parent_home,'Gruppen', '/group_post/'); + $adminbar->add('','Pinwand Karte','/pinwand-karte-erstellen/', 'dashicons-plus'); + } + if(is_singular('pinwall_post') && is_user_logged_in()){ + if(current_user_can('edit_post', get_the_ID())){ + $adminbar->addModal('', 'Bearbeiten', 'edit_pinwall_post', 'dashicons-edit'); + $adminbar->addModalContent('edit_pinwall_post', + '

Pinwand Karte bearbeiten

'.do_shortcode('[acfe_form name="edit_pinwall_post"]').'
', + 'full'); + } + } + + if(is_singular('group_post')){ + #echo do_shortcode('[acfe_form name="edit_group"]'); + $parent =''; + $group_settings_content = '
+

Gruppe konfigurieren

'. + //do_shortcode('[acfe_form name="edit_group"]'). + '
'; + $group_tools_content = ''; + if(group_builder_user_can(get_the_ID(), 'edit')){ + $adminbar->addMegaMenu($parent, 'Gruppe konfigurieren', 'group-edit-modal', 'dashicons-edit'); + $adminbar->addMegaMenu($parent, 'Lernwerkzeuge konfigurieren', 'group_tools', 'dashicons-admin-generic'); + #$adminbar->addMegaMenuContent('group_settings',$group_settings_content); + $adminbar->addMegaMenuContent('group_tools','

Lernwerkzeuge konfigurieren

'); + } + $this->display_modal_frame(); + } + $adminbar->add_modal_and_mega_menu_html(); + + } + + /** * Lädt die benötigten Skripte und Stile */ public function enqueue_scripts() { wp_enqueue_script('group-builder-js', plugin_dir_url(__FILE__) . 'js/group-builder.js', array('jquery'), '1.0', true); - wp_enqueue_style('group-builder-css', plugin_dir_url(__FILE__) . 'css/group-builder.css'); + wp_enqueue_style('group-builder-css', plugin_dir_url(__FILE__) . 'css/colors.css'); + wp_enqueue_style('group-builder-colors-css', plugin_dir_url(__FILE__) . 'css/group-builder.css'); wp_localize_script('group-builder-js', 'group_builder_ajax', array('ajax_url' => admin_url('admin-ajax.php'))); + //Lade Dashicons https://developer.wordpress.org/resource/dashicons ins Frontend + wp_enqueue_style('dashicons'); + wp_enqueue_script('heartbeat'); + + + } + /** + * AJAX-Funktion zum Anzeigen des Interesses an einem Beitrag + */ + public function ajax_leave_group() { + $post_id = $group_id= isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; + if(get_post_type($post_id) !== 'group_post'){ + wp_send_json_error('Ungültige Anfrage'); + } + $user_id = get_current_user_id(); + + + if (!$post_id || !$user_id) { + wp_send_json_error('Ungültige Anfrage'); + } + + + $members = get_post_meta($group_id, '_group_members', true); + if (!is_array($members)) { + $members = array(); + } + + $key = array_search($user_id, $members); + if ($key !== false) { + unset($members[$key]); + update_post_meta($group_id, '_group_members', array_values($members)); + + // Aktualisiere den Zeitstempel nach erfolgreichem Verlassen der Gruppe + $this->update_change_timestamp($post_id); + + wp_send_json_success(array('post_id' => $post_id)); + } else { + wp_send_json_error('Benutzer nicht in der Gruppe'); + } + } + /** + * AJAX-Funktion zum Aktualisieren + * der Gruppen, Interessenten, Mitglieder und Aktionsschalter + */ + public function ajax_get_avatar_list() { + $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; + $client_timestamp = isset($_POST['timestamp']) ? intval($_POST['timestamp']) : 0; + + if (!$post_id) { + wp_send_json_error(array('message' => 'Ungültige Anfrage: Keine post_id angegeben')); + return; + } + + $post_type = get_post_type($post_id); + if($post_type !== 'group_post' && $post_type !== 'pinwall_post') { + wp_send_json_error(array('message' => 'Ungültiger Post-Typ: ' . $post_type)); + return; + } + + $server_timestamp = get_post_meta($post_id, '_avatar_list_updated', true); + + if (!$server_timestamp) { + $server_timestamp = time(); + update_post_meta($post_id, '_avatar_list_updated', $server_timestamp); + } + + $avatar_list = $this->get_avatar_list($post_id); + if ($avatar_list === null) { + wp_send_json_error(array('message' => 'Fehler beim Abrufen der Avatar-Liste für Post-ID: ' . $post_id)); + return; + } + + $updated = $client_timestamp < $server_timestamp; + + wp_send_json_success(array( + 'updated' => $updated, + 'avatar_list' => $updated ? $avatar_list : '', + 'timestamp' => $server_timestamp + )); } + + /** * AJAX-Funktion zum Anzeigen des Interesses an einem Beitrag */ @@ -63,6 +310,7 @@ public function ajax_show_interest() { $success = $this->add_user_interest($post_id, $user_id); if ($success) { + $this->update_change_timestamp($post_id); $avatar_list = $this->get_avatar_list($post_id); wp_send_json_success($avatar_list); } else { @@ -82,28 +330,95 @@ public function ajax_create_group() { $group_id = $this->create_group($post_id); if ($group_id) { + $this->update_change_timestamp($post_id); wp_send_json_success(array('group_id' => $group_id)); } else { wp_send_json_error('Fehler beim Erstellen der Gruppe'); } } /** - * Fügt den Interessen-Button und die Avatar-Liste zum Beitrag hinzu - * - * @param string $content Ursprünglicher Beitragstext - * @return string Modifizierter Beitragstext + * AJAX-Funktion zum Verlassen einer Gruppe */ - public function display_interest_button($content) { - if (get_post_type() === 'pinwall_post') { - $post_id = get_the_ID(); - $avatar_list = $this->get_avatar_list($post_id); - $interest_button = ''; - $group_button = ''; + public function ajax_withdraw_interest() { + $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; + $user_id = get_current_user_id(); + + if (!$post_id || !$user_id) { + wp_send_json_error('Ungültige Anfrage'); + } + + $interested_users = get_post_meta($post_id, '_interested_users', true); + if (!is_array($interested_users)) { + $interested_users = array(); + } + + $key = array_search($user_id, $interested_users); + if ($key !== false) { + unset($interested_users[$key]); + update_post_meta($post_id, '_interested_users', array_values($interested_users)); + // Aktualisiere den Zeitstempel nach erfolgreichem Verlassen der Gruppe + $this->update_change_timestamp($post_id); + + wp_send_json_success(array('post_id' => $post_id)); + } else { + wp_send_json_error('Benutzer war nicht interessiert'); + } + } + /** + * AJAX-Funktion zum Beitreten einer Gruppe + */ + public function ajax_join_group() { + $group_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; + if ($group_id===0) { + $group_id = isset($_POST['group_id']) ? intval($_POST['group_id']) : 0; + } + $user_id = get_current_user_id(); + + if (!$group_id || !$user_id || get_post_type($group_id) !== 'group_post') { + wp_send_json_error('Ungültige Anfrage'); + } + + $members = get_post_meta($group_id, '_group_members', true); + if (!is_array($members)) { + $members = array(); + } + + if (!in_array($user_id, $members)) { + if ($this->check_group_limit($group_id)) { + $members[] = $user_id; + update_post_meta($group_id, '_group_members', $members); + $this->update_change_timestamp($group_id); - $content .= $interest_button . $avatar_list . $group_button; + // Finde den zugehörigen pinwall_post + $args = array( + 'post_type' => 'pinwall_post', + 'meta_query' => array( + array( + 'key' => '_associated_group', + 'value' => $group_id, + ), + ), + ); + $query = new WP_Query($args); + + if ($query->have_posts()) { + $query->the_post(); + $post_id = get_the_ID(); + //@todo: check if this update is really necessary + $this->update_change_timestamp($post_id); + wp_reset_postdata(); + wp_send_json_success(array('post_id' => $post_id)); + } else { + wp_send_json_error('Zugehöriger pinwall_post nicht gefunden'); + } + } else { + wp_send_json_error('Benutzer ist bereits Mitglied der Gruppe'); + } + } else { + wp_send_json_error('Die Gruppe hat die maximale Anzahl an Mitgliedern erreicht'); } - return $content; } + /** * Fügt das Nutzerinteresse zum Beitrag hinzu * @@ -112,8 +427,16 @@ public function display_interest_button($content) { * @return bool Erfolg oder Misserfolg */ private function add_user_interest($post_id, $user_id) { - // Implementierung der Logik zum Hinzufügen des Nutzerinteresses - // Rückgabe: true bei Erfolg, false bei Fehler + $interested_users = get_post_meta($post_id, '_interested_users', true); + if (!is_array($interested_users)) { + $interested_users = array(); + } + if (!in_array($user_id, $interested_users)) { + $interested_users[] = $user_id; + update_post_meta($post_id, '_interested_users', $interested_users); + return true; + } + return false; } /** * Erstellt eine Gruppe zum Beitrag @@ -122,34 +445,662 @@ private function add_user_interest($post_id, $user_id) { * @return int ID der erstellten Gruppe */ private function create_group($post_id) { - // Implementierung der Logik zur Gruppenerstellung + $interested_users = get_post_meta($post_id, '_interested_users', true); + if (!is_array($interested_users) || count($interested_users) < 2) { + return false; + } + $group_id = wp_insert_post(array( 'post_type' => 'group_post', 'post_title' => 'Interessengruppe zum Beitrag ' . get_the_title($post_id), - // Weitere Felder... + 'post_status' => 'publish', )); if ($group_id) { - // Interessierte der Gruppe zuordnen - // Link zum Pinwand-Beitrag aktualisieren + update_post_meta($group_id, '_group_members', $interested_users); + add_post_meta($post_id, '_associated_group', $group_id); + delete_post_meta($post_id, '_interested_users'); + return $group_id; + } + + return false; + } + /** + * Shortcode für die Anzeige der Avatar-Liste + * + * @param array $atts Attribute des Shortcodes + * @return string HTML-Code der Avatar-Liste + */ + public function group_members_shortcode($atts) { + $atts = shortcode_atts(array( + 'post_id' => get_the_ID(), + ), $atts, 'group_members'); + + return $this->get_avatar_list($atts['post_id']); + } + public function get_group_post_avatar_list(){ + if(is_singular(['group_post'])){ + $this->get_avatar_list(); + } + } + public function join_group_button(){ + if(is_singular(['group_post']) && group_builder_user_can(get_the_ID(), 'join')){ + echo '
+ +
'; + } + } + + public function get_pinnwall_post_avatar_list(){ + if(is_singular(['pinwall_post'])){ + $this->get_avatar_list(); + } + } + + public function group_goal(){ + if(is_singular(['group_post'])){ + $goal = get_post_meta(get_the_ID(), 'group_exerpt', true); + if($goal){ + echo '

Unser Ziel:

'.$goal.'

Herausforderungen und Schwerkunkte:

'; + + } } + } - return $group_id; + public function comments_header(){ + if(is_singular(['group_post'])){ + ?> +
+

Diskurs und Ergebnisse:

+ +
+ +
+

Diskussion:

+ +
+ ...'; + public function get_avatar_list($post_id = null) { + + $do_print_output = false; + $has_groups = false; + $output = ''; + + $post_type = get_post_type($post_id); + if($post_type !== 'group_post' && $post_type !== 'pinwall_post') { + return null; + } + if($post_type === 'group_post'){ + $group_id = $post_id; + $members = get_post_meta($post_id, '_group_members', true); + + } else { + $assoziated_group_ids = get_post_meta($post_id, '_associated_group'); + $group_section = ''; + if(is_array($assoziated_group_ids) && !empty($assoziated_group_ids)){ + $has_groups = true; + $group_section .= '

Unsere Gruppe arbeiten bereits dazu:

'; + foreach($assoziated_group_ids as $assoziated_group_id){ + $group_section .= ''; + } + $group_section .= '
'; + } else { + $assoziated_group_ids = false; + } + + $members = get_post_meta($post_id, '_interested_users', true); + + } + if (!$post_id) { + $post_id = get_the_ID(); + $do_print_output = true; + $output = '
'; + } + if ($assoziated_group_ids) { + $output .= $group_section; + } + $output .= '
'; + + if($post_type === 'group_post'){ + //$output .= '

Mitglieder

'; + } else { + if ($has_groups) { + $output .= '

Interesse an weiterer Gruppe?

'; + } else { + $output .= '

Interessenten

'; + } + } + + list($buttons, $create_button)= $this->get_action_buttons($post_id, $post_id,$has_groups); + $output .= '
'; + + if (is_array($members) && !empty($members)) { + foreach ($members as $user_id) { + $output .= ''; + $output .= get_avatar($user_id, 50); + $output .= ''; + } + } + $output .= $buttons; + $output .= '
'; + $output .= '
'; + $output .= $create_button; + $output .= '
'; //attendees-wrapper + + + + if($do_print_output){ + $output .= '
'; + echo $output; + return false; + } + return $output; + } + /** + * Gibt die Aktionsschaltflächen für den Beitrag zurück + * + * @param int $post_id ID des Beitrags + * @param int $group_id ID der Gruppe + * @param bool $has_groups Gibt an, ob der Beitrag mit Gruppen assoziiert ist + * @return string HTML-Code der Aktionsschaltflächen + */ + private function get_action_buttons($post_id, $group_id = null, $has_groups = false) { + + $join_svg = ''; + $leave_svg = ''; + + $current_user_id = get_current_user_id(); + if (!$current_user_id) { + return ''; + } + $create_button = ''; + $button_template = '
+ +
'; + + $button2_template = '
+ +
'; + $buttons = ''; + + if (get_post_type($post_id) === 'pinwall_post') { + $interested_users = get_post_meta($post_id, '_interested_users', true); + if (!is_array($interested_users)) { + $interested_users = array(); + } + + if (in_array($current_user_id, $interested_users)) { + $buttons .= sprintf($button_template, 'withdraw-interest', $post_id,$leave_svg, 'Mein Interesse zurückziehen'); + + if (count($interested_users) >= 2) { + $create_button = sprintf($button2_template, 'create-group', $post_id, 'Gruppe gründen'); + } + } else { + $buttons .= sprintf($button_template, 'show-interest', $post_id,$join_svg, 'Interesse zeigen'); + } + } elseif ($group_id) { + $members = get_post_meta($group_id, '_group_members', true); + if (!is_array($members)) { + $members = array(); + } + if(get_option('group_builder_avatar_actions')) { + + if (in_array($current_user_id, $members)) { + $buttons .= sprintf($button_template, 'leave-group', $group_id,$leave_svg, 'Gruppe verlassen'); + } else { + $buttons .= sprintf($button_template, 'join-group', $group_id,$join_svg, 'Gruppe beitreten'); + } + } + if(!in_array($current_user_id, $members) && count($members) < get_option('group_builder_max_members',4)){ + $buttons .= sprintf($button_template, 'join-group', $group_id,$join_svg, 'Gruppe beitreten'); + } + } + + return [$buttons, $create_button]; + } + /** + * Überprüft, ob die Gruppe die maximale Anzahl an Mitgliedern erreicht hat + * + * @param int $group_id ID der Gruppe + * @return bool true, wenn die Gruppe die maximale Anzahl an Mitgliedern erreicht hat, sonst false + */ + private function check_group_limit($group_id) { + $members = get_post_meta($group_id, '_group_members', true); + $max_members = apply_filters('group_builder_max_members', 10); // Standardmäßig 10, kann mit einem Filter angepasst werden + return count($members) < $max_members; + } + + /** + * Bereinigt verwaiste Daten + */ + public function cleanup_orphaned_data() { + + /** + * Löscht _interested_users in den Metadaten der pinwall_post Beiträge, für die es keine existierenden Nutzer gibt + */ + $args = array( + 'post_type' => 'pinwall_post', + 'meta_query' => array( + array( + 'key' => '_interested_users', + 'compare' => 'EXISTS', + ), + ), + ); + $query = new WP_Query($args); + + if ($query->have_posts()) { + while ($query->have_posts()) { + $query->the_post(); + $post_id = get_the_ID(); + $interested_users = get_post_meta($post_id, '_interested_users', true); + if (empty($interested_users)) { + delete_post_meta($post_id, '_interested_users'); + } + } + } + + /** + * Überprüft ob, die Metadaten für assozierten Gruppen (_associated_group) in den pinwall_post Beiträge + * und löscht die Metadaten, wenn die Gruppe nicht mehr existiert + */ + $args = array( + 'post_type' => 'pinwall_post', + 'meta_query' => array( + array( + 'key' => '_associated_group', + 'compare' => 'EXISTS', + ), + ), + ); + $query = new WP_Query($args); + + if ($query->have_posts()) { + while ($query->have_posts()) { + $query->the_post(); + $post_id = get_the_ID(); + $group_id = get_post_meta($post_id, '_associated_group', true); + if (!get_post($group_id)) { + delete_post_meta($post_id, '_associated_group'); + } + } + } + + wp_reset_postdata(); + } + /** + * Shortcode für das bearbeitungsformular der Group_Post + */ + public function group_edit_form_shortcode($atts) { + // Überprüfen Sie, ob der Benutzer berechtigt ist, die Gruppe zu bearbeiten + $group_id = get_the_ID(); + $current_user_id = get_current_user_id(); + $group_members = $this->get_group_members($group_id); + + if (!in_array($current_user_id, $group_members)) { + return 'Sie sind nicht berechtigt, diese Gruppe zu bearbeiten.'; + } + + // Rendern Sie das ACF-Formular + ob_start(); + acfe_form('edit_group'); + return ob_get_clean(); + } + + /** + * AJAX-Funktion zum Bearbeiten eines Gruppenkommentars + */ + public function restrict_group_comments($query) { + if (!is_admin() && $query->is_comment_feed) { + $post_id = $query->query_vars['post_id']; + $post_type = get_post_type($post_id); + + if ($post_type === 'group_post') { + $current_user_id = get_current_user_id(); + $group_members = $this->get_group_members($post_id); + + if (!in_array($current_user_id, $group_members)) { + $query->set('post__in', array(0)); // Keine Kommentare anzeigen + } + } + } + } + public function customize_comments_template($comment_template) { + if (get_post_type() === 'group_post') { + global $post; + $current_user_id = get_current_user_id(); + $group_members = $this->get_group_members($post->ID); + if (!in_array($current_user_id, $group_members)) { + $comment_template = '

Nur Mitglieder dieser Gruppe können Kommentare sehen.

'; + } + } + return $comment_template; + } + + /** + * Passt das Kommentarformular an + */ + public function customize_comment_form($defaults) { + global $post; + $defaults['title_reply_before'] = '

Kommentare erwünscht.

'; + $defaults['title_reply']=''; + $defaults['logged_in_as'] = ''; + + if (get_post_type($post) === 'group_post') { + $current_user_id = get_current_user_id(); + $group_members = $this->get_group_members($post->ID); + $defaults['label_submit'] = 'Beitrag abschicken'; + $defaults['logged_in_as'] = ''; + $defaults['title_reply'] = '

Beitrag schreiben

'; + $defaults['comment_field'] = str_replace('Kommentar','Beitrag',$defaults['comment_field']); + if (!in_array($current_user_id, $group_members)) { + $defaults['title_reply_before'] = '

Nur Mitglieder dieser Gruppe können hier Beiträge hinterlassen.

'; + $defaults['title_reply'] = ' -- '; + $defaults['logged_in_as'] = ''; + $defaults['comment_field'] = ''; + $defaults['submit_button'] = ''; + } + } + + return $defaults; + } + + private function get_icon($name) { + return ''; } + + + /** + * Zeigt das Modal-Fenster für die Gruppenbearbeitung an + * Hinweis: Wir nutzen die Klassen-Definitionen von meinem custom_wp_adminbar Plugin + */ + public function display_modal_frame() { + if (is_singular('group_post') && group_builder_user_can(get_the_ID(), 'edit')) { + ?> + + + + + + get_invite_link(); + }else{ + $new_status_text = 'Beitritt zur Gruppe freigeben: Jeder kann beitreten'; + $new_status = 'unlock'; + $status = 'lock'; + $link = ''; + } + update_post_meta($group_id, '_join_option', $new_join_option); + wp_send_json_success(array( + 'new_status' => $new_status, + 'new_status_text' => $new_status_text, + 'status_icon' => $this->get_icon($status), + 'link' => $link + + )); + } + + /** + * AJAX-Funktion zur Rückgabe des Einladungslinks + */ + public function ajax_generate_invite_link() { + $invite_url = $this->get_invite_link(); + wp_send_json_success(array('invite_link' =>$invite_url)); + } + + /** + * Gibt den Einladungslink zur Gruppe zurück + * @return string|null //url to the invite link + */ + public function get_invite_link($group_id = null) + { + if(!$group_id){ + $group_id = get_the_ID(); + } + if(!$group_id){ + return 'Fehler: Gruppen-ID nicht gefunden'; + } + + $hash = get_post_meta($group_id, '_invite_hash', true); + // speichere neuen Hash für Einladungslink, wenn noch keiner existiert + if (empty($hash)) { + $hash = md5(uniqid(rand(), true)); + update_post_meta($group_id, '_invite_hash', $hash); + } + + return get_permalink($group_id) . '?invite=' . $hash; + } + + + /** + * Gibt den HTML-Code für den Einladungslink zurück + * @return string + */ + public function invite_link_copy_button(){ + if(!is_singular('group_post')){ + return; + } + if(!is_user_logged_in()){ + return; + } + $group_id = get_the_ID(); + $join_option = get_post_meta($group_id, '_join_option', true); + + if($join_option){ + $link = $this->get_invite_link($group_id); + echo ''; + echo '
'; + echo '
'; + } + + echo $this->leave_button($group_id); + } + private function leave_button($group_id){ + return '
Deine Mitarbeit in der Gruppe beenden:
'; + } + public function get_invite_link_html($group_id = null){ + if(!$group_id){ + $group_id = get_the_ID(); + } + $status = get_post_meta($group_id, '_join_option', true); + if($status === 'invite_only') { + $status_text = 'Jeder kann der Gruppe beitreten. Klicke auf das Schloss, um den Beitritt zur Gruppe zu sperren'; + $status_icon = $this->get_icon('unlock'); + $link = ''; + $html = ' + + + '; + }else{ + $status_text = 'Der Beitritt zur Gruppe ist gesperrt. Nur Mitglieder mit Einladungslink können beitreten. Klicke auf das Schloss, um den Beitritt zur Gruppe freizugeben'; + $status_icon = $this->get_icon('lock'); + $link = $this->get_invite_link(); + $html = ' + + + + '; + } + return $html; + + } + + /** + * Überprüft, ob der Benutzer über einen Einladungslink beigetreten ist + */ + public function check_invite() { + if (isset($_GET['invite'])) { + $group_id = get_the_ID(); + $hash = $_GET['invite']; + if ($this->check_invite_hash($group_id, $hash)) { + $current_user_id = get_current_user_id(); + $members = get_post_meta($group_id, '_group_members', true); + if (!is_array($members)) { + $members = array(); + } + if (!in_array($current_user_id, $members)) { + $members[] = $current_user_id; + update_post_meta($group_id, '_group_members', $members); + $this->update_change_timestamp($group_id); + } + //redirect to the group page + wp_redirect(get_permalink($group_id)); + } + } + + } + + + + // Überprüfe den Einladungslink + private function check_invite_hash($group_id, $hash) { + $invite_hash = get_post_meta($group_id, '_invite_hash', true); + return $invite_hash === $hash; + } + + // Implementierung der Integration mit Ultimate Member + + /** + * Post_types für Ultimate Member hinzufügen + */ + public function ultimate_member_integration_profile_query_make_posts($args) { + $args['post_type'] = 'pinwall_post'; + return $args; + } + + /** + * Fügt den Gruppen-Tab zu Ultimate Member hinzu + */ + function ultimate_member_integration_tab( $tabs ) { + + $tabs['group-builder'] = array( + 'name' => 'Gruppen', + 'icon' => 'um-icon-android-people', + 'custom' => true, + ); + $custom_tab = UM()->options()->get( 'profile_tab_' . 'group-builder' ); + if ( '' === $custom_tab ) { + UM()->options()->update( 'profile_tab_' . 'group-builder', true ); + } + + return $tabs; + + } + + /** + * Gibt die Liste von Group_Posts zurück, bei denen der User Mitglied ist + */ + public function ultimate_member_integration_content() + { + $current_user_id = get_current_user_id(); + $args = array( + 'post_type' => 'group_post', + 'meta_query' => array( + array( + 'key' => '_group_members', + 'value' => $current_user_id, + 'compare' => 'LIKE' + ) + ) + ); + $groups = get_posts($args); + echo '

Mitglied in folgenden Gruppen

'; + echo ''; + } + } -// Initialisierung des Plugins -function group_builder_init() { - GroupBuilder::get_instance(); +function group_builder_user_can($group_id, $action = 'edit') { + $current_user_id = get_current_user_id(); + $group_members = get_post_meta($group_id, '_group_members', true); + + if ($action === 'join') { + + if (is_array($group_members) && in_array($current_user_id, $group_members)) { + return false; + } + $join_option = get_post_meta($group_id, '_join_option', true); + $hash = get_post_meta($group_id, '_invite_hash', true); + return !$join_option || (isset( $_GET['invite']) && $hash === $_GET['invite']); + } + + if (!is_array($group_members)) { + return false; + } + + if ($action === 'edit' || $action === 'invite') { + return in_array($current_user_id, $group_members); + } + + + + return false; } -add_action('plugins_loaded', 'group_builder_init'); +// Initialisierung des Plugins +add_action('plugins_loaded', ['GroupBuilder', 'get_instance']); diff --git a/images/gruppe.png b/images/gruppe.png new file mode 100644 index 0000000..e6a72ab Binary files /dev/null and b/images/gruppe.png differ diff --git a/images/markt.png b/images/markt.png new file mode 100644 index 0000000..f1eb5b0 Binary files /dev/null and b/images/markt.png differ diff --git a/images/netzwerk.png b/images/netzwerk.png new file mode 100644 index 0000000..3b9c54a Binary files /dev/null and b/images/netzwerk.png differ diff --git a/images/pinnwand.png b/images/pinnwand.png new file mode 100644 index 0000000..230da0f Binary files /dev/null and b/images/pinnwand.png differ diff --git a/js/group-builder.js b/js/group-builder.js new file mode 100644 index 0000000..51de96e --- /dev/null +++ b/js/group-builder.js @@ -0,0 +1,241 @@ +jQuery(document).ready(function($) { + const avatarLists = {}; + + function getPostIdFromElement($element) { + let postId = $element.data('post-id'); + if (!postId) { + const $childWithPostId = $element.find('[data-post-id]').first(); + if ($childWithPostId.length) { + postId = $childWithPostId.data('post-id'); + } else { + const $parentWithPostId = $element.closest('[data-post-id]'); + if ($parentWithPostId.length) { + postId = $parentWithPostId.data('post-id'); + } + } + } + return postId; + } + + function initializeAvatarList($element) { + const postId = getPostIdFromElement($element); + if (!postId) { + console.error('Konnte keine gültige postId für das Element finden:', $element); + return; + } + if (!avatarLists[postId]) { + avatarLists[postId] = { + timestamp: 0 + }; + loadAvatarList(postId); + } + } + + function loadAvatarList(postId) { + $.ajax({ + url: group_builder_ajax.ajax_url, + type: 'POST', + data: { + action: 'get_avatar_list', + post_id: postId, + timestamp: avatarLists[postId].timestamp + }, + success: function(response) { + if (response.success) { + if (response.data.updated) { + $('.attendees[data-post-id="' + postId + '"]').html(response.data.avatar_list); + avatarLists[postId].timestamp = response.data.timestamp; + } + console.log('Avatar-Liste aktualisiert für Post-ID:', postId, 'Neuer Timestamp:', avatarLists[postId].timestamp); + } else { + console.error('Fehler beim Laden der Avatar-Liste:', response.data ? response.data.message : 'Unbekannter Fehler'); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + console.error('AJAX-Fehler beim Laden der Avatar-Liste:', textStatus, errorThrown); + } + }); + } + + // Initialisiere alle vorhandenen Avatar-Listen + $('.attendees').each(function() { + initializeAvatarList($(this)); + }); + + // Heartbeat-Sender + $(document).on('heartbeat-send', function(e, data) { + data.group_builder_request = Object.keys(avatarLists).map(postId => ({ + post_id: postId, + timestamp: avatarLists[postId].timestamp + })); + console.log('Heartbeat-Anfrage gesendet:', data.group_builder_request); + }); + + // Heartbeat-Empfänger + $(document).on('heartbeat-tick', function(e, data) { + if (data.group_builder_response) { + data.group_builder_response.forEach(function(item) { + if (item.updated) { + $('.attendees[data-post-id="' + item.post_id + '"]').html(item.avatar_list); + avatarLists[item.post_id].timestamp = item.timestamp; + console.log('Avatar-Liste aktualisiert für Post-ID:', item.post_id, 'Neuer Timestamp:', item.timestamp); + } + }); + } + }); + + // Event-Handler für die Buttons + $(document).on('click', '.show-interest, .withdraw-interest, .create-group, .join-group, .leave-group', function(e) { + e.preventDefault(); + const $button = $(this); + const postId = getPostIdFromElement($button); + if (!postId) { + console.error('Konnte keine gültige postId für den Button finden:', $button); + return; + } + const action = $button.attr('class').split(' ')[0].replace('-', '_'); + const data = { + action: action, + post_id: postId + }; + if (action === 'join_group' || action === 'leave_group') { + data.group_id = $button.data('group-id'); + } + + $.ajax({ + url: group_builder_ajax.ajax_url, + type: 'POST', + data: data, + success: function(response) { + if (response.success) { + console.log('Aktion erfolgreich:', action, 'für Post ID:', postId); + //loadAvatarList(postId); // Lade die Liste sofort neu + location.reload(); + } else { + console.error('Fehler bei der Aktion:', action, 'für Post ID:', postId, response.data.message); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + console.error('AJAX-Fehler bei der Aktion:', action, 'für Post ID:', postId, textStatus, errorThrown); + } + }); + }); + + // Weitere Event-Handler und Funktionen... +// Frontend-Formular Modal + // für die Bearbeitung von Gruppen und Pinnwandeinträge + $(document).on('click', '.edit-group', function(e) { + e.preventDefault(); + const groupId = $(this).data('group-id'); + openModal('#group-edit-modal'); + }); + + // Beitrittsoption umschalten + $(document).on('click', '.toggle-join-option', function(e) { + e.preventDefault(); + const groupId = $(this).data('group-id'); + const toggle = $(this); + console.info(groupId,'toggle-join-option'); + $.ajax({ + url: group_builder_ajax.ajax_url, + type: 'POST', + data: { + action: 'toggle_join_option', + group_id: groupId + }, + success: function(response) { + console.log(response); + if (response.success) { + // Aktualisiere UI + toggle.text(response.data.new_status); + } else { + console.error('Fehler beim Umschalten der Beitrittsoption:', response.data.message); + } + } + }); + }); + + /** + * Funktion zum Kopieren des Einladungstextes in die Zwischenablage + * @param {string} element_id ID des Textfeldes, dessen Inhalt kopiert werden soll + */ + function copy_to_clipboard(element_id) { + // Das Textfeld auswählen + var textfeld = document.getElementById(element_id); + + // Den Inhalt des Textfeldes auswählen + textfeld.select(); + textfeld.setSelectionRange(0, 99999); // Für mobile Geräte + + // Den Text in die Zwischenablage kopieren + navigator.clipboard.writeText(textfeld.value) + .then(() => { + alert("Einladungslink wurde in die Zwischenablage kopiert!"); + }) + .catch(err => { + console.error('Fehler beim Kopieren: ', err); + }); + } + // Einladungslink kopieren + $(document).on('click', '.copy-invite-link', function(e) { + e.preventDefault(); + copy_to_clipboard('invite-link'); + }); + + // Einladungslink generieren + $(document).on('click', '.generate-invite-link', function(e) { + e.preventDefault(); + const groupId = $(this).data('group-id'); + + $.ajax({ + url: group_builder_ajax.ajax_url, + type: 'POST', + data: { + action: 'generate_invite_link', + group_id: groupId + }, + success: function(response) { + if (response.success) { + // Zeige den generierten Link in einem Modal an + $('#invite-link-modal .modal-content').html(` +

Hier ist der Einladungslink für diese Gruppe:

+ + + `); + openModal('#invite-link-modal'); + } else { + console.error('Fehler beim Generieren des Einladungslinks:', response.data.message); + } + } + }); + }); + + $('.ct-comments-title').html('Beiträge'); + + // Todo: Image Pfade für die Menüpunkte anpassen aus dem Pluginpfad ./images/ holen + jQuery("a.ct-menu-link:contains('Startseite')") + .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/markt.png')") + .css('background-size','50px') + .css('background-repeat', 'no-repeat') + .css('background-position', 'center center') + .css('padding-top','70px'); + jQuery("a.ct-menu-link:contains('Pinwand')") + .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/pinnwand.png')") + .css('background-size','50px') + .css('background-repeat', 'no-repeat') + .css('background-position', 'center center') + .css('padding-top','70px'); + jQuery("a.ct-menu-link:contains('Gruppen')") + .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/gruppe.png')") + .css('background-size','50px') + .css('background-repeat', 'no-repeat') + .css('background-position', 'center center') + .css('padding-top','70px'); + jQuery("a.ct-menu-link:contains('Mitglieder')") + .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/netzwerk.png')") + .css('background-size','50px') + .css('background-repeat', 'no-repeat') + .css('background-position', 'center center') + .css('padding-top','70px'); + +});