1. Logout callback fix.\n 2. Store permutations report improvement for demo.

This commit is contained in:
2024-08-07 09:01:33 +01:00
parent f81abed86e
commit 9de1ccce16
2096 changed files with 381570 additions and 388 deletions

View File

@@ -0,0 +1,27 @@
-- Clear previous proc
DROP PROCEDURE IF EXISTS p_clear_split_temp;
DELIMITER //
CREATE PROCEDURE p_clear_split_temp (
)
BEGIN
START TRANSACTION;
DROP TABLE Split_Temp;
COMMIT;
END //
DELIMITER ;
/*
CALL p_clear_shop_user_eval_temp (
'noods, cheese ' # a_guid
);
SELECT *
FROM Shop_User_Eval_Temp;
*/

View File

@@ -0,0 +1,39 @@
-- Clear previous proc
DROP PROCEDURE IF EXISTS p_clear_shop_user_eval_temp;
DELIMITER //
CREATE PROCEDURE p_clear_shop_user_eval_temp (
IN a_guid BINARY(36)
)
BEGIN
IF ISNULL(a_guid) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'GUID is required.';
ELSE
START TRANSACTION; -- trans_clear
DELETE FROM Shop_User_Eval_Temp
WHERE GUID = a_guid
;
COMMIT;
END IF;
END //
DELIMITER ;
/*
CALL p_clear_shop_user_eval_temp (
'noods, cheese ' # a_guid
);
SELECT *
FROM Shop_User_Eval_Temp;
*/

View File

@@ -1,5 +1,4 @@
--
-- USE partsltd_prod;
-- Clear previous proc
DROP PROCEDURE IF EXISTS p_shop_get_many_product;
@@ -165,6 +164,7 @@ BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Image;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Variation;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product_2;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Category;
CREATE TEMPORARY TABLE tmp_Shop_Category (
@@ -319,8 +319,8 @@ BEGIN
PP.quantity_step,
PP.quantity_stock,
PP.is_subscription,
PP.id_recurrence_interval,
PP.count_recurrence_interval,
PP.id_interval_recurrence,
PP.count_interval_recurrence,
PP.id_stripe_product,
P.has_variations
FROM Shop_Product P
@@ -380,7 +380,7 @@ BEGIN
-- select * from tmp_Shop_Product;
IF a_get_first_product_only = 1 THEN
DELETE t_P
DELETE -- t_P
FROM tmp_Shop_Product t_P
WHERE t_P.rank_permutation > 1
;
@@ -412,7 +412,9 @@ BEGIN
*/
# Product Images
INSERT INTO tmp_Shop_Image (
CREATE TEMPORARY TABLE tmp_Shop_Product_2 SELECT * FROM tmp_Shop_Product;
INSERT INTO tmp_Shop_Image (
id_product,
id_permutation,
id_image,
@@ -420,34 +422,47 @@ BEGIN
display_order,
rank_in_product_permutation
)
SELECT id_product,
id_permutation,
id_image,
active,
ROW_NUMBER() OVER (ORDER BY display_order_product_temp, display_order_image),
RANK() OVER (PARTITION BY id_product, id_permutation ORDER BY display_order_product_temp, display_order_image)
/*
WITH CTE_Product AS (
SELECT
t_P.id_product
, t_P.id_permutation
, t_P.product_has_variations
, t_P.rank_permutation
FROM tmp_Shop_Product t_P
)
*/
SELECT
IPP.id_product,
IPP.id_permutation,
IPP.id_image,
IPP.active,
ROW_NUMBER() OVER (ORDER BY IPP.display_order_product_temp, IPP.display_order_image),
RANK() OVER (PARTITION BY IPP.id_product, IPP.id_permutation ORDER BY IPP.display_order_product_temp, IPP.display_order_image)
FROM (
SELECT t_P.id_product,
SELECT
t_P.id_product,
I.id_permutation,
I.id_image,
I.active,
I.display_order AS display_order_image,
t_P.rank_permutation AS display_order_product_temp
FROM Shop_Image I
INNER JOIN tmp_Shop_Product t_P
ON I.id_product = t_P.id_product
AND NOT t_P.product_has_variations
UNION
SELECT t_P.id_product,
I.id_permutation,
I.id_image,
I.active,
I.display_order AS display_order_image,
t_P.rank_permutation AS display_order_product_temp
FROM Shop_Image I
FROM Shop_Product_Image I
INNER JOIN tmp_Shop_Product t_P
ON I.id_permutation = t_P.id_permutation
AND t_P.product_has_variations
AND NOT t_P.product_has_variations
UNION
SELECT
t_P2.id_product,
I.id_permutation,
I.id_image,
I.active,
I.display_order AS display_order_image,
t_P2.rank_permutation AS display_order_product_temp
FROM Shop_Product_Image I
INNER JOIN tmp_Shop_Product_2 t_P2
ON I.id_permutation = t_P2.id_permutation
AND t_P2.product_has_variations
) IPP
WHERE (a_get_all_image OR a_get_first_image_only OR FIND_IN_SET(id_image, a_ids_image) > 0)
AND (a_get_inactive_image OR IPP.active)
@@ -460,6 +475,7 @@ BEGIN
END IF;
/*
select @@version;
IF v_has_filter_image THEN
DELETE FROM tmp_Shop_Product
WHERE id_product NOT IN (SELECT DISTINCT id_product FROM tmp_Shop_Image);
@@ -739,7 +755,7 @@ BEGIN
-- select * from Shop_User_Eval_Temp;
-- select * from tmp_Shop_Product;
DELETE t_P
DELETE -- t_P
FROM tmp_Shop_Product t_P
WHERE
FIND_IN_SET(t_P.id_product, (SELECT GROUP_CONCAT(UET.id_product SEPARATOR ',') FROM Shop_User_Eval_Temp UET)) = 0 # id_product NOT LIKE CONCAT('%', (SELECT GROUP_CONCAT(id_product SEPARATOR '|') FROM Shop_User_Eval_Temp), '%');
@@ -760,11 +776,13 @@ BEGIN
)
;
# CALL p_shop_user_eval_clear_temp(v_guid);
CALL p_clear_shop_user_eval_temp(v_guid);
# DROP TABLE IF EXISTS Shop_User_Eval_Temp;
DELETE FROM Shop_User_Eval_Temp
WHERE GUID = v_guid
/*
DELETE FROM Shop_User_Eval_Temp UE_T
WHERE UE_T.GUID = v_guid
;
*/
END IF;
@@ -807,9 +825,9 @@ BEGIN
t_P.quantity_stock,
t_P.id_stripe_product,
t_P.is_subscription,
RI.name AS name_recurrence_interval,
RI.name_plural AS name_plural_recurrence_interval,
t_P.count_recurrence_interval,
UM.name_singular AS name_recurrence_interval,
UM.name_plural AS name_plural_recurrence_interval,
PP.count_interval_recurrence,
t_P.display_order_category,
t_P.display_order_product,
t_P.display_order_permutation,
@@ -819,7 +837,8 @@ BEGIN
FROM tmp_Shop_Product t_P
INNER JOIN Shop_Product P ON t_P.id_product = P.id_product
INNER JOIN Shop_Product_Permutation PP ON t_P.id_permutation = PP.id_permutation
LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_recurrence_interval = RI.id_interval
-- LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_interval_recurrence = RI.id_interval
LEFT JOIN Shop_Unit_Measurement UM ON PP.id_interval_recurrence = UM.id_unit_measurement
INNER JOIN Shop_Currency CURRENCY ON PP.id_currency_cost = CURRENCY.id_currency
ORDER BY t_P.rank_permutation
;
@@ -920,7 +939,7 @@ BEGIN
I.active,
I.display_order
FROM tmp_Shop_Image t_I
INNER JOIN Shop_Image I
INNER JOIN Shop_Product_Image I
ON t_I.id_image = I.id_image
INNER JOIN tmp_Shop_Product t_P
ON t_I.id_product = t_P.id_product
@@ -1062,23 +1081,26 @@ BEGIN
# select * from tmp_Shop_Product;
-- Clean up
DROP TABLE IF EXISTS tmp_Discount;
DROP TABLE IF EXISTS tmp_Currency;
DROP TABLE IF EXISTS tmp_Delivery_Region;
DROP TABLE IF EXISTS tmp_Shop_Image;
DROP TABLE IF EXISTS tmp_Shop_Variation;
DROP TABLE IF EXISTS tmp_Shop_Product;
DROP TABLE IF EXISTS tmp_Shop_Category;
DROP TEMPORARY TABLE IF EXISTS tmp_Discount;
DROP TEMPORARY TABLE IF EXISTS tmp_Currency;
DROP TEMPORARY TABLE IF EXISTS tmp_Delivery_Region;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Image;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Variation;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product;
DROP TEMPORARY TABLE IF EXISTS tmp_Product;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product_2;
DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Category;
END //
DELIMITER ;
/*
CALL partsltd_prod.p_shop_get_many_product (
'auth0|6582b95c895d09a70ba10fef', # a_id_user
1, #'auth0|6582b95c895d09a70ba10fef', # a_id_user
1, # a_get_all_category
0, # a_get_inactive_category
1, # a_get_inactive_category
0, # a_get_first_category_only
'', # a_ids_category
1, # a_get_all_product
@@ -1089,24 +1111,26 @@ CALL partsltd_prod.p_shop_get_many_product (
0, # a_get_inactive_permutation
0, # a_get_first_permutation_only
'', # a_ids_permutation
0, # a_get_all_image
1, # a_get_all_image
0, # a_get_inactive_image
0, # a_get_first_image_only
'', # a_ids_image
0, # a_get_all_delivery_region
1, # a_get_all_delivery_region
0, # a_get_inactive_delivery_region
0, # a_get_first_delivery_region_only
'', # a_ids_delivery_region
0, # a_get_all_currency
1, # a_get_all_currency
0, # a_get_inactive_currency
0, # a_get_first_currency_only
'', # a_ids_currency
0, # a_get_all_discount
1, # a_get_all_discount
0, # a_get_inactive_discount
'', # a_ids_discount
1 # a_get_products_quantity_stock_below_minimum
);
select * FROM Shop_User_Eval_Temp;
select * from Shop_Product_Permutation;
select * from shop_product_change_set;
insert into shop_product_change_set ( comment ) values ('set stock quantities below minimum for testing');
@@ -1128,4 +1152,9 @@ insert into shop_product_change_set (comment)
set is_subscription = 0,
id_change_set = (select id_change_set from shop_product_change_set order by id_change_set desc limit 1)
where id_product = 1
select * FROM Shop_User_Eval_Temp;
select distinct guid
-- DELETE
FROM Shop_User_Eval_Temp;
*/

View File

@@ -0,0 +1,302 @@
/*
CALL p_shop_get_many_product_variation (
'', # a_id_user
1, # a_get_all_supplier
0, # a_get_inactive_variation
0, # a_get_first_variation_only
'', # a_ids_variation
);
*/
-- Clear previous proc
DROP PROCEDURE IF EXISTS p_shop_get_many_product_variation;
DELIMITER //
CREATE PROCEDURE p_shop_get_many_product_variation (
IN a_id_user INT,
IN a_get_all_variation_type BIT,
IN a_get_inactive_variation_type BIT,
IN a_get_first_variation_type_only BIT,
IN a_ids_variation_type VARCHAR(4000),
IN a_get_all_variation BIT,
IN a_get_inactive_variation BIT,
IN a_get_first_variation_only BIT,
IN a_ids_variation VARCHAR(4000)
)
BEGIN
-- Argument redeclaration
-- Variable declaration
DECLARE v_has_filter_variation BIT;
DECLARE v_has_filter_variation_type BIT;
DECLARE v_guid BINARY(36);
# DECLARE v_id_user VARCHAR(100);
# DECLARE v_ids_permutation_unavailable VARCHAR(4000);
DECLARE v_id_permission_variation INT;
# DECLARE v_ids_product_permission VARCHAR(4000);
# DECLARE v_ids_permutation_permission VARCHAR(4000);
DECLARE v_id_access_level_view INT;
DECLARE v_now TIMESTAMP;
DECLARE v_id_minimum INT;
DECLARE v_code_error_data VARCHAR(50);
SET v_guid := UUID();
SET v_id_access_level_view := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'VIEW' LIMIT 1);
SET v_code_error_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1);
-- Argument validation + default values
SET a_id_user = IFNULL(a_id_user, 0);
SET a_get_all_variation = IFNULL(a_get_all_variation, 1);
SET a_get_inactive_variation = IFNULL(a_get_inactive_variation, 0);
SET a_get_first_variation_only = IFNULL(a_get_first_variation_only, 0);
SET a_ids_variation = TRIM(REPLACE(IFNULL(a_ids_variation, ''), '|', ','));
SET a_get_all_variation_type = IFNULL(a_get_all_variation_type, 1);
SET a_get_inactive_variation_type = IFNULL(a_get_inactive_variation_type, 0);
SET a_get_first_variation_type_only = IFNULL(a_get_first_variation_type_only, 0);
SET a_ids_variation_type = TRIM(REPLACE(IFNULL(a_ids_variation_type, ''), '|', ','));
-- Temporary tables
DROP TABLE IF EXISTS tmp_Variation;
DROP TABLE IF EXISTS tmp_Variation_Type;
CREATE TEMPORARY TABLE tmp_Variation_Type (
id_type INT NOT NULL
, active BIT NOT NULL
, rank_type INT NULL
);
CREATE TEMPORARY TABLE tmp_Variation (
id_variation INT NOT NULL
, id_type INT NOT NULL
, active BIT NOT NULL
, rank_variation INT NULL
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error (
display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
guid BINARY(36) NOT NULL,
id_type INT NOT NULL,
code VARCHAR(50) NOT NULL,
msg VARCHAR(4000) NOT NULL
);
-- Parse filters
SET v_has_filter_variation = CASE WHEN a_ids_variation = '' THEN 0 ELSE 1 END;
SET v_has_filter_variation_type = CASE WHEN a_ids_variation_type = '' THEN 0 ELSE 1 END;
-- select v_has_filter_product, v_has_filter_permutation;
IF v_has_filter_variation = 1 OR a_get_all_variation = 1 OR v_has_filter_variation_type = 1 OR a_get_all_variation_type = 1 THEN
CALL p_split(a_ids_variation_type, ',');
IF EXISTS (SELECT * FROM Split_Temp S_T LEFT JOIN Shop_Variation_Type VT ON S_T.substring = VT.id_type WHERE ISNULL(VT.id_type)) THEN
INSERT INTO tmp_Msg_Error (
guid,
code,
msg
)
VALUES (
v_guid,
v_code_error_data,
CONCAT('Invalid Variation Type IDs: ', (SELECT GROUP_CONCAT(VT.id_type) FROM Split_Temp S_T LEFT JOIN Shop_Variation_Type VT ON S_T.substring = VT.id_type WHERE ISNULL(VT.id_type)))
)
;
CALL p_clear_split_temp;
ELSE
CALL p_clear_split_temp;
CALL p_split(a_ids_variation, ',');
IF EXISTS (SELECT * FROM Split_Temp S_T LEFT JOIN Shop_Variation V ON S_T.substring = V.id_variation WHERE ISNULL(V.id_variation)) THEN
INSERT INTO tmp_Msg_Error (
guid,
code,
msg
)
VALUES (
v_guid,
v_code_error_data,
CONCAT('Invalid Variation IDs: ', (SELECT GROUP_CONCAT(V.id_variation) FROM Split_Temp S_T LEFT JOIN Shop_Variation V ON S_T.substring = V.id_variation WHERE ISNULL(V.id_variation)))
)
;
ELSE
INSERT INTO tmp_Variation (
id_variation
, id_type
, active
, rank_variation
)
SELECT
V.id_variation
, V.id_type
, V.active
, RANK() OVER (ORDER BY id_variation ASC) AS rank_id_variation
FROM Shop_Variation V
INNER JOIN Shop_Variation_Type VT ON V.id_type = VT.id_type
LEFT JOIN Split_Temp S_T ON V.id_variation = S_T.substring
WHERE
(
a_get_all_variation = 1
OR NOT ISNULL(S_T.substring)
)
AND (
a_get_inactive_variation
OR V.active = 1
)
;
END IF;
CALL p_clear_split_temp;
IF a_get_first_variation_only THEN
DELETE t_V
FROM tmp_Shop_Variation t_V
WHERE t_V.rank_variation > 1
;
END IF;
END IF;
END IF;
-- Permissions
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN
# SET v_id_user := (SELECT id_user FROM Shop_User WHERE name = CURRENT_USER());
SET v_id_permission_variation := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_PRODUCT' LIMIT 1);
-- SELECT v_guid, a_id_user, false, v_id_permission_product, v_id_access_level_view, v_ids_permutation_permission;
-- select * from Shop_User_Eval_Temp;
CALL p_shop_user_eval(v_guid, a_id_user, FALSE, v_id_permission_variation, v_id_access_level_view, '');
-- select * from Shop_User_Eval_Temp;
IF NOT EXISTS (SELECT can_view FROM Shop_User_Eval_Temp UE_T WHERE UE_T.GUID = v_guid) THEN
INSERT INTO tmp_Msg_Error (
guid,
code,
msg
)
VALUES (
v_guid,
v_code_error_data,
CONCAT('You do not have view permissions for ', (SELECT name FROM Shop_Permission WHERE id_permission = v_id_permission_supplier LIMIT 1))
)
;
END IF;
END IF;
IF EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN
DELETE FROM tmp_Variation;
DELETE FROM tmp_Variation_Type;
END IF;
-- Returns
# Variation Types
SELECT
t_VT.id_type
, VT.code
, VT.name
, VT.name_plural
, VT.active
FROM tmp_Variation_Type t_VT
INNER JOIN Shop_Variation_Type VT ON t_VT.id_type = VT.id_type
;
# Variations
SELECT
t_V.id_variation
, V.code
, V.name
, V.active
FROM tmp_Variation t_V
INNER JOIN Shop_Variation V ON t_V.id_variation = V.id_variation
;
# Errors
SELECT
*
FROM tmp_Msg_Error t_ME
INNER JOIN Shop_Msg_Error_Type MET
ON t_ME.id_type = MET.id_type
WHERE guid = v_guid
;
-- Clean up
DROP TABLE IF EXISTS tmp_Variation;
DROP TABLE IF EXISTS tmp_Variation_Type;
END //
DELIMITER ;
CALL p_shop_get_many_product_variation (
1, # 'auth0|6582b95c895d09a70ba10fef', # a_id_user
1, # a_get_all_variation_type
0, # a_get_inactive_variation_type
0, # a_get_first_variation_type_only
'', # a_ids_variation_type
1, # a_get_all_variation
0, # a_get_inactive_variation
0, # a_get_first_variation_only
'' # a_ids_variation
);
/*
select * from shop_variation;
select * from shop_variation_type;
*/
/*
select * from shop_supplier;
select * from shop_product;
select * from TMP_MSG_ERROR;
DROP TABLE TMP_MSG_ERROR;
insert into shop_product_change_set (comment)
values ('set product not subscription - test bool output to python');
update shop_product
set is_subscription = 0,
id_change_set = (select id_change_set from shop_product_change_set order by id_change_set desc limit 1)
where id_product = 1
INSERT INTO tmp_Variation_Type (
id_type,
active,
rank_type
)
SELECT
VT.id_type,
S.active,
RANK() OVER (ORDER BY id_type ASC) AS rank_type
FROM Shop_Variation_Type VT
LEFT JOIN Split_Temp S_T ON VT.id_type = S_T.substring
WHERE
(
a_get_all_variation_type = 1
OR NOT ISNULL(S_T.substring)
)
AND (
a_get_inactive_variation_type
OR VT.active = 1
)
;
END IF;
IF a_get_first_variation_type_only THEN
DELETE t_VT
FROM tmp_Shop_Variation_Type t_VT
WHERE t_VT.rank_type > 1
;
END IF;
*/

View File

@@ -149,6 +149,12 @@ BEGIN
)
;
END IF;
/*
DELETE FROM Shop_User_Eval_Temp
WHERE GUID = v_guid;
*/
CALL p_clear_shop_user_eval_temp(v_guid);
END IF;
@@ -230,16 +236,12 @@ BEGIN
-- Clean up
DROP TEMPORARY TABLE IF EXISTS tmp_User;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DELETE FROM Shop_User_Eval_Temp
WHERE GUID = v_guid
;
END //
DELIMITER ;
/*
/*
CALL p_get_many_user (
NULL # a_id_user
, 'auth0|6582b95c895d09a70ba10fef' # a_id_user_auth0
@@ -249,5 +251,6 @@ CALL p_get_many_user (
, NULL # a_ids_user
, 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 # ' --
);
select * from shop_user_eval_temp;
delete from shop_user_eval_temp;
*/

View File

@@ -238,10 +238,6 @@ BEGIN
-- Clean up
DROP TABLE IF EXISTS tmp_Supplier;
DELETE FROM Shop_User_Eval_Temp
WHERE GUID = v_guid
;
END //
DELIMITER ;

View File

@@ -440,6 +440,11 @@ button, .button-submit, input[type="submit"] {
text-decoration: underline;
}
.delete {
text-decoration: underline;
}
/* Overlay modal */
.overlay {
/*

View File

@@ -1,36 +1,98 @@
#pageBody > *, button {
font-size: min(14px, calc(1vh * 5)) !important;
}
thead, tbody {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
th {
}
td {
font-size: min(14px, calc(1vh * 5));
}
th, td {
min-width: fit-content;
}
tr:not(:last-child) > td {
border-bottom: 1px dashed var(--c_purple_dark);
}
td > table > tbody > tr > td {
border: none !important;
}
tr {
min-height: 1px;
border-bottom: 1px solid var(--c_purple_dark);
border-top: 1px solid var(--c_purple_dark);
padding-bottom: 1vh;
background-color: transparent;
}
.category {
width: 20%;
td.category, th.category {
width: 16% !important;
}
.product {
width: 20%;
td.product, th.product {
width: 23% !important;
}
.variations {
width: 20%;
td.variations, th.variations {
width: 19% !important;
}
.quantity-stock {
width: 8%;
td.quantity-stock, th.quantity-stock {
width: 10% !important;
}
.quantity-min {
width: 8%;
td.quantity-min, th.quantity-min {
width: 10% !important;
}
.quantity-max {
width: 8%;
td.quantity-max, th.quantity-max {
width: 10% !important;
}
.cost-local {
width: 16%;
td.cost-local-VAT-incl, th.cost-local-VAT-incl {
width: 6% !important;
}
td.detail, th.detail {
width: 6% !important;
}
.row-new {
visibility: hidden;
}
textarea, select, input {
textarea {
width: 95% !important;
}
select {
width: 100% !important;
}
input {
width: 90% !important;
}
td > input, td > select, td > textarea, .container-input > input, .container-input > select, .container-input > textarea {
border: 2px solid var(--c_purple);
border-radius: 0.5vh;
}
#tableMain tbody tr td button {
padding: 0;
border: 0;
margin: 0;
text-decoration: none;
}
#tableMain tbody tr td table thead tr th.id_variation_type, #tableMain tbody tr td table tbody tr td.id_variation_type, #tableMain tbody tr td table thead tr th.id_variation, #tableMain tbody tr td table tbody tr td.id_variation {
width: 47.5%;
}
/*
select.id_variation, select.id_variation_type {
max-width: 40% !important;
}
*/

View File

@@ -44,9 +44,6 @@
max-width: 100%;
}
.basket-item-delete {
text-decoration: underline;
}
/* Right column */

277
static/js/extras.js Normal file
View File

@@ -0,0 +1,277 @@
/* Page elements */
function displayOverlay(message, show, force) {
if (show) {
_overlayLoadingCount += 1;
}
else if (force) {
_overlayLoadingCount = 0;
}
else {
_overlayLoadingCount -= 1;
if (_overlayLoadingCount < 0) _overlayLoadingCount = 0;
}
var loadingImg = $(idImageLoading);
var overlay = $(loadingImg.closest("div.overlay"));
if (_overlayLoadingCount == 0) {
// Prevent short glimpse of prev. content before switch to new content
// caused by data load but not fully rendered
setTimeout(function() {
overlay.fadeOut();
}, 100);
}
else if (show && _overlayLoadingCount == 1) {
// only show once
loadingImg.html(message);
overlay.show();
}
}
function setBackgroundToLoading(elId, isLoading) {
if (isEmpty(el)) {
var elObj = $(elId);
if (isLoading) {
setTimeout(function() {
elObj.html("");
elObj.css({
"background-image": "url(" + urlImgLoading + ")",
"background-position": "center",
"background-repeat": "no-repeat"
});
}, 0);
}
else {
elObj.css("background-image", "");
}
}
}
function allowClick() {
return !$("body").hasClass(_dataLoadingFlag);
}
function imageExists(url, callback) {
var img = new Image();
img.onload = function() { callback(true); };
img.onerror = function() { callback(false); };
img.src = url;
}
function validateImageUrl(id, img) {
imageExists(img, function(exists) {
if (exists) {
$("#" + id).css({ "background-image": "url(" + url + ")", "background-size": "35px 35px"})
}
})
}
// Date picker inputs
/*
function hookupInputDatePickers(dateInputs, notFuture, notPast, parent, addClearOption) {
if (!isEmpty(dateInputs)) {
let currentInput, currentDateString, currentDate, exceptionsArray;
for (let i = 0; i < dateInputs.length; i++) {
currentInput = $(dateInputs[i]);
currentDateString = currentInput.val();
currentDate = (!isEmpty(currentDateString)) ? convertDDMMYYYYString2Date(currentDateString, false) : null;
exceptionsArray = (currentDate != null) ? [currentDate] : null;
turnInputIntoDatePicker(currentInput, notFuture, notPast, exceptionsArray);
}
if (!isEmpty(parent)) {
// stop user from manually typing date except backspace and delete
// which will clear the whole value to ensure we either have a whole
// date string or none
parent.on("keydown", isDatePickerSelector, function(event) {
if (event.keyCode == 46 | event.keyCode == 8) { // delete or backspace
$(this).val('');
}
else {
event.preventDefault();
event.stopPropagation();
}
return false
});
if (addClearOption) {
// if user right-clicks in date input, give option to clear the date
parent.contextMenu({
selector: isDatePickerSelector,
delay: 100,
autoHide: true,
position: function(opt, x, y) {
var event = opt.$trigger[0]?.ownerDocument?.defaultView?.event || event;
opt.$menu.position({ my: 'center top', at: 'center top', of: event });
},
items: {
"clears": {
name: "Clear Date",
icon: "delete",
disabled: function(key, opt) { return isEmpty($(opt.$trigger)); }, // if it's already empty, don't do anything
callback: function(itemKey, opt, rootMenu, originalEvent) { var input = $(opt.$trigger); input.val(''); input.trigger('change'); }
}
}
});
}
}
}
}
function turnInputIntoDatePicker(input, notFuture, notPast, exceptionValueArray) {
var beforeShowDayCallBack = null;
if (notFuture || notPast) {
var today = new Date();
today.setHours(0, 0, 0, 0);
var tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
var hasExceptions = !isEmpty(exceptionValueArray);
beforeShowDayCallBack = function(date) {
var selectedDate = date.getTime();
var fieldHasException = hasExceptions && arrayContainsItem(exceptionValueArray, date);
if (notFuture && (tomorrow < selectedDate) && fieldHasException) return [false, 'redday', 'You cannot choose a future date'];
if (notPast && (selectedDate < today) && fieldHasException) return [false, 'redday', 'You cannot choose a past date'];
return [true, '', ''];
};
}
input.datepicker({
dateFormat: 'dd-mm-yy',
navigationAsDateFormat: true,
beforeShowDay: beforeShowDayCallBack
});
// prevent datepicker from appearing on right click
input.on('contextmenu', function() { $(this).datepicker('hide'); });
// Disable autocomplete suggestions appearing when clicking on input
input.attr('autocomplete', 'off');
}
function setDatePickerDate(input, objDate) {
if (!isEmpty(objDate)) {
input.val('');
}
else {
input.datepicker('setDate', objDate);
}
}
function getDatePickerDate(input, adjust4DayLightSavings) {
var date = null;
if (!isEmpty(input)) {
date = input.datepicker('getDate');
if (adjust4DayLightSavings) {
formatDateDayLightSavingsTime(date);
}
}
return date;
}
function formatDateDayLightSavingsTime(date) {
// JSON.stringify removes hour delta for daylight savings
// e.g. 13/11/2023 01:00:00 goes to 13/11/2023 00:00:00
// this adds an hour so it becomes the correct time when stringified
if (!isEmpty(date)) {
date.setTime(date.getTime() - date.getTimezoneOffset() * 60 * 1000)
}
}
*/
function convertJSONDateString2Date(dateStr) {
if (isEmpty(dateStr)) return null;
if (dateStr instanceof Date) return dateStr;
return new Date(parseInt(dateStr.substr(6)));
}
function convertDDMMYYYYString2Date(dateStr, adjust4DayLightSavings) {
var date = null;
if (!isEmpty(dateStr)) {
if (dateStr instanceof Date) {
date = dateStr;
}
else {
var dateParts = dateStr.split('-');
if (dateParts.length == 3) {
date = new Date(dateParts[2], dateParts[1] - 1, dateParts[0]);
}
}
if (adjust4DayLightSavings && !isEmpty(date)) {
formatDateDayLightSavingsTime(date);
}
}
return date;
}
function convertDate2DDMMYYYYString(date) {
if (isEmpty(date)) return '';
try {
var dd = date.getDate();
var mm = date.getMonth() + 1;
var yyyy = date.getFullYear();
if (dd < 10) dd = '0' + dd;
if (dd < 10) mm = '0' + mm;
return dd + '-' + mm + '-' + yyyy;
}
catch (err) {
return 'Formatting error';
}
}
// Data tables
function getDataTableCellByNode(table, elRow, indexColumn) {
// normal jQuery selector won't pick up hidden columns
return $(table.DataTable().cells(elRow, indexColumn, null).nodes());
}
function outputTableElementDateInput(table, elRow, indexColumn, value) {
let currentCell = getDataTableCellByNode(table, elRow, indexColumn);
let dateTxt = '';
if (!isEmpty(value)) {
if (typeof value === 'string') value = convertJSONDateString2Date(value);
}
}

View File

@@ -642,38 +642,6 @@ function setPageToLoading(isLoading) {
}
}
/*
function displayOverlay(message, show, force) {
if (show) {
_overlayLoadingCount += 1;
}
else if (force) {
_overlayLoadingCount = 0;
}
else {
_overlayLoadingCount -= 1;
if (_overlayLoadingCount < 0) _overlayLoadingCount = 0;
}
var loadingImg = $(idImageLoading);
var overlay = $(loadingImg.closest("div.overlay"));
if (_overlayLoadingCount == 0) {
// Prevent short glimpse of prev. content before switch to new content
// caused by data load but not fully rendered
setTimeout(function() {
overlay.fadeOut();
}, 100);
}
else if (show && _overlayLoadingCount == 1) {
// only show once
loadingImg.html(message);
overlay.show();
}
}
*/
function setBackgroundToLoading(elId, isLoading) {
@@ -702,23 +670,6 @@ function allowClick() {
return !$("body").hasClass(_dataLoadingFlag);
}
function imageExists(url, callback) {
var img = new Image();
img.onload = function() { callback(true); };
img.onerror = function() { callback(false); };
img.src = url;
}
function validateImageUrl(id, img) {
imageExists(img, function(exists) {
if (exists) {
$("#" + id).css({ "background-image": "url(" + url + ")", "background-size": "35px 35px"})
}
})
}
function getElementCurrentValue(el) {
let returnVal = '';
let element = $(el);
@@ -790,185 +741,7 @@ function getCellFromElement(element) {
return $(element).closest('td');
}
// Date picker inputs
/*
function hookupInputDatePickers(dateInputs, notFuture, notPast, parent, addClearOption) {
if (!isEmpty(dateInputs)) {
let currentInput, currentDateString, currentDate, exceptionsArray;
for (let i = 0; i < dateInputs.length; i++) {
currentInput = $(dateInputs[i]);
currentDateString = currentInput.val();
currentDate = (!isEmpty(currentDateString)) ? convertDDMMYYYYString2Date(currentDateString, false) : null;
exceptionsArray = (currentDate != null) ? [currentDate] : null;
turnInputIntoDatePicker(currentInput, notFuture, notPast, exceptionsArray);
}
if (!isEmpty(parent)) {
// stop user from manually typing date except backspace and delete
// which will clear the whole value to ensure we either have a whole
// date string or none
parent.on("keydown", isDatePickerSelector, function(event) {
if (event.keyCode == 46 | event.keyCode == 8) { // delete or backspace
$(this).val('');
}
else {
event.preventDefault();
event.stopPropagation();
}
return false
});
if (addClearOption) {
// if user right-clicks in date input, give option to clear the date
parent.contextMenu({
selector: isDatePickerSelector,
delay: 100,
autoHide: true,
position: function(opt, x, y) {
var event = opt.$trigger[0]?.ownerDocument?.defaultView?.event || event;
opt.$menu.position({ my: 'center top', at: 'center top', of: event });
},
items: {
"clears": {
name: "Clear Date",
icon: "delete",
disabled: function(key, opt) { return isEmpty($(opt.$trigger)); }, // if it's already empty, don't do anything
callback: function(itemKey, opt, rootMenu, originalEvent) { var input = $(opt.$trigger); input.val(''); input.trigger('change'); }
}
}
});
}
}
}
}
function turnInputIntoDatePicker(input, notFuture, notPast, exceptionValueArray) {
var beforeShowDayCallBack = null;
if (notFuture || notPast) {
var today = new Date();
today.setHours(0, 0, 0, 0);
var tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
var hasExceptions = !isEmpty(exceptionValueArray);
beforeShowDayCallBack = function(date) {
var selectedDate = date.getTime();
var fieldHasException = hasExceptions && arrayContainsItem(exceptionValueArray, date);
if (notFuture && (tomorrow < selectedDate) && fieldHasException) return [false, 'redday', 'You cannot choose a future date'];
if (notPast && (selectedDate < today) && fieldHasException) return [false, 'redday', 'You cannot choose a past date'];
return [true, '', ''];
};
}
input.datepicker({
dateFormat: 'dd-mm-yy',
navigationAsDateFormat: true,
beforeShowDay: beforeShowDayCallBack
});
// prevent datepicker from appearing on right click
input.on('contextmenu', function() { $(this).datepicker('hide'); });
// Disable autocomplete suggestions appearing when clicking on input
input.attr('autocomplete', 'off');
}
function setDatePickerDate(input, objDate) {
if (!isEmpty(objDate)) {
input.val('');
}
else {
input.datepicker('setDate', objDate);
}
}
function getDatePickerDate(input, adjust4DayLightSavings) {
var date = null;
if (!isEmpty(input)) {
date = input.datepicker('getDate');
if (adjust4DayLightSavings) {
formatDateDayLightSavingsTime(date);
}
}
return date;
}
function formatDateDayLightSavingsTime(date) {
// JSON.stringify removes hour delta for daylight savings
// e.g. 13/11/2023 01:00:00 goes to 13/11/2023 00:00:00
// this adds an hour so it becomes the correct time when stringified
if (!isEmpty(date)) {
date.setTime(date.getTime() - date.getTimezoneOffset() * 60 * 1000)
}
}
*/
function convertJSONDateString2Date(dateStr) {
if (isEmpty(dateStr)) return null;
if (dateStr instanceof Date) return dateStr;
return new Date(parseInt(dateStr.substr(6)));
}
function convertDDMMYYYYString2Date(dateStr, adjust4DayLightSavings) {
var date = null;
if (!isEmpty(dateStr)) {
if (dateStr instanceof Date) {
date = dateStr;
}
else {
var dateParts = dateStr.split('-');
if (dateParts.length == 3) {
date = new Date(dateParts[2], dateParts[1] - 1, dateParts[0]);
}
}
if (adjust4DayLightSavings && !isEmpty(date)) {
formatDateDayLightSavingsTime(date);
}
}
return date;
}
function convertDate2DDMMYYYYString(date) {
if (isEmpty(date)) return '';
try {
var dd = date.getDate();
var mm = date.getMonth() + 1;
var yyyy = date.getFullYear();
if (dd < 10) dd = '0' + dd;
if (dd < 10) mm = '0' + mm;
return dd + '-' + mm + '-' + yyyy;
}
catch (err) {
return 'Formatting error';
}
}
// Textareas
function removeBlankTextAreaLines(textarea) {
@@ -1011,23 +784,6 @@ function fitTextAreaToContent(textarea) {
}
// Data tables
function getDataTableCellByNode(table, elRow, indexColumn) {
// normal jQuery selector won't pick up hidden columns
return $(table.DataTable().cells(elRow, indexColumn, null).nodes());
}
function outputTableElementDateInput(table, elRow, indexColumn, value) {
let currentCell = getDataTableCellByNode(table, elRow, indexColumn);
let dateTxt = '';
if (!isEmpty(value)) {
if (typeof value === 'string') value = convertJSONDateString2Date(value);
}
}
// Local storage
/*

View File

@@ -117,7 +117,7 @@ function callbackLoadPermutations(response) {
row.find('td.' + flagQuantityStock + ' input').val(dataRow[flagQuantityStock]);
row.find('td.' + flagQuantityMin + ' input').val(dataRow[flagQuantityMin]);
row.find('td.' + flagQuantityMax + ' input').val(dataRow[flagQuantityMax]);
row.find('td.' + flagCostLocal).html(dataRow[flagCostLocal]);
row.find('td.' + flagCostLocalVATIncl).html(dataRow[flagCostLocalVATIncl]);
row.attr(attrIdCategory, dataRow[flagCategory]);
row.attr(attrIdProduct, dataRow[flagProduct]);
row.attr(attrIdPermutation, dataRow[attrIdPermutation]);
@@ -135,13 +135,15 @@ function hookupButtonsSaveCancel() {
event.stopPropagation();
showOverlayConfirm();
});
btnSave.addClass(flagCollapsed);
let parentSave = btnSave.closest('div.' + flagColumn);
// parentSave.addClass(flagCollapsed);
btnCancel.on("click", function(event) {
event.stopPropagation();
loadPermutations();
});
btnCancel.addClass(flagCollapsed);
let parentCancel = btnCancel.closest('div.' + flagColumn);
// parentCancel.addClass(flagCollapsed);
btnAdd.on("click", function(event) {
event.stopPropagation();
@@ -231,7 +233,7 @@ function hookupTableMain() {
});
*/
let ddlCategory, ddlProduct, variations, quantityStock, quantityMin, quantityMax, costLocal;
let ddlCategory, ddlProduct, variations, quantityStock, quantityMin, quantityMax, costLocal, detail;
table.find('tbody tr').each(function(index, row) {
console.log("hooking up row ", index);
row = $(row);
@@ -241,7 +243,8 @@ function hookupTableMain() {
quantityStock = row.find('td.' + flagQuantityStock + ' input');
quantityMin = row.find('td.' + flagQuantityMin + ' input');
quantityMax = row.find('td.' + flagQuantityMax + ' input');
detail = row.find('td.' + flagDetail + ' button');
initialiseEventHandler(ddlCategory, flagInitialised, function() {
// ddlCategory = $(ddlCategory);
ddlCategory.on('change', function() {
@@ -273,8 +276,8 @@ function hookupTableMain() {
initialiseEventHandler(variations, flagInitialised, function() {
// variations = $(variations);
variations.on('change', function() {
handleChangeInputPermutations(this);
variations.on('click', function() {
handleClickPermutationsInputVariations(this);
});
});
@@ -300,6 +303,12 @@ function hookupTableMain() {
handleChangeInputPermutations(this);
});
});
initialiseEventHandler(detail, flagInitialised, function() {
detail.on('click', function() {
console.log("not implemented error: detail clicked");
});
});
});
}
@@ -313,7 +322,7 @@ function handleChangeInputPermutations(element) {
let wasDirty = isElementDirty(objJQuery);
if (objJQuery.hasClass(flagVariations)) {
objJQuery.attr(attrValueCurrent, getVariationsCurrentValue(objJQuery));
objJQuery.attr(attrValueCurrent, getProductVariationsText(objJQuery));
} else {
objJQuery.attr(attrValueCurrent, getElementCurrentValue(objJQuery));
}
@@ -368,7 +377,9 @@ function isRowDirty(row) {
return isDirty;
}
function getVariationsCurrentValue(element) {
function getProductVariationsText(element) {
element = $(element);
/*
let value = element.val();
let variations = value.split('\n');
variations = variations.map(function(variation) {
@@ -377,5 +388,113 @@ function getVariationsCurrentValue(element) {
variations = variations.filter(function(variation) {
return variation.length > 0;
});
return variations.join(',');
*/
let variations = dictVariations[element.attr(attrIdVariation)].map((variation, index) => {
return variation[keyNameVariationType] + ': ' + variation[keyNameVariation];
});
return variations.join(',\n');
}
function getElementProductVariations(element) {
element = $(element);
let variations = element.attr(attrValueCurrent);
let objVariations = [];
if (!isEmpty(variations)) {
variations = variations.split(',');
variations.forEach((variation) => {
let parts = variation.split(':');
if (parts.length == 2) {
objVariations.push({
[attrIdVariationType]: parts[0].trim(),
[attrIdVariation]: parts[1].trim(),
});
}
});
}
return objVariations;
}
function handleClickPermutationsInputVariations(element) {
element = $(element);
let jsonVariation, jsonVariationType, tr, tdVariationType, variationType, attributesVariationType, tdNameVariation, nameVariation, attributesNameVariation, tdDelete, buttonDelete, tmpJsonVariation, tmpJsonVariationType;
let variations = getElementProductVariations(element);
let tblVariations = $("<table>");
tblVariations.append("<thead><tr><th>Type</th><th>Name</th></tr></thead>");
let tbody = $("<tbody>");
console.log('variations:', variations);
if (isEmpty(variations)) {
return;
}
variations.forEach((variation, index) => {
jsonVariationType = dictVariations[variation[attrIdVariationType]];
jsonVariation = dictVariations[variation[attrIdVariation]];
tdVariationType = $("<td>", {
class: attrIdVariationType,
});
attributesVariationType = {
class: attrIdVariationType,
value: variation[attrIdVariationType],
};
attributesVariationType[attrValueCurrent] = jsonVariation[attrIdVariationType];
attributesVariationType[attrValuePrevious] = jsonVariation[attrIdVariationType];
variationType = $("<select>", attributesVariationType);
listVariationTypes.forEach((idVariationType) => {
tmpJsonVariationType = dictVariationTypes[idVariationType];
variationType.append($('<option>', {
value: jsonVariationType[attrIdVariationType],
text: jsonVariationType[keyNameVariationType],
selected: (idVariationType == jsonVariationType[attrIdVariationType]),
}));
});
tdNameVariation = $("<td>", {
class: attrIdVariation,
});
attributesNameVariation = {
class: attrIdVariation,
value: variation[attrIdVariation],
};
attributesNameVariation[attrValueCurrent] = jsonVariation[attrIdVariation];
attributesNameVariation[attrValuePrevious] = jsonVariation[attrIdVariation];
nameVariation = $("<select>", attributesNameVariation);
listVariations.forEach((idVariation) => {
tmpJsonVariation = dictVariations[idVariation];
console.log("id_variation: ", idVariation);
console.log("tmpJsonVariation: ", tmpJsonVariation);
nameVariation.append($('<option>', {
value: tmpJsonVariation[attrIdVariation],
text: tmpJsonVariation[keyNameVariation],
selected: (idVariation == jsonVariation[attrIdVariation]),
}));
});
tdDelete = $("<td>", {
class: flagDelete,
});
buttonDelete = $("<button>", {
class: flagDelete,
text: 'x',
});
tr = $("<tr>");
tdVariationType.append(variationType);
tr.append(tdVariationType);
tdNameVariation.append(nameVariation);
tr.append(tdNameVariation);
tdDelete.append(buttonDelete);
tr.append(tdDelete);
tbody.append(tr);
});
tr = $("<tr>");
let buttonAdd = $("<button>", {
class: flagAdd,
text: '+',
});
let tdAdd = $("<td>");
tdAdd.append(buttonAdd);
tr.append(tdAdd);
tbody.append(tr);
tblVariations.append(tbody);
let parent = element.parent();
parent.html('');
parent.append(tblVariations);
console.log("tblVariations: ", tblVariations);
}