mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-12 16:46:35 +00:00
01_FHEMWEB.pm: unsaved changes (Forum #32296)
git-svn-id: https://svn.fhem.de/fhem/trunk@7688 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
06fe0dd5b6
commit
aab0aedc60
@ -7,7 +7,6 @@ use warnings;
|
||||
use TcpServerUtils;
|
||||
use HttpUtils;
|
||||
use Time::HiRes qw(gettimeofday);
|
||||
use Errno qw(:POSIX);
|
||||
|
||||
#########################
|
||||
# Forward declaration
|
||||
@ -1265,8 +1264,6 @@ FW_roomOverview($)
|
||||
|
||||
my $class = "menu_$l1";
|
||||
$class =~ s/[^A-Z0-9]/_/gi;
|
||||
$class .= ($lastDefChange>$lastSavedChange) ? " changed" : ""
|
||||
if($l1 eq "Save config");
|
||||
|
||||
# image tag if we have an icon, else empty
|
||||
my $icoName = "ico$l1";
|
||||
@ -1275,12 +1272,18 @@ FW_roomOverview($)
|
||||
my $icon = FW_iconName($icoName) ?
|
||||
FW_makeImage($icoName,$icoName,"icon")." " : "";
|
||||
|
||||
if($l1 eq "Save config") {
|
||||
$l1 .= '</a> <a id="saveCheck" class="changed" style="visibility:'.
|
||||
(int(@structChangeHist) ? 'visible' : 'hidden').'">?</a>';
|
||||
}
|
||||
|
||||
# Force external browser if FHEMWEB is installed as an offline app.
|
||||
if($l2 =~ m/.html$/ || $l2 =~ m/^http/) {
|
||||
FW_pO "<td><div><a href=\"$l2\">$icon$l1</a></div></td>";
|
||||
} else {
|
||||
FW_pH $l2, "$icon$l1", 1, $class;
|
||||
}
|
||||
|
||||
FW_pO "</tr>";
|
||||
}
|
||||
}
|
||||
@ -2268,13 +2271,9 @@ FW_Notify($$)
|
||||
my ($ntfy, $dev) = @_;
|
||||
|
||||
if( $dev->{NAME} eq "global" ) {
|
||||
my $n = "#FHEMWEB:$ntfy->{NAME}";
|
||||
if( grep(m/^SAVE|INITIALIZED|REREADCFG|SHUTDOWN$/, @{$dev->{CHANGED}}) ) {
|
||||
FW_directNotify($n, '$(".menu_Save_config").removeClass("changed")', '');
|
||||
} elsif( grep(m/^DEFINED|MODIFIED|DELETED|ATTR|DELETEATTR$/,
|
||||
@{$dev->{CHANGED}}) ) {
|
||||
FW_directNotify($n, '$(".menu_Save_config").addClass("changed")', '');
|
||||
}
|
||||
my $vs = int(@structChangeHist) ? 'visible' : 'hidden';
|
||||
FW_directNotify( "#FHEMWEB:$ntfy->{NAME}",
|
||||
"\$('#saveCheck').css('visibility','$vs')", '');
|
||||
}
|
||||
|
||||
my $h = $ntfy->{inform};
|
||||
|
@ -5,7 +5,6 @@ package main;
|
||||
use strict;
|
||||
use warnings;
|
||||
use IO::Socket;
|
||||
use Errno qw(:POSIX);
|
||||
|
||||
sub
|
||||
TcpServer_Open($$$)
|
||||
@ -57,7 +56,7 @@ TcpServer_Accept($$)
|
||||
my $name = $hash->{NAME};
|
||||
my @clientinfo = $hash->{SERVERSOCKET}->accept();
|
||||
if(!@clientinfo) {
|
||||
Log3 $name, 1, "Accept failed ($name: $!)" if($! != EAGAIN());
|
||||
Log3 $name, 1, "Accept failed ($name: $!)" if($! != EAGAIN);
|
||||
return undef;
|
||||
}
|
||||
$hash->{CONNECTS}++;
|
||||
|
59
fhem/fhem.pl
59
fhem/fhem.pl
@ -219,7 +219,7 @@ use vars qw(%readyfnlist); # devices which want a "readyfn"
|
||||
use vars qw(%selectlist); # devices which want a "select"
|
||||
use vars qw(%value); # Current values, see commandref.html
|
||||
use vars qw($lastDefChange); # number of last def/attr change
|
||||
use vars qw($lastSavedChange); # will be synced with lastDefChange on save
|
||||
use vars qw(@structChangeHist); # Contains the last 10 structural changes
|
||||
use vars qw($cmdFromAnalyze); # used by the warnings-sub
|
||||
|
||||
my $AttrList = "verbose:0,1,2,3,4,5 room group comment alias ".
|
||||
@ -242,7 +242,6 @@ my @cmdList; # Remaining commands in a chain. Used by sleep
|
||||
|
||||
$init_done = 0;
|
||||
$lastDefChange = 0;
|
||||
$lastSavedChange = 0;
|
||||
$readytimeout = ($^O eq "MSWin32") ? 0.1 : 5.0;
|
||||
|
||||
|
||||
@ -508,7 +507,6 @@ foreach my $d (keys %defs) {
|
||||
}
|
||||
}
|
||||
|
||||
$lastSavedChange = $lastDefChange;
|
||||
DoTrigger("global", "INITIALIZED", 1);
|
||||
$fhem_started = time;
|
||||
|
||||
@ -1234,7 +1232,7 @@ CommandRereadCfg($$)
|
||||
|
||||
$defs{$name} = $selectlist{$name} = $cl if($name && $name ne "__anonymous__");
|
||||
$inform{$name} = $informMe if($informMe);
|
||||
$lastSavedChange = $lastDefChange;
|
||||
@structChangeHist = ();
|
||||
DoTrigger("global", "REREADCFG", 1);
|
||||
|
||||
$init_done = 1;
|
||||
@ -1327,6 +1325,12 @@ CommandSave($$)
|
||||
{
|
||||
my ($cl, $param) = @_;
|
||||
|
||||
if($param eq "?") {
|
||||
return "No structural changes." if(!@structChangeHist);
|
||||
return "Last 10 structural changes:\n ".join("\n ", @structChangeHist);
|
||||
}
|
||||
|
||||
@structChangeHist = ();
|
||||
DoTrigger("global", "SAVE", 1);
|
||||
|
||||
my $ret = WriteStatefile();
|
||||
@ -1413,7 +1417,6 @@ CommandSave($$)
|
||||
$ret .= "$key: $!" if(!close($fh{$key}));
|
||||
}
|
||||
|
||||
$lastSavedChange = $lastDefChange;
|
||||
return ($ret ? $ret : "Wrote configuration to $param");
|
||||
}
|
||||
|
||||
@ -1619,9 +1622,9 @@ CommandDefine($$)
|
||||
$modules{$m}{NotifyOrderPrefix} : "50-") . $name;
|
||||
}
|
||||
%ntfyHash = ();
|
||||
addStructChange("define", $name, $def);
|
||||
DoTrigger("global", "DEFINED $name", 1) if($init_done);
|
||||
}
|
||||
$lastDefChange++ if(!$hash{TEMPORARY});
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@ -1647,11 +1650,11 @@ CommandModify($$)
|
||||
if($ret) {
|
||||
$hash->{DEF} = $hash->{OLDDEF};
|
||||
} else {
|
||||
addStructChange("modify", $a[0], $def);
|
||||
DoTrigger("global", "MODIFIED $a[0]", 1) if($init_done);
|
||||
}
|
||||
|
||||
delete($hash->{OLDDEF});
|
||||
$lastDefChange++ if(!$hash->{TEMPORARY});
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@ -1714,7 +1717,7 @@ CommandDelete($$)
|
||||
my ($cl, $def) = @_;
|
||||
return "Usage: delete <name>$namedef\n" if(!$def);
|
||||
|
||||
my (@rets, $isReal);
|
||||
my @rets;
|
||||
foreach my $sdev (devspec2array($def)) {
|
||||
if(!defined($defs{$sdev})) {
|
||||
push @rets, "Please define $sdev first";
|
||||
@ -1732,7 +1735,6 @@ CommandDelete($$)
|
||||
next;
|
||||
}
|
||||
|
||||
$isReal = 1 if(!$defs{$sdev}{TEMPORARY});
|
||||
|
||||
# Delete releated hashes
|
||||
foreach my $p (keys %selectlist) {
|
||||
@ -1745,13 +1747,13 @@ CommandDelete($$)
|
||||
if($readyfnlist{$p} && $readyfnlist{$p}{NAME} eq $sdev);
|
||||
}
|
||||
|
||||
delete($attr{$sdev});
|
||||
my $temporary = $defs{$sdev}{TEMPORARY};
|
||||
delete($defs{$sdev}); # Remove the main entry
|
||||
addStructChange("delete", $sdev, $sdev) if(!$temporary);
|
||||
delete($attr{$sdev});
|
||||
delete($defs{$sdev});
|
||||
DoTrigger("global", "DELETED $sdev", 1) if(!$temporary);
|
||||
|
||||
}
|
||||
$lastDefChange++ if($isReal);
|
||||
return join("\n", @rets);
|
||||
}
|
||||
|
||||
@ -1764,7 +1766,7 @@ CommandDeleteAttr($$)
|
||||
my @a = split(" ", $def, 2);
|
||||
return "Usage: deleteattr <name> [<attrname>]\n$namedef" if(@a < 1);
|
||||
|
||||
my (@rets, $isReal);
|
||||
my @rets;
|
||||
foreach my $sdev (devspec2array($a[0])) {
|
||||
|
||||
if(!defined($defs{$sdev})) {
|
||||
@ -1784,21 +1786,20 @@ CommandDeleteAttr($$)
|
||||
next;
|
||||
}
|
||||
|
||||
$isReal = 1 if(!$defs{$sdev}{TEMPORARY});
|
||||
|
||||
if(@a == 1) {
|
||||
delete($attr{$sdev});
|
||||
addStructChange("deleteAttr", $sdev, $def);
|
||||
DoTrigger("global", "DELETEATTR $sdev", 1) if($init_done);
|
||||
|
||||
} else {
|
||||
delete($attr{$sdev}{$a[1]}) if(defined($attr{$sdev}));
|
||||
addStructChange("deleteAttr", $sdev, $def);
|
||||
DoTrigger("global", "DELETEATTR $sdev $a[1]", 1) if($init_done);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$lastDefChange++ if($isReal);
|
||||
return join("\n", @rets);
|
||||
}
|
||||
|
||||
@ -2101,8 +2102,8 @@ CommandRename($$)
|
||||
|
||||
CallFn($new, "RenameFn", $new,$old);# ignore replies
|
||||
|
||||
addStructChange("rename", $new, $param);
|
||||
DoTrigger("global", "RENAMED $old $new", 1);
|
||||
$lastDefChange++ if(!$defs{$new}{TEMPORARY});
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -2239,7 +2240,7 @@ sub
|
||||
CommandAttr($$)
|
||||
{
|
||||
my ($cl, $param) = @_;
|
||||
my ($ret, $isReal, @a);
|
||||
my ($ret, @a);
|
||||
|
||||
@a = split(" ", $param, 3) if($param);
|
||||
|
||||
@ -2315,8 +2316,6 @@ CommandAttr($$)
|
||||
next;
|
||||
}
|
||||
|
||||
$isReal = 1 if(!$defs{$sdev}{TEMPORARY});
|
||||
|
||||
$a[0] = $sdev;
|
||||
$ret = CallFn($sdev, "AttrFn", "set", @a);
|
||||
if($ret) {
|
||||
@ -2326,6 +2325,12 @@ CommandAttr($$)
|
||||
|
||||
my $val = $a[2];
|
||||
$val = 1 if(!defined($val));
|
||||
|
||||
addStructChange("attr", $sdev, $param)
|
||||
if(!($attr{$sdev} &&
|
||||
defined($attr{$sdev}{$attrName}) &&
|
||||
$attr{$sdev}{$attrName} eq $val));
|
||||
|
||||
$attr{$sdev}{$attrName} = $val;
|
||||
|
||||
if($attrName eq "IODev") {
|
||||
@ -2342,7 +2347,6 @@ CommandAttr($$)
|
||||
|
||||
}
|
||||
|
||||
$lastDefChange++ if($isReal);
|
||||
Log 3, join(" ", @rets) if(!$cl && @rets);
|
||||
return join("\n", @rets);
|
||||
}
|
||||
@ -4075,5 +4079,18 @@ setKeyValue($$)
|
||||
return FileWrite($fName, @new);
|
||||
}
|
||||
|
||||
sub
|
||||
addStructChange($$$)
|
||||
{
|
||||
return if(!$init_done);
|
||||
|
||||
my ($cmd, $dev, $param) = @_;
|
||||
return if(!$defs{$dev} || $defs{$dev}{TEMPORARY});
|
||||
|
||||
$lastDefChange++;
|
||||
shift @structChangeHist if(@structChangeHist > 10);
|
||||
$param = substr($param, 0, 40)."..." if(length($param) > 40);
|
||||
push @structChangeHist, "$cmd $param";
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -112,6 +112,13 @@ FW_jqueryReadyFn()
|
||||
});
|
||||
*/
|
||||
|
||||
$("#saveCheck")
|
||||
.css("cursor", "pointer")
|
||||
.click(function(){
|
||||
FW_cmd(FW_root+"?cmd=save ?&XHR=1", function(data) {
|
||||
FW_okDialog('<pre>'+data+'</pre>');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user