<?php
|
|
use JVBase\utility\Features;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
|
add_action('wp_footer', 'jvbClientQueue');
|
|
function jvbClientQueue():void
|
{
|
if (!Features::forSite()->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('refresh', ['title'=> 'Check now']) ?>
|
</button>
|
</div>
|
<div class="popup row"><span></span></div>
|
</div>
|
|
<div class="header col start">
|
<h3>Queue Status</h3>
|
<nav class="filters">
|
<?php
|
$filters = [
|
'all' => 'All',
|
'queued' => 'Received',
|
'localProcessing' => 'Checking Data',
|
'uploading' => 'Uploading',
|
'pending' => 'Pending',
|
'processing' => 'Processing',
|
'completed' => 'Completed',
|
'failed' => 'Failed',
|
];
|
$i = 0;
|
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>
|
<?php
|
$i++;
|
}
|
|
?>
|
</nav>
|
</div>
|
<div class="qitems col">
|
<!-- Operations will be listed here -->
|
</div>
|
<div class="queue-actions row btw">
|
<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>
|
<?= jvbIcon('save') ?>
|
<span class="screen-reader-text"></span>
|
<span class="indicator"></span>
|
<span class="count row"></span>
|
</button>
|
<template class="queueItem">
|
<div class="item">
|
<div class="header row btw">
|
<span class="type"></span>
|
<span class="status row"><span class="screen-reader-text"></span></span>
|
</div>
|
<?php jvbRenderProgressBar() ?>
|
<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>
|
</div>
|
</div>
|
<div class="actions row end">
|
</div>
|
</div>
|
</template>
|
<template class="typedText">
|
<span id="typed-text"></span>
|
<span class="cursor">|</span>
|
</template>
|
<template class="button">
|
<button></button>
|
</template>
|
<template class="emptyQueue">
|
<div class="empty-queue row">Everything is up to date.</div>
|
</template>
|
<?php
|
}
|
|
/**
|
* Outputs the notification menu in the header
|
* @return string
|
*/
|
function jvbNotificationMenu():string
|
{
|
if (jvbSiteHasNotifications() && is_user_logged_in()) {
|
|
ob_start();
|
?>
|
<li>
|
<a href="<?=get_home_url(null, '/dash/')?>" title="Behind the Scenes">
|
<?= jvbIcon('dashboard', ['title' => 'Behind the Scenes'])?>
|
<span class="screen-reader-text">Go Behind the Scenes</span>
|
</a>
|
</li>
|
<li class="notifications has-submenu">
|
<button class="toggle notifications" type="button" 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">
|
<li id="view-all"><a href="<?=get_home_url(null, '/dash/notifications/')?>" class="view-all">View All Notifications</a></li>
|
</ul>
|
<template class="notificationItem">
|
<li class="notification-preview">
|
<p></p>
|
<time></time>
|
</li>
|
</template>
|
<template class="emptyNotification">
|
<li class="empty-state">No new notifications</li>
|
</template>
|
<template class="notificationActions">
|
<div class="notification-actions">
|
<button type="button" data-action="mark-read" title="Mark as Read" onclick="handleNotificationAction(this)"><?=jvbIcon('check')?></button>
|
</div>
|
</template>
|
</li>
|
<?php
|
return ob_get_clean();
|
}
|
return '';
|
}
|
|
/**
|
* Outputs the help menu
|
* @return string
|
*/
|
function jvbHelpMenu():string
|
{
|
$out = get_option(BASE.'help_menu');
|
if ($out === false) {
|
$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();
|
}
|
|
$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('help', ['title'=> 'Quick Help']).'</button>
|
<ul class="submenu">
|
'.$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('logout').'<span class="screen-reader-text">Logout</span></a></li>';
|
} else {
|
$out .= '<li><a href="'.wp_login_url(null, true).'" title="Login">'.jvbIcon('login').'<span class="screen-reader-text">Login</span></a></li>';
|
}
|
return $out;
|
}
|
|
|
/**
|
* Outputs the search bar (likely don't need anymore)
|
* @return string
|
*/
|
function jvbSearch(string $placeholder = '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('search').'</button>
|
</div>';
|
}
|
|
|
|
function jvbModalActions()
|
{
|
return '<div class="m-actions row">
|
<button type="button" class="cancel">'.jvbIcon('close').'<span class="screen-reader-text">Cancel</span></button>
|
<button type="submit" class="save">'.jvbIcon('save').'<span class="screen-reader-text">Save</span></button>
|
</div>';
|
}
|
|
function jvbNewModal(string $class, string $title, string $form)
|
{
|
return '<dialog class="'.$class.'">
|
<div class="wrap">
|
<h2>'.$title.'</h2>
|
'.str_replace('</form>', jvbModalActions().'</form>', $form).'
|
</div>
|
</dialog>';
|
}
|
|
/**
|
* Formats an image to match our image replacement formatting
|
* @param int|string $imgID
|
* @param string $start
|
* @param string $end
|
*
|
* @return string
|
*/
|
function jvbFormatImage(int|string $imgID, string $start = 'tiny', string $end = 'large'):string
|
{
|
$block = new \JVBase\blocks\CustomBlocks();
|
if ($imgID === '' || $imgID === 0) {
|
$imgID = $block->imageID($imgID);
|
}
|
if ($imgID === '' || $imgID === 0 || $imgID === false) {
|
return '';
|
}
|
|
$imgID = (int)$imgID;
|
|
return $block->formatImage($imgID, $start, $end);
|
}
|
|
/**
|
* Outputs the notification container in the footer
|
* @return void
|
*/
|
add_action('wp_footer', 'jvbToastContainer');
|
|
|
function jvbToastContainer():void
|
{
|
?>
|
<aside class="toasts col rev">
|
|
</aside>
|
<template class="notificationPopup">
|
<div class="toast" role="status" aria-live="polite">
|
<div class="toast-content row btw">
|
<p></p>
|
<button type="button" class="close-toast" aria-label="Close">
|
<?= jvbIcon('close') ?>
|
</button>
|
</div>
|
</div>
|
</template>
|
<?php
|
}
|
|
|
function jvbOnThisPage(array $ids):string
|
{
|
if (empty($ids)) {
|
return '';
|
}
|
|
ob_start();
|
$obj = get_queried_object();
|
$id = match (true) {
|
is_tax() => jvbNoBase($obj->taxonomy),
|
default => jvbNoBase($obj->post_type)
|
};
|
|
?>
|
<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('add') ?>
|
</button>
|
</label>
|
<ul>
|
<li>
|
<a href="#top" title="Back to Top">
|
<?= jvbIcon('up') ?>
|
</a>
|
</li>
|
<?php
|
foreach ($ids as $slug) {
|
?>
|
<li>
|
<a href="#<?= sanitize_title($slug) ?>"><?= ucwords(str_replace('-', ' ', str_replace('_', ' ', $slug))) ?></a>
|
</li>
|
<?php
|
}
|
?>
|
</ul>
|
</nav>
|
<?php
|
|
return ob_get_clean();
|
}
|
|
add_action('wp_footer', 'jvbLoadingScreen');
|
function jvbLoadingScreen():string
|
{
|
return '<dialog class="loading">
|
<div class="col">
|
<div class="spinner"></div>
|
<div class="status col">
|
<div class="icon">'.apply_filters('jvbLoadingIcon', jvbIcon('tattoo')).'</div>
|
<h3>Loading</h3>
|
<p class="typeText">Please wait...</p>
|
</div>
|
</div>
|
</dialog>';
|
}
|
|
/**
|
* @param array $tabs Array containing:
|
* $tabs = [
|
* 'tab1' => [
|
* 'title' => $title1,
|
* 'icon' => 'artist',
|
* 'description' => $description1,
|
* 'content' => $content1
|
* ],
|
* 'tab2' => [
|
* 'title' => $title2,
|
* 'content' => $content2
|
* ]
|
* ]
|
* @param bool $return Whether to output or return the form
|
* @return mixed
|
*/
|
function jvbRenderTabs(array $tabs, bool $return = false):string
|
{
|
if (empty($tabs)) {
|
echo '';
|
return '';
|
}
|
$header = '<nav class="tabs row start" role="tablist">';
|
$content = '';
|
$i = 0;
|
|
foreach ($tabs as $slug => $config) {
|
//Header
|
$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">';
|
if (array_key_exists('icon', $config)) {
|
$header .= jvbIcon($config['icon']);
|
}
|
$header .= $config['title'].'</h2>
|
</button>';
|
|
//Content
|
$selected = ($i === 0) ? 'false' : 'true';
|
$content .= '<div class="tab-content'.$active.'" data-tab="'.$slug.'" role="tabpanel" aria-hidden="'.$selected.'"';
|
if ($i !== 0) {
|
$content .= ' hidden';
|
}
|
$content .= '>
|
<h2>'.$config['title'].'</h2>';
|
if ( $config['description']) {
|
if (!is_array($config['description'])) {
|
$content .= apply_filters('the_content', $config['description']);
|
} else {
|
// foreach ($config['description'] as $desc) {
|
// $content .= apply_filters('the_content', $desc);
|
// }
|
$content .= implode('',array_map(function ($paragraph) {
|
return apply_filters('the_content', $paragraph);
|
}, $config['description']));
|
}
|
|
}
|
|
$content .= $config['content'].'
|
</div>';
|
$i++;
|
}
|
$header .= '</nav>';
|
$out = $header.$content;
|
|
if ($return) {
|
return $out;
|
}
|
echo $out;
|
return $out;
|
}
|
|
function jvbRenderProgressBar(string $inside ='', $top = false)
|
{
|
$top = $top ? ' abs top' : '';
|
?>
|
<div class="progress<?=$top?>">
|
<div class="bar">
|
<div class="fill"></div>
|
</div>
|
<div class="details row btw">
|
<?=$inside?>
|
</div>
|
</div>
|
<?php
|
}
|