diff --git a/CHANGELOG.md b/CHANGELOG.md index 8449698e..45c1a7cf 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,14 @@ # CHANGELOG +### Version 11.5 +- Fix revisions comparison +- Update logout script +- Check if session already started for user session +- Improved filtering for advanced search in ingredients +- UI updates for ingredients +- Improve PV Online search +- Refactor local ingredients module +- Refactor PV-Online ingredients search + ### Version 11.4 - Add shelf life for ingredients - Add temprature measurement unit diff --git a/VERSION.md b/VERSION.md index 1c7134df..8204473e 100755 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -11.4 +11.5 diff --git a/core/ajax-session.php b/core/ajax-session.php index 46321bfa..fdafd087 100644 --- a/core/ajax-session.php +++ b/core/ajax-session.php @@ -1,5 +1,8 @@ +?> \ No newline at end of file diff --git a/logout.php b/logout.php index e1c77a8c..bd664bd6 100644 --- a/logout.php +++ b/logout.php @@ -3,5 +3,5 @@ unset($_SESSION['parfumvault']); session_unset(); session_destroy(); -header('Location: login.php'); +header('Location: /login.php'); ?> diff --git a/modules/suppliers/local.php b/modules/suppliers/local.php index 4d8b59ff..535837c3 100644 --- a/modules/suppliers/local.php +++ b/modules/suppliers/local.php @@ -157,4 +157,4 @@ echo json_encode($response,JSON_UNESCAPED_UNICODE); return; -?> +?> \ No newline at end of file diff --git a/modules/suppliers/pvOnline.php b/modules/suppliers/pvOnline.php index 26bf3088..a5a5c21a 100644 --- a/modules/suppliers/pvOnline.php +++ b/modules/suppliers/pvOnline.php @@ -1,5 +1,5 @@ 'ingredients', + 'start' => $row, + 'length' => $limit, + 'order_by' => $order_by, + 'order_as' => $order, + 'src' => 'PV_PRO', + 'search[value]' => $s +]; -$s = trim($_POST['search']['value']); -$data = [ - 'request' => 'ingredients', - 'start' => $row, - 'length' => $limit, - 'order_by' => $order_by, - 'order_as' => $order, - 'src' => 'PV_PRO', - 'search[value]=' => $s - ]; - +// Make API request and decode the JSON response $output = json_decode(pvPost($pvOnlineAPI, $data)); -$rx = array(); -foreach ($output->ingredients as $ingredient){ - $r['id'] = (int)$ingredient->id; - $r['name'] = (string)filter_var ( $ingredient->name, FILTER_SANITIZE_FULL_SPECIAL_CHARS); - $r['cas'] = (string)$ingredient->cas ?: 'N/A'; - $r['odor'] = (string)$ingredient->odor ?: 'N/A'; - $r['profile'] = (string)$ingredient->profile ?: 'Uknown'; - $r['physical_state'] = $ingredient->physical_state ?: 1; - $r['category'] = $ingredient->category ?: 0; - $r['type'] = (string)$ingredient->type ?: 'N/A'; - $r['IUPAC'] = (string)filter_var ( $ingredient->INCI, FILTER_SANITIZE_FULL_SPECIAL_CHARS); - $r['strength'] = (string)$ingredient->strength ?: 'N/A'; - $r['purity'] = $ingredient->purity ?: 100; - $r['FEMA'] = (string)$ingredient->FEMA ?: 'N/A'; - $r['tenacity'] = (string)$ingredient->tenacity ?: 'N/A'; - $r['chemical_name'] = (string)$ingredient->chemical_name ?: 'N/A'; - $r['formula'] = (string)$ingredient->formula ?: 'N/A'; - $r['flash_point'] = (string)$ingredient->flash_point ?: 'N/A'; - $r['appearance'] = (string)$ingredient->appearance ?: 'N/A'; - $r['notes'] = (string)$ingredient->notes ?: 'N/A'; - $r['allergen'] = $ingredient->allergen ?: 0; - $r['flavor_use'] = $ingredient->flavor_use ?: 0; - $r['einecs'] = (string)$ingredient->einecs ?: 'N/A' ; - $r['usage']['limit'] = $ingredient->cat4 ?: 100; - $r['usage']['reason'] = (string)$ingredient->risk ?: 'N/A'; - $r['impact_top'] = $ingredient->impact_top ?: 0; - $r['impact_heart'] = $ingredient->impact_heart ?: 0; - $r['impact_base'] = $ingredient->impact_base ?: 0; - - - $r['stock'] = (double)0; //Not available in online - $r['info']['byPassIFRA'] = (int)0;//Not available in online - +// Initialize response array +$rx = []; +if (isset($output->ingredients) && is_array($output->ingredients)) { + foreach ($output->ingredients as $ingredient) { + if (empty($ingredient->name)) { + continue; + } - $rx[]=$r; + $r = [ + 'id' => (int) $ingredient->id, + 'name' => (string) filter_var($ingredient->name, FILTER_SANITIZE_FULL_SPECIAL_CHARS), + 'cas' => (string) ($ingredient->cas ?: 'N/A'), + 'odor' => (string) ($ingredient->odor ?: 'N/A'), + 'profile' => (string) ($ingredient->profile ?: 'Unknown'), + 'physical_state' => (int) ($ingredient->physical_state ?: 1), + 'category' => (int) ($ingredient->category ?: 0), + 'type' => (string) ($ingredient->type ?: 'N/A'), + 'IUPAC' => (string) filter_var($ingredient->INCI, FILTER_SANITIZE_FULL_SPECIAL_CHARS), + 'strength' => (string) ($ingredient->strength ?: 'N/A'), + 'purity' => (float) ($ingredient->purity ?: 100), + 'FEMA' => (string) ($ingredient->FEMA ?: 'N/A'), + 'tenacity' => (string) ($ingredient->tenacity ?: 'N/A'), + 'chemical_name' => (string) ($ingredient->chemical_name ?: 'N/A'), + 'formula' => (string) ($ingredient->formula ?: 'N/A'), + 'flash_point' => (string) ($ingredient->flash_point ?: 'N/A'), + 'appearance' => (string) ($ingredient->appearance ?: 'N/A'), + 'notes' => (string) ($ingredient->notes ?: 'N/A'), + 'allergen' => (int) ($ingredient->allergen ?: 0), + 'flavor_use' => (int) ($ingredient->flavor_use ?: 0), + 'einecs' => (string) ($ingredient->einecs ?: 'N/A'), + 'usage' => [ + 'limit' => (float) ($ingredient->cat4 ?: 100), + 'reason' => (string) ($ingredient->risk ?: 'N/A') + ], + 'impact_top' => (int) ($ingredient->impact_top ?: 0), + 'impact_heart' => (int) ($ingredient->impact_heart ?: 0), + 'impact_base' => (int) ($ingredient->impact_base ?: 0), + 'stock' => 0.0, // Stock not available from online source + 'info' => [ + 'byPassIFRA' => 0 // Not available from online source + ] + ]; + + $rx[] = $r; + } } -$response = array( - "source" => 'PVOnline', - "draw" => (int)$_POST['draw'], - "recordsTotal" => (int)$output->ingredientsTotal, - "recordsFiltered" => (int)$output->ingredientsFiltered, - "data" => $rx -); +// Prepare final response +$response = [ + 'source' => 'PVOnline', + 'draw' => isset($_POST['draw']) ? (int) $_POST['draw'] : 0, + 'recordsTotal' => (int) ($output->ingredientsTotal ?? 0), + 'recordsFiltered' => (int) ($output->ingredientsFiltered ?? 0), + 'data' => $rx +]; -if(empty($rx)){ - $response['data'] = []; +// If no data found, ensure an empty array is returned +if (empty($rx)) { + $response['data'] = []; } +// Send the response as JSON header('Content-Type: application/json; charset=utf-8'); -echo json_encode($response,JSON_UNESCAPED_UNICODE); -return; \ No newline at end of file +echo json_encode($response, JSON_UNESCAPED_UNICODE); +return; diff --git a/pages/ingredients.php b/pages/ingredients.php index 88d99e1e..91e5a204 100755 --- a/pages/ingredients.php +++ b/pages/ingredients.php @@ -54,7 +54,7 @@
- +
@@ -99,7 +99,7 @@ @@ -107,6 +107,12 @@ @@ -214,7 +220,8 @@ var profile = $('#ing_profile').val(); var cat = $('#ing_category').val(); var synonym = $('#ing_synonym').val(); - + var retainModal = $('#retainModal').is(':checked'); + $.ajax({ url: '/pages/listIngredients.php', type: 'GET', @@ -231,6 +238,10 @@ dataType: 'html', success: function (data) { $('#list_ingredients').html(data); + if (!retainModal) { + $('#adv_search').modal('hide'); + } + }, error: function (xhr, status, error) { $('#advsearchmsg').html('
An ' + status + ' occurred, check server logs for more info. '+ error +'
'); diff --git a/pages/listIngredients.php b/pages/listIngredients.php index c9c0adf5..31431a3b 100644 --- a/pages/listIngredients.php +++ b/pages/listIngredients.php @@ -93,9 +93,74 @@ }, dom: 'lr<"#advanced_search">tip', initComplete: function(settings, json) { - $("#advanced_search").html('
Advanced Search
'); + $("#advanced_search").html(` + +
+
+ + Advanced Search + +
+ `); + $("#tdDataIng_filter").detach().appendTo('#pv_search'); + + var filters = { + "Ingredient name": $('#ing_name').val(), + "CAS#": $('#ing_cas').val(), + "EINECS": $('#ing_einecs').val(), + "Odor": $('#ing_odor').val(), + "Profile": $('#ing_profile').val(), + "Category": $('#ing_category').find('option:selected').data('text'), + "Synonym": $('#ing_synonym').val() + }; + + $.each(filters, function(key, value) { + if (value) { + $('#filter').append(` + + ${key}: ${value} + + + `); + } + }); + + $('#filter').on('click', '.btn-close', function() { + var field = $(this).data('field'); + + switch (field) { + case "Ingredient name": + $('#ing_name').val(''); + break; + case "CAS#": + $('#ing_cas').val(''); + break; + case "EINECS": + $('#ing_einecs').val(''); + break; + case "Odor": + $('#ing_odor').val(''); + break; + case "Profile": + $('#ing_profile').val('').trigger('change'); + break; + + case "Category": + $('#ing_category').val('').trigger('change'); + break; + + case "Synonym": + $('#ing_synonym').val(''); + break; + } + + tdDataIng.search('').draw(); + $('#btnAdvSearch').trigger('click'); + $(this).parent().remove(); + }); }, + processing: true, serverSide: true, searching: true, @@ -103,7 +168,7 @@ language: { loadingRecords: ' ', processing: 'Blending...', - zeroRecords: '
Nothing found, try advanced search instead?
', + zeroRecords: '
Nothing found, try advanced search instead?
', search: 'Quick Search:', searchPlaceholder: 'Name, CAS, EINECS, IUPAC, odor..', }, @@ -177,10 +242,13 @@ tdDataIng.search($(this).val()).draw(); }); - $('#pv_search').on('click', '[id*=pv_search_btn]', function () { - var ingSearch = {}; - ingSearch.txt = $('#ing_search').val(); - tdDataIng.search(ingSearch.txt).draw(); + $("#pv_search_btn").click(function () { + var ingSearch = { + txt: $('#ing_search').val() + }; + if (tdDataIng) { + tdDataIng.search(ingSearch.txt).draw(); + } }); @@ -439,7 +507,7 @@ className : "btn-secondary", }); function reload_ingredients_data() { - $('#tdDataIng').DataTable().ajax.reload(null, true); + $('#tdDataIng').DataTable().ajax.reload(null, false); } $(".input-group-btn .dropdown-menu li a").click(function () { @@ -449,11 +517,12 @@ function reload_ingredients_data() { $(this).parents(".input-group-btn").find(".btn-search").html(selText); $(this).parents(".input-group-btn").find(".btn-search").attr('data-provider',provider); - $('#pv_search_btn').click(); - if($('#pv_search_btn').data().provider == 'local'){ + $('#pv_search_btn').trigger('click'); + if($('#pv_search_btn').data('provider') === 'local'){ $("#advanced_search").html('
Advanced Search
'); }else{ $("#advanced_search").html(''); + tdDataIng.settings()[0].oLanguage.sEmptyTable = '
Nothing found, try a different term instead? You can search for ingredient name or CAS number
'; } }); diff --git a/pages/views/formula/cmp_formulas_data.php b/pages/views/formula/cmp_formulas_data.php index 56c2db0e..0d6e0f8d 100644 --- a/pages/views/formula/cmp_formulas_data.php +++ b/pages/views/formula/cmp_formulas_data.php @@ -13,145 +13,149 @@