mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-09 23:48:30 +01:00
using bootstrap icons as stock icons for categories (former api/images) and allow to search arbitrary bootstrap icons when adding/editing categories
also fixed error editing categories in the root ('0' is not allowed validation message)
This commit is contained in:
parent
1f7325b648
commit
51e7269d88
@ -128,7 +128,10 @@ class admin_categories
|
|||||||
$readonlys['__ALL__'] = true;
|
$readonlys['__ALL__'] = true;
|
||||||
$readonlys['button[cancel]'] = false;
|
$readonlys['button[cancel]'] = false;
|
||||||
}
|
}
|
||||||
$content['base_url'] = self::icon_url();
|
if (!empty($content['data']['icon']))
|
||||||
|
{
|
||||||
|
$content['data']['icon'] = preg_replace('/\.(png|svg|jpe?g|gif)$/i', '', $content['data']['icon']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elseif ($content['button'] || $content['delete'])
|
elseif ($content['button'] || $content['delete'])
|
||||||
{
|
{
|
||||||
@ -258,12 +261,9 @@ class admin_categories
|
|||||||
}
|
}
|
||||||
$content['msg'] = $msg;
|
$content['msg'] = $msg;
|
||||||
if(!$content['appname']) $content['appname'] = $appname;
|
if(!$content['appname']) $content['appname'] = $appname;
|
||||||
if($content['data']['icon'])
|
if (!$content['parent']) $content['parent'] = '';
|
||||||
{
|
|
||||||
$content['icon_url'] = Api\Image::find('vfs',$content['data']['icon']) ?: self::icon_url($content['data']['icon']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$sel_options['icon'] = self::get_icons();
|
$sel_options['icon'] = self::get_icons($content['data']['icon']);
|
||||||
$sel_options['owner'] = array();
|
$sel_options['owner'] = array();
|
||||||
|
|
||||||
// User's category - add current value to be able to preserve owner
|
// User's category - add current value to be able to preserve owner
|
||||||
@ -333,51 +333,61 @@ class admin_categories
|
|||||||
),2);
|
),2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return URL of an icon, or base url with trailing slash
|
|
||||||
*
|
|
||||||
* @param string $icon = '' filename
|
|
||||||
* @return string url
|
|
||||||
*/
|
|
||||||
static function icon_url($icon='')
|
|
||||||
{
|
|
||||||
return $GLOBALS['egw_info']['server']['webserver_url'].self::ICON_PATH.'/'.$icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return icons from /api/images
|
* Return icons from /api/images
|
||||||
*
|
*
|
||||||
* @return array filename => label
|
* @return array filename => label
|
||||||
*/
|
*/
|
||||||
static function get_icons()
|
static function get_icons(string $_icon=null)
|
||||||
{
|
{
|
||||||
$icons = array();
|
$stock_icon = false;
|
||||||
if (file_exists($image_dir=EGW_SERVER_ROOT.self::ICON_PATH) && ($dir = dir($image_dir)))
|
$icons = [];
|
||||||
|
foreach(Api\Image::map() as $app => $images)
|
||||||
{
|
{
|
||||||
$matches = null;
|
if (!in_array($app, ['global', 'vfs'])) continue;
|
||||||
while(($file = $dir->read()))
|
|
||||||
|
foreach($images as $image => $icon)
|
||||||
{
|
{
|
||||||
if (preg_match('/^(.*)\\.(png|gif|jpe?g)$/i',$file,$matches))
|
if ($app === 'vfs' || str_starts_with($image, 'images/'))
|
||||||
{
|
{
|
||||||
$icons[$file] = ucfirst($matches[1]);
|
if ($app !== 'vfs') $image = substr($image, 7);
|
||||||
|
$icons[] = ['value' => $image, 'label' => ucfirst($image), 'icon' => $icon];
|
||||||
|
if ($_icon === $image) $stock_icon = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$dir->close();
|
|
||||||
}
|
}
|
||||||
|
// add arbitrary icons
|
||||||
// Get custom icons
|
if ($_icon && !$stock_icon && ($icon = Api\Image::find('vfs', $_icon)))
|
||||||
$map = Api\Image::map();
|
|
||||||
if(array_key_exists('vfs', $map))
|
|
||||||
{
|
{
|
||||||
foreach($map['vfs'] as $name => $path)
|
$icons[] = ['value' => $_icon, 'label' => ucfirst($_icon), 'icon' => $icon];
|
||||||
{
|
|
||||||
$icons[$name] = $name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
asort($icons);
|
uasort($icons, static function ($a, $b) {
|
||||||
|
return strnatcasecmp($a['label'], $b['label']);
|
||||||
|
});
|
||||||
return $icons;
|
return $icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search bootstrap icons
|
||||||
|
*
|
||||||
|
* @param string $pattern
|
||||||
|
* @throws Api\Json\Exception
|
||||||
|
*/
|
||||||
|
public function ajax_search(string $pattern)
|
||||||
|
{
|
||||||
|
$pattern = strtolower($pattern);
|
||||||
|
$icons = [];
|
||||||
|
foreach(Api\Image::map()['bootstrap'] ?? [] as $image => $icon)
|
||||||
|
{
|
||||||
|
if (strpos($image, $pattern) !== false)
|
||||||
|
{
|
||||||
|
$icons[] = ['value' => $image, 'label' => $image, 'icon' => $icon];
|
||||||
|
}
|
||||||
|
if (count($icons) > 100) break;
|
||||||
|
}
|
||||||
|
Api\Json\Response::get()->data($icons);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* query rows for the nextmatch widget
|
* query rows for the nextmatch widget
|
||||||
*
|
*
|
||||||
@ -430,7 +440,12 @@ class admin_categories
|
|||||||
$row['level_spacer'] = str_repeat(' ',$row['level']);
|
$row['level_spacer'] = str_repeat(' ',$row['level']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($row['data']['icon']) $row['icon_url'] = Api\Image::find('vfs',$row['data']['icon']) ?: self::icon_url($row['data']['icon']);
|
if (!empty($row['data']['icon']))
|
||||||
|
{
|
||||||
|
$row['data']['icon'] = preg_replace('/\.(png|svg|jpe?g|gif)$/i', '', $row['data']['icon']);
|
||||||
|
$row['icon_url'] = Api\Image::find('', 'images/'.$row['data']['icon']) ?:
|
||||||
|
Api\Image::find('vfs', $row['data']['icon']);
|
||||||
|
}
|
||||||
|
|
||||||
$row['subs'] = $row['children'] ? count($row['children']) : 0;
|
$row['subs'] = $row['children'] ? count($row['children']) : 0;
|
||||||
|
|
||||||
|
@ -26,10 +26,7 @@
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<et2-description value="Icon" for="data[icon]"></et2-description>
|
<et2-description value="Icon" for="data[icon]"></et2-description>
|
||||||
<et2-hbox cellpadding="0" cellspacing="0" >
|
<et2-select id="data[icon]" emptyLabel="None" search="true" searchUrl="preferences.preferences_categories_ui.ajax_search"></et2-select>
|
||||||
<et2-select id="data[icon]" onchange="app.admin.change_icon(widget);" emptyLabel="None"></et2-select>
|
|
||||||
<et2-image src="icon_url" id="icon_url" class="leftPad5"></et2-image>
|
|
||||||
</et2-hbox>
|
|
||||||
</row>
|
</row>
|
||||||
<row disabled="@appname=phpgw">
|
<row disabled="@appname=phpgw">
|
||||||
<et2-description value="Application"></et2-description>
|
<et2-description value="Application"></et2-description>
|
||||||
|
@ -50,7 +50,9 @@ foreach($categories as $cat)
|
|||||||
}
|
}
|
||||||
if (!empty($cat['data']['icon']))
|
if (!empty($cat['data']['icon']))
|
||||||
{
|
{
|
||||||
$content .= ".cat_{$cat['id']} .cat_icon { background-image: url('". admin_categories::icon_url($cat['data']['icon']) ."');} /*{$cat['name']}*/\n";
|
$icon = preg_replace('/\.(png|svg|jpe?g|gif)$/i', '', $cat['data']['icon']);
|
||||||
|
$content .= ".cat_{$cat['id']} .cat_icon { background-image: url('". (
|
||||||
|
Api\Image::find('', 'images/'.$icon) ?: Api\Image::find('vfs', $icon)) ."');} /*{$cat['name']}*/\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,4 +80,4 @@ if (in_array('gzip', explode(',',$_SERVER['HTTP_ACCEPT_ENCODING'])) && function_
|
|||||||
|
|
||||||
// Content-Lenght header is important, otherwise browsers dont cache!
|
// Content-Lenght header is important, otherwise browsers dont cache!
|
||||||
Header('Content-Length: '.bytes($content));
|
Header('Content-Length: '.bytes($content));
|
||||||
echo $content;
|
echo $content;
|
@ -549,7 +549,7 @@ export class Et2TreeDropdown extends SearchMixin<Constructor<any> & Et2InputWidg
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
?disabled=${this.disabled}
|
?disabled=${this.disabled}
|
||||||
?readonly=${this.readonly}
|
?readonly=${this.readonly}
|
||||||
placeholder="${this.hasFocus || this.value.length > 0 || this.disabled || this.readonly ? "" : this.placeholder || this.emptyLabel}"
|
placeholder="${this.hasFocus || this.value.length > 0 || this.disabled || this.readonly ? "" : this.egw().lang(this.placeholder || this.emptyLabel)}"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@keydown=${this.handleSearchKeyDown}
|
@keydown=${this.handleSearchKeyDown}
|
||||||
@blur=${() => {this.hasFocus = false;}}
|
@blur=${() => {this.hasFocus = false;}}
|
||||||
|
@ -150,7 +150,8 @@ class Select extends Etemplate\Widget
|
|||||||
$widget_type = substr($widget_type, 4);
|
$widget_type = substr($widget_type, 4);
|
||||||
}
|
}
|
||||||
$multiple = $this->attrs['multiple'] || $this->getElementAttribute($form_name, 'multiple') || $this->getElementAttribute($form_name, 'rows') > 1;
|
$multiple = $this->attrs['multiple'] || $this->getElementAttribute($form_name, 'multiple') || $this->getElementAttribute($form_name, 'rows') > 1;
|
||||||
$allowFreeEntries = $this->attrs['allowFreeEntries'] || $this->getElementAttribute($form_name, 'allowFreeEntries');
|
$allowFreeEntries = $this->attrs['allowFreeEntries'] || $this->getElementAttribute($form_name, 'allowFreeEntries') ||
|
||||||
|
$this->attrs['searchUrl'] || $this->getElementAttribute($form_name, 'searchUrl');
|
||||||
|
|
||||||
$ok = true;
|
$ok = true;
|
||||||
if (!$this->is_readonly($cname, $form_name))
|
if (!$this->is_readonly($cname, $form_name))
|
||||||
@ -771,7 +772,8 @@ class Select extends Etemplate\Widget
|
|||||||
}))),
|
}))),
|
||||||
//add different class per level to allow different styling for each category level:
|
//add different class per level to allow different styling for each category level:
|
||||||
'class' => "cat_level" . $cat['level'] . " cat_{$cat['id']}",
|
'class' => "cat_level" . $cat['level'] . " cat_{$cat['id']}",
|
||||||
'icon' => !empty($cat['data']['icon']) ? \admin_categories::icon_url($cat['data']['icon']) : null,
|
'icon' => empty($cat['data']['icon']) ? null :
|
||||||
|
(Api\Image::find('', 'images/'.$cat['data']['icon']) ?: Api\Image::find('vfs', $cat['data']['icon'])),
|
||||||
// send cat-date too
|
// send cat-date too
|
||||||
]+(is_array($cat['data']) ? $cat['data'] : []));
|
]+(is_array($cat['data']) ? $cat['data'] : []));
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user