mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 07:53:39 +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['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'])
|
||||
{
|
||||
@ -258,12 +261,9 @@ class admin_categories
|
||||
}
|
||||
$content['msg'] = $msg;
|
||||
if(!$content['appname']) $content['appname'] = $appname;
|
||||
if($content['data']['icon'])
|
||||
{
|
||||
$content['icon_url'] = Api\Image::find('vfs',$content['data']['icon']) ?: self::icon_url($content['data']['icon']);
|
||||
}
|
||||
if (!$content['parent']) $content['parent'] = '';
|
||||
|
||||
$sel_options['icon'] = self::get_icons();
|
||||
$sel_options['icon'] = self::get_icons($content['data']['icon']);
|
||||
$sel_options['owner'] = array();
|
||||
|
||||
// User's category - add current value to be able to preserve owner
|
||||
@ -333,49 +333,59 @@ class admin_categories
|
||||
),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 array filename => label
|
||||
*/
|
||||
static function get_icons()
|
||||
static function get_icons(string $_icon=null)
|
||||
{
|
||||
$icons = array();
|
||||
if (file_exists($image_dir=EGW_SERVER_ROOT.self::ICON_PATH) && ($dir = dir($image_dir)))
|
||||
$stock_icon = false;
|
||||
$icons = [];
|
||||
foreach(Api\Image::map() as $app => $images)
|
||||
{
|
||||
$matches = null;
|
||||
while(($file = $dir->read()))
|
||||
if (!in_array($app, ['global', 'vfs'])) continue;
|
||||
|
||||
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
|
||||
if ($_icon && !$stock_icon && ($icon = Api\Image::find('vfs', $_icon)))
|
||||
{
|
||||
$icons[] = ['value' => $_icon, 'label' => ucfirst($_icon), 'icon' => $icon];
|
||||
}
|
||||
uasort($icons, static function ($a, $b) {
|
||||
return strnatcasecmp($a['label'], $b['label']);
|
||||
});
|
||||
return $icons;
|
||||
}
|
||||
|
||||
// Get custom icons
|
||||
$map = Api\Image::map();
|
||||
if(array_key_exists('vfs', $map))
|
||||
/**
|
||||
* Search bootstrap icons
|
||||
*
|
||||
* @param string $pattern
|
||||
* @throws Api\Json\Exception
|
||||
*/
|
||||
public function ajax_search(string $pattern)
|
||||
{
|
||||
foreach($map['vfs'] as $name => $path)
|
||||
$pattern = strtolower($pattern);
|
||||
$icons = [];
|
||||
foreach(Api\Image::map()['bootstrap'] ?? [] as $image => $icon)
|
||||
{
|
||||
$icons[$name] = $name;
|
||||
if (strpos($image, $pattern) !== false)
|
||||
{
|
||||
$icons[] = ['value' => $image, 'label' => $image, 'icon' => $icon];
|
||||
}
|
||||
if (count($icons) > 100) break;
|
||||
}
|
||||
asort($icons);
|
||||
return $icons;
|
||||
Api\Json\Response::get()->data($icons);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -430,7 +440,12 @@ class admin_categories
|
||||
$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;
|
||||
|
||||
|
@ -26,10 +26,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<et2-description value="Icon" for="data[icon]"></et2-description>
|
||||
<et2-hbox cellpadding="0" cellspacing="0" >
|
||||
<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>
|
||||
<et2-select id="data[icon]" emptyLabel="None" search="true" searchUrl="preferences.preferences_categories_ui.ajax_search"></et2-select>
|
||||
</row>
|
||||
<row disabled="@appname=phpgw">
|
||||
<et2-description value="Application"></et2-description>
|
||||
|
@ -50,7 +50,9 @@ foreach($categories as $cat)
|
||||
}
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ export class Et2TreeDropdown extends SearchMixin<Constructor<any> & Et2InputWidg
|
||||
autocomplete="off"
|
||||
?disabled=${this.disabled}
|
||||
?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"
|
||||
@keydown=${this.handleSearchKeyDown}
|
||||
@blur=${() => {this.hasFocus = false;}}
|
||||
|
@ -150,7 +150,8 @@ class Select extends Etemplate\Widget
|
||||
$widget_type = substr($widget_type, 4);
|
||||
}
|
||||
$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;
|
||||
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:
|
||||
'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
|
||||
]+(is_array($cat['data']) ? $cat['data'] : []));
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user