95_Dashboard: support for devspecs in dashboard - storing and restore of currently selected tab - style adjustments

git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@8990 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
talkabout
2015-07-26 20:42:15 +00:00
parent 6b476b5ed2
commit 39aca5a01e
7 changed files with 243 additions and 194 deletions

View File

@@ -1,5 +1,9 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # 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. # 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 - change: SYSMON: warning (userdefined readings), reading for perl version
- feature: 38_CO20.pm: added advanced features, retries and timeout (by Markus M.) - feature: 38_CO20.pm: added advanced features, retries and timeout (by Markus M.)
- feature: 32_yowsup.pm: added support for groups - feature: 32_yowsup.pm: added support for groups

View File

@@ -60,6 +60,7 @@
# Optimized icon loading. # Optimized icon loading.
# Optimized fullscreen view. # Optimized fullscreen view.
# Minor improvements in javascript and css. # 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: # 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...) # 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 $dashboard_groupListfhem;
my $fwjquery = "jquery.min.js"; my $fwjquery = "jquery.min.js";
my $fwjqueryui = "jquery-ui.min.js"; my $fwjqueryui = "jquery-ui.min.js";
my $dashboardversion = "3.00"; my $dashboardversion = "3.10";
my @fhemweb_instances = ();
############################################################################################# #############################################################################################
sub Dashboard_Initialize ($) { sub Dashboard_Initialize ($) {
@@ -132,11 +131,9 @@ sub Dashboard_Initialize ($) {
$hash->{AttrList} = "disable:0,1 ". $hash->{AttrList} = "disable:0,1 ".
"dashboard_colcount:1,2,3,4,5 ". "dashboard_colcount:1,2,3,4,5 ".
"dashboard_debug:0,1 ". "dashboard_debug:0,1 ".
"dashboard_lockstate:dont-use-this-attribut ". #obolet since 04.2014
"dashboard_rowtopheight ". "dashboard_rowtopheight ".
"dashboard_rowbottomheight ". "dashboard_rowbottomheight ".
"dashboard_row:top,center,bottom,top-center,center-bottom,top-center-bottom ". "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 ". "dashboard_showtogglebuttons:0,1 ".
#new attribute vers. 2.00 #new attribute vers. 2.00
"dashboard_activetab:1,2,3,4,5,6,7 ". "dashboard_activetab:1,2,3,4,5,6,7 ".
@@ -146,15 +143,16 @@ sub Dashboard_Initialize ($) {
"dashboard_rowcentercolwidth ". "dashboard_rowcentercolwidth ".
"dashboard_showfullsize:0,1 ". "dashboard_showfullsize:0,1 ".
#new attribute vers. 2.02 #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 ". "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 #new attribute vers. 2.06
"dashboard_customcss " . "dashboard_customcss " .
#new attribute vers. 3.00
"dashboard_flexible " . "dashboard_flexible " .
#tab-specific attributes #tab-specific attributes
"dashboard_tab1name " . "dashboard_tab1name " .
"dashboard_tab1groups " . "dashboard_tab1groups " .
#new attribute vers. 3.10
"dashboard_tab1devices " .
"dashboard_tab1sorting " . "dashboard_tab1sorting " .
"dashboard_tab1icon " . "dashboard_tab1icon " .
"dashboard_tab1colcount " . "dashboard_tab1colcount " .
@@ -163,6 +161,8 @@ sub Dashboard_Initialize ($) {
# dynamic attributes # dynamic attributes
"dashboard_tab[0-9]+name " . "dashboard_tab[0-9]+name " .
"dashboard_tab[0-9]+groups " . "dashboard_tab[0-9]+groups " .
#new attribute vers. 3.10
"dashboard_tab[0-9]+devices " .
"dashboard_tab[0-9]+sorting " . "dashboard_tab[0-9]+sorting " .
"dashboard_tab[0-9]+icon " . "dashboard_tab[0-9]+icon " .
"dashboard_tab[0-9]+colcount " . "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 @iconFolders = split(":", AttrVal($FW_wname, "iconPath", "$FW_sp:default:fhemSVG:openautomation"));
my $iconDirs = ""; my $iconDirs = "";
foreach my $idir (@iconFolders) {$iconDirs .= "$attr{global}{modpath}/www/images/".$idir.",";} 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"; $res .= ($i != $x) ? ",\n" : "\n";
foreach my $attr (sort keys %$attrdata) { foreach my $attr (sort keys %$attrdata) {
@@ -248,7 +248,10 @@ sub Dashboard_Get($@) {
if (@splitattr == 2) { if (@splitattr == 2) {
$res .= " \"".Dashboard_Escape($attr)."\": \"".$splitattr[0]."\",\n"; $res .= " \"".Dashboard_Escape($attr)."\": \"".$splitattr[0]."\",\n";
$res .= " \"".Dashboard_Escape($attr)."color\": \"".$splitattr[1]."\""; $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 .= ($i != $x) ? ",\n" : "\n";
} }
$res .= " }\n"; $res .= " }\n";
@@ -258,15 +261,15 @@ sub Dashboard_Get($@) {
} elsif ($arg eq "groupWidget") { } elsif ($arg eq "groupWidget") {
#### Comming Soon ###### #### Comming Soon ######
# For dynamic load of GroupWidgets from JavaScript # 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 #for (my $p=2;$p<@a;$p++){$dbgroup .= $a[$p]." ";} #For Groupnames with Space
$dashboard_groupListfhem = Dashboard_GetGroupList; #$dashboard_groupListfhem = Dashboard_GetGroupList;
%group = BuildGroupList($dashboard_groupListfhem); #%group = BuildGroupList($dashboard_groupListfhem);
$res .= BuildGroupWidgets(1,1,1212,trim($dbgroup),"t1c1,".trim($dbgroup).",true,0,0:"); #$res .= BuildGroupWidgets(1,1,1212,trim($dbgroup),"t1c1,".trim($dbgroup).",true,0,0:");
return $res; #return $res;
#For dynamic loading of tabs #For dynamic loading of tabs
} elsif ($arg eq "tab" && $arg2 =~ /^\d+$/) { } elsif ($arg eq "tab" && $arg2 =~ /^\d+$/) {
return BuildDashboardTab($arg2, $hash->{NAME}); return BuildDashboardTab($arg2, $hash->{NAME});
} elsif ($arg eq "icon") { } elsif ($arg eq "icon") {
@@ -277,7 +280,7 @@ sub Dashboard_Get($@) {
return FW_iconPath($icon); return FW_iconPath($icon);
} else { } 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); RemoveInternalTimer($hash);
InternalTimer ($now + 5, 'CheckDashboardAttributUssage', $hash, 0); InternalTimer ($now + 5, 'CheckDashboardAttributUssage', $hash, 0);
my $dashboard_groupListfhem = Dashboard_GetGroupList;
my $url = '/dashboard/' . $name; my $url = '/dashboard/' . $name;
@@ -320,8 +322,15 @@ sub Dashboard_attr($$$) {
my ($cmd, $name, $attrName, $attrVal) = @_; my ($cmd, $name, $attrName, $attrVal) = @_;
# add dynamic attributes # 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) . "name");
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "devices");
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "groups"); addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "groups");
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "sorting"); addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "sorting");
addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "icon"); addToDevAttrList($name, "dashboard_tab" . ($1 + 1) . "icon");
@@ -358,7 +367,7 @@ sub Dashboard_CGI($)
FW_pO $ret; FW_pO $ret;
return 1; return 0;
} }
sub DashboardAsHtml($) sub DashboardAsHtml($)
@@ -399,7 +408,7 @@ sub Dashboard_SummaryFN($$$$)
my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center"); my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center");
my $debug = AttrVal($defs{$d}{NAME}, "dashboard_debug", "0"); 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 $tabcount = GetTabCount($defs{$d}, 1);
my $dbwidth = AttrVal($defs{$d}{NAME}, "dashboard_width", "100%"); my $dbwidth = AttrVal($defs{$d}{NAME}, "dashboard_width", "100%");
my @tabnames = (); my @tabnames = ();
@@ -407,7 +416,7 @@ sub Dashboard_SummaryFN($$$$)
if ($showfullsize) { if ($showfullsize) {
if ($FW_RET =~ m/<body[^>]*class="([^"]+)"[^>]*>/) { 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 { else {
$FW_RET =~ s/<body/<body class="dashboard_fullsize"/; $FW_RET =~ s/<body/<body class="dashboard_fullsize"/;
@@ -451,7 +460,6 @@ sub Dashboard_SummaryFN($$$$)
if ($room ne "all") { 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"; $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 $id = $defs{$d}{NR};
my $colcount = AttrVal($defs{$d}{NAME}, 'dashboard_tab' . ($t + 1) . 'colcount', AttrVal($defs{$d}{NAME}, "dashboard_colcount", 1)); 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 $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/,/:/; $colwidths =~ tr/,/:/;
my $backgroundimage = AttrVal($defs{$d}{NAME}, 'dashboard_tab' . ($t + 1) . 'backgroundimage', "");
my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center"); my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center");
my $tabcount = GetTabCount($defs{$d}, 1); my $tabcount = GetTabCount($defs{$d}, 1);
my @tabgroups = (); my $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($t + 1) . "groups", "");
my @tabsortings = (); 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++) { unless ($tabgroups || $tabdevicegroups) {
$tabgroups[$i] = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($i + 1) . "groups", ""); readingsSingleUpdate( $defs{$d}, "state", "No Groups or devices set", 0 );
$tabsortings[$i] = AttrVal($defs{$d}{NAME}, "dashboard_tab" . ($i + 1) . "sorting", "");
}
unless (@tabgroups) {
readingsSingleUpdate( $defs{$d}, "state", "No Groups set", 0 );
return ""; 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; $groups =~ s/#/ /g;
my @groups = split(',', $groups); my @groups = split(',', $groups);
my @temptabgroup = split(",", $tabgroups);
my @temptabgroup = split(",", $tabgroups[$t]); #Set temp. position for groups without an stored position
my @tabgroup = ();
my @index = ();
# resolve group names from regular expressions
for (my $i=0;$i<@temptabgroup;$i++) { for (my $i=0;$i<@temptabgroup;$i++) {
my @stabgroup = split(":", trim($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) { if (@index > 0) {
for (my $j=0; $j<@index;$j++) { for (my $j=0; $j<@index;$j++) {
my $groupname = @groups[$index[$j]]; my $groupname = @groups[$index[$j]];
$groupname .= ':' . 'group=' . $groupname;
if (@stabgroup > 1) { if (@stabgroup > 1) {
$groupname .= ':' . $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);
# add sortings for groups not already having a defined sorting
$tabgroups[$t] = join(',', @tabgroup); for (my $i=0;$i<@tabdevicegroups;$i++) {
my @stabgroup = split(":", trim($tabdevicegroups[$i]));
for (my $i=0;$i<@tabgroup;$i++) {
my @stabgroup = split(":", trim($tabgroup[$i]));
my $matchGroup = "," . quotemeta(trim($stabgroup[0])) . ","; my $matchGroup = "," . quotemeta(trim($stabgroup[0])) . ",";
if ($tabsortings[$t] !~ m/$matchGroup/) { if ($tabsortings !~ m/$matchGroup/) {
$tabsortings[$t] = $tabsortings[$t]."t".$t."c".GetMaxColumnId($row,$colcount).",".trim($stabgroup[0]).",true,0,0:"; $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."\" 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[$t]."\" 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 .= " <ul class=\"dashboard_tabcontent\">\n";
$ret .= " <table class=\"dashboard_tabcontent\">\n"; $ret .= " <table class=\"dashboard_tabcontent\">\n";
##################### Top Row (only one Column) ############################################# ##################### Top Row (only one Column) #############################################
if ($row eq "top-center-bottom" || $row eq "top-center" || $row eq "top"){ 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) ############################################ ##################### Center Row (max. 5 Column) ############################################
if ($row eq "top-center-bottom" || $row eq "top-center" || $row eq "center-bottom" || $row eq "center") { 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) ############################################ ############################# Bottom Row (only one Column) ############################################
if ($row eq "top-center-bottom" || $row eq "center-bottom" || $row eq "bottom"){ 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"; $ret .= " </table>\n";
@@ -613,12 +620,12 @@ sub BuildDashboardTab($$)
} }
sub BuildDashboardTopRow($$$$){ sub BuildDashboardTopRow($$$$){
my ($t,$id, $dbgroups, $dbsorting) = @_; my ($t,$id, $devicegroups, $groupsorting) = @_;
my $ret; my $ret;
$ret .= "<tr><td class=\"dashboard_row\">\n"; $ret .= "<tr><td class=\"dashboard_row\">\n";
$ret .= "<div id=\"dashboard_rowtop_tab".$t."\" class=\"dashboard dashboard_rowtop\">\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 .= " <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 .= "</div>\n"; $ret .= "</div>\n";
$ret .= "</td></tr>\n"; $ret .= "</td></tr>\n";
@@ -626,9 +633,9 @@ sub BuildDashboardTopRow($$$$){
} }
sub BuildDashboardCenterRow($$$$$){ sub BuildDashboardCenterRow($$$$$){
my ($t,$id, $dbgroups, $dbsorting, $colcount) = @_; my ($t,$id, $devicegroups, $groupsorting, $colcount) = @_;
my $ret;
$ret .= "<tr><td class=\"dashboard_row\">\n"; my $ret = "<tr><td class=\"dashboard_row\">\n";
$ret .= "<div id=\"dashboard_rowcenter_tab".$t."\" class=\"dashboard dashboard_rowcenter\">\n"; $ret .= "<div id=\"dashboard_rowcenter_tab".$t."\" class=\"dashboard dashboard_rowcenter\">\n";
my $currentcol = $colcount; my $currentcol = $colcount;
@@ -636,16 +643,16 @@ sub BuildDashboardCenterRow($$$$$){
my $replace = "t" . $t . "c" . $maxcolindex . ","; my $replace = "t" . $t . "c" . $maxcolindex . ",";
# replace all sortings referencing not existing columns # replace all sortings referencing not existing columns
# this does only work if there is not empty column inbetween # this does only work if there is no empty column inbetween
while (index($dbsorting, "t".$t."c".$currentcol.",") >= 0) { while (index($groupsorting, "t".$t."c".$currentcol.",") >= 0) {
my $search = "t" . $t . "c" . $currentcol . ","; my $search = "t" . $t . "c" . $currentcol . ",";
$dbsorting =~ s/$search/$replace/g; $groupsorting =~ s/$search/$replace/g;
$currentcol++; $currentcol++;
} }
for (my $i=0;$i<$colcount;$i++){ 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 .= " <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";
} }
$ret .= "</div>\n"; $ret .= "</div>\n";
@@ -654,12 +661,12 @@ sub BuildDashboardCenterRow($$$$$){
} }
sub BuildDashboardBottomRow($$$$){ sub BuildDashboardBottomRow($$$$){
my ($t,$id, $dbgroups, $dbsorting) = @_; my ($t,$id, $devicegroups, $groupsorting) = @_;
my $ret; my $ret;
$ret .= "<tr><td class=\"dashboard_row\">\n"; $ret .= "<tr><td class=\"dashboard_row\">\n";
$ret .= "<div id=\"dashboard_rowbottom_tab".$t."\" class=\"dashboard dashboard_rowbottom\">\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 .= " <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 .= "</div>\n"; $ret .= "</div>\n";
$ret .= "</td></tr>\n"; $ret .= "</td></tr>\n";
@@ -667,38 +674,36 @@ sub BuildDashboardBottomRow($$$$){
} }
sub BuildGroupWidgets($$$$$) { sub BuildGroupWidgets($$$$$) {
my ($tab,$column,$id,$dbgroups, $dbsorting) = @_; my ($tab,$column,$id,$devicegroups, $groupsorting) = @_;
my $ret = ""; my $ret = "";
my $counter = 0; my $counter = 0;
my @storedsorting = split(":", $dbsorting); my %sorting = ();
my @dbgroup = split(",", $dbgroups);
foreach (split(":", $groupsorting)) {
my @parts = split (',', $_);
$sorting{$parts[1]} = $_;
}
my $groupicon = ''; my $groupicon = '';
foreach my $singlesorting (@storedsorting) { my @devicegroups = split('§§§', $devicegroups);
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) ); 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);
$counter++; # 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;
return $ret;
$ret .= BuildGroup( ($groupname,$groupdevices,$sorting{$groupname},$groupId,$groupicon) );
$counter++;
}
return $ret;
} }
sub BuildGroupList($) { sub BuildGroupList($) {
@@ -730,34 +735,36 @@ sub Dashboard_GetGroupList() {
sub BuildGroup sub BuildGroup
{ {
my ($currentgroup,$singleSorting,$groupId,$icon) = @_; my ($groupname,$devices,$sorting,$groupId,$icon) = @_;
my $ret = ""; my $ret = "";
my $row = 1; my $row = 1;
my %extPage = (); my %extPage = ();
my $foundDevices = 0; my $foundDevices = 0;
my $replaceGroup = ""; my $replaceGroup = "";
my $rf = ($FW_room ? "&amp;room=$FW_room" : ""); # stay in the room my $rf = ($FW_room ? "&amp;room=$FW_room" : ""); # stay in the room
foreach my $g (keys %group) { $ret .= " <div class=\"dashboard dashboard_widget ui-widget\" data-groupwidget=\"".$sorting."\" id=\"".$groupId."\">\n";
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_widgetinner\">\n"; $ret .= " <div class=\"dashboard_widgetinner\">\n";
$ret .= " <div class=\"dashboard_widgetheader ui-widget-header dashboard_group_header\">";
if ($icon) { if ($groupname && $groupname ne $devices) {
$ret .= FW_makeImage($icon,$icon,"dashboard_group_icon"); $ret .= " <div class=\"dashboard_widgetheader ui-widget-header dashboard_group_header\">";
} if ($icon) {
$ret .= $currentgroup."</div>\n"; $ret.= FW_makeImage($icon,$icon,"dashboard_group_icon");
}
$ret .= $groupname . "</div>\n";
}
$ret .= " <div data-userheight=\"\" class=\"dashboard_content\">\n"; $ret .= " <div data-userheight=\"\" class=\"dashboard_content\">\n";
$ret .= "<table class=\"dashboard block wide\" id=\"TYPE_$groupname\">";
$ret .= "<table class=\"dashboard block wide\" id=\"TYPE_$currentgroup\">"; my %seen;
# make sure devices are not contained twice in the list
my @devices = grep { ! $seen{$_} ++ } devspec2array($devices);
foreach my $d (sort { lc(AttrVal($a,"sortby",AttrVal($a,"alias",$a))) cmp lc(AttrVal($b,"sortby",AttrVal($b,"alias",$b))) } keys %{$group{$g}}) { foreach my $d (@devices) {
next if (!defined($defs{$d}));
$foundDevices++; $foundDevices++;
$ret .= sprintf("<tr class=\"%s\">", ($row&1)?"odd":"even"); $ret .= sprintf("<tr class=\"%s\">", ($row&1)?"odd":"even");
my $type = $defs{$d}{TYPE}; my $type = $defs{$d}{TYPE};
@@ -774,7 +781,7 @@ sub BuildGroup
my ($allSets, $cmdlist, $txt) = FW_devState($d, $rf, \%extPage); my ($allSets, $cmdlist, $txt) = FW_devState($d, $rf, \%extPage);
############## Customize Result for Special Types ##################### ############## Customize Result for Special Types #####################
my @txtarray = split(">", $txt); my @txtarray = split(">", $txt);
if ($modules{$defs{$d}{TYPE}}{FW_atPageEnd}) { if ($modules{$defs{$d}{TYPE}}{FW_atPageEnd}) {
no strict "refs"; no strict "refs";
@@ -787,12 +794,12 @@ sub BuildGroup
$ret .= ">$devret</td>"; $ret .= ">$devret</td>";
use strict "refs"; use strict "refs";
} else { } else {
$ret .= "<td class=\"dashboard_dev_container\" informId=\"$d\">$txt</td>"; $ret .= "<td informId=\"$d\">$txt</td>";
} }
########################################################### ###########################################################
###### Commands, slider, dropdown ###### Commands, slider, dropdown
if(!$FW_ss && $cmdlist) { if(!$FW_ss && $cmdlist) {
foreach my $cmd (split(":", $cmdlist)) { foreach my $cmd (split(":", $cmdlist)) {
my $htmlTxt; my $htmlTxt;
my @c = split(' ', $cmd); my @c = split(' ', $cmd);
@@ -816,23 +823,21 @@ sub BuildGroup
} }
$ret .= "</tr>"; $ret .= "</tr>";
} }
$ret .= "</table>";
$ret .= "</table>";
$ret .= " </div>\n"; $ret .= " </div>\n";
$ret .= " </div>\n"; $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($$) { sub GetMaxColumnId($$) {
@@ -904,13 +909,34 @@ GetTabCount ($$)
my $tabCount = 0; 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++; $tabCount++;
} }
return $tabCount ? $tabCount : $defaultTabCount; 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; 1;
=pod =pod
@@ -1019,6 +1045,13 @@ GetTabCount ($$)
Additionally a group can contain a regular expression to show all groups matching a criteria. 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" Example: .*Light.* to show all groups that contain the string "Light"
</li><br> </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> <a name="dashboard_tabXicon"></a>
<li>dashboard_tabXicon<br> <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. 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/> 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. Beispiel: .*Licht.* zeigt alle Gruppen an, die das Wort "Licht" im Namen haben.
</li><br> </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> <a name="dashboard_tabXicon"></a>
<li>dashboard_tabXicon<br> <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. 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.

View File

@@ -499,39 +499,6 @@ function dashboard_insert_tab(tabIndex, content) {
FW_replaceWidgets($("#dashboard_tab" + tabIndex)); FW_replaceWidgets($("#dashboard_tab" + tabIndex));
dashboard_init_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) { function dashboard_init_tab(tabIndex) {
@@ -553,6 +520,39 @@ function dashboard_init_tab(tabIndex) {
event.stopImmediatePropagation(); event.stopImmediatePropagation();
}); });
} else { $("#dashboard_tab" + tabIndex + " .dashboard_widgetheader").addClass( "dashboard_widgetheader ui-corner-all" );} } 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) { function restoreGroupVisibility(tabId) {
@@ -602,7 +602,6 @@ function dashboard_buildDashboard(){
var params = dashboard_get_params(); var params = dashboard_get_params();
dashboard_buttonbar = params[4]; dashboard_buttonbar = params[4];
dashboard_init_tab(0);
if (DashboardConfigHash['dashboard_showfullsize'] == 1){ //disable roomlist and header if (DashboardConfigHash['dashboard_showfullsize'] == 1){ //disable roomlist and header
//$("#menuScrollArea").remove(); //$("#menuScrollArea").remove();
@@ -616,16 +615,25 @@ function dashboard_buildDashboard(){
$("#dashboardtabs").tabs({ $("#dashboardtabs").tabs({
active: 0, active: 0,
create: function(event, ui) { create: function(event, ui) {
$( "#dashboardtabs" ).tabs( "option", "active", DashboardConfigHash['dashboard_activetab']-1);//set active Tab /*$( "#dashboardtabs" ).tabs( "option", "active", 2);//set active Tab
restoreOrder(); restoreOrder();
restoreGroupVisibility(0); restoreGroupVisibility(0);*/
}, },
activate: function (event, ui) { activate: function (event, ui) {
var tabIndex = ui.newTab.parent().children('li').index(ui.newTab); var tabIndex = ui.newTab.parent().children('li').index(ui.newTab);
$.cookie('dashboard_activetab', tabIndex + 1, {expires : 365});
//restoreOrder(tabIndex); //restoreOrder(tabIndex);
//restoreGroupVisibility(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 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 $(".dashboard_tab_hidden").css("display", "none"); //hide Tabs

View File

@@ -179,10 +179,6 @@ body.dashboard_fullsize #content {
border: none !important; border: none !important;
} }
.col2 {
text-align: center;
}
.dashboard_widgetheader svg { .dashboard_widgetheader svg {
margin-right: 5px; margin-right: 5px;
} }

View File

@@ -43,7 +43,7 @@ svg.dashboard_tabicon { fill:#929292; }
#dashboard .dashboard_widgetheader {background: none repeat scroll 0 0 #FFFFFF; /*border: 1px solid #FFFFFF; #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;} 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 .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:before,
#dashboard .ui-helper-clearfix:after {content: "";display: table;border-collapse: collapse;} #dashboard .ui-helper-clearfix:after {content: "";display: table;border-collapse: collapse;}
#dashboard .ui-helper-clearfix:after {clear: both;} #dashboard .ui-helper-clearfix:after {clear: both;}

View File

@@ -42,7 +42,7 @@
#dashboard .dashboard_widgetinner .block .block {border: none; box-shadow: none;} #dashboard .dashboard_widgetinner .block .block {border: none; box-shadow: none;}
#dashboard .dashboard_tabcontent {width: 100%; padding: 0; margin: 0; } #dashboard .dashboard_tabcontent {width: 100%; padding: 0; margin: 0; }
#dashboard .dashboard_widget {border-radius: 8px; float: left;} #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; #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;} 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 .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 .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 .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_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-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-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;} #dashboard .ui-state-default a {color: #F8F8d5;text-decoration: none;}
@@ -171,10 +172,6 @@ body.dashboard_fullsize #content {
border: none !important; border: none !important;
} }
.col2 {
text-align: center;
}
.dashboard_widgetheader svg { .dashboard_widgetheader svg {
margin-right: 5px; margin-right: 5px;
} }

View File

@@ -603,6 +603,10 @@ table.block tr:last-child td {
font-weight:700 font-weight:700
} }
.block > tbody > tr > td:last-child {
padding-right:10px;
}
.roomoverview table.block td:first-child { .roomoverview table.block td:first-child {
min-width:50px min-width:50px
} }