mirror of
https://github.com/processwire/processwire.git
synced 2025-08-14 18:55:56 +02:00
Add support for group notifications in AdminThemeFramework (AdminThemeUikit), along with a config option in the AdminThemeUikit module. Also fix an issue in ProcessProfile that was interfering with ajax requests.
This commit is contained in:
@@ -579,10 +579,12 @@ abstract class AdminThemeFramework extends AdminTheme {
|
||||
|
||||
/**
|
||||
* Test all notice types
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function testNotices() {
|
||||
if(!$this->wire('user')->isLoggedin()) return;
|
||||
if(!$this->wire('user')->isLoggedin()) return false;
|
||||
$this->message('Message test');
|
||||
$this->message('Message test debug', Notice::debug);
|
||||
$this->message('Message test markup <a href="#">example</a>', Notice::allowMarkup);
|
||||
@@ -592,27 +594,19 @@ abstract class AdminThemeFramework extends AdminTheme {
|
||||
$this->error('Error test');
|
||||
$this->error('Error test debug', Notice::debug);
|
||||
$this->error('Error test markup <a href="#">example</a>', Notice::allowMarkup);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render runtime notices div#notices
|
||||
*
|
||||
* @param Notices $notices
|
||||
* @param array $options See defaults in method
|
||||
* @return string
|
||||
* @param Notices|bool $notices Notices object or specify boolean true to return array of all available $options
|
||||
* @param array $options See defaults in method
|
||||
* @return string|array Returns string unless you specify true for $notices argument, then it returns an array.
|
||||
*
|
||||
*/
|
||||
public function renderNotices($notices, array $options = array()) {
|
||||
|
||||
// if(!count($notices)) return '';
|
||||
|
||||
/*
|
||||
if($this->isLoggedIn && $this->wire('modules')->isInstalled('SystemNotifications')) {
|
||||
$systemNotifications = $this->wire('modules')->get('SystemNotifications');
|
||||
if(!$systemNotifications->placement) return '';
|
||||
}
|
||||
*/
|
||||
|
||||
$defaults = array(
|
||||
'messageClass' => 'NoticeMessage', // class for messages
|
||||
'messageIcon' => 'check-square', // default icon to show with notices
|
||||
@@ -622,20 +616,42 @@ abstract class AdminThemeFramework extends AdminTheme {
|
||||
'errorIcon' => 'exclamation-triangle', // icon for errors
|
||||
'debugClass' => 'NoticeDebug', // class for debug items (appended)
|
||||
'debugIcon' => 'bug', // icon for debug notices
|
||||
'closeClass' => 'notice-remove', // class for close notices link <a>
|
||||
'closeClass' => 'pw-notice-remove notice-remove', // class for close notices link <a>
|
||||
'closeIcon' => 'times', // icon for close notices link
|
||||
'listMarkup' => "<ul class='pw-notices' id='notices'>{out}</ul><!--/notices-->",
|
||||
'itemMarkup' => "<li class='{class}'>{remove}{icon}{text}</li>"
|
||||
'itemMarkup' => "<li class='{class}'>{remove}{icon}{text}</li>",
|
||||
// the following apply only when groupByType==true
|
||||
'groupByType' => true, // Group notices by type
|
||||
'groupParentClass' => 'pw-notice-group-parent', // class for parent notices
|
||||
'groupChildClass' => 'pw-notice-group-child', // class for children (of parent notices)
|
||||
'groupToggleMarkup' => "<a class='pw-notice-group-toggle' href='#'>{label}" .
|
||||
"<i class='fa fa-fw fa-bell-o' data-toggle='fa-bell-o fa-bell'></i>" .
|
||||
"<i class='fa fa-fw fa-angle-right' data-toggle='fa-angle-right fa-angle-down'></i></a>",
|
||||
'groupToggleLabel' => $this->_("+{n-1}"),
|
||||
);
|
||||
|
||||
|
||||
$options = array_merge($defaults, $options);
|
||||
if($notices === true) return $options;
|
||||
$config = $this->wire('config');
|
||||
$noticesArray = array();
|
||||
$out = '';
|
||||
|
||||
$removeIcon = $this->renderIcon($options['closeIcon']);
|
||||
$removeLabel = $this->_('Close all');
|
||||
$removeLink = "<a class='$options[closeClass]' href='#' title='$removeLabel'>$removeIcon</a>";
|
||||
|
||||
if($this->isLoggedIn && $this->wire('modules')->isInstalled('SystemNotifications')) {
|
||||
$defaults['groupByType'] = false;
|
||||
//$systemNotifications = $this->wire('modules')->get('SystemNotifications');
|
||||
//if(!$systemNotifications->placement) return '';
|
||||
}
|
||||
|
||||
foreach($notices as $n => $notice) {
|
||||
|
||||
$text = $notice->text;
|
||||
if($notice->flags & Notice::allowMarkup) {
|
||||
$allowMarkup = $notice->flags & Notice::allowMarkup;
|
||||
|
||||
if($allowMarkup) {
|
||||
// leave $text alone
|
||||
} else {
|
||||
// unencode + re-encode entities, just in case module already entity some or all of output
|
||||
@@ -646,41 +662,70 @@ abstract class AdminThemeFramework extends AdminTheme {
|
||||
if($notice instanceof NoticeError) {
|
||||
$class = $options['errorClass'];
|
||||
$icon = $options['errorIcon'];
|
||||
$noticeType = 'errors';
|
||||
|
||||
} else if($notice instanceof NoticeWarning) {
|
||||
$class = $options['warningClass'];
|
||||
$icon = $options['warningIcon'];
|
||||
$noticeType = 'warnings';
|
||||
|
||||
} else {
|
||||
$class = $options['messageClass'];
|
||||
$icon = $options['messageIcon'];
|
||||
$noticeType = 'messages';
|
||||
}
|
||||
|
||||
if($notice->flags & Notice::debug) {
|
||||
$class .= " " . $options['debugClass'];
|
||||
$icon = $options['debugIcon'];
|
||||
// ensure non-debug version is set as well
|
||||
if(!isset($noticesArray[$noticeType])) $noticesArray[$noticeType] = array();
|
||||
$noticeType .= "-debug";
|
||||
}
|
||||
|
||||
// indicate which class the notice originated from in debug mode
|
||||
if($notice->class && $config->debug) $text = "{$notice->class}: $text";
|
||||
|
||||
// show remove link for first item only
|
||||
if($n) {
|
||||
$remove = '';
|
||||
} else {
|
||||
$removeIcon = $this->renderIcon($options['closeIcon']);
|
||||
$removeLabel = $this->_('Close all');
|
||||
$remove = "<a class='$options[closeClass]' href='#' title='$removeLabel'>$removeIcon</a>";
|
||||
}
|
||||
|
||||
$replacements = array(
|
||||
'{class}' => $class,
|
||||
'{remove}' => $remove,
|
||||
'{remove}' => '',
|
||||
'{icon}' => $this->renderNavIcon($notice->icon ? $notice->icon : $icon),
|
||||
'{text}' => $text,
|
||||
);
|
||||
|
||||
$out .= str_replace(array_keys($replacements), array_values($replacements), $options['itemMarkup']);
|
||||
|
||||
if($options['groupByType']) {
|
||||
if(!isset($noticesArray[$noticeType])) $noticesArray[$noticeType] = array();
|
||||
$noticesArray[$noticeType][] = $replacements;
|
||||
} else {
|
||||
if($n === 0) $replacements['{remove}'] = $removeLink;
|
||||
$out .= str_replace(array_keys($replacements), array_values($replacements), $options['itemMarkup']);
|
||||
}
|
||||
}
|
||||
|
||||
if($options['groupByType']) {
|
||||
$cnt = 0;
|
||||
foreach($noticesArray as $noticeType => $noticeReplacements) {
|
||||
if(strpos($noticeType, '-debug')) continue;
|
||||
if(isset($noticesArray["$noticeType-debug"])) {
|
||||
$noticeReplacements = array_merge($noticeReplacements, $noticesArray["$noticeType-debug"]);
|
||||
}
|
||||
$n = count($noticeReplacements);
|
||||
if($n > 1) {
|
||||
$notice =& $noticeReplacements[0];
|
||||
$label = str_replace(array('{n}', '{n-1}'), array($n, $n-1), $options['groupToggleLabel']);
|
||||
$notice['{text}'] .= ' ' . str_replace(array('{label}'), array($label), $options['groupToggleMarkup']);
|
||||
$notice['{class}'] .= ' ' . $options['groupParentClass'];
|
||||
$childClass = $options['groupChildClass'];
|
||||
} else {
|
||||
$childClass = '';
|
||||
}
|
||||
foreach($noticeReplacements as $i => $replacements) {
|
||||
if(!$cnt) $replacements['{remove}'] = $removeLink;
|
||||
if($childClass && $i > 0) $replacements['{class}'] .= ' ' . $childClass;
|
||||
$out .= str_replace(array_keys($replacements), array_values($replacements), $options['itemMarkup']);
|
||||
$cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$out = str_replace('{out}', $out, $options['listMarkup']);
|
||||
|
@@ -15,7 +15,8 @@
|
||||
* @property string $layout Layout type (blank=default, sidenav=multi-pane, sidenav-tree=left-tree, sidenav-tree-alt=right-tree)
|
||||
* @property int $logoAction Logo click action (0=admin root page list, 1=offcanvas nav)
|
||||
* @property string $userLabel Text containing user {vars} to use for user label in masthead (default="{Name}")
|
||||
* @property int $maxWidth Maimum layout width in pixels, or 0 for no max (default=1600).
|
||||
* @property int $maxWidth Maximum layout width in pixels, or 0 for no max (default=1600).
|
||||
* @property bool|int $groupNotices Whether or not notices should be grouped by type
|
||||
*
|
||||
*/
|
||||
class AdminThemeUikit extends AdminThemeFramework implements Module, ConfigurableModule {
|
||||
@@ -23,7 +24,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
|
||||
public static function getModuleInfo() {
|
||||
return array(
|
||||
'title' => 'Uikit',
|
||||
'version' => 20,
|
||||
'version' => 21,
|
||||
'summary' => 'Uikit v3 admin theme (beta)',
|
||||
'autoload' => 'template=admin',
|
||||
'requires' => 'ProcessWire>=3.0.61'
|
||||
@@ -73,6 +74,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
|
||||
$this->set('userLabel', '{Name}');
|
||||
$this->set('userAvatar', 'icon.user-circle');
|
||||
$this->set('maxWidth', 1600);
|
||||
$this->set('groupNotices', true);
|
||||
$this->addHookAfter('InputfieldSelector::ajaxReady', $this, 'hookInputfieldSelectorAjax');
|
||||
}
|
||||
|
||||
@@ -113,7 +115,9 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
|
||||
}
|
||||
|
||||
$session->removeFor('Page', 'appendEditUrl');
|
||||
$modules->get('JqueryUI')->use('panel');
|
||||
/** @var JqueryUI $jqueryUI */
|
||||
$jqueryUI = $modules->get('JqueryUI');
|
||||
$jqueryUI->use('panel');
|
||||
|
||||
// add rendering hooks
|
||||
$this->addHookBefore('Inputfield::render', $this, 'hookBeforeRenderInputfield');
|
||||
@@ -149,6 +153,22 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all notice types
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function testNotices() {
|
||||
if(parent::testNotices()) {
|
||||
$v = $this->wire('input')->get('test_notices');
|
||||
if($v === 'group-off') $this->groupNotices = false;
|
||||
if($v === 'group-on') $this->groupNotices = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*******************************************************************************************
|
||||
* HOOKS
|
||||
@@ -541,14 +561,15 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
|
||||
/**
|
||||
* Render runtime notices div#notices
|
||||
*
|
||||
* @param Notices|bool $notices
|
||||
* @param array $options See defaults in method
|
||||
* @param Notices $notices
|
||||
* @return string
|
||||
* @return string|array
|
||||
*
|
||||
*/
|
||||
public function renderNotices($notices, array $options = array()) {
|
||||
|
||||
$defaults = array(
|
||||
'groupByType' => $this->groupNotices ? true : false,
|
||||
'messageClass' => 'NoticeMessage uk-alert uk-alert-primary', // class for messages
|
||||
'messageIcon' => 'check-square', // default icon to show with notices
|
||||
'warningClass' => 'NoticeWarning uk-alert uk-alert-warning', // class for warnings
|
||||
@@ -557,7 +578,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
|
||||
'errorIcon' => 'exclamation-triangle', // icon for errors
|
||||
'debugClass' => 'NoticeDebug uk-alert', // class for debug items (appended)
|
||||
'debugIcon' => 'bug', // icon for debug notices
|
||||
'closeClass' => 'notice-remove', // class for close notices link <a>
|
||||
'closeClass' => 'pw-notice-remove notice-remove', // class for close notices link <a>
|
||||
'closeIcon' => 'times', // icon for close notices link
|
||||
'listMarkup' => "<ul class='pw-notices' id='notices'>{out}</ul><!--/notices-->",
|
||||
'itemMarkup' =>
|
||||
|
@@ -11,10 +11,12 @@ if(!defined("PROCESSWIRE")) die();
|
||||
*/
|
||||
function AdminThemeUikitConfig(AdminTheme $adminTheme, InputfieldWrapper $inputfields) {
|
||||
|
||||
$defaultNote = __('When blank, the default file used.') . ' ';
|
||||
$defaultDesc = __('Enter path relative to homepage URL.');
|
||||
$defaultFileNote = __('When blank, the default file used.') . ' ';
|
||||
$defaultFileDesc = __('Enter path relative to homepage URL.');
|
||||
$recommendedLabel = __('(RECOMMENDED)');
|
||||
$experimentalLabel = __('(EXPERIMENTAL)');
|
||||
$defaultLabel = __('(default)');
|
||||
$exampleLabel = __('example');
|
||||
|
||||
$modules = $adminTheme->wire('modules');
|
||||
$session = $adminTheme->wire('session');
|
||||
@@ -139,6 +141,18 @@ function AdminThemeUikitConfig(AdminTheme $adminTheme, InputfieldWrapper $inputf
|
||||
$f->attr('value', $adminTheme->maxWidth);
|
||||
$fieldset->add($f);
|
||||
|
||||
$testURL = $modules->wire('config')->urls->admin . 'profile/?test_notices';
|
||||
$f = $modules->get('InputfieldRadios');
|
||||
$f->attr('name', 'groupNotices');
|
||||
$f->label = __('Notifications style');
|
||||
$f->notes = __('Does not apply if the SystemNotifications module is installed.');
|
||||
$f->addOption(1, __('Group by type with expand/collapse control') . " ([$exampleLabel]($testURL=group-on))");
|
||||
$f->addOption(0, __('Always show all') . " ([$exampleLabel]($testURL=group-off))");
|
||||
$f->attr('value', (int) $adminTheme->groupNotices);
|
||||
$fieldset->appendMarkup .= "<script>$('#wrap_Inputfield_groupNotices .InputfieldContent').find('a').addClass('pw-modal');</script>";
|
||||
$modules->get('JqueryUI')->use('modal');
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldFieldset $fieldset */
|
||||
$fieldset = $modules->get('InputfieldFieldset');
|
||||
$fieldset->label = __('Custom files');
|
||||
@@ -151,9 +165,9 @@ function AdminThemeUikitConfig(AdminTheme $adminTheme, InputfieldWrapper $inputf
|
||||
$f->attr('name', 'cssURL');
|
||||
$f->attr('value', $adminTheme->get('cssURL'));
|
||||
$f->label = __('Primary CSS file');
|
||||
$f->description = $defaultDesc . ' ' .
|
||||
$f->description = $defaultFileDesc . ' ' .
|
||||
__('We do not recommend changing this unless you are an admin theme developer.');
|
||||
$f->notes = $defaultNote . "\nsite/modules/AdminThemeUikit/uikit/dist/css/uikit.pw.css";
|
||||
$f->notes = $defaultFileNote . "\nsite/modules/AdminThemeUikit/uikit/dist/css/uikit.pw.css";
|
||||
$f->collapsed = Inputfield::collapsedBlank;
|
||||
$f->icon = 'file-code-o';
|
||||
$fieldset->add($f);
|
||||
@@ -163,8 +177,8 @@ function AdminThemeUikitConfig(AdminTheme $adminTheme, InputfieldWrapper $inputf
|
||||
$f->attr('name', 'logoURL');
|
||||
$f->attr('value', $adminTheme->get('logoURL'));
|
||||
$f->label = __('Logo image file');
|
||||
$f->description = $defaultDesc;
|
||||
$f->notes = $defaultNote .
|
||||
$f->description = $defaultFileDesc;
|
||||
$f->notes = $defaultFileNote .
|
||||
__('File should be PNG, GIF, JPG or SVG, on transparent background, and at least 100px in both dimensions.');
|
||||
$f->collapsed = Inputfield::collapsedBlank;
|
||||
$f->icon = 'file-image-o';
|
||||
|
@@ -15454,9 +15454,11 @@ a.InputfieldButtonLink:hover {
|
||||
padding-left: 0;
|
||||
margin: 3px 0;
|
||||
}
|
||||
.pw-notices .pw-notice-remove,
|
||||
.pw-notices .notice-remove {
|
||||
float: right;
|
||||
color: #354b60;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.pw-notices .uk-alert-primary .notice-remove {
|
||||
color: #3eb998;
|
||||
@@ -15467,6 +15469,17 @@ a.InputfieldButtonLink:hover {
|
||||
.pw-notices .uk-alert-danger .notice-remove {
|
||||
color: #bc283d;
|
||||
}
|
||||
.pw-notices .uk-alert-danger a {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
.pw-notices .pw-notice-group-toggle {
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
.pw-notices .pw-notice-group-toggle:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.pw-layout-sidenav-tree .pw-notices,
|
||||
.pw-layout-sidenav-tree-alt .pw-notices {
|
||||
margin-top: 0;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -8,6 +8,7 @@
|
||||
*
|
||||
*
|
||||
* @property array $profileFields Names of fields user is allowed to edit in their profile
|
||||
* @method bool|string isDisallowedUserName($value)
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -208,10 +209,6 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
|
||||
$user = $this->user;
|
||||
$languages = $this->wire('languages');
|
||||
$id = (int) $this->input->post('id');
|
||||
|
||||
if($id !== $user->id) throw new WireException('Invalid POST data');
|
||||
|
||||
$form->processInput($this->input->post);
|
||||
|
||||
if(count($form->getErrors())) {
|
||||
@@ -321,6 +318,8 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
if(!$language->isDefault()) $user->set("name$language->id", $userName);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -15,7 +15,26 @@ var ProcessWireAdmin = {
|
||||
this.setupButtonStates();
|
||||
this.setupTooltips();
|
||||
this.setupDropdowns();
|
||||
this.setupNotices();
|
||||
},
|
||||
|
||||
setupNotices: function() {
|
||||
$(".pw-notice-group-toggle").click(function() {
|
||||
var $parent = $(this).closest('.pw-notice-group-parent');
|
||||
var $children = $parent.nextUntil('.pw-notice-group-parent');
|
||||
if($parent.hasClass('pw-notice-group-open')) {
|
||||
$parent.removeClass('pw-notice-group-open');
|
||||
$children.slideUp('fast');
|
||||
} else {
|
||||
$parent.addClass('pw-notice-group-open');
|
||||
$children.slideDown('fast');
|
||||
}
|
||||
$parent.find('i[data-toggle]').each(function() {
|
||||
$(this).toggleClass($(this).attr('data-toggle'));
|
||||
});
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable jQuery UI tooltips
|
||||
|
2
wire/templates-admin/scripts/main.min.js
vendored
2
wire/templates-admin/scripts/main.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -29,4 +29,5 @@
|
||||
user-select: none;
|
||||
/* prevent selection of this element */ }
|
||||
|
||||
/*# sourceMappingURL=AdminTheme.css.map */
|
||||
.pw-notices .pw-notice-group-child {
|
||||
display: none; }
|
||||
|
@@ -67,4 +67,9 @@
|
||||
.pw-description {}
|
||||
|
||||
// Small muted text
|
||||
.pw-detail {}
|
||||
.pw-detail {}
|
||||
|
||||
.pw-notices .pw-notice-group-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user