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