Commit 434ca4cc authored by Malcolm Blaney's avatar Malcolm Blaney

Fix gitlab runner dependency conflict between php 7 and mysql 8.

Add support to Banking module for BuyerGroup to be called from
Cart module. Cart module now supports different price levels for
logged in users, and can display items from the Stock module.
The Stock module now supports updating images for stock items so
that they can also be used by the Cart module. The Browser module
is called from the stock grid, and it now shows upload progress
and image search. Cart sales are also saved to the purchase and
payment modules when items are tracked from the Stock module.
parent 5dfba66a
Pipeline #23602659 passed with stage
in 1 minute and 24 seconds
image: php:latest image: php:latest
services: services:
- mysql:latest - mysql:5.7
variables: variables:
MYSQL_DATABASE: dobrado_test MYSQL_DATABASE: dobrado_test
......
This diff is collapsed.
<?php <?php
// Dobrado Content Management System // Dobrado Content Management System
// Copyright (C) 2016 Malcolm Blaney // Copyright (C) 2018 Malcolm Blaney
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
...@@ -51,13 +51,21 @@ class Browser extends Base { ...@@ -51,13 +51,21 @@ class Browser extends Base {
public function Content($id) { public function Content($id) {
if (!$this->user->loggedIn) return ''; if (!$this->user->loggedIn) return '';
$content = '<form id="upload-form">'. $content = '<form id="browser-upload-form">' .
'Upload a file: <input id="upload-input" name="upload" type="file">'. '<div class="form-spacing">' .
'<button class="upload">upload</button>'. '<label for="browser-upload-input">Upload a file:</label>' .
'</form>'; '<input id="browser-upload-input" name="upload" type="file">' .
'<button id="browser-upload">upload</button>' .
'</div>' .
'<div id="browser-upload-progress"></div>' .
'</form>' .
'<div class="form-spacing">' .
'<label for="browser-search">Search:</label>' .
'<input id="browser-search" type="text">' .
'</div>';
$html_path = $this->user->name === 'admin' ? '/public/' : $html_path = $this->user->name === 'admin' ? '/public/' :
'/'.$this->user->name.'/public/'; '/' . $this->user->name . '/public/';
// Display thumbnails for all files in this user's public folder. // Display thumbnails for all files in this user's public folder.
if ($handle = opendir($this->PublicDirectory())) { if ($handle = opendir($this->PublicDirectory())) {
while (($file = readdir($handle)) !== false) { while (($file = readdir($handle)) !== false) {
...@@ -70,18 +78,19 @@ class Browser extends Base { ...@@ -70,18 +78,19 @@ class Browser extends Base {
$type = $matches[2]; $type = $matches[2];
$src = ''; $src = '';
if (in_array(strtolower($type), ['gif', 'jpeg', 'jpg', 'png'])) { if (in_array(strtolower($type), ['gif', 'jpeg', 'jpg', 'png'])) {
$name .= '_thumb.'.$type; $name .= '_thumb.' . $type;
if (file_exists($this->PublicDirectory($name))) { if (file_exists($this->PublicDirectory($name))) {
$src = '<img src="'.$html_path.$name.'">'; $src = '<img title = "' . $file . '" src="' . $html_path .
$name . '">';
} }
else { else {
$src = '<b>no thumbnail</b>'; $src = '<b title="' . $file . '">no thumbnail</b>';
} }
} }
else { else {
$src = '<b>'.$type.'</b>'; $src = '<b title="' . $file . '">' . $type . '</b>';
} }
$content .= $this->ImageContent($src, $html_path.$file); $content .= $this->ImageContent($src, $html_path . $file);
} }
} }
} }
...@@ -111,9 +120,11 @@ class Browser extends Base { ...@@ -111,9 +120,11 @@ class Browser extends Base {
public function Install($path) { public function Install($path) {
$this->AppendScript($path, 'dobrado.browser.js', false); $this->AppendScript($path, 'dobrado.browser.js', false);
$site_style = ['"",".browser","display","none"', $site_style = ['"",".browser","display","none"',
'"",".upload","float","right"', '"","#browser-upload","float","right"',
'"","#upload-form","padding","20px 0px"', '"","#browser-upload-form","padding","20px 0px"',
'"","#upload-form","border-bottom","2px solid #777777"', '"","#browser-upload-form","border-bottom",' .
'"2px solid #777777"',
'"","#browser-upload-progress","display","none"',
'"",".thumbnail.highlight","background-color","#fffeee"', '"",".thumbnail.highlight","background-color","#fffeee"',
'"",".thumbnail.highlight","border","2px solid #cccccc"', '"",".thumbnail.highlight","border","2px solid #cccccc"',
'"",".thumbnail.highlight","padding","5px"', '"",".thumbnail.highlight","padding","5px"',
...@@ -161,7 +172,7 @@ class Browser extends Base { ...@@ -161,7 +172,7 @@ class Browser extends Base {
$type = $matches[2]; $type = $matches[2];
unlink($this->PublicDirectory($us_file)); unlink($this->PublicDirectory($us_file));
if (in_array(strtolower($type), ['gif', 'jpeg', 'jpg', 'png'])) { if (in_array(strtolower($type), ['gif', 'jpeg', 'jpg', 'png'])) {
unlink($this->PublicDirectory($name.'_thumb.'.$type)); unlink($this->PublicDirectory($name . '_thumb.' . $type));
} }
return ['done' => true]; return ['done' => true];
} }
...@@ -170,7 +181,7 @@ class Browser extends Base { ...@@ -170,7 +181,7 @@ class Browser extends Base {
private function UploadFile() { private function UploadFile() {
// First check if the user's upload directory is at capacity. // First check if the user's upload directory is at capacity.
$handle = popen('/usr/bin/du -sm '.$this->PublicDirectory(), 'r'); $handle = popen('/usr/bin/du -sm ' . $this->PublicDirectory(), 'r');
$size = fgets($handle); $size = fgets($handle);
pclose($handle); pclose($handle);
if (!preg_match('/^([0-9]+)/', $size, $matches)) { if (!preg_match('/^([0-9]+)/', $size, $matches)) {
...@@ -183,7 +194,8 @@ class Browser extends Base { ...@@ -183,7 +194,8 @@ class Browser extends Base {
$max_file_size = $this->user->config->MaxFileSize(); $max_file_size = $this->user->config->MaxFileSize();
// ['upload']['size'] is given in bytes, MaxFileSize is in megabytes. // ['upload']['size'] is given in bytes, MaxFileSize is in megabytes.
if ($_FILES['upload']['size'] > $max_file_size * 1000000) { if ($_FILES['upload']['size'] > $max_file_size * 1000000) {
return ['error' => 'Upload file is too large. (max '.$max_file_size.'M)']; return ['error' => 'Upload file is too large. (max ' .
$max_file_size . 'M)'];
} }
// Replace spaces in the uploaded file name. // Replace spaces in the uploaded file name.
$file = preg_replace('/ /', '_', basename($_FILES['upload']['name'])); $file = preg_replace('/ /', '_', basename($_FILES['upload']['name']));
...@@ -205,12 +217,12 @@ class Browser extends Base { ...@@ -205,12 +217,12 @@ class Browser extends Base {
} }
$tmp = $_FILES['upload']['tmp_name']; $tmp = $_FILES['upload']['tmp_name'];
if (!move_uploaded_file($tmp, $path)) { if (!move_uploaded_file($tmp, $path)) {
return ['error' => 'File: '.$file.' was not uploaded.']; return ['error' => 'File: ' . $file . ' was not uploaded.'];
} }
$name .= '_thumb.'.$type; $name .= '_thumb.' . $type;
$html_path = $this->user->name === 'admin' ? '/public/' : $html_path = $this->user->name === 'admin' ? '/public/' :
'/'.$this->user->name.'/public/'; '/' . $this->user->name . '/public/';
$src = ''; $src = '';
if (in_array(strtolower($type), ['gif', 'jpeg', 'jpg', 'png'])) { if (in_array(strtolower($type), ['gif', 'jpeg', 'jpg', 'png'])) {
...@@ -244,20 +256,19 @@ class Browser extends Base { ...@@ -244,20 +256,19 @@ class Browser extends Base {
$this->ResizeImage($new_width, $new_height, $old_width, $old_height, $this->ResizeImage($new_width, $new_height, $old_width, $old_height,
$type, $path); $type, $path);
} }
// Store the html for the new thumbnail. $src = '<img title="' . $file . '" src="' . $html_path . $name . '">';
$src = '<img src="'.$html_path.$name.'">';
} }
else { else {
$src = '<b>'.$type.'</b>'; $src = '<b title="' . $file . '">' . $type . '</b>';
} }
return ['content' => $this->ImageContent($src, $html_path.$file)]; return ['content' => $this->ImageContent($src, $html_path . $file)];
} }
private function ImageContent($src, $image) { private function ImageContent($src, $image) {
return '<span class="thumbnail hidden">'.$src. return '<span class="thumbnail hidden">' . $src .
'<span class="filename hidden">'.$image.'</span><br>'. '<span class="filename hidden">' . $image . '</span><br>' .
'<button class="select hidden">select</button>'. '<button class="select hidden">select</button>' .
'<button class="remove hidden">remove</button>'. '<button class="remove hidden">remove</button>' .
'</span>'; '</span>';
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
...@@ -1970,7 +1970,7 @@ class Purchase extends Base { ...@@ -1970,7 +1970,7 @@ class Purchase extends Base {
$prev_price = $current_price; $prev_price = $current_price;
$prev_supplier = $current_supplier; $prev_supplier = $current_supplier;
$prev_timestamp = $timestamp; $prev_timestamp = $timestamp;
$day_total += $quantity * $current_price; $day_total += round($quantity * $current_price, 2);
$day_quantity += $quantity; $day_quantity += $quantity;
$day_count++; $day_count++;
} }
......
This diff is collapsed.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// @licstart The following is the entire license notice // @licstart The following is the entire license notice
// for the JavaScript code in this page. // for the JavaScript code in this page.
// //
// Copyright (C) 2017 Malcolm Blaney // Copyright (C) 2018 Malcolm Blaney
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
...@@ -26,13 +26,16 @@ ...@@ -26,13 +26,16 @@
if(!this.dobrado.browser){dobrado.browser={};} if(!this.dobrado.browser){dobrado.browser={};}
(function(){'use strict';var callback=false;$(function(){if($('.browser').length===0){return;} (function(){'use strict';var callback=false;$(function(){if($('.browser').length===0){return;}
$(".browser").dialog({show:true,width:720,height:500,position:{my:"top",at:"top+50",of:window},title:"Browser",create:dobrado.fixedDialog,close:function(){$(".browser").remove();}});$(".upload").button().click(upload);$(".thumbnail").show().click(highlight);$(".thumbnail .select").button().click(select);$(".thumbnail .remove").button({icon:'ui-icon-trash',showLabel:false}).click(remove);});function remove(){var that=this;$.post("/php/request.php",{request:"browser",action:"remove",file:$(this).siblings(".filename").html(),url:location.href,token:dobrado.token},function(response){if(dobrado.checkResponseError(response,"browser remove")){return;} $('.browser').dialog({show:true,width:720,height:500,position:{my:'top',at:'top+50',of:window},title:'Browser',create:dobrado.fixedDialog,close:function(){$('.browser').remove();}});$('#browser-upload-input').val('').change(upload);$('#browser-upload').button({disabled:true}).click(upload);$('#browser-upload-progress').progressbar();$('.thumbnail').show().click(highlight);$('.thumbnail .select').button().click(select);$('.thumbnail .remove').button({icon:'ui-icon-trash',showLabel:false}).click(remove);var filenames=[];$('.browser .filename').each(function(){filenames.push($(this).text());});$('#browser-search').autocomplete({minLength:1,search:dobrado.fixAutoCompleteMemoryLeak,source:filenames,response:filter,close:filterReset});});function remove(){var that=this;$.post('/php/request.php',{request:'browser',action:'remove',file:$(this).siblings('.filename').html(),url:location.href,token:dobrado.token},function(response){if(dobrado.checkResponseError(response,'browser remove')){return;}
$(that).parent().remove();});} $(that).parent().remove();});}
function select(){if(/^[0-9]+$/.test(callback)){CKEDITOR.tools.callFunction(callback,$(this).siblings(".filename").html());} function select(){if(/^[0-9]+$/.test(callback)){CKEDITOR.tools.callFunction(callback,$(this).siblings('.filename').html());}
else if(callback&&dobrado[callback]){dobrado[callback].select($(this).siblings(".filename").html());} else if(callback&&dobrado[callback]){dobrado[callback].select($(this).siblings('.filename').html());}
callback=false;$(".browser").dialog("close");} callback=false;$('.browser').dialog('close');}
function highlight(){$(".thumbnail .select").hide();$(".thumbnail .remove").hide();$(".thumbnail").removeClass("highlight");$(this).addClass("highlight");$(this).children(".select").show();$(this).children(".remove").show();} function highlight(){$('.thumbnail .select').hide();$('.thumbnail .remove').hide();$('.thumbnail').removeClass('highlight');$(this).addClass('highlight');$(this).children('.select').show();$(this).children('.remove').show();}
function upload(){var formData=new FormData();if(!formData){dobrado.log("Your browser doesn't support file uploading.","error");return;} function filter(e,ui){var filenames=[];$.each(ui.content,function(i,data){filenames.push(data.value);});$('.browser .filename').each(function(){if($.inArray($(this).text(),filenames)==-1){$(this).parent().hide();}});}
formData.append("upload",$("#upload-input").get(0).files[0]);formData.append("request","browser");formData.append("action","upload");formData.append("url",location.href);formData.append("token",dobrado.token);$.ajax({url:"/php/request.php",data:formData,contentType:false,processData:false,type:"POST",success:function(response){if(dobrado.checkResponseError(response,"browser upload")){return;} function filterReset(e,ui){if($('#browser-search').val()===''){$('.browser .filename').parent().show();}}
var browser=JSON.parse(response);$("#upload-form").after(browser.content);$(".thumbnail").click(highlight);$(".thumbnail .select:first").button().click(select);$(".thumbnail .remove:first").button({icon:'ui-icon-trash',showLabel:false}).click(remove);$("#upload-input").val("");}});return false;} function upload(){var formData=new FormData();if(!formData){dobrado.log('Your browser doesn\'t support file uploading.','error');return;}
dobrado.browser.newModuleCallback=function(selector,context){callback=context;if(/^[0-9]+$/.test(callback)){setTimeout(function(){$(selector).parents(".ui-dialog").css("z-index",11000);},100);}};})(); if($('#browser-upload-input').val()===''){$('#browser-upload').button({disabled:true});return;}
\ No newline at end of file $('#browser-upload').button({disabled:false});formData.append('upload',$('#browser-upload-input').get(0).files[0]);formData.append('request','browser');formData.append('action','upload');formData.append('url',location.href);formData.append('token',dobrado.token);$.ajax({url:'/php/request.php',data:formData,contentType:false,processData:false,type:'POST',xhr:function(){var xhr=new XMLHttpRequest();xhr.upload.addEventListener('progress',function(e){if(e.lengthComputable){var percent=e.loaded/e.total*100;if(percent<100){$('#browser-upload-progress').show();$('#browser-upload-progress').progressbar('value',percent);}}});return xhr;},success:function(response){if(dobrado.checkResponseError(response,'browser upload')){return;}
var browser=JSON.parse(response);$('#browser-upload-form').after(browser.content);$('.thumbnail').click(highlight);$('.thumbnail .select:first').button().click(select);$('.thumbnail .remove:first').button({icon:'ui-icon-trash',showLabel:false}).click(remove);$('#browser-upload-input').val('');$('#browser-upload').button({disabled:true});$('#browser-upload-progress').hide();}});return false;}
dobrado.browser.newModuleCallback=function(selector,context){callback=context;if(/^[0-9]+$/.test(callback)){setTimeout(function(){$(selector).parents('.ui-dialog').css('z-index',11000);},100);}};}());
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// @licstart The following is the entire license notice // @licstart The following is the entire license notice
// for the JavaScript code in this page. // for the JavaScript code in this page.
// //
// Copyright (C) 2017 Malcolm Blaney // Copyright (C) 2018 Malcolm Blaney
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
...@@ -41,29 +41,41 @@ if (!this.dobrado.browser) { ...@@ -41,29 +41,41 @@ if (!this.dobrado.browser) {
return; return;
} }
$(".browser").dialog({ $('.browser').dialog({
show: true, show: true,
width: 720, width: 720,
height: 500, height: 500,
position: { my: "top", at: "top+50", of: window }, position: { my: 'top', at: 'top+50', of: window },
title: "Browser", title: 'Browser',
create: dobrado.fixedDialog, create: dobrado.fixedDialog,
close: function() { $(".browser").remove(); } close: function() { $('.browser').remove(); }
}); });
$(".upload").button().click(upload); $('#browser-upload-input').val('').change(upload);
$(".thumbnail").show().click(highlight); $('#browser-upload').button({ disabled: true }).click(upload);
$(".thumbnail .select").button().click(select); $('#browser-upload-progress').progressbar();
$(".thumbnail .remove").button({ icon: 'ui-icon-trash', $('.thumbnail').show().click(highlight);
$('.thumbnail .select').button().click(select);
$('.thumbnail .remove').button({ icon: 'ui-icon-trash',
showLabel: false }).click(remove); showLabel: false }).click(remove);
var filenames = [];
$('.browser .filename').each(function() {
filenames.push($(this).text());
});
$('#browser-search').autocomplete({ minLength: 1,
search: dobrado.fixAutoCompleteMemoryLeak,
source: filenames,
response: filter,
close: filterReset });
}); });
function remove() { function remove() {
var that = this; var that = this;
$.post("/php/request.php", { request: "browser", action: "remove", $.post('/php/request.php',
file: $(this).siblings(".filename").html(), { request: 'browser', action: 'remove',
url: location.href, token: dobrado.token }, file: $(this).siblings('.filename').html(),
url: location.href, token: dobrado.token },
function(response) { function(response) {
if (dobrado.checkResponseError(response, "browser remove")) { if (dobrado.checkResponseError(response, 'browser remove')) {
return; return;
} }
$(that).parent().remove(); $(that).parent().remove();
...@@ -74,56 +86,94 @@ if (!this.dobrado.browser) { ...@@ -74,56 +86,94 @@ if (!this.dobrado.browser) {
// ckeditor uses numeric callback values. // ckeditor uses numeric callback values.
if (/^[0-9]+$/.test(callback)) { if (/^[0-9]+$/.test(callback)) {
CKEDITOR.tools.callFunction(callback, CKEDITOR.tools.callFunction(callback,
$(this).siblings(".filename").html()); $(this).siblings('.filename').html());
} }
else if (callback && dobrado[callback]) { else if (callback && dobrado[callback]) {
dobrado[callback].select($(this).siblings(".filename").html()); dobrado[callback].select($(this).siblings('.filename').html());
} }
callback = false; callback = false;
$(".browser").dialog("close"); $('.browser').dialog('close');
} }
function highlight() { function highlight() {
// Hide options for other thumbnails. // Hide options for other thumbnails.
$(".thumbnail .select").hide(); $('.thumbnail .select').hide();
$(".thumbnail .remove").hide(); $('.thumbnail .remove').hide();
$(".thumbnail").removeClass("highlight"); $('.thumbnail').removeClass('highlight');
$(this).addClass("highlight"); $(this).addClass('highlight');
$(this).children(".select").show(); $(this).children('.select').show();
$(this).children(".remove").show(); $(this).children('.remove').show();
}
function filter(e, ui) {
var filenames = [];
$.each(ui.content, function(i, data) {
filenames.push(data.value);
});
$('.browser .filename').each(function() {
if ($.inArray($(this).text(), filenames) == -1) {
$(this).parent().hide();
}
});
}
function filterReset(e, ui) {
if ($('#browser-search').val() === '') {
$('.browser .filename').parent().show();
}
} }
function upload() { function upload() {
var formData = new FormData(); var formData = new FormData();
if (!formData) { if (!formData) {
dobrado.log("Your browser doesn't support file uploading.", "error"); dobrado.log('Your browser doesn\'t support file uploading.', 'error');
return;
}
if ($('#browser-upload-input').val() === '') {
$('#browser-upload').button({ disabled: true });
return; return;
} }
formData.append("upload", $("#upload-input").get(0).files[0]); $('#browser-upload').button({ disabled: false });
formData.append("request", "browser"); formData.append('upload', $('#browser-upload-input').get(0).files[0]);
formData.append("action", "upload"); formData.append('request', 'browser');
formData.append("url", location.href); formData.append('action', 'upload');
formData.append("token", dobrado.token); formData.append('url', location.href);
formData.append('token', dobrado.token);
$.ajax({ $.ajax({
url: "/php/request.php", url: '/php/request.php',
data: formData, data: formData,
contentType: false, contentType: false,
processData: false, processData: false,
type: "POST", type: 'POST',
xhr: function() {
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
var percent = e.loaded / e.total * 100;
if (percent < 100) {
$('#browser-upload-progress').show();
$('#browser-upload-progress').progressbar('value', percent);
}
}
});
return xhr;
},
success: function(response) { success: function(response) {
if (dobrado.checkResponseError(response, "browser upload")) { if (dobrado.checkResponseError(response, 'browser upload')) {
return; return;
} }
var browser = JSON.parse(response); var browser = JSON.parse(response);
$("#upload-form").after(browser.content); $('#browser-upload-form').after(browser.content);
$(".thumbnail").click(highlight); $('.thumbnail').click(highlight);
$(".thumbnail .select:first").button().click(select); $('.thumbnail .select:first').button().click(select);
$(".thumbnail .remove:first").button({ $('.thumbnail .remove:first').button({
icon: 'ui-icon-trash', icon: 'ui-icon-trash',
showLabel: false showLabel: false
}).click(remove); }).click(remove);
$("#upload-input").val(""); $('#browser-upload-input').val('');
$('#browser-upload').button({ disabled: true });
$('#browser-upload-progress').hide();
} }
}); });
return false; return false;
...@@ -138,9 +188,9 @@ if (!this.dobrado.browser) { ...@@ -138,9 +188,9 @@ if (!this.dobrado.browser) {
// There also appears to be a race condition when opening the browser, // There also appears to be a race condition when opening the browser,
// this callback needs to run last. // this callback needs to run last.
setTimeout(function() { setTimeout(function() {
$(selector).parents(".ui-dialog").css("z-index", 11000); $(selector).parents('.ui-dialog').css('z-index', 11000);
}, 100); }, 100);
} }
}; };
})(); }());
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -66,7 +66,10 @@ if (!this.dobrado.stock) { ...@@ -66,7 +66,10 @@ if (!this.dobrado.stock) {
// This is the auto-complete list for categories. // This is the auto-complete list for categories.
var categories = []; var categories = [];
var mobile = false; var mobile = false;
// The grid image editor needs to be called when an image is selected using
// the browser module.
var currentImageEditor = null;
$(function() { $(function() {
// Don't run if the module isn't on the page. // Don't run if the module isn't on the page.
if ($('.stock').length === 0) { if ($('.stock').length === 0) {
...@@ -307,9 +310,9 @@ if (!this.dobrado.stock) { ...@@ -307,9 +310,9 @@ if (!this.dobrado.stock) {
this.keyCaptureList = [$.ui.keyCode.UP, $.ui.keyCode.DOWN]; this.keyCaptureList = [$.ui.keyCode.UP, $.ui.keyCode.DOWN];
this.init = function() { this.init = function() {
$input = $("<INPUT type=text class='editor-text' />") $input = $('<input type="text" class="editor-text">')
.appendTo(args.container) .appendTo(args.container)
.on("keydown.nav", function (e) { .on('keydown.nav', function (e) {
if (e.keyCode === $.ui.keyCode.LEFT || if (e.keyCode === $.ui.keyCode.LEFT ||
e.keyCode === $.ui.keyCode.RIGHT) { e.keyCode === $.ui.keyCode.RIGHT) {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
...@@ -372,6 +375,138 @@ if (!this.dobrado.stock) { ...@@ -372,6 +375,138 @@ if (!this.dobrado.stock) {
this.init(); this.init();
} }
function imageEditor(args) {
var $input;
var $wrapper;
var defaultValue;
currentImageEditor = this;
this.init = function() {
var $container = $('body');
$wrapper = $('<div style="z-index:100;position:absolute;' +
'background:white;width:200px;padding:5px;' +
'border:2px solid gray;-moz-border-radius:5px;' +
'border-radius:5px;"></div>').appendTo($container);
$input = $('<img src="" style="width:190px;height:auto;">').
appendTo($wrapper);
$('<div><button class="stock-image-remove">Remove</button>' +
'<button class="stock-image-edit">Edit</button></div>').
appendTo($wrapper);
$wrapper.find('button.stock-image-edit').button().click(this.edit);
$wrapper.find('button.stock-image-remove').button().click(this.remove);
$wrapper.on('keydown', this.handleKeyDown);
currentImageEditor.position(args.position);
$input.focus();
};
this.handleKeyDown = function(e) {
if (e.which == $.ui.keyCode.ESCAPE) {
e.preventDefault();
currentImageEditor.cancel();
}
else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
e.preventDefault();
args.grid.navigatePrev();
}
else if (e.which == $.ui.keyCode.TAB) {
e.preventDefault();
args.grid.navigateNext();
}
};
this.edit = function() {
dobrado.createModule('browser', 'browser', 'stock');
};
this.save = function(filename) {
$input.attr('src', filename);
args.commitChanges();
$wrapper.hide();
};
this.cancel = function() {
$input.attr('src', defaultValue);
args.cancelChanges();
};
this.remove = function() {
$input.attr('src', '');
args.commitChanges();
};
this.hide = function() {
$wrapper.hide();
};
this.show = function() {
$wrapper.show();
};
this.position = function (position) {
$wrapper.css('top', position.top - 5).css('left', position.left - 5);
};
this.destroy = function() {
$wrapper.remove();
};
this.focus = function() {
$input.focus();
};
this.loadValue = function(item) {
defaultValue = item[args.column.field] || '';
// Add '_thumb' to the end of the image name.
var fields = defaultValue.match(/^(.+)(\.[a-z]+)$/i);
if (fields && fields.length === 3) {
defaultValue = fields[1] + '_thumb' + fields[2];
}
$input.attr('src', defaultValue);
$input.focus();
};
this.serializeValue = function() {
return $input.attr('src');
};
this.applyValue = function(item, state) {
item[args.column.field] = state;
};
this.isValueChanged = function() {
return !($input.attr('src') === '' && !defaultValue) &&
$input.attr('src') !== defaultValue;
};
this.validate = function() {
if (args.column.validator) {
var validationResults = args.column.validator($input.attr('src'));
if (!validationResults.valid) {
return validationResults;
}
}
return { valid: true, msg: null };
};