Image caching improved

This commit is contained in:
Juan Ferrer 2019-05-27 15:38:06 +02:00
parent fb422846dd
commit dc41737464
11 changed files with 167 additions and 170 deletions

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
hedera-web (1.406.48) stable; urgency=low hedera-web (1.406.49) stable; urgency=low
* Initial Release. * Initial Release.

View File

@ -3,6 +3,6 @@ Hedera.Items = new Class({
Extends: Hedera.Form, Extends: Hedera.Form,
activate: function() { activate: function() {
this.$('items').setInfo('item', 'item', 'vn', ['id']); this.$('items').setInfo('i', 'item', 'vn', ['id']);
} }
}); });

View File

@ -19,9 +19,9 @@
{ {
margin-right: 1em; margin-right: 1em;
float: left; float: left;
border-radius: 50%; border-radius: 3%;
height: 3.2em; height: 5.5em;
width: 3.2em; width: 5.5em;
} }
.items .row > p .items .row > p
{ {

View File

@ -13,12 +13,16 @@
<div class="rows box"> <div class="rows box">
<htk-repeater form-id="iter" empty-message="_Enter a search term"> <htk-repeater form-id="iter" empty-message="_Enter a search term">
<db-model property="model" id="items"> <db-model property="model" id="items">
SELECT id, longName, size, category, image, SELECT i.id, i.longName, i.size, i.category,
value5, value6, value7 i.value5, i.value6, i.value7,
FROM vn.item i.image, im.updated
WHERE longName LIKE CONCAT('%', #filter, '%') FROM vn.item i
OR id = #filter LEFT JOIN image im
ORDER BY longName LIMIT 50 ON im.collectionFk = 'catalog'
AND im.name = i.image
WHERE i.longName LIKE CONCAT('%', #filter, '%')
OR i.id = #filter
ORDER BY i.longName LIMIT 50
<sql-batch property="batch"> <sql-batch property="batch">
<custom> <custom>
<item name="filter" param="filter"/> <item name="filter" param="filter"/>
@ -30,6 +34,7 @@
<htk-image <htk-image
form="iter" form="iter"
column="image" column="image"
stamp-column="updated"
class="photo" class="photo"
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"

View File

@ -29,10 +29,14 @@
<div class="lines"> <div class="lines">
<htk-repeater form-id="iter" renderer="repeaterFunc"> <htk-repeater form-id="iter" renderer="repeaterFunc">
<db-model id="items" property="model" updatable="true"> <db-model id="items" property="model" updatable="true">
SELECT bi.id, bi.amount, bi.price, i.longName item, i.image, SELECT bi.id, bi.amount, bi.price, i.longName item,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7 i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
i.image, im.updated
FROM myBasketItem bi FROM myBasketItem bi
JOIN vn.item i ON i.id = bi.itemFk JOIN vn.item i ON i.id = bi.itemFk
LEFT JOIN image im
ON im.collectionFk = 'catalog'
AND im.name = i.image
</db-model> </db-model>
<custom> <custom>
<div class="line"> <div class="line">
@ -46,6 +50,7 @@
<htk-image <htk-image
form="iter" form="iter"
column="image" column="image"
stamp-column="updated"
class="photo" class="photo"
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"

View File

@ -60,11 +60,14 @@
JOIN vn.itemType t ON t.id = i.typeFk JOIN vn.itemType t ON t.id = i.typeFk
WHERE #filter; WHERE #filter;
CALL bionic_calc; CALL bionic_calc;
SELECT i.id, i.description, i.image, i.longName item, SELECT i.id, i.description, i.longName item,
i.subName, i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7, i.subName, i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
b.available, b.price b.available, b.price, i.image, im.updated
FROM tmp.bionic_item b FROM tmp.bionic_item b
JOIN vn.item i ON i.id = b.item_id JOIN vn.item i ON i.id = b.item_id
LEFT JOIN image im
ON im.collectionFk = 'catalog'
AND im.name = i.image
WHERE b.available > 0 WHERE b.available > 0
ORDER BY i.relevancy DESC, i.name, i.size ORDER BY i.relevancy DESC, i.name, i.size
LIMIT 400; LIMIT 400;
@ -113,6 +116,7 @@
subdir="200x200" subdir="200x200"
form="item" form="item"
column="image" column="image"
stamp-column="updated"
full-dir="1600x900"/> full-dir="1600x900"/>
<div class="item-info"> <div class="item-info">
<htk-button <htk-button
@ -387,6 +391,7 @@
subdir="200x200" subdir="200x200"
form="card" form="card"
column="image" column="image"
stamp-column="updated"
full-dir="1600x900" full-dir="1600x900"
conn="conn" conn="conn"
editable="true"/> editable="true"/>

View File

@ -75,6 +75,7 @@
<htk-image <htk-image
form="iter" form="iter"
column="image" column="image"
stamp-column="updated"
class="photo" class="photo"
directory="catalog" directory="catalog"
subdir="200x200" subdir="200x200"

View File

@ -1,81 +1,71 @@
var Widget = require ('./widget'); var Widget = require('./widget');
module.exports = new Class module.exports = new Class({
({
Extends: Widget Extends: Widget
,Tag: 'htk-field' ,Tag: 'htk-field'
,Child: 'param' ,Child: 'param'
,Properties: ,Properties:
{ {
value: value: {
{
type: String type: String
,set: function (x) ,set: function(x) {
{ if (Vn.Value.compare(x, this._value))
if (Vn.Value.compare (x, this._value))
return; return;
if (x instanceof Date) if (x instanceof Date)
x = x.clone (); x = x.clone();
this.valueChanged (x); this.valueChanged(x);
this.putValue (x); this.putValue(x);
} }
,get: function (x) ,get: function(x) {
{
return this._value; return this._value;
} }
}, },
param: param: {
{
type: Vn.Param type: Vn.Param
,set: function (x) ,set: function(x) {
{ this.link({_param: x}, {'changed': this.onParamChange});
this.link ({_param: x}, {'changed': this.onParamChange}); this.onParamChange();
this.onParamChange ();
} }
,get: function () ,get: function() {
{
return this._param; return this._param;
} }
}, },
editable: editable: {
{
type: Boolean type: Boolean
,set: function (x) ,set: function(x) {
{ if (x != this._editable) {
if (x != this._editable)
{
this._editable = x; this._editable = x;
this.setEditable (x); this.setEditable(x);
} }
} }
,get: function () ,get: function() {
{
return this._editable; return this._editable;
} }
}, },
form: form: {
{
type: Db.Iterator type: Db.Iterator
,set: function (x) ,set: function(x) {
{
this._form = x; this._form = x;
this.bindToForm (); this.bindToForm();
}
,get: function() {
return this._form;
} }
}, },
column: column: {
{
type: String type: String
,set: function (x) ,set: function(x) {
{
this._paramName = x; this._paramName = x;
this.bindToForm (); this.bindToForm();
}
,get: function() {
return this._paramName;
} }
}, },
conditionalFunc: conditionalFunc: {
{
type: Function type: Function
,value: null ,value: null
} }
@ -87,18 +77,15 @@ module.exports = new Class
,_blockParamChange: false ,_blockParamChange: false
,_blockValueChange: false ,_blockValueChange: false
,onParamChange: function () ,onParamChange: function() {
{ if (!this._blockValueChange) {
if (!this._blockValueChange)
{
this._blockParamChange = true; this._blockParamChange = true;
this.value = this._param.value; this.value = this._param.value;
this._blockParamChange = false; this._blockParamChange = false;
} }
} }
,bindToForm: function () ,bindToForm: function() {
{
if (this._form && this._paramName) if (this._form && this._paramName)
this.param = new Db.Param this.param = new Db.Param
({ ({
@ -113,7 +100,7 @@ module.exports = new Class
* *
* @param {Boolean} editable Whether the user is allowed to edit the entry * @param {Boolean} editable Whether the user is allowed to edit the entry
**/ **/
,setEditable: function (editable) {} ,setEditable: function(editable) {}
/** /**
* Virtual method that must be implemented by class childs to put the value * Virtual method that must be implemented by class childs to put the value
@ -121,7 +108,7 @@ module.exports = new Class
* *
* @param {Object} value The new value for the entry * @param {Object} value The new value for the entry
**/ **/
,putValue: function (value) {} ,putValue: function(value) {}
/** /**
* Protected method that should be called from class childs when the value * Protected method that should be called from class childs when the value
@ -129,21 +116,19 @@ module.exports = new Class
* *
* @param {Object} value The new entry value * @param {Object} value The new entry value
**/ **/
,valueChanged: function (value) ,valueChanged: function(value) {
{
this._value = value; this._value = value;
if (this.conditionalFunc) if (this.conditionalFunc)
this.conditionalFunc (this, value); this.conditionalFunc(this, value);
if (this._param && !this._blockParamChange) if (this._param && !this._blockParamChange) {
{
this._blockValueChange = true; this._blockValueChange = true;
this._param.value = value; this._param.value = value;
this._blockValueChange = false; this._blockValueChange = false;
} }
this.signalEmit ('changed'); this.signalEmit('changed');
} }
}); });

View File

@ -1,8 +1,7 @@
/** /**
* Class to display or edit an image. Also it allows to show it's full version. * Class to display or edit an image. Also it allows to show it's full version.
**/ **/
module.exports = new Class module.exports = new Class({
({
Extends: Htk.Field Extends: Htk.Field
,Tag: 'htk-image' ,Tag: 'htk-image'
,Properties: ,Properties:
@ -10,56 +9,59 @@ module.exports = new Class
/** /**
* The directory where the images are allocated. * The directory where the images are allocated.
**/ **/
directory: directory: {
{
type: String type: String
,set: function (x) ,set: function(x) {
{
this._directory = x; this._directory = x;
this._refreshSrc (); this._refreshSrc();
} }
,get: function () ,get: function() {
{
return this._directory; return this._directory;
} }
}, },
/** /**
* The subdirectory where the images are allocated. * The subdirectory where the images are allocated.
**/ **/
subdir: subdir: {
{
type: String type: String
,set: function (x) ,set: function(x) {
{
this._subdir = x; this._subdir = x;
this._refreshSrc (); this._refreshSrc();
} }
,get: function () ,get: function() {
{
return this._subdir; return this._subdir;
} }
}, },
/**
* The timestamp field of the last update, used for caching purposes.
**/
stampColumn: {
type: String
,set: function(x) {
this._stampColumn = x;
this._refreshSrc();
}
,get: function() {
return this._stampColumn;
}
},
/** /**
* Whether to show the full image when mouse hover. * Whether to show the full image when mouse hover.
**/ **/
fullDir: fullDir: {
{
type: String type: String
,set: function (x) ,set: function(x) {
{
this._fullDir = x; this._fullDir = x;
this._refreshClick (); this._refreshClick();
} }
,get: function () ,get: function() {
{
return this._fullDir; return this._fullDir;
} }
}, },
/** /**
* The REST connection used to upload the image. * The REST connection used to upload the image.
**/ **/
conn: conn: {
{
type: Vn.JsonConnection type: Vn.JsonConnection
} }
} }
@ -70,67 +72,59 @@ module.exports = new Class
,_error: false ,_error: false
,_editable: false ,_editable: false
,render: function () ,render: function() {
{ var node = this.createRoot('div');
var node = this.createRoot ('div');
node.className = 'htk-image'; node.className = 'htk-image';
var img = this.img = this.createElement ('img'); var img = this.img = this.createElement('img');
img.addEventListener ('error', this._onImageError.bind (this)); img.addEventListener('error', this._onImageError.bind(this));
node.appendChild (img); node.appendChild(img);
this.setEditable (); this.setEditable();
this._refreshClick (); this._refreshClick();
this._refreshSrc (); this._refreshSrc();
} }
,_refreshClick: function () ,_refreshClick: function() {
{
if (!this.node) if (!this.node)
return; return;
if (this.clickHandler) if (this.clickHandler) {
{ Vn.Node.removeClass(this.node, 'clickable');
Vn.Node.removeClass (this.node, 'clickable'); this.node.removeEventListener('click', this.clickHandler);
this.node.removeEventListener ('click', this.clickHandler);
this.clickHander = null; this.clickHander = null;
} }
if (this._fullDir) if (this._fullDir) {
{ this.clickHandler = this._onClick.bind(this);
this.clickHandler = this._onClick.bind (this); this.node.addEventListener('click', this.clickHandler);
this.node.addEventListener ('click', this.clickHandler); Vn.Node.addClass(this.node, 'clickable');
Vn.Node.addClass (this.node, 'clickable');
} }
} }
,setEditable: function () ,setEditable: function() {
{
if (!this.node) if (!this.node)
return; return;
if (this.editButton) if (this.editButton) {
{ this.node.removeChild(this.editButton);
this.node.removeChild (this.editButton);
this.editButton = null; this.editButton = null;
} }
if (this._editable) if (this._editable) {
{ var button = this.createElement('button');
var button = this.createElement ('button'); button.addEventListener('click', this._onEditClick.bind(this));
button.addEventListener ('click', this._onEditClick.bind (this));
button.title = _('UpdateImage'); button.title = _('UpdateImage');
this.node.appendChild (button); this.node.appendChild(button);
var icon = new Htk.Icon ({icon: 'add-photo'}); var icon = new Htk.Icon({icon: 'add-photo'});
button.appendChild (icon.node); button.appendChild(icon.node);
this.editButton = button; this.editButton = button;
} }
} }
,_makeSrc: function (subdir) ,_makeSrc: function(subdir) {
{
var src = Vn.Config.imageUrl +'/'; var src = Vn.Config.imageUrl +'/';
if (this._directory) if (this._directory)
@ -139,78 +133,68 @@ module.exports = new Class
src += subdir +'/'; src += subdir +'/';
src += this._value; src += this._value;
if (this._stamp) if (this._stamp)
src += '?'+ this._stamp; src += '?'+ this._stamp;
else if (this._stampColumn && this.form)
src += '?'+ this.form.get(this._stampColumn);
return src; return src;
} }
,_refreshSrc: function () ,_refreshSrc: function() {
{
if (!this.node) if (!this.node)
return; return;
if (this._value) if (this._value) {
{
this._error = false; this._error = false;
this.img.src = this._makeSrc (this._subdir); this.img.src = this._makeSrc(this._subdir);
} } else
else
delete this.img.src; delete this.img.src;
} }
,putValue: function (value) ,putValue: function() {
{ this._refreshSrc();
this._refreshSrc ();
} }
,_onImageError: function () ,_onImageError: function() {
{
this._error = true; this._error = true;
} }
,_onClick: function () ,_onClick: function() {
{
if (!this._fullDir || !this._value || this._error) if (!this._fullDir || !this._value || this._error)
return; return;
(new Htk.FullImage ()).show (this._makeSrc (this._fullDir)); (new Htk.FullImage()).show(this._makeSrc(this._fullDir));
} }
,_onEditClick: function (event) ,_onEditClick: function(event) {
{ event.stopPropagation();
event.stopPropagation ();
var editor = new Htk.ImageEditor ({conn: this.conn}); var editor = new Htk.ImageEditor({conn: this.conn});
editor.setData (this.value, this._directory); editor.setData(this.value, this._directory);
editor.on ('name-changed', this._onNameChange, this); editor.on('name-changed', this._onNameChange, this);
editor.on ('file-uploaded', this._onFileUpload, this); editor.on('file-uploaded', this._onFileUpload, this);
editor.on ('closed', this._onEditorClose, this); editor.on('closed', this._onEditorClose, this);
this.popup = new Htk.Popup this.popup = new Htk.Popup({
({
modal: true, modal: true,
child: editor child: editor
}); });
this.popup.show (this.node); this.popup.show(this.node);
} }
,_onNameChange: function (editor, value) ,_onNameChange: function(editor, value) {
{
this.value = value; this.value = value;
} }
,_onFileUpload: function (cell, editor) ,_onFileUpload: function(cell) {
{ this._stamp = new Date().getTime();
this._stamp = new Date ().getTime (); this._refreshSrc(cell);
this._refreshSrc (cell); this.popup.hide();
this.popup.hide ();
} }
,_onEditorClose: function (editor) ,_onEditorClose: function(editor) {
{ editor.disconnectByInstance(this);
editor.disconnectByInstance (this);
} }
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "hedera-web", "name": "hedera-web",
"version": "1.406.48", "version": "1.406.49",
"description": "Verdnatura web page", "description": "Verdnatura web page",
"license": "GPL-3.0", "license": "GPL-3.0",
"repository": { "repository": {

View File

@ -108,9 +108,21 @@ class Upload extends Vn\Web\JsonRequest {
Image::resizeSave($image, $dstFile, $i['height'], $i['width'], $i['crop'], $symbolicSrc); Image::resizeSave($image, $dstFile, $i['height'], $i['width'], $i['crop'], $symbolicSrc);
} }
$query =
"INSERT INTO `image`
SET `collectionFk` = #collection,
`name` = #name,
`updated` = UNIX_TIMESTAMP()
ON DUPLICATE KEY UPDATE
`updated` = VALUES(updated)";
$db->query ($query, [
'collection' => $collection,
'name' => $name
]);
imagedestroy($image); imagedestroy($image);
unlink($tmpName); unlink($tmpName);
return TRUE; return TRUE;
} }
} }