| | |
| | | <?php |
| | | namespace JVBase\users; |
| | | |
| | | use JVBase\JVB; |
| | | use JVBase\registry\ContentRegistry; |
| | | //use JVBase\registry\ContentRegistry; |
| | | |
| | | if (!defined('ABSPATH')) { |
| | | exit; // Exit if accessed directly |
| | | } |
| | | |
| | | class UserSettings extends ContentRegistry |
| | | { |
| | | protected array $fields; |
| | | protected array $sections = [ |
| | | 'account' => [ |
| | | 'title' => 'Account', |
| | | 'icon' => 'settings', |
| | | ], |
| | | 'notifications' => [ |
| | | 'title' => 'Notifications', |
| | | 'icon' => 'email' |
| | | ], |
| | | 'newsletter' => [ |
| | | 'title' => 'Newsletter', |
| | | 'icon' => 'logo' |
| | | ], |
| | | 'invitations' => [ |
| | | 'title' => 'Invite Artists', |
| | | 'icon' => 'new-user', |
| | | ] |
| | | ]; |
| | | protected array $frequency = [ |
| | | 'never' => 'Never', |
| | | 'daily' => 'Daily', |
| | | 'weekly' => 'Weekly', |
| | | 'monthly' => 'Monthly', |
| | | ]; |
| | | |
| | | public function initType():void |
| | | { |
| | | $this->object_type = 'user'; |
| | | $this->userFields(); |
| | | } |
| | | |
| | | public function getFields():array |
| | | { |
| | | return $this->fields; |
| | | } |
| | | public function getSections():array |
| | | { |
| | | return $this->sections; |
| | | } |
| | | public function userFields():void |
| | | { |
| | | |
| | | $this->fields = [ |
| | | 'display_name' => [ |
| | | 'type' => 'text', |
| | | 'label' => 'Name', |
| | | 'description' => 'Optional. Only used if you allow artists to see your info when you favourite them.', |
| | | 'default' => '', |
| | | 'section' => 'account', |
| | | 'role' => ['ei_enthusiast'] |
| | | ], |
| | | 'user_email' => [ |
| | | 'type' => 'email', |
| | | 'label' => 'Email', |
| | | 'description' => 'Required for any notifications you subscribe to.', |
| | | 'default' => '', |
| | | 'section' => 'account', |
| | | 'role' => ['ei_enthusiast'] |
| | | ], |
| | | 'city' => [ |
| | | 'type' => 'text', |
| | | 'label' => 'City', |
| | | 'description' => 'Optional. Just helps us know where people who use this site are located.', |
| | | 'default' => '', |
| | | 'section' => 'account', |
| | | 'role' => ['ei_enthusiast'] |
| | | ], |
| | | 'notify' => [ |
| | | 'type' => 'true_false', |
| | | 'label' => 'Notify artists when you favourite their work', |
| | | 'description' => 'If you select this, artists will see your name when you favourite their work, else they will just get an anonymous notification.', |
| | | 'default' => false, |
| | | 'section' => 'account', |
| | | ], |
| | | 'dark_mode' => [ |
| | | 'type' => 'true_false', |
| | | 'label' => 'Dark Mode', |
| | | 'default' => false, |
| | | ], |
| | | 'email_digest' => [ |
| | | 'type' => 'radio', |
| | | 'label' => 'Email Summary Frequency', |
| | | 'options' => $this->frequency, |
| | | 'default' => 'never', |
| | | 'section' => 'notifications' |
| | | ], |
| | | 'digest_override' => [ |
| | | 'type' => 'true_false', |
| | | 'label' => 'Apply to all notifications', |
| | | 'description' => 'Override individual notification settings and apply this frequency to all your notifications', |
| | | 'default' => false, |
| | | 'section' => 'notifications' |
| | | ], |
| | | 'notifications' => [ |
| | | 'type' => 'callback', |
| | | 'callback' => 'renderNotifications', |
| | | 'label' => 'Notifications', |
| | | 'section' => 'notifications', |
| | | 'default' => '', |
| | | ], |
| | | 'site_updates' => [ |
| | | 'type' => 'true_false', |
| | | 'label' => 'Site Updates', |
| | | 'description' => 'Get notified when new features are added to edmonton.ink', |
| | | 'default' => false, |
| | | 'section' => 'account', |
| | | ], |
| | | 'newsletter' => [ |
| | | 'type' => 'true_false', |
| | | 'label' => 'Newsletter', |
| | | 'description' => 'Sign up for our monthly-ish newsletter, featuring upcoming events, featured artists, new artists, and their work.', |
| | | 'default' => false, |
| | | 'section' => 'newsletter', |
| | | ], |
| | | 'owner_of' => [ |
| | | 'type' => 'taxonomy', |
| | | 'label' => __('Owner of', 'jvb'), |
| | | 'taxonomy_type' => 'reference', |
| | | 'taxonomy' => BASE. 'shop', |
| | | 'quickEdit' => true, |
| | | 'default' => '', |
| | | ], |
| | | 'manager_of' => [ |
| | | 'type' => 'taxonomy', |
| | | 'label' => __('Manager of', 'jvb'), |
| | | 'taxonomy_type' => 'reference', |
| | | 'taxonomy' => BASE. 'shop', |
| | | 'hidden' => true, |
| | | 'default' => '', |
| | | ], |
| | | |
| | | 'invitations' => [ |
| | | 'type' => 'callback', |
| | | 'callback' => 'handleInvitationsManagement', |
| | | 'section' => 'invitations', |
| | | 'label' => __('Invite Artists', 'jvb'), |
| | | 'role' => ['ei_artist'] |
| | | ], |
| | | ]; |
| | | } |
| | | |
| | | /** |
| | | * Render custom notification preferences UI |
| | | * @param int $user_id |
| | | * |
| | | * @return string |
| | | */ |
| | | public function renderNotifications(int $user_id):string |
| | | { |
| | | $favourites = $this->getUserFavourites($user_id); |
| | | $preferences = $this->getUserNotificationPreferences($user_id); |
| | | global $notify; |
| | | |
| | | ob_start(); |
| | | ?> |
| | | <div class="notification-preferences"> |
| | | <?php foreach ($favourites as $type => $items) : ?> |
| | | <details class="notification-group"> |
| | | <summary class="notification-group-header row btw"> |
| | | <span class="type-label"><?=jvbIcon('heart', ['style' => 'fill'])?> <?= $notify[$type] ?></span> |
| | | <span class="type-count">( <?= count($items); ?> )</span> |
| | | </summary> |
| | | |
| | | <?php if (!empty($items)) : ?> |
| | | <table class="notification-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>Name</th> |
| | | <th>Frequency</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <?php foreach ($items as $item) : ?> |
| | | <?php |
| | | $current = isset($preferences['preferences'][$type][$item['id']]) |
| | | ? $preferences['preferences'][$type][$item['id']] |
| | | : $preferences['default_frequency']; |
| | | ?> |
| | | <tr> |
| | | <td><?= esc_html($item['name']); ?></td> |
| | | <td> |
| | | <div class="radio-options row"> |
| | | <?php foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?> |
| | | <input type="radio" |
| | | name="notification_preferences[<?= esc_attr($type); ?>][<?= esc_attr($item['id']); ?>]" |
| | | id="<?= esc_attr("{$type}_{$item['id']}_$freq"); ?>" |
| | | value="<?= esc_attr($freq); ?>" |
| | | <?php checked($current, $freq); ?>> |
| | | <label for="<?= esc_attr("{$type}_{$item['id']}_$freq"); ?>"> |
| | | <?= ucfirst($freq); ?> |
| | | </label> |
| | | <?php endforeach; ?> |
| | | </div> |
| | | </td> |
| | | </tr> |
| | | <?php endforeach; ?> |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | |
| | | <th>Set all <?= $type ?>s to: </th> |
| | | <th> |
| | | <div class="radio-options row"> |
| | | <?php foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?> |
| | | <input type="radio" |
| | | name="toggle-all-<?=$type?>" |
| | | id="toggle-all-<?=$type?>-<?=$freq?>" |
| | | value="<?= esc_attr($freq); ?>" |
| | | class="toggle-all"> |
| | | <label for="toggle-all-<?=$type?>-<?=$freq?>"> |
| | | <?= ucfirst($freq); ?> |
| | | </label> |
| | | <?php endforeach; ?> |
| | | </div> |
| | | </th> |
| | | |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | <?php else : ?> |
| | | <p class="no-items">No favourites yet</p> |
| | | <?php endif; ?> |
| | | </details> |
| | | <?php endforeach; ?> |
| | | </div> |
| | | <script> |
| | | function initGroupOverrides() { |
| | | document.querySelectorAll('.toggle-all').forEach(toggle => { |
| | | toggle.addEventListener('change', e => { |
| | | e.preventDefault(); |
| | | if(toggle.checked){ |
| | | const table = e.target.closest('table'); |
| | | console.log(table); |
| | | const value = toggle.value; |
| | | |
| | | // Enable/disable individual controls |
| | | table.querySelectorAll('input[value="'+value+'"]').forEach(radio => { |
| | | radio.checked = true; |
| | | }); |
| | | } |
| | | |
| | | }); |
| | | }); |
| | | |
| | | // Listen for changes to default frequency |
| | | document.querySelector('input[name="digest_override"]').addEventListener('change', e=>{ |
| | | let value = document.querySelector('input[name="email_digest"]:checked').value; |
| | | |
| | | console.log(value); |
| | | document.querySelectorAll('input[value="'+value+'"]').forEach(toggle => { |
| | | toggle.checked = true; |
| | | }); |
| | | |
| | | setTimeout(function () { |
| | | e.target.checked = false; |
| | | }, 1000) |
| | | |
| | | }); |
| | | |
| | | } |
| | | initGroupOverrides(); |
| | | </script> |
| | | <?php |
| | | return ob_get_clean(); |
| | | } |
| | | |
| | | /** |
| | | * Get user's favourites grouped by type |
| | | */ |
| | | protected function getUserFavourites(int $user_id):array |
| | | { |
| | | global $wpdb; |
| | | $table = $wpdb->prefix . BASE.'favourites'; |
| | | global $notify; |
| | | global $types; |
| | | |
| | | |
| | | $favourites = []; |
| | | foreach (array_keys($notify) as $type) { |
| | | $favourites[$type] = []; |
| | | } |
| | | |
| | | // Fetch favourites from database |
| | | $results = $wpdb->get_results($wpdb->prepare( |
| | | "SELECT * FROM $table WHERE user_id = %d", |
| | | $user_id |
| | | )); |
| | | |
| | | foreach ($results as $result) { |
| | | $type = str_replace(BASE, '', $result->type); |
| | | |
| | | |
| | | if (!array_key_exists($type, $favourites)) { |
| | | continue; |
| | | } |
| | | // Get proper name based on type |
| | | switch ($types[BASE.$type]['table']) { |
| | | case 'post': |
| | | $name = get_the_title($result->target_id); |
| | | break; |
| | | case 'term': |
| | | $term = get_term($result->target_id, BASE.$type); |
| | | $name = $term ? html_entity_decode($term->name) : ''; |
| | | break; |
| | | default: |
| | | $name = ''; |
| | | } |
| | | |
| | | if ($name) { |
| | | $favourites[$type][] = [ |
| | | 'id' => $result->target_id, |
| | | 'name' => $name |
| | | ]; |
| | | } |
| | | } |
| | | |
| | | return $favourites; |
| | | } |
| | | |
| | | /** |
| | | * Get current notification preferences |
| | | */ |
| | | protected function getNotificationPreferences(int $user_id):array |
| | | { |
| | | return get_user_meta($user_id, 'notification_preferences', true) ?: []; |
| | | } |
| | | |
| | | protected function getUserNotificationPreferences(int $user_id):array |
| | | { |
| | | global $wpdb; |
| | | $table = $wpdb->prefix . BASE.'notification_preferences'; |
| | | |
| | | // error_log('Getting notification preferences for user: ' . $user_id); |
| | | |
| | | // Get user's preferences from the table |
| | | $raw_preferences = $wpdb->get_results($wpdb->prepare( |
| | | "SELECT notification_type, item_id, frequency |
| | | FROM {$table} |
| | | WHERE user_id = %d", |
| | | $user_id |
| | | ), ARRAY_A); |
| | | |
| | | // error_log('Raw preferences from database: ' . print_r($raw_preferences, true)); |
| | | |
| | | // Structure the preferences |
| | | $preferences = []; |
| | | if (!empty($raw_preferences)) { |
| | | foreach ($raw_preferences as $pref) { |
| | | $type = $pref['notification_type']; |
| | | $item_id = intval($pref['item_id']); |
| | | $frequency = $pref['frequency']; |
| | | |
| | | if (!isset($preferences[$type])) { |
| | | $preferences[$type] = []; |
| | | } |
| | | $preferences[$type][$item_id] = $frequency; |
| | | } |
| | | } |
| | | |
| | | // Get default frequency |
| | | $default_frequency = get_user_meta($user_id, BASE.'email_digest', true) ?: 'never'; |
| | | |
| | | // error_log('Structured preferences: ' . print_r($preferences, true)); |
| | | // error_log('Default frequency: ' . $default_frequency); |
| | | |
| | | return [ |
| | | 'preferences' => $preferences, |
| | | 'default_frequency' => $default_frequency |
| | | ]; |
| | | } |
| | | |
| | | public function handleInvitationsManagement(int $userID):void |
| | | { |
| | | $name = 'artist_invite'; |
| | | ?> |
| | | <div class="field"> |
| | | <script type="text/javascript"> |
| | | function addArtist(button){ |
| | | let template = window.getTemplate('artistInvite'); |
| | | let container = button.closest('.field').querySelector('.invite-artists'); |
| | | |
| | | let nameLabel = template.querySelector('label[for="invited-artist-name"]'), |
| | | nameInput = template.querySelector('input#invited-artist-name'), |
| | | emailLabel = template.querySelector('label[for="invited-artist-email"]'), |
| | | emailInput = template.querySelector('input#invited-artist-email'), |
| | | shopLabel = template.querySelector('label[for="invited-add-to-shop"]'), |
| | | shopInput = template.querySelector('input#invited-add-to-shop'); |
| | | |
| | | |
| | | let count = container.childNodes.length; |
| | | console.log(container.childNodes); |
| | | [ |
| | | nameLabel.htmlFor, |
| | | nameInput.id, |
| | | nameInput.name, |
| | | emailLabel.htmlFor, |
| | | emailInput.id, |
| | | emailInput.name, |
| | | shopLabel.htmlFor, |
| | | shopInput.id, |
| | | shopInput.name |
| | | ] = |
| | | [ |
| | | `${nameLabel.getAttribute('for')}-${count}`, |
| | | `${nameInput.id}-${count}`, |
| | | `${nameInput.name}-${count}`, |
| | | `${emailLabel.htmlFor}-${count}`, |
| | | `${emailInput.id}-${count}`, |
| | | `${emailInput.name}-${count}`, |
| | | `${shopLabel.htmlFor}-${count}`, |
| | | `${shopInput.id}-${count}`, |
| | | `${shopInput.name}-${count}` |
| | | ]; |
| | | container.append(template); |
| | | } |
| | | function removeArtist(button){ |
| | | button.closest('.invited-artist').remove(); |
| | | } |
| | | |
| | | async function revokeInvite(button){ |
| | | try { |
| | | let artist = button.closest('tr'); |
| | | let id = artist.id; |
| | | |
| | | const headers = { |
| | | 'X-WP-Nonce': eiSettings.nonce, |
| | | 'action_nonce': eiSettings.dash, |
| | | 'Content-Type': 'application/json' |
| | | }; |
| | | |
| | | let body = { |
| | | user: eiSettings.currentUser, |
| | | revoke: id |
| | | }; |
| | | let request = { |
| | | method: 'POST', |
| | | headers: headers, |
| | | body: JSON.stringify(body) |
| | | }; |
| | | console.log(request); |
| | | |
| | | |
| | | const response = await fetch(`${eiSettings.api}invitations`, request); |
| | | |
| | | console.log(response); |
| | | if (!response.ok) { |
| | | const errorData = await response.json().catch(() => ({})); |
| | | } |
| | | |
| | | const data = await response.json(); |
| | | if(data.success){ |
| | | artist.remove(); |
| | | } |
| | | }catch (error) { |
| | | } |
| | | } |
| | | |
| | | async function resendInvite(button){ |
| | | try { |
| | | let artist = button.closest('tr'); |
| | | let id = artist.id; |
| | | |
| | | const headers = { |
| | | 'X-WP-Nonce': eiSettings.nonce, |
| | | 'action_nonce': eiSettings.dash, |
| | | 'Content-Type': 'application/json' |
| | | }; |
| | | |
| | | let body = { |
| | | user: eiSettings.currentUser, |
| | | refresh: id |
| | | }; |
| | | let request = { |
| | | method: 'POST', |
| | | headers: headers, |
| | | body: JSON.stringify(body) |
| | | }; |
| | | console.log(request); |
| | | |
| | | |
| | | const response = await fetch(`${eiSettings.api}invitations`, request); |
| | | |
| | | console.log(response); |
| | | if (!response.ok) { |
| | | const errorData = await response.json().catch(() => ({})); |
| | | } |
| | | |
| | | const data = await response.json(); |
| | | |
| | | }catch (error) { |
| | | } |
| | | } |
| | | |
| | | function sendInvites(button){ |
| | | if(document.querySelector('.invited-artist')){ |
| | | let newArtists = []; |
| | | document.querySelectorAll('.invited-artist').forEach(invited => { |
| | | let name = invited.querySelector('input[type="text"]'), |
| | | email = invited.querySelector('input[type="email"]'), |
| | | toShop = invited.querySelector('input[type="checkbox"]'); |
| | | if(name.value === '' || email.value === ''){ |
| | | invited.classList.add('required'); |
| | | return; |
| | | } |
| | | |
| | | newArtists.push({ |
| | | name: name.value, |
| | | email: email.value, |
| | | toShop: toShop.checked |
| | | }); |
| | | invited.remove(); |
| | | }); |
| | | if(newArtists.length > 0){ |
| | | window.queueManager.addToQueue({ |
| | | type: 'invite_artist', |
| | | data: newArtists |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <section class="invite-artists"> |
| | | <div class="invited-artist"> |
| | | <button type="button" onclick="removeArtist(this)" title="Remove Invite"><?=jvbIcon('trash')?></button> |
| | | <div> |
| | | <label for="invited-artist-name-1">First Name</label> |
| | | <input type="text" id="invited-artist-name-1" name="invited-artist-name-1"> |
| | | </div> |
| | | <div> |
| | | <label for="invited-artist-email-1">Email</label> |
| | | <input type="email" id="invited-artist-email-1" name="invited-artist-email-1"> |
| | | </div> |
| | | <div> |
| | | <input type="checkbox" name="invited-add-to-shop-1" id="invited-add-to-shop-1"> |
| | | <label for="invited-add-to-shop-1">Add to shop?</label> |
| | | </div> |
| | | </div> |
| | | </section> |
| | | <div class="actions"> |
| | | <button type="button" onclick="addArtist(this)" class="add-artist"><?= jvbIcon('plus-square')?>Add Artist</button> |
| | | <button type="button" onclick="sendInvites(this)" class="send-invites"><?=jvbIcon('envelope')?>Send Invites</button> |
| | | </div> |
| | | |
| | | <template class="artistInvite"> |
| | | <div class="invited-artist"> |
| | | <button type="button" onclick="removeArtist(this)" title="Remove Invite"><?=jvbIcon('trash')?></button> |
| | | <div> |
| | | <label for="invited-artist-name">First Name</label> |
| | | <input type="text" id="invited-artist-name" name="invited-artist-name"> |
| | | </div> |
| | | <div> |
| | | <label for="invited-artist-email">Email</label> |
| | | <input type="email" id="invited-artist-email" name="invited-artist-email"> |
| | | </div> |
| | | <div> |
| | | <input type="checkbox" name="invited-add-to-shop" id="invited-add-to-shop"> |
| | | <label for="invited-add-to-shop">Add to shop?</label> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | <?php |
| | | |
| | | $invites = JVB()->routes('invites')->getUserInvitations($userID); |
| | | |
| | | ?> |
| | | <table class="artist-invite"> |
| | | <thead> |
| | | <tr> |
| | | <th scope="col" style="width:100%;">Name</th> |
| | | <th scope="col" style="padding:0 .5rem">Email</th> |
| | | <th scope="col" style="padding:0 .5rem">Status</th> |
| | | <th scope="col" style="padding:0 .5rem">Expires</th> |
| | | <th scope="col" style="padding:0 .5rem">Actions</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <?php |
| | | if (!empty($invites->invitations)) { |
| | | foreach ($invites->invitations as $invite) { |
| | | ?> |
| | | <tr id="<?=$invite['id']?>"> |
| | | <td> |
| | | <?=$invite['name']?> |
| | | </td> |
| | | <td> |
| | | <?=$invite['email']?> |
| | | </td> |
| | | <td> |
| | | <?=$invite['status']?> |
| | | </td> |
| | | <td> |
| | | <?=$invite['expires_at']?> |
| | | </td> |
| | | <td class="actions"> |
| | | <button type="button" data-action="revoke" title="Revoke Invitation" onclick="revokeInvite(this)"> |
| | | <?=jvbIcon('trash')?> |
| | | <span class="screen-reader-text">Revoke invite</span> |
| | | </button> |
| | | <button type="button" data-action="resend"<?=($invite['status'] === 'exipired') ? '' : ' disabled'?> title="Resend Invitation" onclick="resendInvite(this)"> |
| | | <?=jvbIcon('arrows-clockwise')?> |
| | | <span class="screen-reader-text">Try Again</span> |
| | | </button> |
| | | </td> |
| | | |
| | | </tr> |
| | | <?php |
| | | } |
| | | } else { |
| | | ?> |
| | | <tr><td><i>No invites yet</i></td><td></td><td></td><td></td><td></td></tr> |
| | | <?php |
| | | } |
| | | ?> |
| | | </tbody> |
| | | </table> |
| | | <?php |
| | | } |
| | | } |
| | | //TODO: Likely replaced with Registrar? |
| | | // |
| | | //class UserSettings extends ContentRegistry |
| | | //{ |
| | | // protected array $fields; |
| | | // protected array $sections = [ |
| | | // 'account' => [ |
| | | // 'title' => 'Account', |
| | | // 'icon' => 'settings', |
| | | // ], |
| | | // 'notifications' => [ |
| | | // 'title' => 'Notifications', |
| | | // 'icon' => 'email' |
| | | // ], |
| | | // 'newsletter' => [ |
| | | // 'title' => 'Newsletter', |
| | | // 'icon' => 'logo' |
| | | // ], |
| | | // 'invitations' => [ |
| | | // 'title' => 'Invite Artists', |
| | | // 'icon' => 'new-user', |
| | | // ] |
| | | // ]; |
| | | // protected array $frequency = [ |
| | | // 'never' => 'Never', |
| | | // 'daily' => 'Daily', |
| | | // 'weekly' => 'Weekly', |
| | | // 'monthly' => 'Monthly', |
| | | // ]; |
| | | // |
| | | // public function initType():void |
| | | // { |
| | | // $this->object_type = 'user'; |
| | | // $this->userFields(); |
| | | // } |
| | | // |
| | | // public function getFields():array |
| | | // { |
| | | // return $this->fields; |
| | | // } |
| | | // public function getSections():array |
| | | // { |
| | | // return $this->sections; |
| | | // } |
| | | // public function userFields():void |
| | | // { |
| | | // |
| | | // $this->fields = [ |
| | | // 'display_name' => [ |
| | | // 'type' => 'text', |
| | | // 'label' => 'Name', |
| | | // 'description' => 'Optional. Only used if you allow artists to see your info when you favourite them.', |
| | | // 'default' => '', |
| | | // 'section' => 'account', |
| | | // 'role' => ['ei_enthusiast'] |
| | | // ], |
| | | // 'user_email' => [ |
| | | // 'type' => 'email', |
| | | // 'label' => 'Email', |
| | | // 'description' => 'Required for any notifications you subscribe to.', |
| | | // 'default' => '', |
| | | // 'section' => 'account', |
| | | // 'role' => ['ei_enthusiast'] |
| | | // ], |
| | | // 'city' => [ |
| | | // 'type' => 'text', |
| | | // 'label' => 'City', |
| | | // 'description' => 'Optional. Just helps us know where people who use this site are located.', |
| | | // 'default' => '', |
| | | // 'section' => 'account', |
| | | // 'role' => ['ei_enthusiast'] |
| | | // ], |
| | | // 'notify' => [ |
| | | // 'type' => 'true_false', |
| | | // 'label' => 'Notify artists when you favourite their work', |
| | | // 'description' => 'If you select this, artists will see your name when you favourite their work, else they will just get an anonymous notification.', |
| | | // 'default' => false, |
| | | // 'section' => 'account', |
| | | // ], |
| | | // 'dark_mode' => [ |
| | | // 'type' => 'true_false', |
| | | // 'label' => 'Dark Mode', |
| | | // 'default' => false, |
| | | // ], |
| | | // 'email_digest' => [ |
| | | // 'type' => 'radio', |
| | | // 'label' => 'Email Summary Frequency', |
| | | // 'options' => $this->frequency, |
| | | // 'default' => 'never', |
| | | // 'section' => 'notifications' |
| | | // ], |
| | | // 'digest_override' => [ |
| | | // 'type' => 'true_false', |
| | | // 'label' => 'Apply to all notifications', |
| | | // 'description' => 'Override individual notification settings and apply this frequency to all your notifications', |
| | | // 'default' => false, |
| | | // 'section' => 'notifications' |
| | | // ], |
| | | // 'notifications' => [ |
| | | // 'type' => 'callback', |
| | | // 'callback' => 'renderNotifications', |
| | | // 'label' => 'Notifications', |
| | | // 'section' => 'notifications', |
| | | // 'default' => '', |
| | | // ], |
| | | // 'site_updates' => [ |
| | | // 'type' => 'true_false', |
| | | // 'label' => 'Site Updates', |
| | | // 'description' => 'Get notified when new features are added to edmonton.ink', |
| | | // 'default' => false, |
| | | // 'section' => 'account', |
| | | // ], |
| | | // 'newsletter' => [ |
| | | // 'type' => 'true_false', |
| | | // 'label' => 'Newsletter', |
| | | // 'description' => 'Sign up for our monthly-ish newsletter, featuring upcoming events, featured artists, new artists, and their work.', |
| | | // 'default' => false, |
| | | // 'section' => 'newsletter', |
| | | // ], |
| | | // 'owner_of' => [ |
| | | // 'type' => 'selector', |
| | | // 'subtype'=> 'taxonomy', |
| | | // 'label' => __('Owner of', 'jvb'), |
| | | // 'isReference' => true, |
| | | // 'taxonomy' => BASE. 'shop', |
| | | // 'quickEdit' => true, |
| | | // 'default' => '', |
| | | // ], |
| | | // 'manager_of' => [ |
| | | // 'type' => 'selector', |
| | | // 'subtype' => 'taxonomy', |
| | | // 'label' => __('Manager of', 'jvb'), |
| | | // 'isReference' => true, |
| | | // 'taxonomy' => BASE. 'shop', |
| | | // 'hidden' => true, |
| | | // 'default' => '', |
| | | // ], |
| | | // |
| | | // 'invitations' => [ |
| | | // 'type' => 'callback', |
| | | // 'callback' => 'handleInvitationsManagement', |
| | | // 'section' => 'invitations', |
| | | // 'label' => __('Invite Artists', 'jvb'), |
| | | // 'role' => ['ei_artist'] |
| | | // ], |
| | | // ]; |
| | | // } |
| | | // |
| | | // /** |
| | | // * Render custom notification preferences UI |
| | | // * @param int $user_id |
| | | // * |
| | | // * @return string |
| | | // */ |
| | | // public function renderNotifications(int $user_id):string |
| | | // { |
| | | // $favourites = $this->getUserFavourites($user_id); |
| | | // $preferences = $this->getUserNotificationPreferences($user_id); |
| | | // global $notify; |
| | | // |
| | | // ob_start(); |
| | | // ?> |
| | | <!-- <div class="notification-preferences">--> |
| | | <!-- --><?php //foreach ($favourites as $type => $items) : ?> |
| | | <!-- <details class="notification-group">--> |
| | | <!-- <summary class="notification-group-header row x-btw">--> |
| | | <!-- <span class="type-label">--><?php //=jvbIcon('heart', ['style' => 'fill'])?><!-- --><?php //= $notify[$type] ?><!--</span>--> |
| | | <!-- <span class="type-count">( --><?php //= count($items); ?><!-- )</span>--> |
| | | <!-- </summary>--> |
| | | <!----> |
| | | <!-- --><?php //if (!empty($items)) : ?> |
| | | <!-- <table class="notification-table">--> |
| | | <!-- <thead>--> |
| | | <!-- <tr>--> |
| | | <!-- <th>Name</th>--> |
| | | <!-- <th>Frequency</th>--> |
| | | <!-- </tr>--> |
| | | <!-- </thead>--> |
| | | <!-- <tbody>--> |
| | | <!-- --><?php //foreach ($items as $item) : ?> |
| | | <!-- --><?php |
| | | // $current = isset($preferences['preferences'][$type][$item['id']]) |
| | | // ? $preferences['preferences'][$type][$item['id']] |
| | | // : $preferences['default_frequency']; |
| | | // ?> |
| | | <!-- <tr>--> |
| | | <!-- <td>--><?php //= esc_html($item['name']); ?><!--</td>--> |
| | | <!-- <td>--> |
| | | <!-- <div class="radio-options row">--> |
| | | <!-- --><?php //foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?> |
| | | <!-- <input type="radio"--> |
| | | <!-- name="notification_preferences[--><?php //= esc_attr($type); ?><!--][--><?php //= esc_attr($item['id']); ?><!--]"--> |
| | | <!-- id="--><?php //= esc_attr("{$type}_{$item['id']}_$freq"); ?><!--"--> |
| | | <!-- value="--><?php //= esc_attr($freq); ?><!--"--> |
| | | <!-- --><?php //checked($current, $freq); ?><!-->--> |
| | | <!-- <label for="--><?php //= esc_attr("{$type}_{$item['id']}_$freq"); ?><!--">--> |
| | | <!-- --><?php //= ucfirst($freq); ?> |
| | | <!-- </label>--> |
| | | <!-- --><?php //endforeach; ?> |
| | | <!-- </div>--> |
| | | <!-- </td>--> |
| | | <!-- </tr>--> |
| | | <!-- --><?php //endforeach; ?> |
| | | <!-- </tbody>--> |
| | | <!-- <tfoot>--> |
| | | <!-- <tr>--> |
| | | <!----> |
| | | <!-- <th>Set all --><?php //= $type ?><!--s to: </th>--> |
| | | <!-- <th>--> |
| | | <!-- <div class="radio-options row">--> |
| | | <!-- --><?php //foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?> |
| | | <!-- <input type="radio"--> |
| | | <!-- name="toggle-all---><?php //=$type?><!--"--> |
| | | <!-- id="toggle-all---><?php //=$type?><!-----><?php //=$freq?><!--"--> |
| | | <!-- value="--><?php //= esc_attr($freq); ?><!--"--> |
| | | <!-- class="toggle-all">--> |
| | | <!-- <label for="toggle-all---><?php //=$type?><!-----><?php //=$freq?><!--">--> |
| | | <!-- --><?php //= ucfirst($freq); ?> |
| | | <!-- </label>--> |
| | | <!-- --><?php //endforeach; ?> |
| | | <!-- </div>--> |
| | | <!-- </th>--> |
| | | <!----> |
| | | <!-- </tr>--> |
| | | <!-- </tfoot>--> |
| | | <!-- </table>--> |
| | | <!-- --><?php //else : ?> |
| | | <!-- <p class="no-items">No favourites yet</p>--> |
| | | <!-- --><?php //endif; ?> |
| | | <!-- </details>--> |
| | | <!-- --><?php //endforeach; ?> |
| | | <!-- </div>--> |
| | | <!-- <script>--> |
| | | <!-- function initGroupOverrides() {--> |
| | | <!-- document.querySelectorAll('.toggle-all').forEach(toggle => {--> |
| | | <!-- toggle.addEventListener('change', e => {--> |
| | | <!-- e.preventDefault();--> |
| | | <!-- if(toggle.checked){--> |
| | | <!-- const table = e.target.closest('table');--> |
| | | <!-- console.log(table);--> |
| | | <!-- const value = toggle.value;--> |
| | | <!----> |
| | | <!-- // Enable/disable individual controls--> |
| | | <!-- table.querySelectorAll('input[value="'+value+'"]').forEach(radio => {--> |
| | | <!-- radio.checked = true;--> |
| | | <!-- });--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- });--> |
| | | <!-- });--> |
| | | <!----> |
| | | <!-- // Listen for changes to default frequency--> |
| | | <!-- document.querySelector('input[name="digest_override"]').addEventListener('change', e=>{--> |
| | | <!-- let value = document.querySelector('input[name="email_digest"]:checked').value;--> |
| | | <!----> |
| | | <!-- console.log(value);--> |
| | | <!-- document.querySelectorAll('input[value="'+value+'"]').forEach(toggle => {--> |
| | | <!-- toggle.checked = true;--> |
| | | <!-- });--> |
| | | <!----> |
| | | <!-- setTimeout(function () {--> |
| | | <!-- e.target.checked = false;--> |
| | | <!-- }, 1000)--> |
| | | <!----> |
| | | <!-- });--> |
| | | <!----> |
| | | <!-- }--> |
| | | <!-- initGroupOverrides();--> |
| | | <!-- </script>--> |
| | | <!-- --><?php |
| | | // return ob_get_clean(); |
| | | // } |
| | | // |
| | | // /** |
| | | // * Get user's favourites grouped by type |
| | | // */ |
| | | // protected function getUserFavourites(int $user_id):array |
| | | // { |
| | | // global $wpdb; |
| | | // $table = $wpdb->prefix . BASE.'favourites'; |
| | | // global $notify; |
| | | // global $types; |
| | | // |
| | | // |
| | | // $favourites = []; |
| | | // foreach (array_keys($notify) as $type) { |
| | | // $favourites[$type] = []; |
| | | // } |
| | | // |
| | | // // Fetch favourites from database |
| | | // $results = $wpdb->get_results($wpdb->prepare( |
| | | // "SELECT * FROM $table WHERE user_id = %d", |
| | | // $user_id |
| | | // )); |
| | | // |
| | | // foreach ($results as $result) { |
| | | // $type = str_replace(BASE, '', $result->type); |
| | | // |
| | | // |
| | | // if (!array_key_exists($type, $favourites)) { |
| | | // continue; |
| | | // } |
| | | // // Get proper name based on type |
| | | // switch ($types[BASE.$type]['table']) { |
| | | // case 'post': |
| | | // $name = get_the_title($result->target_id); |
| | | // break; |
| | | // case 'term': |
| | | // $term = get_term($result->target_id, BASE.$type); |
| | | // $name = $term ? html_entity_decode($term->name) : ''; |
| | | // break; |
| | | // default: |
| | | // $name = ''; |
| | | // } |
| | | // |
| | | // if ($name) { |
| | | // $favourites[$type][] = [ |
| | | // 'id' => $result->target_id, |
| | | // 'name' => $name |
| | | // ]; |
| | | // } |
| | | // } |
| | | // |
| | | // return $favourites; |
| | | // } |
| | | // |
| | | // /** |
| | | // * Get current notification preferences |
| | | // */ |
| | | // protected function getNotificationPreferences(int $user_id):array |
| | | // { |
| | | // return get_user_meta($user_id, 'notification_preferences', true) ?: []; |
| | | // } |
| | | // |
| | | // protected function getUserNotificationPreferences(int $user_id):array |
| | | // { |
| | | // global $wpdb; |
| | | // $table = $wpdb->prefix . BASE.'notification_preferences'; |
| | | // |
| | | //// error_log('Getting notification preferences for user: ' . $user_id); |
| | | // |
| | | // // Get user's preferences from the table |
| | | // $raw_preferences = $wpdb->get_results($wpdb->prepare( |
| | | // "SELECT notification_type, item_id, frequency |
| | | // FROM {$table} |
| | | // WHERE user_id = %d", |
| | | // $user_id |
| | | // ), ARRAY_A); |
| | | // |
| | | //// error_log('Raw preferences from database: ' . print_r($raw_preferences, true)); |
| | | // |
| | | // // Structure the preferences |
| | | // $preferences = []; |
| | | // if (!empty($raw_preferences)) { |
| | | // foreach ($raw_preferences as $pref) { |
| | | // $type = $pref['notification_type']; |
| | | // $item_id = intval($pref['item_id']); |
| | | // $frequency = $pref['frequency']; |
| | | // |
| | | // if (!isset($preferences[$type])) { |
| | | // $preferences[$type] = []; |
| | | // } |
| | | // $preferences[$type][$item_id] = $frequency; |
| | | // } |
| | | // } |
| | | // |
| | | // // Get default frequency |
| | | // $default_frequency = get_user_meta($user_id, BASE.'email_digest', true) ?: 'never'; |
| | | // |
| | | //// error_log('Structured preferences: ' . print_r($preferences, true)); |
| | | //// error_log('Default frequency: ' . $default_frequency); |
| | | // |
| | | // return [ |
| | | // 'preferences' => $preferences, |
| | | // 'default_frequency' => $default_frequency |
| | | // ]; |
| | | // } |
| | | // |
| | | // public function handleInvitationsManagement(int $userID):void |
| | | // { |
| | | // $name = 'artist_invite'; |
| | | // ?> |
| | | <!-- <div class="field">--> |
| | | <!-- <script type="text/javascript">--> |
| | | <!-- function addArtist(button){--> |
| | | <!-- let template = window.getTemplate('artistInvite');--> |
| | | <!-- let container = button.closest('.field').querySelector('.invite-artists');--> |
| | | <!----> |
| | | <!-- let nameLabel = template.querySelector('label[for="invited-artist-name"]'),--> |
| | | <!-- nameInput = template.querySelector('input#invited-artist-name'),--> |
| | | <!-- emailLabel = template.querySelector('label[for="invited-artist-email"]'),--> |
| | | <!-- emailInput = template.querySelector('input#invited-artist-email'),--> |
| | | <!-- shopLabel = template.querySelector('label[for="invited-add-to-shop"]'),--> |
| | | <!-- shopInput = template.querySelector('input#invited-add-to-shop');--> |
| | | <!----> |
| | | <!----> |
| | | <!-- let count = container.childNodes.length;--> |
| | | <!-- console.log(container.childNodes);--> |
| | | <!-- [--> |
| | | <!-- nameLabel.htmlFor,--> |
| | | <!-- nameInput.id,--> |
| | | <!-- nameInput.name,--> |
| | | <!-- emailLabel.htmlFor,--> |
| | | <!-- emailInput.id,--> |
| | | <!-- emailInput.name,--> |
| | | <!-- shopLabel.htmlFor,--> |
| | | <!-- shopInput.id,--> |
| | | <!-- shopInput.name--> |
| | | <!-- ] =--> |
| | | <!-- [--> |
| | | <!-- `${nameLabel.getAttribute('for')}-${count}`,--> |
| | | <!-- `${nameInput.id}-${count}`,--> |
| | | <!-- `${nameInput.name}-${count}`,--> |
| | | <!-- `${emailLabel.htmlFor}-${count}`,--> |
| | | <!-- `${emailInput.id}-${count}`,--> |
| | | <!-- `${emailInput.name}-${count}`,--> |
| | | <!-- `${shopLabel.htmlFor}-${count}`,--> |
| | | <!-- `${shopInput.id}-${count}`,--> |
| | | <!-- `${shopInput.name}-${count}`--> |
| | | <!-- ];--> |
| | | <!-- container.append(template);--> |
| | | <!-- }--> |
| | | <!-- function removeArtist(button){--> |
| | | <!-- button.closest('.invited-artist').remove();--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- async function revokeInvite(button){--> |
| | | <!-- try {--> |
| | | <!-- let artist = button.closest('tr');--> |
| | | <!-- let id = artist.id;--> |
| | | <!----> |
| | | <!-- const headers = {--> |
| | | <!-- 'X-WP-Nonce': eiSettings.nonce,--> |
| | | <!-- 'action_nonce': eiSettings.dash,--> |
| | | <!-- 'Content-Type': 'application/json'--> |
| | | <!-- };--> |
| | | <!----> |
| | | <!-- let body = {--> |
| | | <!-- user: eiSettings.currentUser,--> |
| | | <!-- revoke: id--> |
| | | <!-- };--> |
| | | <!-- let request = {--> |
| | | <!-- method: 'POST',--> |
| | | <!-- headers: headers,--> |
| | | <!-- body: JSON.stringify(body)--> |
| | | <!-- };--> |
| | | <!-- console.log(request);--> |
| | | <!----> |
| | | <!----> |
| | | <!-- const response = await fetch(`${eiSettings.api}invitations`, request);--> |
| | | <!----> |
| | | <!-- console.log(response);--> |
| | | <!-- if (!response.ok) {--> |
| | | <!-- const errorData = await response.json().catch(() => ({}));--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- const data = await response.json();--> |
| | | <!-- if(data.success){--> |
| | | <!-- artist.remove();--> |
| | | <!-- }--> |
| | | <!-- }catch (error) {--> |
| | | <!-- }--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- async function resendInvite(button){--> |
| | | <!-- try {--> |
| | | <!-- let artist = button.closest('tr');--> |
| | | <!-- let id = artist.id;--> |
| | | <!----> |
| | | <!-- const headers = {--> |
| | | <!-- 'X-WP-Nonce': eiSettings.nonce,--> |
| | | <!-- 'action_nonce': eiSettings.dash,--> |
| | | <!-- 'Content-Type': 'application/json'--> |
| | | <!-- };--> |
| | | <!----> |
| | | <!-- let body = {--> |
| | | <!-- user: eiSettings.currentUser,--> |
| | | <!-- refresh: id--> |
| | | <!-- };--> |
| | | <!-- let request = {--> |
| | | <!-- method: 'POST',--> |
| | | <!-- headers: headers,--> |
| | | <!-- body: JSON.stringify(body)--> |
| | | <!-- };--> |
| | | <!-- console.log(request);--> |
| | | <!----> |
| | | <!----> |
| | | <!-- const response = await fetch(`${eiSettings.api}invitations`, request);--> |
| | | <!----> |
| | | <!-- console.log(response);--> |
| | | <!-- if (!response.ok) {--> |
| | | <!-- const errorData = await response.json().catch(() => ({}));--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- const data = await response.json();--> |
| | | <!----> |
| | | <!-- }catch (error) {--> |
| | | <!-- }--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- function sendInvites(button){--> |
| | | <!-- if(document.querySelector('.invited-artist')){--> |
| | | <!-- let newArtists = [];--> |
| | | <!-- document.querySelectorAll('.invited-artist').forEach(invited => {--> |
| | | <!-- let name = invited.querySelector('input[type="text"]'),--> |
| | | <!-- email = invited.querySelector('input[type="email"]'),--> |
| | | <!-- toShop = invited.querySelector('input[type="checkbox"]');--> |
| | | <!-- if(name.value === '' || email.value === ''){--> |
| | | <!-- invited.classList.add('required');--> |
| | | <!-- return;--> |
| | | <!-- }--> |
| | | <!----> |
| | | <!-- newArtists.push({--> |
| | | <!-- name: name.value,--> |
| | | <!-- email: email.value,--> |
| | | <!-- toShop: toShop.checked--> |
| | | <!-- });--> |
| | | <!-- invited.remove();--> |
| | | <!-- });--> |
| | | <!-- if(newArtists.length > 0){--> |
| | | <!-- window.queueManager.addToQueue({--> |
| | | <!-- type: 'invite_artist',--> |
| | | <!-- data: newArtists--> |
| | | <!-- });--> |
| | | <!-- }--> |
| | | <!-- }--> |
| | | <!-- }--> |
| | | <!-- </script>--> |
| | | <!----> |
| | | <!-- <section class="invite-artists">--> |
| | | <!-- <div class="invited-artist">--> |
| | | <!-- <button type="button" onclick="removeArtist(this)" title="Remove Invite">--><?php //=jvbIcon('trash')?><!--</button>--> |
| | | <!-- <div>--> |
| | | <!-- <label for="invited-artist-name-1">First Name</label>--> |
| | | <!-- <input type="text" id="invited-artist-name-1" name="invited-artist-name-1">--> |
| | | <!-- </div>--> |
| | | <!-- <div>--> |
| | | <!-- <label for="invited-artist-email-1">Email</label>--> |
| | | <!-- <input type="email" id="invited-artist-email-1" name="invited-artist-email-1">--> |
| | | <!-- </div>--> |
| | | <!-- <div>--> |
| | | <!-- <input type="checkbox" name="invited-add-to-shop-1" id="invited-add-to-shop-1">--> |
| | | <!-- <label for="invited-add-to-shop-1">Add to shop?</label>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <!-- </section>--> |
| | | <!-- <div class="actions">--> |
| | | <!-- <button type="button" onclick="addArtist(this)" class="add-artist">--><?php //= jvbIcon('plus-square')?><!--Add Artist</button>--> |
| | | <!-- <button type="button" onclick="sendInvites(this)" class="send-invites">--><?php //=jvbIcon('envelope')?><!--Send Invites</button>--> |
| | | <!-- </div>--> |
| | | <!----> |
| | | <!-- <template class="artistInvite">--> |
| | | <!-- <div class="invited-artist">--> |
| | | <!-- <button type="button" onclick="removeArtist(this)" title="Remove Invite">--><?php //=jvbIcon('trash')?><!--</button>--> |
| | | <!-- <div>--> |
| | | <!-- <label for="invited-artist-name">First Name</label>--> |
| | | <!-- <input type="text" id="invited-artist-name" name="invited-artist-name">--> |
| | | <!-- </div>--> |
| | | <!-- <div>--> |
| | | <!-- <label for="invited-artist-email">Email</label>--> |
| | | <!-- <input type="email" id="invited-artist-email" name="invited-artist-email">--> |
| | | <!-- </div>--> |
| | | <!-- <div>--> |
| | | <!-- <input type="checkbox" name="invited-add-to-shop" id="invited-add-to-shop">--> |
| | | <!-- <label for="invited-add-to-shop">Add to shop?</label>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <!-- </template>--> |
| | | <!-- </div>--> |
| | | <!-- --><?php |
| | | // |
| | | // $invites = JVB()->routes('invites')->getUserInvitations($userID); |
| | | // |
| | | // ?> |
| | | <!-- <table class="artist-invite">--> |
| | | <!-- <thead>--> |
| | | <!-- <tr>--> |
| | | <!-- <th scope="col" style="width:100%;">Name</th>--> |
| | | <!-- <th scope="col" style="padding:0 .5rem">Email</th>--> |
| | | <!-- <th scope="col" style="padding:0 .5rem">Status</th>--> |
| | | <!-- <th scope="col" style="padding:0 .5rem">Expires</th>--> |
| | | <!-- <th scope="col" style="padding:0 .5rem">Actions</th>--> |
| | | <!-- </tr>--> |
| | | <!-- </thead>--> |
| | | <!-- <tbody>--> |
| | | <!-- --><?php |
| | | // if (!empty($invites->invitations)) { |
| | | // foreach ($invites->invitations as $invite) { |
| | | // ?> |
| | | <!-- <tr id="--><?php //=$invite['id']?><!--">--> |
| | | <!-- <td>--> |
| | | <!-- --><?php //=$invite['name']?> |
| | | <!-- </td>--> |
| | | <!-- <td>--> |
| | | <!-- --><?php //=$invite['email']?> |
| | | <!-- </td>--> |
| | | <!-- <td>--> |
| | | <!-- --><?php //=$invite['status']?> |
| | | <!-- </td>--> |
| | | <!-- <td>--> |
| | | <!-- --><?php //=$invite['expires_at']?> |
| | | <!-- </td>--> |
| | | <!-- <td class="actions">--> |
| | | <!-- <button type="button" data-action="revoke" title="Revoke Invitation" onclick="revokeInvite(this)">--> |
| | | <!-- --><?php //=jvbIcon('trash')?> |
| | | <!-- <span class="screen-reader-text">Revoke invite</span>--> |
| | | <!-- </button>--> |
| | | <!-- <button type="button" data-action="resend"--><?php //=($invite['status'] === 'exipired') ? '' : ' disabled'?><!-- title="Resend Invitation" onclick="resendInvite(this)">--> |
| | | <!-- --><?php //=jvbIcon('arrows-clockwise')?> |
| | | <!-- <span class="screen-reader-text">Try Again</span>--> |
| | | <!-- </button>--> |
| | | <!-- </td>--> |
| | | <!----> |
| | | <!-- </tr>--> |
| | | <!-- --><?php |
| | | // } |
| | | // } else { |
| | | // ?> |
| | | <!-- <tr><td><i>No invites yet</i></td><td></td><td></td><td></td><td></td></tr>--> |
| | | <!-- --><?php |
| | | // } |
| | | // ?> |
| | | <!-- </tbody>--> |
| | | <!-- </table>--> |
| | | <!-- --><?php |
| | | // } |
| | | //} |