mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-27 14:24:52 +00:00
95_Dashboard: support for devspecs in dashboard - storing and restore of currently selected tab - style adjustments
git-svn-id: https://svn.fhem.de/fhem/trunk@8990 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
ecd698850d
commit
08c21124b0
@ -1,5 +1,9 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- feature: 95_Dashboard: added new attribute dashboard_tabXdevices which
|
||||
supports devspec definitions for shown dashboard groups.
|
||||
Storage of current opened tab and restore when opening dashboard.
|
||||
Fixed some CSS issues (text alignment, colors ...)
|
||||
- change: SYSMON: warning (userdefined readings), reading for perl version
|
||||
- feature: 38_CO20.pm: added advanced features, retries and timeout (by Markus M.)
|
||||
- feature: 32_yowsup.pm: added support for groups
|
||||
|
@ -60,6 +60,7 @@
|
||||
# Optimized icon loading.
|
||||
# Optimized fullscreen view.
|
||||
# Minor improvements in javascript and css.
|
||||
# 3.10: added attribute dashboard_tabXdevices, which can contain devspec definitions and thus allow to also shown not grouped devices
|
||||
#
|
||||
# Known Bugs/Todos:
|
||||
# BUG: Nicht alle Inhalte aller Tabs laden, bei Plots dauert die bedienung des Dashboards zu lange. -> elemente hidden? -> widgets aus js über XHR nachladen und dann anzeigen (jquery xml nachladen...)
|
||||
@ -115,9 +116,7 @@ my %group;
|
||||
my $dashboard_groupListfhem;
|
||||
my $fwjquery = "jquery.min.js";
|
||||
my $fwjqueryui = "jquery-ui.min.js";
|
||||
my $dashboardversion = "3.00";
|
||||
my @fhemweb_instances = ();
|
||||
|
||||
my $dashboardversion = "3.10";
|
||||
|
||||
#############################################################################################
|
||||
sub Dashboard_Initialize ($) {
|
||||
@ -132,11 +131,9 @@ sub Dashboard_Initialize ($) {
|
||||
$hash->{AttrList} = "disable:0,1 ".
|
||||
"dashboard_colcount:1,2,3,4,5 ".
|
||||
"dashboard_debug:0,1 ".
|
||||
"dashboard_lockstate:dont-use-this-attribut ". #obolet since 04.2014
|
||||
"dashboard_rowtopheight ".
|
||||
"dashboard_rowbottomheight ".
|
||||
"dashboard_row:top,center,bottom,top-center,center-bottom,top-center-bottom ".
|
||||
"dashboard_showhelper:dont-use-this-attribut ". #obolet since 04.2014
|
||||
"dashboard_showtogglebuttons:0,1 ".
|
||||
#new attribute vers. 2.00
|
||||
"dashboard_activetab:1,2,3,4,5,6,7 ".
|
||||
@ -146,15 +143,16 @@ sub Dashboard_Initialize ($) {
|
||||
"dashboard_rowcentercolwidth ".
|
||||
"dashboard_showfullsize:0,1 ".
|
||||
#new attribute vers. 2.02
|
||||
#"dashboard_showtabs:tabs-and-buttonbar-at-the-top,tabs-at-the-top-buttonbar-hidden,tabs-and-buttonbar-on-the-bottom,tabs-on-the-bottom-buttonbar-hidden,tabs-and-buttonbar-hidden ".
|
||||
"dashboard_showtabs:tabs-and-buttonbar-at-the-top,tabs-and-buttonbar-on-the-bottom,tabs-and-buttonbar-hidden ".
|
||||
#new attribute vers. 2.03
|
||||
#new attribute vers. 2.06
|
||||
"dashboard_customcss " .
|
||||
#new attribute vers. 3.00
|
||||
"dashboard_flexible " .
|
||||
#tab-specific attributes
|
||||
"dashboard_tab1name " .
|
||||
"dashboard_tab1groups " .
|
||||
#new attribute vers. 3.10
|
||||
"dashboard_tab1devices " .
|
||||
"dashboard_tab1sorting " .
|
||||
"dashboard_tab1icon " .
|
||||
"dashboard_tab1colcount " .
|
||||
@ -163,6 +161,8 @@ sub Dashboard_Initialize ($) {
|
||||
# dynamic attributes
|
||||
"dashboard_tab[0-9]+name " .
|
||||
"dashboard_tab[0-9]+groups " .
|
||||
#new attribute vers. 3.10
|
||||
"dashboard_tab[0-9]+devices " .
|
||||
"dashboard_tab[0-9]+sorting " .
|
||||
"dashboard_tab[0-9]+icon " .
|
||||
"dashboard_tab[0-9]+colcount " .
|
||||
@ -239,7 +239,7 @@ sub Dashboard_Get($@) {
|
||||
my @iconFolders = split(":", AttrVal($FW_wname, "iconPath", "$FW_sp:default:fhemSVG:openautomation"));
|
||||
my $iconDirs = "";
|
||||
foreach my $idir (@iconFolders) {$iconDirs .= "$attr{global}{modpath}/www/images/".$idir.",";}
|
||||
$res .= " \"icondirs\": \"$iconDirs\", \"dashboard_tabcount\": " . GetTabCount($hash, 0);
|
||||
$res .= " \"icondirs\": \"$iconDirs\", \"dashboard_tabcount\": " . GetTabCount($hash, 0). ", \"dashboard_activetab\": " . GetActiveTab($hash->{NAME});
|
||||
|
||||
$res .= ($i != $x) ? ",\n" : "\n";
|
||||
foreach my $attr (sort keys %$attrdata) {
|
||||
@ -248,7 +248,10 @@ sub Dashboard_Get($@) {
|
||||
if (@splitattr == 2) {
|
||||
$res .= " \"".Dashboard_Escape($attr)."\": \"".$splitattr[0]."\",\n";
|
||||
$res .= " \"".Dashboard_Escape($attr)."color\": \"".$splitattr[1]."\"";
|
||||
} else { $res .= " \"".Dashboard_Escape($attr)."\": \"".$attrdata->{$attr}."\"";}
|
||||
} elsif ($attr ne "dashboard_activetab") { $res .= " \"".Dashboard_Escape($attr)."\": \"".$attrdata->{$attr}."\"";}
|
||||
else {
|
||||
next;
|
||||
}
|
||||
$res .= ($i != $x) ? ",\n" : "\n";
|
||||
}
|
||||
$res .= " }\n";
|
||||
@ -258,15 +261,15 @@ sub Dashboard_Get($@) {
|
||||
} elsif ($arg eq "groupWidget") {
|
||||
#### Comming Soon ######
|
||||
# For dynamic load of GroupWidgets from JavaScript
|
||||
my $dbgroup = "";
|
||||
#my $dbgroup = "";
|
||||
#for (my $p=2;$p<@a;$p++){$dbgroup .= @a[$p]." ";} #For Groupnames with Space
|
||||
for (my $p=2;$p<@a;$p++){$dbgroup .= $a[$p]." ";} #For Groupnames with Space
|
||||
#for (my $p=2;$p<@a;$p++){$dbgroup .= $a[$p]." ";} #For Groupnames with Space
|
||||
|
||||
$dashboard_groupListfhem = Dashboard_GetGroupList;
|
||||
%group = BuildGroupList($dashboard_groupListfhem);
|
||||
$res .= BuildGroupWidgets(1,1,1212,trim($dbgroup),"t1c1,".trim($dbgroup).",true,0,0:");
|
||||
return $res;
|
||||
#For dynamic loading of tabs
|
||||
#$dashboard_groupListfhem = Dashboard_GetGroupList;
|
||||
#%group = BuildGroupList($dashboard_groupListfhem);
|
||||
#$res .= BuildGroupWidgets(1,1,1212,trim($dbgroup),"t1c1,".trim($dbgroup).",true,0,0:");
|
||||
#return $res;
|
||||
#For dynamic loading of tabs
|
||||
} elsif ($arg eq "tab" && $arg2 =~ /^\d+$/) {
|
||||
return BuildDashboardTab($arg2, $hash->{NAME});
|
||||
} elsif ($arg eq "icon") {
|
||||
@ -277,7 +280,7 @@ sub Dashboard_Get($@) {
|
||||
|
||||
return FW_iconPath($icon);
|
||||
} else {
|
||||
return "Unknown argument $arg choose one of config:noArg groupWidget";
|
||||
return "Unknown argument $arg choose one of config:noArg groupWidget tab icon";
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,7 +296,6 @@ sub Dashboard_define ($$) {
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer ($now + 5, 'CheckDashboardAttributUssage', $hash, 0);
|
||||
my $dashboard_groupListfhem = Dashboard_GetGroupList;
|
||||
|
||||
my $url = '/dashboard/' . $name;
|
||||
|
||||
@ -320,8 +322,15 @@ sub Dashboard_attr($$$) {
|
||||
my ($cmd, $name, $attrName, $attrVal) = @_;
|
||||
|
||||
# add dynamic attributes
|
||||
if ($cmd eq "set" && $attrName =~ m/dashboard_tab([1-9][0-9]*)groups/) {
|
||||
if (
|
||||
$cmd eq "set" &&
|
||||
(
|
||||
$attrName =~ m/dashboard_tab([1-9][0-9]*)groups/
|
||||
|| $attrName =~ m/dashboard_tab([1-9][0-9]*)devices/
|
||||
)
|
||||
) {
|
||||
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "name");
|
||||
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "devices");
|
||||
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "groups");
|
||||
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "sorting");
|
||||
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "icon");
|
||||
@ -358,7 +367,7 @@ sub Dashboard_CGI($)
|
||||
|
||||
FW_pO $ret;
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub DashboardAsHtml($)
|
||||
@ -399,7 +408,7 @@ sub Dashboard_SummaryFN($$$$)
|
||||
my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center");
|
||||
my $debug = AttrVal($defs{$d}{NAME}, "dashboard_debug", "0");
|
||||
|
||||
my $activetab = AttrVal($defs{$d}{NAME}, "dashboard_activetab", 1);
|
||||
my $activetab = GetActiveTab($d);
|
||||
my $tabcount = GetTabCount($defs{$d}, 1);
|
||||
my $dbwidth = AttrVal($defs{$d}{NAME}, "dashboard_width", "100%");
|
||||
my @tabnames = ();
|
||||
@ -407,7 +416,7 @@ sub Dashboard_SummaryFN($$$$)
|
||||
|
||||
if ($showfullsize) {
|
||||
if ($FW_RET =~ m/<body[^>]*class="([^"]+)"[^>]*>/) {
|
||||
$FW_RET =~ s/style="$1"/style="$1 dashboard_fullsize"/;
|
||||
$FW_RET =~ s/class="$1"/class="$1 dashboard_fullsize"/;
|
||||
}
|
||||
else {
|
||||
$FW_RET =~ s/<body/<body class="dashboard_fullsize"/;
|
||||
@ -451,7 +460,6 @@ sub Dashboard_SummaryFN($$$$)
|
||||
if ($room ne "all") {
|
||||
|
||||
################################
|
||||
$dashboard_groupListfhem = Dashboard_GetGroupList;
|
||||
################################
|
||||
|
||||
$ret .= "<div id=\"tabEdit\" class=\"dashboard-dialog-content dashboard-widget-content\" title=\"Dashboard-Tab\" style=\"display:none;\">\n";
|
||||
@ -519,90 +527,89 @@ sub BuildDashboardTab($$)
|
||||
my $id = $defs{$d}{NR};
|
||||
my $colcount = AttrVal($defs{$d}{NAME}, 'dashboard_tab' . ($t + 1) . 'colcount', AttrVal($defs{$d}{NAME}, "dashboard_colcount", 1));
|
||||
my $colwidths = AttrVal($defs{$d}{NAME}, 'dashboard_tab' . ($t + 1) . 'rowcentercolwidth', AttrVal($defs{$d}{NAME}, "dashboard_rowcentercolwidth", 100));
|
||||
my $backgroundimage = AttrVal($defs{$d}{NAME}, 'dashboard_tab' . ($t + 1) . 'backgroundimage', "");
|
||||
$colwidths =~ tr/,/:/;
|
||||
my $backgroundimage = AttrVal($defs{$d}{NAME}, 'dashboard_tab' . ($t + 1) . 'backgroundimage', "");
|
||||
my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center");
|
||||
my $tabcount = GetTabCount($defs{$d}, 1);
|
||||
my @tabgroups = ();
|
||||
my @tabsortings = ();
|
||||
my $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($t + 1) . "groups", "");
|
||||
my $tabsortings = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($t + 1) . "sorting", "");
|
||||
my $tabdevicegroups = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($t + 1) . "devices", "");
|
||||
|
||||
for (my $i = 0; $i < $tabcount; $i++) {
|
||||
$tabgroups[$i] = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($i + 1) . "groups", "");
|
||||
$tabsortings[$i] = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($i + 1) . "sorting", "");
|
||||
}
|
||||
|
||||
unless (@tabgroups) {
|
||||
readingsSingleUpdate( $defs{$d}, "state", "No Groups set", 0 );
|
||||
unless ($tabgroups || $tabdevicegroups) {
|
||||
readingsSingleUpdate( $defs{$d}, "state", "No Groups or devices set", 0 );
|
||||
return "";
|
||||
}
|
||||
|
||||
my $groups = Dashboard_GetGroupList();
|
||||
my @temptabdevicegroup = split(' ', $tabdevicegroups);
|
||||
my @tabdevicegroups = ();
|
||||
|
||||
# make sure device groups without a group name are splitted into
|
||||
# separate groups for every device they are containing
|
||||
for my $devicegroup (@temptabdevicegroup) {
|
||||
my @groupparts = split(':', $devicegroup);
|
||||
|
||||
if (@groupparts == 1) {
|
||||
my @devices = map { $_ . ':' . $_ } devspec2array($groupparts[0]);
|
||||
push(@tabdevicegroups, @devices);
|
||||
}
|
||||
else {
|
||||
push(@tabdevicegroups, $devicegroup);
|
||||
}
|
||||
}
|
||||
|
||||
my $groups = Dashboard_GetGroupList();
|
||||
$groups =~ s/#/ /g;
|
||||
my @groups = split(',', $groups);
|
||||
|
||||
my @temptabgroup = split(",", $tabgroups[$t]); #Set temp. position for groups without an stored position
|
||||
my @tabgroup = ();
|
||||
my @index = ();
|
||||
|
||||
my @groups = split(',', $groups);
|
||||
my @temptabgroup = split(",", $tabgroups);
|
||||
|
||||
# resolve group names from regular expressions
|
||||
for (my $i=0;$i<@temptabgroup;$i++) {
|
||||
my @stabgroup = split(":", trim($temptabgroup[$i]));
|
||||
@index = grep { $groups[$_] eq $stabgroup[0] } (0 .. @groups-1);
|
||||
my @index = grep { $groups[$_] eq $stabgroup[0] } (0 .. @groups-1);
|
||||
|
||||
if (@index == 0) {
|
||||
my $matchGroup = '^' . $stabgroup[0] . '$';
|
||||
@index = grep { $groups[$_] =~ m/$matchGroup/ } (0 .. @groups-1);
|
||||
}
|
||||
|
||||
if (@index > 0) {
|
||||
for (my $j=0; $j<@index;$j++) {
|
||||
my $groupname = @groups[$index[$j]];
|
||||
$groupname .= ':' . 'group=' . $groupname;
|
||||
if (@stabgroup > 1) {
|
||||
$groupname .= ':' . $stabgroup[1];
|
||||
}
|
||||
push(@tabgroup,$groupname);
|
||||
push(@tabdevicegroups,$groupname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
my $matchGroup = '^' . $stabgroup[0] . '$';
|
||||
@index = grep { $groups[$_] =~ m/$matchGroup/ } (0 .. @groups-1);
|
||||
|
||||
if (@index > 0) {
|
||||
for (my $j=0; $j<@index;$j++) {
|
||||
my $groupname = @groups[$index[$j]];
|
||||
if (@stabgroup > 1) {
|
||||
$groupname .= ':' . $stabgroup[1];
|
||||
}
|
||||
push(@tabgroup,$groupname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$tabgroups = join('§§§', @tabdevicegroups);
|
||||
|
||||
$tabgroups[$t] = join(',', @tabgroup);
|
||||
|
||||
for (my $i=0;$i<@tabgroup;$i++) {
|
||||
my @stabgroup = split(":", trim($tabgroup[$i]));
|
||||
# add sortings for groups not already having a defined sorting
|
||||
for (my $i=0;$i<@tabdevicegroups;$i++) {
|
||||
my @stabgroup = split(":", trim($tabdevicegroups[$i]));
|
||||
my $matchGroup = "," . quotemeta(trim($stabgroup[0])) . ",";
|
||||
|
||||
if ($tabsortings[$t] !~ m/$matchGroup/) {
|
||||
$tabsortings[$t] = $tabsortings[$t]."t".$t."c".GetMaxColumnId($row,$colcount).",".trim($stabgroup[0]).",true,0,0:";
|
||||
if ($tabsortings !~ m/$matchGroup/) {
|
||||
$tabsortings = $tabsortings."t".$t."c".GetMaxColumnId($row,$colcount).",".trim($stabgroup[0]).",true,0,0:";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%group = BuildGroupList($tabgroups[$t]);
|
||||
|
||||
my $ret = " <div id=\"dashboard_tab".$t."\" data-tabwidgets=\"".$tabsortings[$t]."\" data-tabcolwidths=\"".$colwidths."\" class=\"dashboard dashboard_tabpanel\" style=\"background: " . ($backgroundimage ? "url(/fhem/images/" . FW_iconPath($backgroundimage) . ")" : "none") . " no-repeat !important;\">\n";
|
||||
my $ret = " <div id=\"dashboard_tab".$t."\" data-tabwidgets=\"".$tabsortings."\" data-tabcolwidths=\"".$colwidths."\" class=\"dashboard dashboard_tabpanel\" style=\"background: " . ($backgroundimage ? "url(/fhem/images/" . FW_iconPath($backgroundimage) . ")" : "none") . " no-repeat !important;\">\n";
|
||||
$ret .= " <ul class=\"dashboard_tabcontent\">\n";
|
||||
$ret .= " <table class=\"dashboard_tabcontent\">\n";
|
||||
##################### Top Row (only one Column) #############################################
|
||||
if ($row eq "top-center-bottom" || $row eq "top-center" || $row eq "top"){
|
||||
$ret .= BuildDashboardTopRow($t,$id,$tabgroups[$t],$tabsortings[$t]);
|
||||
$ret .= BuildDashboardTopRow($t,$id,$tabgroups,$tabsortings);
|
||||
}
|
||||
##################### Center Row (max. 5 Column) ############################################
|
||||
if ($row eq "top-center-bottom" || $row eq "top-center" || $row eq "center-bottom" || $row eq "center") {
|
||||
$ret .= BuildDashboardCenterRow($t,$id,$tabgroups[$t],$tabsortings[$t],$colcount);
|
||||
$ret .= BuildDashboardCenterRow($t,$id,$tabgroups,$tabsortings,$colcount);
|
||||
}
|
||||
############################# Bottom Row (only one Column) ############################################
|
||||
if ($row eq "top-center-bottom" || $row eq "center-bottom" || $row eq "bottom"){
|
||||
$ret .= BuildDashboardBottomRow($t,$id,$tabgroups[$t],$tabsortings[$t]);
|
||||
$ret .= BuildDashboardBottomRow($t,$id,$tabgroups,$tabsortings);
|
||||
}
|
||||
#############################################################################################
|
||||
$ret .= " </table>\n";
|
||||
@ -613,12 +620,12 @@ sub BuildDashboardTab($$)
|
||||
}
|
||||
|
||||
sub BuildDashboardTopRow($$$$){
|
||||
my ($t,$id, $dbgroups, $dbsorting) = @_;
|
||||
my ($t,$id, $devicegroups, $groupsorting) = @_;
|
||||
my $ret;
|
||||
$ret .= "<tr><td class=\"dashboard_row\">\n";
|
||||
$ret .= "<div id=\"dashboard_rowtop_tab".$t."\" class=\"dashboard dashboard_rowtop\">\n";
|
||||
$ret .= " <div class=\"dashboard ui-row dashboard_row dashboard_column\" id=\"dashboard_tab".$t."column100\">\n";
|
||||
$ret .= BuildGroupWidgets($t,"100",$id,$dbgroups,$dbsorting);
|
||||
$ret .= BuildGroupWidgets($t,"100",$id,$devicegroups,$groupsorting);
|
||||
$ret .= " </div>\n";
|
||||
$ret .= "</div>\n";
|
||||
$ret .= "</td></tr>\n";
|
||||
@ -626,9 +633,9 @@ sub BuildDashboardTopRow($$$$){
|
||||
}
|
||||
|
||||
sub BuildDashboardCenterRow($$$$$){
|
||||
my ($t,$id, $dbgroups, $dbsorting, $colcount) = @_;
|
||||
my $ret;
|
||||
$ret .= "<tr><td class=\"dashboard_row\">\n";
|
||||
my ($t,$id, $devicegroups, $groupsorting, $colcount) = @_;
|
||||
|
||||
my $ret = "<tr><td class=\"dashboard_row\">\n";
|
||||
$ret .= "<div id=\"dashboard_rowcenter_tab".$t."\" class=\"dashboard dashboard_rowcenter\">\n";
|
||||
|
||||
my $currentcol = $colcount;
|
||||
@ -636,16 +643,16 @@ sub BuildDashboardCenterRow($$$$$){
|
||||
my $replace = "t" . $t . "c" . $maxcolindex . ",";
|
||||
|
||||
# replace all sortings referencing not existing columns
|
||||
# this does only work if there is not empty column inbetween
|
||||
while (index($dbsorting, "t".$t."c".$currentcol.",") >= 0) {
|
||||
# this does only work if there is no empty column inbetween
|
||||
while (index($groupsorting, "t".$t."c".$currentcol.",") >= 0) {
|
||||
my $search = "t" . $t . "c" . $currentcol . ",";
|
||||
$dbsorting =~ s/$search/$replace/g;
|
||||
$groupsorting =~ s/$search/$replace/g;
|
||||
$currentcol++;
|
||||
}
|
||||
|
||||
for (my $i=0;$i<$colcount;$i++){
|
||||
$ret .= " <div class=\"dashboard ui-row dashboard_row dashboard_column\" id=\"dashboard_tab".$t."column".$i."\">\n";
|
||||
$ret .= BuildGroupWidgets($t,$i,$id,$dbgroups,$dbsorting);
|
||||
$ret .= BuildGroupWidgets($t,$i,$id,$devicegroups,$groupsorting);
|
||||
$ret .= " </div>\n";
|
||||
}
|
||||
$ret .= "</div>\n";
|
||||
@ -654,12 +661,12 @@ sub BuildDashboardCenterRow($$$$$){
|
||||
}
|
||||
|
||||
sub BuildDashboardBottomRow($$$$){
|
||||
my ($t,$id, $dbgroups, $dbsorting) = @_;
|
||||
my ($t,$id, $devicegroups, $groupsorting) = @_;
|
||||
my $ret;
|
||||
$ret .= "<tr><td class=\"dashboard_row\">\n";
|
||||
$ret .= "<div id=\"dashboard_rowbottom_tab".$t."\" class=\"dashboard dashboard_rowbottom\">\n";
|
||||
$ret .= " <div class=\"dashboard ui-row dashboard_row dashboard_column\" id=\"dashboard_tab".$t."column200\">\n";
|
||||
$ret .= BuildGroupWidgets($t,"200",$id,$dbgroups,$dbsorting);
|
||||
$ret .= BuildGroupWidgets($t,"200",$id,$devicegroups,$groupsorting);
|
||||
$ret .= " </div>\n";
|
||||
$ret .= "</div>\n";
|
||||
$ret .= "</td></tr>\n";
|
||||
@ -667,38 +674,36 @@ sub BuildDashboardBottomRow($$$$){
|
||||
}
|
||||
|
||||
sub BuildGroupWidgets($$$$$) {
|
||||
my ($tab,$column,$id,$dbgroups, $dbsorting) = @_;
|
||||
my ($tab,$column,$id,$devicegroups, $groupsorting) = @_;
|
||||
my $ret = "";
|
||||
|
||||
my $counter = 0;
|
||||
my @storedsorting = split(":", $dbsorting);
|
||||
my @dbgroup = split(",", $dbgroups);
|
||||
my %sorting = ();
|
||||
|
||||
foreach (split(":", $groupsorting)) {
|
||||
my @parts = split (',', $_);
|
||||
$sorting{$parts[1]} = $_;
|
||||
}
|
||||
my $groupicon = '';
|
||||
|
||||
my @devicegroups = split('§§§', $devicegroups);
|
||||
|
||||
foreach my $singlegroup (@devicegroups) {
|
||||
# make sure that splitting with colon is not destroying the devspec that might
|
||||
# also contain a colon followed by a filter
|
||||
my ($groupname, $groupdevices, $groupicon) = split(/:(?!FILTER=)/, $singlegroup);
|
||||
|
||||
# if the device is not stored in the current column, skip it
|
||||
next if (index($sorting{$groupname}, 't'.$tab.'c'.$column) < 0);
|
||||
|
||||
my $groupId = $id."t".$tab."c".$column."w".$counter;
|
||||
|
||||
$ret .= BuildGroup( ($groupname,$groupdevices,$sorting{$groupname},$groupId,$groupicon) );
|
||||
|
||||
$counter++;
|
||||
}
|
||||
|
||||
foreach my $singlesorting (@storedsorting) {
|
||||
my @groupdata = split(",", $singlesorting);
|
||||
$groupicon = '';
|
||||
if (scalar(@groupdata) > 1) {
|
||||
if (
|
||||
index($dbsorting, "t".$tab."c".$column.",".$groupdata[1]) >= 0
|
||||
&& index($dbgroups, $groupdata[1]) >= 0
|
||||
&& $groupdata[1] ne ""
|
||||
) { #group is set to tab
|
||||
my $groupId = $id."t".$tab."c".$column."w".$counter;
|
||||
foreach my $strdbgroup (@dbgroup) {
|
||||
my @temp= split(":", trim($strdbgroup));
|
||||
if (defined($temp[1]) && $groupdata[1] eq $temp[0]) {
|
||||
$groupicon = $temp[1];
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= BuildGroup( ($groupdata[1],$singlesorting,$groupId,$groupicon) );
|
||||
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub BuildGroupList($) {
|
||||
@ -730,34 +735,36 @@ sub Dashboard_GetGroupList() {
|
||||
|
||||
sub BuildGroup
|
||||
{
|
||||
my ($currentgroup,$singleSorting,$groupId,$icon) = @_;
|
||||
my $ret = "";
|
||||
my $row = 1;
|
||||
my %extPage = ();
|
||||
my $foundDevices = 0;
|
||||
my $replaceGroup = "";
|
||||
my ($groupname,$devices,$sorting,$groupId,$icon) = @_;
|
||||
my $ret = "";
|
||||
my $row = 1;
|
||||
my %extPage = ();
|
||||
my $foundDevices = 0;
|
||||
my $replaceGroup = "";
|
||||
|
||||
my $rf = ($FW_room ? "&room=$FW_room" : ""); # stay in the room
|
||||
my $rf = ($FW_room ? "&room=$FW_room" : ""); # stay in the room
|
||||
|
||||
foreach my $g (keys %group) {
|
||||
next if ($g ne $currentgroup);
|
||||
$replaceGroup = "," . quotemeta($currentgroup) . ",";
|
||||
$singleSorting =~ s/$replaceGroup/,$g,/;
|
||||
$currentgroup = $g;
|
||||
|
||||
$ret .= " <div class=\"dashboard dashboard_widget ui-widget\" data-groupwidget=\"".$singleSorting."\" id=\"".$groupId."\">\n";
|
||||
$ret .= " <div class=\"dashboard dashboard_widget ui-widget\" data-groupwidget=\"".$sorting."\" id=\"".$groupId."\">\n";
|
||||
$ret .= " <div class=\"dashboard_widgetinner\">\n";
|
||||
$ret .= " <div class=\"dashboard_widgetheader ui-widget-header dashboard_group_header\">";
|
||||
if ($icon) {
|
||||
$ret .= FW_makeImage($icon,$icon,"dashboard_group_icon");
|
||||
}
|
||||
$ret .= $currentgroup."</div>\n";
|
||||
$ret .= " <div data-userheight=\"\" class=\"dashboard_content\">\n";
|
||||
|
||||
$ret .= "<table class=\"dashboard block wide\" id=\"TYPE_$currentgroup\">";
|
||||
|
||||
foreach my $d (sort { lc(AttrVal($a,"sortby",AttrVal($a,"alias",$a))) cmp lc(AttrVal($b,"sortby",AttrVal($b,"alias",$b))) } keys %{$group{$g}}) {
|
||||
if ($groupname && $groupname ne $devices) {
|
||||
$ret .= " <div class=\"dashboard_widgetheader ui-widget-header dashboard_group_header\">";
|
||||
if ($icon) {
|
||||
$ret.= FW_makeImage($icon,$icon,"dashboard_group_icon");
|
||||
}
|
||||
$ret .= $groupname . "</div>\n";
|
||||
}
|
||||
$ret .= " <div data-userheight=\"\" class=\"dashboard_content\">\n";
|
||||
$ret .= "<table class=\"dashboard block wide\" id=\"TYPE_$groupname\">";
|
||||
|
||||
my %seen;
|
||||
# make sure devices are not contained twice in the list
|
||||
my @devices = grep { ! $seen{$_} ++ } devspec2array($devices);
|
||||
|
||||
foreach my $d (@devices) {
|
||||
next if (!defined($defs{$d}));
|
||||
$foundDevices++;
|
||||
|
||||
$ret .= sprintf("<tr class=\"%s\">", ($row&1)?"odd":"even");
|
||||
|
||||
my $type = $defs{$d}{TYPE};
|
||||
@ -774,7 +781,7 @@ sub BuildGroup
|
||||
|
||||
my ($allSets, $cmdlist, $txt) = FW_devState($d, $rf, \%extPage);
|
||||
|
||||
############## Customize Result for Special Types #####################
|
||||
############## Customize Result for Special Types #####################
|
||||
my @txtarray = split(">", $txt);
|
||||
if ($modules{$defs{$d}{TYPE}}{FW_atPageEnd}) {
|
||||
no strict "refs";
|
||||
@ -787,12 +794,12 @@ sub BuildGroup
|
||||
$ret .= ">$devret</td>";
|
||||
use strict "refs";
|
||||
} else {
|
||||
$ret .= "<td class=\"dashboard_dev_container\" informId=\"$d\">$txt</td>";
|
||||
$ret .= "<td informId=\"$d\">$txt</td>";
|
||||
}
|
||||
###########################################################
|
||||
|
||||
###### Commands, slider, dropdown
|
||||
if(!$FW_ss && $cmdlist) {
|
||||
if(!$FW_ss && $cmdlist) {
|
||||
foreach my $cmd (split(":", $cmdlist)) {
|
||||
my $htmlTxt;
|
||||
my @c = split(' ', $cmd);
|
||||
@ -816,23 +823,21 @@ sub BuildGroup
|
||||
}
|
||||
$ret .= "</tr>";
|
||||
}
|
||||
|
||||
$ret .= "</table>";
|
||||
|
||||
$ret .= " </div>\n";
|
||||
$ret .= " </div>\n";
|
||||
$ret .= " </div>\n";
|
||||
}
|
||||
if (!$foundDevices) {
|
||||
$ret .= "<table class=\"block wide\" id=\"TYPE_unknowngroup\">";
|
||||
$ret .= "<tr class=\"odd\"><td class=\"changed\">Unknown Group: $currentgroup</td></tr>";
|
||||
$ret .= "<tr class=\"even\"><td class=\"changed\">Check if the group attribute is really set</td></tr>";
|
||||
$ret .= "<tr class=\"odd\"><td class=\"changed\">Check if the groupname is correct written</td></tr>";
|
||||
$ret .= "</table>";
|
||||
}
|
||||
|
||||
|
||||
if (!$foundDevices) {
|
||||
$ret .= "<table class=\"block wide\" id=\"TYPE_unknowngroup\">";
|
||||
$ret .= "<tr class=\"odd\"><td class=\"changed\">Devices for group not found: $groupname</td></tr>";
|
||||
$ret .= "<tr class=\"even\"><td class=\"changed\">Check if the device/group attribute is really set</td></tr>";
|
||||
$ret .= "<tr class=\"odd\"><td class=\"changed\">Check if the device spec is correctly written</td></tr>";
|
||||
$ret .= "</table>";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub GetMaxColumnId($$) {
|
||||
@ -904,13 +909,34 @@ GetTabCount ($$)
|
||||
|
||||
my $tabCount = 0;
|
||||
|
||||
while (AttrVal($hash->{NAME}, 'dashboard_tab' . ($tabCount + 1) . 'groups', '') ne "") {
|
||||
while (
|
||||
AttrVal($hash->{NAME}, 'dashboard_tab' . ($tabCount + 1) . 'groups', '') ne ""
|
||||
|| AttrVal($hash->{NAME}, 'dashboard_tab' . ($tabCount + 1) . 'devices', '') ne ""
|
||||
) {
|
||||
$tabCount++;
|
||||
}
|
||||
|
||||
return $tabCount ? $tabCount : $defaultTabCount;
|
||||
}
|
||||
|
||||
sub
|
||||
GetActiveTab ($)
|
||||
{
|
||||
my ($d) = @_;
|
||||
|
||||
if (defined($FW_httpheader{Cookie})) {
|
||||
my %cookie = map({ split('=', $_) } split(/; */, $FW_httpheader{Cookie}));
|
||||
if (defined($cookie{dashboard_activetab})) {
|
||||
my $activeTab = $cookie{dashboard_activetab};
|
||||
if ($activeTab <= GetTabCount($defs{$d}, 1)) {
|
||||
return $activeTab;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AttrVal($defs{$d}{NAME}, 'dashboard_activetab', 1);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
@ -1019,6 +1045,13 @@ GetTabCount ($$)
|
||||
Additionally a group can contain a regular expression to show all groups matching a criteria.
|
||||
Example: .*Light.* to show all groups that contain the string "Light"
|
||||
</li><br>
|
||||
<a name="dashboard_tabXdevices"></a>
|
||||
<li>dashboard_tabXdevices<br>
|
||||
devspec list of devices that should appear in the tab. The format is:<br/>
|
||||
GROUPNAME:devspec1,devspec2,...,devspecN:ICONNAME</br/>
|
||||
THe icon name is optional. Also the group name is optional. In case of missing group name, the matching devices are not grouped but shown as separate widgets without titles. For further details on the devspec format see:<br/>
|
||||
<a href="http://192.168.20.20:8083/fhem/docs/commandref.html#devspec">Dev-Spec</a>
|
||||
</li><br>
|
||||
<a name="dashboard_tabXicon"></a>
|
||||
<li>dashboard_tabXicon<br>
|
||||
Set the icon for a Tab. There must exist an icon with the name ico.(png|svg) in the modpath directory. If the image is referencing an SVG icon, then you can use the @colorname suffix to color the image.
|
||||
@ -1181,6 +1214,13 @@ GetTabCount ($$)
|
||||
Der Gruppenname kann ebenfalls einen regulären Ausdruck beinhalten, um alle Gruppen anzuzeigen, die darauf passen.<br/>
|
||||
Beispiel: .*Licht.* zeigt alle Gruppen an, die das Wort "Licht" im Namen haben.
|
||||
</li><br>
|
||||
<a name="dashboard_tabXdevices"></a>
|
||||
<li>dashboard_tabXdevices<br>
|
||||
devspec Liste von Geräten, die im Tab angezeigt werden sollen. Das format ist:<br/>
|
||||
GROUPNAME:devspec1,devspec2,...,devspecN:ICONNAME</br/>
|
||||
Das Icon ist optional. Auch der Gruppenname muss nicht vorhanden sein. Im Falle dass dieser fehlt, werden die gefunden Geräte nicht gruppiert sondern als einzelne Widgets im Tab angezeigt. Für weitere Details bezüglich devspec:
|
||||
<a href="http://192.168.20.20:8083/fhem/docs/commandref.html#devspec">Dev-Spec</a>
|
||||
</li><br>
|
||||
<a name="dashboard_tabXicon"></a>
|
||||
<li>dashboard_tabXicon<br>
|
||||
Zeigt am Tab ein Icon an. Es muss sich dabei um ein exisitereindes Icon mit modpath Verzeichnis handeln. Handelt es sich um ein SVG Icon kann der Suffix @colorname für die Farbe des Icons angegeben werden.
|
||||
|
@ -499,39 +499,6 @@ function dashboard_insert_tab(tabIndex, content) {
|
||||
FW_replaceWidgets($("#dashboard_tab" + tabIndex));
|
||||
|
||||
dashboard_init_tab(tabIndex);
|
||||
|
||||
// call FHEMWEB specific link replacement
|
||||
$("#dashboard_tab" + tabIndex + " a").each(function() { FW_replaceLink(this); });
|
||||
|
||||
restoreOrder(tabIndex);
|
||||
if (gridSize = is_dashboard_flexible()) {
|
||||
var $container = $("#dashboard_rowcenter_tab" + tabIndex);
|
||||
$("#dashboard_tab" + tabIndex + " .dashboard_widget").draggable({
|
||||
cursor: 'move',
|
||||
grid: [gridSize,gridSize],
|
||||
containment: [$container.offset().left,$container.offset().top],
|
||||
stop: function() { saveOrder(); }
|
||||
});
|
||||
}
|
||||
else {
|
||||
$("#dashboard_tab" + tabIndex + " .dashboard_column").sortable({
|
||||
connectWith: ['.dashboard_column', '.ui-row'],
|
||||
cursor: 'move',
|
||||
tolerance: 'pointer',
|
||||
stop: function() { saveOrder(); }
|
||||
});
|
||||
}
|
||||
makeResizable('.dashboard_widget');
|
||||
|
||||
// call the initialization of reading groups
|
||||
FW_readingsGroupReadyFn($('#dashboard_tab' + tabIndex));
|
||||
|
||||
if ((DashboardConfigHash['lockstate'] == "lock") || (dashboard_buttonbar == "hidden")) {
|
||||
dashboard_setlock();
|
||||
} else {
|
||||
dashboard_unsetlock();
|
||||
}
|
||||
restoreGroupVisibility(tabIndex);
|
||||
}
|
||||
|
||||
function dashboard_init_tab(tabIndex) {
|
||||
@ -553,6 +520,39 @@ function dashboard_init_tab(tabIndex) {
|
||||
event.stopImmediatePropagation();
|
||||
});
|
||||
} else { $("#dashboard_tab" + tabIndex + " .dashboard_widgetheader").addClass( "dashboard_widgetheader ui-corner-all" );}
|
||||
|
||||
// call FHEMWEB specific link replacement
|
||||
$("#dashboard_tab" + tabIndex + " a").each(function() { FW_replaceLink(this); });
|
||||
|
||||
restoreOrder(tabIndex);
|
||||
if (gridSize = is_dashboard_flexible()) {
|
||||
var $container = $("#dashboard_rowcenter_tab" + tabIndex);
|
||||
$("#dashboard_tab" + tabIndex + " .dashboard_widget").draggable({
|
||||
cursor: 'move',
|
||||
grid: [gridSize,gridSize],
|
||||
containment: [$container.offset().left,$container.offset().top],
|
||||
stop: function() { saveOrder(); }
|
||||
});
|
||||
}
|
||||
else {
|
||||
$("#dashboard_tab" + tabIndex + " .dashboard_column").sortable({
|
||||
connectWith: ['.dashboard_column', '.ui-row'],
|
||||
cursor: 'move',
|
||||
tolerance: 'pointer',
|
||||
stop: function() { saveOrder(); }
|
||||
});
|
||||
}
|
||||
makeResizable('.dashboard_widget');
|
||||
|
||||
// call the initialization of reading groups
|
||||
FW_readingsGroupReadyFn($('#dashboard_tab' + tabIndex));
|
||||
|
||||
if ((DashboardConfigHash['lockstate'] == "lock") || (dashboard_buttonbar == "hidden")) {
|
||||
dashboard_setlock();
|
||||
} else {
|
||||
dashboard_unsetlock();
|
||||
}
|
||||
restoreGroupVisibility(tabIndex);
|
||||
}
|
||||
|
||||
function restoreGroupVisibility(tabId) {
|
||||
@ -602,7 +602,6 @@ function dashboard_buildDashboard(){
|
||||
var params = dashboard_get_params();
|
||||
dashboard_buttonbar = params[4];
|
||||
|
||||
dashboard_init_tab(0);
|
||||
|
||||
if (DashboardConfigHash['dashboard_showfullsize'] == 1){ //disable roomlist and header
|
||||
//$("#menuScrollArea").remove();
|
||||
@ -616,16 +615,25 @@ function dashboard_buildDashboard(){
|
||||
$("#dashboardtabs").tabs({
|
||||
active: 0,
|
||||
create: function(event, ui) {
|
||||
$( "#dashboardtabs" ).tabs( "option", "active", DashboardConfigHash['dashboard_activetab']-1);//set active Tab
|
||||
/*$( "#dashboardtabs" ).tabs( "option", "active", 2);//set active Tab
|
||||
restoreOrder();
|
||||
restoreGroupVisibility(0);
|
||||
restoreGroupVisibility(0);*/
|
||||
},
|
||||
activate: function (event, ui) {
|
||||
var tabIndex = ui.newTab.parent().children('li').index(ui.newTab);
|
||||
$.cookie('dashboard_activetab', tabIndex + 1, {expires : 365});
|
||||
//restoreOrder(tabIndex);
|
||||
//restoreGroupVisibility(tabIndex);
|
||||
}
|
||||
});
|
||||
|
||||
var iActiveTab = getTabIndexFromTab($('#dashboardtabs .dashboard_tabpanel'));
|
||||
|
||||
$( "#dashboardtabs" ).tabs( "option", "active", iActiveTab);//set active Tab
|
||||
dashboard_init_tab(iActiveTab);
|
||||
restoreOrder(iActiveTab);
|
||||
restoreGroupVisibility(iActiveTab);
|
||||
|
||||
if ($("#dashboard_tabnav").hasClass("dashboard_tabnav_bottom")) { $(".dashboard_tabnav").appendTo(".dashboard_tabs"); } //set Tabs on the Bottom
|
||||
$(".dashboard_tab_hidden").css("display", "none"); //hide Tabs
|
||||
|
||||
|
@ -179,10 +179,6 @@ body.dashboard_fullsize #content {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.col2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dashboard_widgetheader svg {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ svg.dashboard_tabicon { fill:#929292; }
|
||||
#dashboard .dashboard_widgetheader {background: none repeat scroll 0 0 #FFFFFF; /*border: 1px solid #FFFFFF;
|
||||
box-shadow: 5px 5px 5px #000000;*/ margin: 0.2em; padding-bottom: 4px; padding-top: 3px; padding-left: 0.7em; font-weight: normal;}
|
||||
#dashboard .ui-widget .ui-widget {font-size: 1em; font-family: Arial,Helvetica,sans-serif;}
|
||||
#dashboard .ui-widget-header {background-color: #FFFFFF;/*color: #ffffff;*/}
|
||||
#dashboard .ui-widget-header {border: none; background: #FFFFFF;/*color: #ffffff;*/}
|
||||
#dashboard .ui-helper-clearfix:before,
|
||||
#dashboard .ui-helper-clearfix:after {content: "";display: table;border-collapse: collapse;}
|
||||
#dashboard .ui-helper-clearfix:after {clear: both;}
|
||||
|
@ -42,7 +42,7 @@
|
||||
#dashboard .dashboard_widgetinner .block .block {border: none; box-shadow: none;}
|
||||
#dashboard .dashboard_tabcontent {width: 100%; padding: 0; margin: 0; }
|
||||
#dashboard .dashboard_widget {border-radius: 8px; float: left;}
|
||||
#dashboard .dashboard_widgethelper {background-color: #D7FFFF; }
|
||||
#dashboard .dashboard_widgethelper {background-color: #A8A870; }
|
||||
#dashboard .dashboard_widgetheader {background: none repeat scroll 0 0 #F0F0D8; border: 1px solid #808080;
|
||||
margin: 0.2em; padding-bottom: 4px; padding-top: 3px; padding-left: 0.7em; font-weight: normal;}
|
||||
#dashboard .ui-widget .ui-widget {font-size: 1em; font-family: Arial,Helvetica,sans-serif;}
|
||||
@ -60,6 +60,7 @@
|
||||
#dashboard .ui-tabs .ui-tabs-nav .ui-tabs-anchor {float: left;padding: .5em .5em;text-decoration: none;}
|
||||
#dashboard .ui-tabs-icon {width: 23px;height: 23px; margin: -8px 2px -6px -3px; padding-right: 2px;/*float: left;vertical-align: top;margin-left: 0.3em;margin-top: 0.5em;*/}
|
||||
#dashboard .dashboard_tabnav_hidden{background-color: #F8F8d5;}
|
||||
#dashboard .dashboard_tabnav {background: #e9e9c8 !important;}
|
||||
#dashboard .ui-widget-header .ui-state-default {border: 1px solid #278727;background-color: #d5d5b7;font-weight: normal;color: #F0F0dd;}
|
||||
#dashboard .ui-widget-header .ui-state-active{border: 1px solid #278727;background: #F8F8d5;font-weight: normal;color: #278727;}
|
||||
#dashboard .ui-state-default a {color: #F8F8d5;text-decoration: none;}
|
||||
@ -171,10 +172,6 @@ body.dashboard_fullsize #content {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.col2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dashboard_widgetheader svg {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
@ -602,6 +602,10 @@ table.block tr:last-child td {
|
||||
padding-left:10px;
|
||||
font-weight:700
|
||||
}
|
||||
|
||||
.block > tbody > tr > td:last-child {
|
||||
padding-right:10px;
|
||||
}
|
||||
|
||||
.roomoverview table.block td:first-child {
|
||||
min-width:50px
|
||||
@ -832,4 +836,4 @@ table.room tr.sel a:hover svg {
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background:#777
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user