0;
var circle = new Chartist.Svg('circle', {
cx: [data.x],
cy: [data.y],
r: data.value.y > 0 ? [5] : [0],
"ct:value": data.value.y,
"data-clickable": clickable
}, 'ct-circle');
var circle = data.element.replace(circle);
if (clickable) {
circle.getNode().onclick = function() {
if (!Dashboard.edit_mode) {
window.location = url;
}
}
}
}
});
// hide other lines when hovering a point
chart.on('created', function(bar) {
$('#chart-{$p['rand']} .ct-series .ct-circle, #chart-{$p['rand']} .ct-series .ct-circle + .ct-label')
.mouseover(function() {
$(this)
.attr('r', "9")
.parent(".ct-series")
.siblings().children()
.css('stroke-opacity', "0.05")
.filter(".ct-circle, .ct-label").css('fill-opacity', "0.1");
})
.mouseout(function() {
$(this)
.attr('r', "5")
.parent(".ct-series")
.siblings().children()
.css('stroke-opacity', "1")
.filter(".ct-circle, .ct-label").css('fill-opacity', "1");
});
});
});
JAVASCRIPT;
$js = Html::scriptBlock($js);
return $html.$js;
}
/**
* Display an editable markdown widget
*
* @param array $params with these keys:
* - string 'color': hex color
* - string 'markdown_content': text content formatted with warkdown
*
* @return string html
*/
public static function markdown(array $params = []): string {
$default = [
'color' => '',
'markdown_content' => '',
];
$p = array_merge($default, $params);
// fix auto-escaping
if (isset($p['markdown_content'])) {
$p['markdown_content'] = \Html::cleanPostForTextArea($p['markdown_content']);
}
$ph = __("Type markdown text here");
$fg_color = Toolbox::getFgColor($p['color']);
$border_color = Toolbox::getFgColor($p['color'], 10);
$md = new MarkdownExtra();
// Prevent escaping as code is already escaped by GLPI sanityze
$md->code_span_content_func = function ($code) { return $code; };
$md->code_block_content_func = function ($code) { return $code; };
$html = <<
{$md->transform($p['markdown_content'])}
HTML;
return $html;
}
/**
* Display an html table from a \Search result
*
* @param array $params contains these keys:
* - string 'itemtype': Glpi oObject to search
* - array 's_criteria': parameters to pass to the search engine (@see \Search::manageParams)
* - string 'label': global title of the widget
* - string 'url': link to the full search result
* - string 'alt': tooltip
* - string 'color': hex color of the widget
* - string 'icon': font awesome class to display an icon side of the label
* - string 'id': unique dom identifier
* - int 'limit': the number of displayed lines
* - array 'filters': array of filter's id to apply classes on widget html
*
* @return string html of the widget
*/
public static function searchShowList(array $params = []): string {
$default = [
'url' => '',
'label' => '',
'alt' => '',
'color' => '',
'icon' => '',
's_criteria' => '',
'itemtype' => '',
'limit' => $_SESSION['glpilist_limit'],
'rand' => mt_rand(),
'filters' => [],
];
$p = array_merge($default, $params);
$id = "search-table-".$p['rand'];
$color = new Color($p['color']);
$is_light = $color->isLight();
$fg_color = Toolbox::getFgColor($p['color'], $is_light ? 65 : 40);
$fg_color2 = Toolbox::getFgColor($p['color'], 5);
$href = strlen($p['url'])
? "href='{$p['url']}'"
: "";
$class = count($p['filters']) > 0 ? " filter-".implode(' filter-', $p['filters']) : "";
// prepare search data
$_GET['_in_modal'] = true;
$params = [
'criteria' => $p['s_criteria'],
'reset' => 'reset',
];
ob_start();
$params = Search::manageParams($p['itemtype'], $params);
// remove parts of search list
$params = array_merge($params, [
'showmassiveactions' => false,
'dont_flush' => true,
'show_pager' => false,
'show_footer' => false,
'no_sort' => true,
'list_limit' => $p['limit']
]);
Search::showList($p['itemtype'], $params);
$search_result = ob_get_clean();
$html = <<
#{$id} .tab_cadrehov th {
background: {$fg_color2};
}
HTML;
return $html;
}
public static function articleList(array $params): string {
$default = [
'data' => [],
'label' => '',
'alt' => '',
'url' => '',
'color' => '',
'icon' => '',
'limit' => 99999,
'class' => "articles-list",
'rand' => mt_rand(),
'filters' => [],
];
$p = array_merge($default, $params);
$default_entry = [
'url' => '',
'icon' => '',
'label' => '',
'number' => '',
];
$nb_lines = min($p['limit'], count($p['data']));
array_splice($p['data'], $nb_lines);
$fg_color = Toolbox::getFgColor($p['color']);
$bg_color_2 = Toolbox::getFgColor($p['color'], 5);
$class = $p['class'];
$class.= count($p['filters']) > 0 ? " filter-".implode(' filter-', $p['filters']) : "";
$i = 0;
$list_html = "";
foreach ($p['data'] as $entry) {
if (!is_array($entry)) {
continue;
}
$entry = array_merge($default_entry, $entry);
$href = strlen($entry['url'])
? "href='{$entry['url']}'"
: "";
$author = strlen($entry['author'])
? " {$entry['author']}"
: "";
$content_size = strlen($entry['content']);
$content = strlen($entry['content'])
? Toolbox::getHtmlToDisplay($entry['content']).
($content_size > 300
? "...
"
: ""
)
: "";
$list_html.= <<
{$entry['label']}
{$content}
$author
{$entry['date']}
HTML;
$i++;
}
$nodata = isset($p['data']['nodata']) && $p['data']['nodata'];
if ($nodata) {
$list_html = "
".__('No data found')."
";
}
$view_all = strlen($p['url'])
? ""
: "";
$html = <<
#chart-{$p['rand']} .line {
background-color: $bg_color_2;
}
#chart-{$p['rand']} .fa-eye {
color: {$fg_color};
}
HTML;
$js = << [...]
* 'colors' => [...]
* ]
*/
public static function getGradientPalette(
string $bgcolor = "",
int $nb_series = 1,
bool $revert = true
) {
if ($nb_series == 0) {
return [
'names' => [],
'colors' => [],
];
}
if ($nb_series == 1) {
return [
'names' => ['a'],
'colors' => [Toolbox::getFgColor($bgcolor)],
];
}
$alphabet = range('a', 'z');
$min_l = 20; // min for luminosity
$max_l = 20; // max ...
$min_s = 30; // min for saturation
$max_s = 50; // max ...
$step_l = (100 - ($min_l + $max_l)) / ($nb_series * 100);
$step_s = (100 - ($min_s + $max_s)) / ($nb_series * 100);
$color_instance = new Color($bgcolor);
$hsl = $color_instance->getHsl();
$names = [];
$colors = [];
for ($i = 1; $i <= $nb_series; $i++) {
$names[$i - 1] = $alphabet[$i - 1];
// adjust luminosity
$i_l_step = $i * $step_l + $min_l / 100;
$hsl['L'] = min(1, $revert
? 1 - $i_l_step
: $i_l_step);
// adjust saturation
if ($hsl['H'] != 0 && $hsl['H'] != 1) {
$i_s_step = $i * $step_s + $min_s / 100;
$hsl['S'] = min(1, $revert
? $i_s_step
: 1 - $i_s_step);
}
$colors[$i - 1] = "#".Color::hslToHex($hsl);
}
return [
'names' => $names,
'colors' => $colors,
];
}
/**
* Generate a css ruleset for chartist given a starting background color
* Based on @see self::getGradientPalette
*/
public static function getCssGradientPalette(
string $bgcolor = "",
int $nb_series = 1,
string $css_dom_parent = "",
bool $revert = true
) {
$palette = self::getGradientPalette($bgcolor, $nb_series, $revert);
$series_names = implode(',', $palette['names']);
$series_colors = implode(',', $palette['colors']);
$scss = new Compiler();
$scss->addImportPath(GLPI_ROOT);
$palette_css = $scss->compile("{$css_dom_parent} {
\$ct-series-names: ({$series_names});
\$ct-series-colors: ({$series_colors});
@import 'css/chartist/generate';
}");
return $palette_css;
}
}