countdown: convert datetime server-side into a duration to avoid problems with wrong time or timezone on client

This commit is contained in:
Ralf Becker 2021-01-28 16:02:38 +02:00
parent 69b33e9288
commit 5b4a436ab3
4 changed files with 72 additions and 6 deletions

View File

@ -34,7 +34,9 @@ var et2_core_valueWidget_1 = require("./et2_core_valueWidget");
/** /**
* Class which implements the "countdown" XET-Tag * Class which implements the "countdown" XET-Tag
* *
* Value for countdown is the expiry date of the counter. * Value for countdown is the expiry date of the counter or a numeric timeout in seconds.
*
* The timeout has the benefit, that it does not depend on the correct set time and timezone of the browser / computer of the user.
*/ */
var et2_countdown = /** @class */ (function (_super) { var et2_countdown = /** @class */ (function (_super) {
__extends(et2_countdown, _super); __extends(et2_countdown, _super);
@ -65,11 +67,21 @@ var et2_countdown = /** @class */ (function (_super) {
// create a date widget // create a date widget
_this.time = et2_core_widget_1.et2_createWidget('date-time', {}); _this.time = et2_core_widget_1.et2_createWidget('date-time', {});
_this.setDOMNode(_this.container[0]); _this.setDOMNode(_this.container[0]);
_this.offset = (new Date).getTimezoneOffset();
return _this; return _this;
} }
et2_countdown.prototype.set_value = function (_time) { et2_countdown.prototype.set_value = function (_time) {
if (_time == "") if (_time == "")
return; return;
if (!isNaN(_time)) {
var t = new Date();
t.setSeconds(t.getSeconds() + parseInt(_time));
_time = t;
this.offset = 0;
}
else {
this.offset = (new Date).getTimezoneOffset();
}
this.time.set_value(_time); this.time.set_value(_time);
var self = this; var self = this;
this.timer = setInterval(function () { this.timer = setInterval(function () {
@ -82,7 +94,7 @@ var et2_countdown = /** @class */ (function (_super) {
}; };
et2_countdown.prototype._updateTimer = function () { et2_countdown.prototype._updateTimer = function () {
var tempDate = new Date(); var tempDate = new Date();
var now = new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate(), tempDate.getHours(), tempDate.getMinutes() - tempDate.getTimezoneOffset(), tempDate.getSeconds()); var now = new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate(), tempDate.getHours(), tempDate.getMinutes() - this.offset, tempDate.getSeconds());
var time = new Date(this.time.getValue()); var time = new Date(this.time.getValue());
var distance = time.getTime() - now.getTime(); var distance = time.getTime() - now.getTime();
if (distance < 0) if (distance < 0)

View File

@ -23,7 +23,9 @@ import {et2_valueWidget} from "./et2_core_valueWidget";
/** /**
* Class which implements the "countdown" XET-Tag * Class which implements the "countdown" XET-Tag
* *
* Value for countdown is the expiry date of the counter. * Value for countdown is the expiry date of the counter or a numeric timeout in seconds.
*
* The timeout has the benefit, that it does not depend on the correct set time and timezone of the browser / computer of the user.
*/ */
export class et2_countdown extends et2_valueWidget { export class et2_countdown extends et2_valueWidget {
static readonly _attributes: any = { static readonly _attributes: any = {
@ -57,7 +59,6 @@ export class et2_countdown extends et2_valueWidget {
default: "", default: "",
description: "Defines a callback to gets called at alarm - timer. This only will work if there's an alarm set." description: "Defines a callback to gets called at alarm - timer. This only will work if there's an alarm set."
} }
}; };
private time : et2_date; private time : et2_date;
@ -68,6 +69,7 @@ export class et2_countdown extends et2_valueWidget {
private hours : JQuery = null; private hours : JQuery = null;
private minutes : JQuery = null; private minutes : JQuery = null;
private seconds : JQuery = null; private seconds : JQuery = null;
private offset;
/** /**
* Constructor * Constructor
@ -90,11 +92,23 @@ export class et2_countdown extends et2_valueWidget {
// create a date widget // create a date widget
this.time = <et2_date> et2_createWidget('date-time', {}); this.time = <et2_date> et2_createWidget('date-time', {});
this.setDOMNode(this.container[0]); this.setDOMNode(this.container[0]);
this.offset = (new Date).getTimezoneOffset();
} }
public set_value(_time) public set_value(_time)
{ {
if (_time == "") return; if (_time == "") return;
if (!isNaN(_time))
{
let t = new Date();
t.setSeconds(t.getSeconds()+parseInt(_time));
_time = t;
this.offset = 0;
}
else
{
this.offset = (new Date).getTimezoneOffset();
}
this.time.set_value(_time); this.time.set_value(_time);
let self = this; let self = this;
this.timer = setInterval(function(){ this.timer = setInterval(function(){
@ -114,7 +128,7 @@ export class et2_countdown extends et2_valueWidget {
tempDate.getMonth(), tempDate.getMonth(),
tempDate.getDate(), tempDate.getDate(),
tempDate.getHours(), tempDate.getHours(),
tempDate.getMinutes()-tempDate.getTimezoneOffset(), tempDate.getMinutes()-this.offset,
tempDate.getSeconds() tempDate.getSeconds()
); );

View File

@ -0,0 +1,40 @@
<?php
/**
* EGroupware - eTemplate serverside countdown widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <rb@egroupware.org>
* @copyright 2021 by rb@egroupware.org
*/
namespace EGroupware\Api\Etemplate\Widget;
use EGroupware\Api;
/**
* eTemplate countdown widget
*
*/
class Countdown extends Api\Etemplate\Widget
{
/**
* Convert end-datetime of countdown into a difference in seconds to avoid errors due to wrong time&timezone on client
*
* @param string $cname
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
*/
public function beforeSendToClient($cname, array $expand=null)
{
$form_name = self::form_name($cname, $this->id, $expand);
$value =& self::get_array(self::$request->content, $form_name, false, true);
if ($value)
{
$value = Api\DateTime::to($value, 'utc') - Api\DateTime::to('now', 'utc');
}
}
}
\EGroupware\Api\Etemplate\Widget::registerWidget(Countdown::class, 'countdown');

View File

@ -256,4 +256,4 @@ class Date extends Transformer
} }
} }
} }
\EGroupware\Api\Etemplate\Widget::registerWidget(__NAMESPACE__.'\\Date', array('time_or_date', 'countdown')); \EGroupware\Api\Etemplate\Widget::registerWidget(__NAMESPACE__.'\\Date', array('time_or_date'));