| | |
| | | <?php |
| | | |
| | | use JVBase\utility\Features; |
| | | use JVBase\managers\Cache; |
| | | use JVBase\meta\Form; |
| | | use JVBase\base\Site; |
| | | use JVBase\utility\Image; |
| | | |
| | | if (!defined('ABSPATH')) { |
| | | exit; |
| | |
| | | |
| | | function jvbClientQueue():void |
| | | { |
| | | if (!Features::forSite()->has('dashboard') || !is_user_logged_in()) { |
| | | if (!Site::has('dashboard') || !is_user_logged_in()) { |
| | | return; |
| | | } |
| | | |
| | | ?> |
| | | <aside id="queue" class="left col start btw" aria-expanded="false" hidden> |
| | | <div class="status-actions row start nowrap"> |
| | | <div class="refresh row btw"> |
| | | <span class="countdown row" title="Will refresh again...">5</span> |
| | | <button class="refreshNow row" title="Check now"> |
| | | <?= jvbIcon('arrows-clockwise', ['title'=> 'Check now']) ?> |
| | | </button> |
| | | </div> |
| | | <aside id="queue" class="left col start btw main" aria-expanded="false" > |
| | | <div class="m-actions row start nowrap"> |
| | | <button class="refresh row" title="Check now"> |
| | | <?= jvbIcon('arrows-clockwise', ['title'=> 'Check now']) ?> |
| | | <span class="countdown row indicator" title="Will refresh again...">5</span> |
| | | </button> |
| | | <div class="popup row"><span></span></div> |
| | | </div> |
| | | |
| | | <div class="header col start"> |
| | | <h3>Queue Status</h3> |
| | | <h2>Queue Status</h2> |
| | | <nav class="filters"> |
| | | <?php |
| | | $filters = [ |
| | |
| | | foreach($filters as $filter => $title) { |
| | | $active = ($i === 0) ? ' active': ''; |
| | | ?> |
| | | <button class="filter<?=$active?>" data-filter="<?=$filter?>" data-count="0"><span class="count row"></span><?=$title?></button> |
| | | <input type="radio" id="qfilter-<?=$filter?>" name="qfilter" class="btn filter<?=$active?>" data-filter="<?=$filter?>"> |
| | | <label for="qfilter-<?=$filter?>" data-count="0"><span class="count indicator row"></span><?=$title?></label> |
| | | <?php |
| | | $i++; |
| | | } |
| | |
| | | ?> |
| | | </nav> |
| | | </div> |
| | | <div class="qitems col"> |
| | | <!-- Operations will be listed here --> |
| | | <div class="qitems item-grid col a-start nowrap"> |
| | | </div> |
| | | <div class="queue-actions row btw"> |
| | | <div class="queue-actions row btw nowrap"> |
| | | <button class="dismiss-all">Clear Completed</button> |
| | | <button class="retry-all">Retry Failed</button> |
| | | </div> |
| | | </aside> |
| | | <button class="qtoggle row" title="Show Queue" aria-controls="queue" hidden> |
| | | <button class="qtoggle sticky" title="Show Queue" aria-controls="queue" > |
| | | <?= jvbIcon('floppy-disk') ?> |
| | | <span class="screen-reader-text"></span> |
| | | <span class="indicator"></span> |
| | |
| | | <div class="item"> |
| | | <div class="header row btw"> |
| | | <span class="type"></span> |
| | | <span class="status row"><span class="screen-reader-text"></span></span> |
| | | <span class="status row"><?= jvbIcon('arrows-clockwise') ?><span class="screen-reader-text"></span></span> |
| | | </div> |
| | | <?php jvbRenderProgressBar() ?> |
| | | <?php jvbRenderProgressBar('',false,false) ?> |
| | | <div class="info"> |
| | | <div class="details"></div> |
| | | <div class="time row start"> |
| | | <?= jvbIcon('clock') ?> |
| | | <span class="started">Started: <span class="time"></span> |
| | | <span class="completed"></span> |
| | | <span class="started">Started: <time></time></span> |
| | | <span class="completed" hidden><span>Completed: </span><time></time></span> |
| | | </div> |
| | | </div> |
| | | <div class="actions row end"> |
| | | <button class="retry" data-action="retry"><span>Retry</span><?= jvbIcon('arrows-clockwise')?></button> |
| | | <button class="cancel" data-action="cancel"><span>Cancel</span><?= jvbIcon('x-square')?></button> |
| | | <button class="refresh" data-action="refresh" title="Refresh to see changes"><span>Refresh</span><?= jvbIcon('arrows-clockwise')?></button> |
| | | <button class="dismiss" data-action="dismiss"><span>Dismiss</span><?= jvbIcon('eye-closed')?></button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <button></button> |
| | | </template> |
| | | <template class="emptyQueue"> |
| | | <div class="empty-queue row">Everything is up to date.</div> |
| | | <div class="empty queue row">Everything is up to date.</div> |
| | | </template> |
| | | <?php |
| | | } |
| | |
| | | */ |
| | | function jvbNotificationMenu():string |
| | | { |
| | | if (jvbSiteHasNotifications() && is_user_logged_in()) { |
| | | $membership = Site::membership(); |
| | | if ($membership && $membership->has('notifications') && is_user_logged_in()) { |
| | | |
| | | ob_start(); |
| | | ?> |
| | |
| | | </a> |
| | | </li> |
| | | <li class="notifications has-submenu"> |
| | | <button class="toggle notifications" type="button" title="Toggle Notifications" aria-expanded="false" aria-controls="notifications-dropdown"> |
| | | <button class="toggle notifications" type="button" data-action="toggle-submenu" title="Toggle Notifications" aria-expanded="false" aria-controls="notifications-dropdown"> |
| | | <?= jvbIcon('bell', ['title'=> 'No Notifications'])?> |
| | | <?= jvbIcon('bell-ringing', ['title'=> 'New Notifications']) ?> |
| | | <span class="notification-badge" aria-label="Notifications"> |
| | | </span> |
| | | </button> |
| | | <ul class="notifications-preview submenu"> |
| | | <ul class="notifications-preview submenu" id="notifications-dropdown"> |
| | | <li id="view-all"><a href="<?=get_home_url(null, '/dash/notifications/')?>" class="view-all">View All Notifications</a></li> |
| | | </ul> |
| | | <template class="notificationItem"> |
| | |
| | | */ |
| | | function jvbHelpMenu():string |
| | | { |
| | | $out = get_option(BASE.'help_menu'); |
| | | if (!Site::has('help_menu')) { |
| | | return ''; |
| | | } |
| | | |
| | | if ($out === false) { |
| | | $open = '<li><a href="'; |
| | | $mid = '">'; |
| | | $close = '</a></li>'; |
| | | $cache = Cache::for('help_menu'); |
| | | $out = $cache->remember( |
| | | 'help_menu', |
| | | function () { |
| | | $open = '<li><a href="'; |
| | | $mid = '">'; |
| | | $close = '</a></li>'; |
| | | |
| | | $titles = array( |
| | | 'About', |
| | | 'Contact', |
| | | 'Request a Feature', |
| | | 'Technical Issue', |
| | | ); |
| | | $links = ''; |
| | | foreach ($titles as $t) { |
| | | $page = new WP_Query(array( |
| | | 'post_type' => 'page', |
| | | 'title' => $t, |
| | | 'fields' => 'ids' |
| | | )); |
| | | if ($page->have_posts()) { |
| | | $end = ($t == 'About') ? '<li><a href="'.get_home_url(null, '/directory/partners/').'" title="View our Partners">Partners</a></li>' : ''; |
| | | $links .= $open.get_the_permalink($page->posts[0]).'" title="'.$t.$mid.$t.$close.$end; |
| | | } |
| | | wp_reset_postdata(); |
| | | } |
| | | $titles = array( |
| | | 'About', |
| | | 'Contact', |
| | | 'Request a Feature', |
| | | 'Technical Issue', |
| | | ); |
| | | $links = ''; |
| | | foreach ($titles as $t) { |
| | | $page = new WP_Query(array( |
| | | 'post_type' => 'page', |
| | | 'title' => $t, |
| | | 'fields' => 'ids' |
| | | )); |
| | | if ($page->have_posts()) { |
| | | $end = ($t == 'About') ? '<li><a href="'.get_home_url(null, '/directory/partners/').'" title="View our Partners">Partners</a></li>' : ''; |
| | | $links .= $open.get_the_permalink($page->posts[0]).'" title="'.$t.$mid.$t.$close.$end; |
| | | } |
| | | wp_reset_postdata(); |
| | | } |
| | | |
| | | $out = '<li class="has-submenu"> |
| | | <button class="toggle quick-help" type="button" title="Toggle Quick Help Menu" aria-expanded="false" aria-controls="quick-help" aria-label="Toggle Quick Help Menu">'.jvbIcon('question', ['title'=> 'Quick Help']).'</button> |
| | | <ul class="submenu"> |
| | | return '<li class="has-submenu"> |
| | | <button class="toggle quick-help" data-action="toggle-submenu" type="button" title="Toggle Quick Help Menu" aria-expanded="false" aria-controls="quick-help" aria-label="Toggle Quick Help Menu">'.jvbIcon('question', ['title'=> 'Quick Help']).'</button> |
| | | <ul class="submenu" id="quick-help"> |
| | | '.$links.' |
| | | </ul> |
| | | </li>'; |
| | | |
| | | update_option(BASE.'help_menu', $out); |
| | | } |
| | | } |
| | | ); |
| | | |
| | | if (is_user_logged_in()) { |
| | | $out .= '<li><a href="'.wp_logout_url(get_home_url()).'" title="Logout">'.jvbIcon('sign-out').'<span class="screen-reader-text">Logout</span></a></li>'; |
| | |
| | | * Outputs the search bar (likely don't need anymore) |
| | | * @return string |
| | | */ |
| | | function jvbSearch(string $placeholder = 'Search...'):string |
| | | function jvbSearch(string $placeholder = 'Search...', string $id = 'search'):string |
| | | { |
| | | return '<div class="search-container row start nowrap"> |
| | | <input type="search" id="search" placeholder="'.$placeholder.'"> |
| | | <button |
| | | title="Clear Search" |
| | | type="button" |
| | | class="clear-search" |
| | | aria-label="Clear search" |
| | | onclick="this.previousElementSibling.value = \'\'; this.previousElementSibling.focus();" |
| | | >'.jvbIcon('x', ['title'=> 'Clear Search']).'</button> |
| | | <button type="button" title="Search" class="toggle search" aria-label="Toggles search input visually" onclick="this.parentNode.classList.toggle(\'open\');this.previousElementSibling.previousElementSibling.focus();">'.jvbIcon('magnifying-glass').'</button> |
| | | </div>'; |
| | | return Form::search($placeholder, $id); |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return string |
| | | */ |
| | | function jvbFormatImage(int|string $imgID, string $start = 'tiny', string $end = 'large'):string |
| | | function jvbFormatImage(int $imgID, string $start = 'tiny', string $end = 'large', bool $addLink = true, ?string $postSlug = null):string |
| | | { |
| | | $block = new \JVBase\blocks\CustomBlocks(); |
| | | if ($imgID === '' || $imgID === 0) { |
| | | $imgID = $block->imageID($imgID); |
| | | } |
| | | if ($imgID === '' || $imgID === 0 || $imgID === false) { |
| | | return ''; |
| | | } |
| | | $image = new Image(); |
| | | return $image->formatImage($imgID, $start, $end, $addLink, $postSlug); |
| | | } |
| | | |
| | | $imgID = (int)$imgID; |
| | | |
| | | return $block->formatImage($imgID, $start, $end); |
| | | function jvbImageCaption(int $imgID, string $start = 'tiny', string $end = 'large', bool $addLink = true, ?string $postSlug = null):string |
| | | { |
| | | $caption = wp_get_attachment_caption($imgID); |
| | | $caption = ($caption && $caption !== '') ? '<figcaption>'.jvb_filter_content( $caption).'</figcaption>' : ''; |
| | | return '<figure>'.jvbFormatImage($imgID, $start, $end, $addLink, $postSlug).$caption.'</figure>'; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return void |
| | | */ |
| | | add_action('wp_footer', 'jvbToastContainer'); |
| | | |
| | | |
| | | function jvbToastContainer():void |
| | | { |
| | | ?> |
| | |
| | | |
| | | ?> |
| | | <nav id="<?=$id?>" class="on-this-page index"> |
| | | <label>Jump to: |
| | | <button type="button" aria-label="Show Index" title="Show Index" class="toggle" aria-expanded="false"> |
| | | <?= jvbIcon('plus-square') ?> |
| | | </button> |
| | | </label> |
| | | <button type="button" aria-label="Show Index" title="Show Index" class="toggle main" aria-expanded="false"> |
| | | <span>Jump To:</span><?= jvbIcon('plus-square') ?> |
| | | </button> |
| | | <ul> |
| | | <li> |
| | | <li id="back-to-top"> |
| | | <a href="#top" title="Back to Top"> |
| | | <?= jvbIcon('caret-circle-up') ?> |
| | | <?= jvbIcon('caret-circle-up') ?><span>Back to Top</span> |
| | | </a> |
| | | </li> |
| | | <?php |
| | |
| | | add_action('wp_footer', 'jvbLoadingScreen'); |
| | | function jvbLoadingScreen():string |
| | | { |
| | | $icon = apply_filters('jvbLoadingIcon', 'drop-simple'); |
| | | return '<dialog class="loading"> |
| | | <div class="col"> |
| | | <div class="spinner"></div> |
| | | <div class="status col"> |
| | | <div class="icon">'.apply_filters('jvbLoadingIcon', jvbIcon('drop-simple')).'</div> |
| | | <div class="icon">'.jvbIcon($icon).'</div> |
| | | <h3>Loading</h3> |
| | | <p class="typeText">Please wait...</p> |
| | | </div> |
| | |
| | | $active = ($i === 0) ? ' active' : ''; |
| | | $selected = ($i === 0) ? 'true' : 'false'; |
| | | $hidden = (array_key_exists('hidden', $config)) ? ' hidden' : ''; |
| | | $header .= '<button type="button" class="button tab'.$active.'" data-tab="'.$slug.'" role="tab" aria-selected="'.$selected.'"'.$hidden.'> |
| | | <h2 class="row">'; |
| | | $header .= '<button type="button" class="button tab'.$active.'" data-tab="'.$slug.'" role="tab" aria-selected="'.$selected.'"'.$hidden.'>'; |
| | | if (array_key_exists('icon', $config)) { |
| | | $header .= jvbIcon($config['icon']); |
| | | } |
| | | $header .= $config['title'].'</h2> |
| | | $header .= $config['title'].' |
| | | </button>'; |
| | | |
| | | //Content |
| | |
| | | if ($i !== 0) { |
| | | $content .= ' hidden'; |
| | | } |
| | | $content .= '> |
| | | <h2>'.$config['title'].'</h2>'; |
| | | if ( $config['description']) { |
| | | $content .= '>'; |
| | | |
| | | if (array_key_exists('header', $config)) { |
| | | $content .= $config['header']; |
| | | } else { |
| | | $content .= '<h2>'.$config['title'].'</h2>'; |
| | | if ( array_key_exists('description', $config)) { |
| | | if (!is_array($config['description'])) { |
| | | $content .= apply_filters('the_content', $config['description']); |
| | | $content .= jvb_filter_content( $config['description']); |
| | | } else { |
| | | // foreach ($config['description'] as $desc) { |
| | | // $content .= apply_filters('the_content', $desc); |
| | | // $content .= jvb_filter_content( $desc); |
| | | // } |
| | | $content .= implode('',array_map(function ($paragraph) { |
| | | return apply_filters('the_content', $paragraph); |
| | | return jvb_filter_content( $paragraph); |
| | | }, $config['description'])); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | $content .= $config['content'].' |
| | | </div>'; |
| | |
| | | return $out; |
| | | } |
| | | |
| | | function jvbRenderProgressBar(string $inside ='', $top = false) |
| | | function jvbRenderProgressBar(string $inside ='', $top = false, $icon = true, $return = false):string |
| | | { |
| | | |
| | | $top = $top ? ' abs top' : ''; |
| | | ?> |
| | | <div class="progress<?=$top?>"> |
| | | $bar = sprintf( |
| | | '<div class="progress%s"> |
| | | <div class="bar"> |
| | | <div class="fill"></div> |
| | | </div> |
| | | <div class="details row btw"> |
| | | <?=$inside?> |
| | | <div class="row btw"> |
| | | %s |
| | | <div class="details"> |
| | | %s |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <?php |
| | | </div>', |
| | | $top, |
| | | ($icon) ? '<i class="icon"></i>': '', |
| | | $inside |
| | | ); |
| | | if (!$return) { |
| | | echo $bar; |
| | | } |
| | | return $bar; |
| | | } |
| | | |
| | | function jvbFormStatus(string $message = '') { |
| | |
| | | </div> |
| | | <div class="fstatus row" hidden> |
| | | <div class="spinner"></div> |
| | | <i class="icon"></i> |
| | | <p class="message">'.$message.'</p> |
| | | </div>'; |
| | | } |
| | | |
| | | |
| | | function jvbDarkModeToggle():string |
| | | { |
| | | $checked = (is_user_logged_in() && current_user_can('prefers_dark_theme', true)) ? ' checked' : ''; |
| | | $title = ($checked == '') ? 'Toggle Dark Mode' : 'Toggle Light Mode'; |
| | | $showThemeSwitch = (bool)apply_filters('jvb_show_theme_switch', true); |
| | | $themeSwitch = sprintf( |
| | | '<label title="%s" id="theme-switch" class="switch" for="theme-switcher"> |
| | | <input class="theme-switch row" id="theme-switcher" name="theme-switcher" type="checkbox"%s data-setting="theme" data-theme role="switch" name="dark-mode" aria-label="Toggle dark mode"> |
| | | <span class="slider">%s%s</span> |
| | | </label>', |
| | | $title, |
| | | $checked, |
| | | jvbIcon('sun-dim', ['title'=> 'Light Mode']), |
| | | jvbIcon('moon', ['title'=>'Dark Mode']) |
| | | ); |
| | | return ($showThemeSwitch) ? $themeSwitch : ''; |
| | | } |