Files
assetmgt/product.php
“VeLiTi” ec20d44267 Refactor UI elements for consistency and clarity
- Updated action buttons across multiple files to use icons (e.g., "Save" to "💾+", "Delete" to "X").
- Replaced "Cancel" button text with a left arrow (←) for a more intuitive navigation experience.
- Removed unnecessary action columns from tables to streamline the interface.
- Enhanced table rows to be clickable for better user interaction, redirecting to relevant management pages.
- Adjusted font sizes and styles in CSS for improved readability and aesthetics.
- Standardized back button functionality to use a left arrow across various pages.
2025-12-15 17:08:44 +01:00

619 lines
25 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
defined(page_security_key) or exit;
if (debug && debug_id == $_SESSION['id']){
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
}
include_once './assets/functions.php';
include_once './settings/settings_redirector.php';
//SET ORIGIN FOR NAVIGATION
$prev_page = $_SESSION['prev_origin'] ?? '';
$page = 'product';
//create backbutton to prev_origin
$back_btn_orgin = ($prev_page != '')? '<a href="'.$prev_page.'" class="btn alt mar-right-2">←</a>':'';
//Check if allowed
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
header('location: index.php');
exit;
}
//GET PARAMETERS && STORE in SESSION for FURTHER USE/NAVIGATION
$pagination_page = $_SESSION['p'] = isset($_GET['p']) ? $_GET['p'] : 1;
//PAGE Security
$page_manage = 'product_manage';
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
$update_allowed_edit = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'U');
$delete_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'D');
$create_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'C');
$media_update = isAllowed('products_media' ,$_SESSION['profile'],$_SESSION['permission'],'U');
$software_update = isAllowed('products_software_assignment' ,$_SESSION['profile'],$_SESSION['permission'],'U');
//GET Details from URL
$GET_VALUES = urlGETdetails($_GET) ?? '';
//CALL TO API FOR General information
$api_url = '/v2/products/'.$GET_VALUES;
$responses = ioServer($api_url,'');
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses);}else{$responses = null;}
$responses = $responses[0];
//CALL TO API FOR Product_versions
$api_url = '/v2/products_versions/productrowid='.$_GET['rowID'];
$product_versions = ioServer($api_url,'');
//Decode Payload
if (!empty($product_versions)){$product_versions = json_decode($product_versions);}else{$product_versions = null;}
//CALL TO API FOR Product_software
$api_url = '/v1/products_software/productrowid='.$_GET['rowID'];
$product_software = ioServer($api_url,'');
//Decode Payload
if (!empty($product_software)){$product_software = decode_payload($product_software);}else{$product_software = null;}
//CALL TO API FOR Product_configuration
$api_url = '/v2/products_configurations/version_status=1&productrowid='.$_GET['rowID'];
$products_configurations = ioServer($api_url,'');
//Decode Payload
if (!empty($products_configurations)){$products_configurations = json_decode($products_configurations,true);}else{$products_configurations = null;}
//GET RELATED CATEGORIES
$api_url = '/v2/products_categories/product_id='.$_GET['rowID'];
$product['categories'] = ioServer($api_url,'');
//Decode Payload
if (!empty($product['categories'] )){$product['categories'] = json_decode($product['categories'] ,true);}else{$product['categories'] = null;}
//GET RELATED MEDIA
$api_url = '/v2/products_media/product_id='.$_GET['rowID'];
$products_media = ioServer($api_url,'');
//Decode Payload
if (!empty($products_media)){$products_media = json_decode($products_media ,true);}else{$products_media = null;}
//GET ASSIGNED SOFTWARE VERSIONS
$api_url = '/v2/products_software_assignment/product_id='.$_GET['rowID'];
$products_software_assignment = ioServer($api_url,'');
//Decode Payload
if (!empty($products_software_assignment)){$products_software_assignment = json_decode($products_software_assignment,true);}else{$products_software_assignment = null;}
if ($media_update == 1){
//GET ALL MEDIA
$api_url = '/v2/media/list=product_image';
$media_responses_all = ioServer($api_url,'');
//Decode Payload
if (!empty($media_responses_all)){$media_responses_all = json_decode($media_responses_all,true);}else{$media_responses_all = null;}
}
if ($media_update == 1 && (isset($_POST['media']) || isset($_POST['delete']))){
//CHECK IF MEDIA IS AN ARRAY
if (isset($_POST['media']) && is_array($_POST['media'])){
foreach($_POST['media'] as $p_media){
//GET ALL POST DATA
$payload = json_encode(array("product_id" => $_POST['product_id'], "media_id" => $p_media), JSON_UNESCAPED_UNICODE);
//API call
$responses = ioServer('/v2/products_media', $payload);
}
if ($responses === 'NOK'){
} else {
header('Location: index.php?page=product&success_msg=2&rowID='.$_GET['rowID'].'');
exit;
}
}
if (isset($_POST['delete'])){
//GET ALL POST DATA
$payload = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//API call
$responses = ioServer('/v2/products_media', $payload);
// Redirect and delete product
if ($responses === 'NOK'){
} else {
header('Location: index.php?page=product&success_msg=2&rowID='.$_GET['rowID'].'');
exit;
}
}
}
//------------------------------
// Variables
//------------------------------
$status_text = 'prod_status_'.$responses->status ?? '';
$product_category_text = 'product_category'.$responses->product_category ?? '';
$parttype_text = 'part_type'.$responses->parttype ?? '';
// Handle success messages
if (isset($_GET['success_msg'])) {
if ($_GET['success_msg'] == 1) {
$success_msg = $message_pr_1;
}
if ($_GET['success_msg'] == 2) {
$success_msg = $message_pr_2;
}
if ($_GET['success_msg'] == 3) {
$success_msg = $message_pr_3;
}
}
template_header('Product', 'product', 'view');
$view = '
<div class="content-title responsive-flex-wrap responsive-pad-bot-3">
<h2 class="responsive-width-100">'.$responses->productcode.' - '.(${$responses->productname} ?? $responses->productname).'</h2>
<a href="index.php?page='.$_SESSION['origin'].'&p='.$_SESSION['p'].'" class="btn alt mar-right-2">←</a>
';
//------------------------------------
//
//------------------------------------
if ($update_allowed_edit === 1){
$view .= '<a href="index.php?page=product_manage&id='.$_GET['rowID'].'" class="btn">✏️</a>';
}
$view .= '</div>';
if (isset($success_msg)){
$view .= ' <div class="msg success">
<i class="fas fa-check-circle"></i>
<p>'.$success_msg.'</p>
<i class="fas fa-times"></i>
</div>';
}
$view .= '<div class="content-block-wrapper">';
$view .= ' <div class="content-block order-details">
<div class="block-header">
<i class="fa-solid fa-circle-info"></i></i>'.($product_data ?? '').'
</div>
<div class="order-detail">
<h3>'.$product_status.'</h3>
<p><span class="status id'.$responses->status.'">'.$$status_text.'</span></p>
</div>
<div class="order-detail">
<h3>'.$product_category.'</h3>
<p><span class="status id'.$responses->product_category.'">'.$$product_category_text.'</span></p>
</div>
<div class="order-detail">
<h3>'.$product_parttype.'</h3>
<p><span class="status id'.$responses->parttype.'">'.$$parttype_text.'</span></p>
</div>
<div class="order-detail">
<h3>'.$product_code.'</h3>
<p>'.$responses->productcode.'</p>
</div>
<div class="order-detail">
<h3>'.$product_name.'</h3>
<p>'.(${$responses->productname} ?? $responses->productname).'</p>
</div>
<div class="order-detail">
<h3>'.($product_slug ?? 'Product_slug').'</h3>
<p>'.(${$responses->url_slug} ?? $responses->url_slug).'</p>
</div>
<div class="order-detail">
<h3>'.($product_quantity ?? 'Quantity').'</h3>
<p>'.(${$responses->quantity} ?? $responses->quantity).'</p>
</div>
<div class="order-detail">
<h3>'.($product_categories_text ?? 'Categories').'</h3>
<p><div class="multiselect" data-name="categories[]">';
foreach ($product['categories'] as $cat){
$view .= ' <span class="item">
<i class="remove">&times;</i>'.$cat['name'].'
</span>';
}
$view .= ' </div>
</p>
</div>';
$view .='
</div>
';
$view .='<div class="content-block order-details">
<div class="block-header">
<i class="fa-solid fa-user fa-sm"></i>
</div>';
if (!empty($responses->full_path)){
$view .='
<div class="order-detail">
<img style="border-radius: 4px;height: 200px;margin: auto;" src="'.$responses->full_path.'" alt="">
</div>
';
}
$view .='
</div>
';
$view .= '</div>';
$view .= '<div class="content-block">
<div class="block-header">
<i class="fa-solid fa-bars fa-sm"></i>'.$product_description.'
</div>
<div class="table order-table">
'.(${$responses->productdescription} ?? $responses->productdescription).'
</div>
</div>
';
$view .= '<div class="content-block">
<div class="block-header">
<i class="fa-solid fa-bars fa-sm"></i>'.($product_version ?? '').'
<a href="index.php?page=products_versions&productrowid='.$_GET['rowID'].'" class="btn2"> + </a>
</div>';
if (!empty($product_versions)){
$view .= '
<div class="table">
<table class="sortable">
<thead>
<tr>
<th>'.$product_version_number.'</th>
<th>'.$product_status.'</th>
<th>'.$product_version_version.'</th>
<th>'.($product_version_config ?? 'Config').'</th>
</tr>
</thead>
<tbody>';
foreach ($product_versions as $version){
$view .= '<tr onclick="window.location.href=\'index.php?page=products_versions&productrowid='.$_GET['rowID'].'&rowID='.$version->rowID.'\'" style="cursor: pointer;">
<td>'.$version->rowID.'</td>
<td>'.(($version->status == 1)? '<span class="status enabled">'.$prod_status_1:'<span class="status">'.$prod_status_0).'</td>
<td>'.$version->version.'</td>
<td>'.(!empty($version->config) ? ($general_yes ?? 'Y') : ($general_no ?? 'N')).'</td>
</tr>';
}
$view .= '
</tbody>
</table>
</div>
';
}
$view .= '
</div>
';
if ($responses->configurable == 1){
$view .= '<div class="content-block">
<div class="block-header">
<i class="fa-solid fa-bars fa-sm"></i>'.($product_configuration ?? 'Product configuration').'
<a href="index.php?page=products_configurations&productrowid='.$_GET['rowID'].'" class="btn2"> + </a>
</div>';
if (!empty($products_configurations)){
$view .= '
<div class="table">
<table class="sortable">
<thead>
<tr>
<th>'.($product_configuration_version ?? 'Config-version').'</th>
<th>'.($product_configuration_assignment ?? 'Code').'</th>
<th>'.($product_configuration_assignment ?? 'Name').'</th>
</tr>
</thead>
<tbody>';
foreach ($products_configurations as $product_config){
$view .= '<tr onclick="window.location.href=\'index.php?page=products_configurations&productrowid='.$_GET['rowID'].'&rowID='.$product_config['rowID'].'\'" style="cursor: pointer;">
<td>'.$product_config['version'].'</td>
<td>'.$product_config['assignment'].'</td>
<td>'.(${$product_config['assignment_name']} ?? $product_config['assignment_name']).'</td>
</tr>';
}
$view .= '
</tbody>
</table>
</div>
';
}
$view .= '
</div>
';
}
$view .= '<div class="content-block">
<h2 class="responsive-width-100">'.($products_software_assignment_header ?? 'Software').' <a href="index.php?page=products_software_assignments&productrowid='.$_GET['rowID'].'" class="btn2">Manage</a></h2>
<div id="selectedSoftware">';
if(!empty($products_software_assignment)){
foreach ($products_software_assignment as $assignment){
// Get software version details
$api_url = '/v2/products_software_versions/rowID=' . $assignment['software_version_id'];
$version_details = ioServer($api_url, '');
$version = json_decode($version_details);
if (!empty($version)) {
$version = $version[0];
$view .= '
<div class="software-container" style="display: inline-block; position: relative; margin: 5px; padding: 10px; border: 1px solid #ccc;">
<strong>' . $version->name . '</strong><br>
Version: ' . $version->version . '<br>
HW: ' . $version->hw_version . '
</div>';
}
}
}
$view .='</div>
</div>
</div>';
$view .= '<div class="content-block">
<div class="block-header">
<i class="fa-solid fa-bars fa-sm"></i>'.$tab4.'
</div>
<div class="table order-table">
<table>
</tr>
<tr>
<td style="width:25%;">'.($product_configurable ?? 'Configurable').'</td>
<td>'.(($responses->configurable == 1)? $enabled : $disabled).'</td>
</tr>
<tr>
<td style="width:25%;">'.$product_serialized.'</td>
<td>'.(($responses->sn == 1)? $enabled : $disabled).'</td>
</tr>
<tr>
<td style="width:25%;">'.$product_sales.'</td>
<td>'.(($responses->salesflag == 1)? $enabled : $disabled).'</td>
</tr>
<tr>
<td style="width:25%;">'.$product_build.'</td>
<td>'.(($responses->build == 1)? $enabled : $disabled).'</td>
</tr>
<tr>
<td style="width:25%;">'.$view_asset_data_ranking.'</td>
<td>'.(($responses->healthindex == 1)? $enabled : $disabled).'</td>
</tr>
</table>
</div>
</div>
';
$view .= '
<div class="content-block">
<h2 class="responsive-width-100">'.($products_media_header ?? 'Product media').' <button class="btn2" onClick="openDialog()" > + </button><input form="pictures" class="btn2" type="submit" name="update" value="Save" class="btn"></h2>
<div id="selectedImages">';
if(!empty($products_media)){
foreach ($products_media as $prod_media){
$view .= '
<div class="image-container" style="display: inline-block; position: relative; margin: 5px;">
<img src="'.$prod_media['full_path'].'" style="max-width: 100px; margin: 5px;">
<form method="POST" action="" style="position: absolute; top: 0; right: 0;">
<input type="hidden" name="rowID" value="'.$prod_media['rowID'].'">
<input type="hidden" name="product_id" value="'.$_GET['rowID'].'">
<input type="hidden" name="delete" value="delete">
<button type="submit" style="background-color: red; color: white; border: none; border-radius: 50%; width: 20px; height: 20px; padding: 0; font-size: 12px; cursor: pointer;">×</button>
</form>
</div>';
}
}
$view .='</div>
<form action="" id="pictures" method="post">
<input type="hidden" form="pictures" name="product_id" value="'.$_GET['rowID'].'">
<div id="selectedImagesID"></div>
</form>
<div id="selectedImagesPreview"></div>
</div>
</div>
<dialog id="imageSelector">
<h3>'.(isset($image_select) ? ${$image_select} : 'Select Images').'</h3>
<div id="imageGrid">';
if ($media_update == 1){
foreach ($media_responses_all as $media_response){
$view .= '
<img src="'.$media_response['full_path'].'" alt="'.$media_response['title'].'" title="'.$media_response['title'].'" id="'.$media_response['rowID'].'" onclick="toggleImage(this)" style="width: 10%;cursor: pointer">
';
}
}
$view .= '
</div>
<br>
<button onclick="confirmSelection()">Confirm Selection</button>
<button onclick="closeImageSelector()">Cancel</button>
</dialog>
<script>
const dialog = document.getElementById(\'imageSelector\');
const openButton = document.getElementById(\'openSelectorBtn\');
const imageArrayInput = document.getElementById(\'imageArray\');
const previewContainer = document.getElementById(\'selectedImagesPreview\');
const previewID = document.getElementById(\'selectedImagesID\');
function openDialog(){
dialog.showModal();
document.querySelectorAll(\'#imageGrid img\').forEach(img => {img.style.border = \'none\';});
}
function toggleImage(img) {
if (img.style.border === \'2px solid blue\') {
img.style.border = \'none\';
} else {
img.style.border = \'2px solid blue\';
}
}
function confirmSelection() {
// Get all selected images with their details
const selectedImages = Array.from(document.querySelectorAll(\'#imageGrid img[style*="blue"]\'))
.map(img => ({
id: img.id,
src: img.src
}));
// Update preview
let preview = \'\';
previewContainer.innerHTML = \'\';
selectedImages.forEach(image => {
const previewImg = document.createElement(\'img\');
previewImg.src = image.src;
previewImg.id = image.id;
previewImg.style.maxWidth = \'100px\';
previewImg.style.margin = \'5px\';
previewContainer.appendChild(previewImg);
preview += \'<input name="media[]" form="pictures" type="hidden" value="\'+image.id+\'">\';
});
previewID.innerHTML = preview;
dialog.close();
}
function closeImageSelector() {
dialog.close();
}
</script>
';
$view .= '<dialog id="softwareSelector">
<h3>'.(isset($software_select) ? ${$software_select} : 'Select Software Versions').'</h3>
<div id="softwareGrid">';
if ($software_update == 1){
if (isset($software_versions_all) && is_array($software_versions_all)){
foreach ($software_versions_all as $software_version){
$view .= '
<div class="software-item" id="'.$software_version['rowID'].'" onclick="toggleSoftware(this)" style="border: 1px solid #ccc; padding: 10px; margin: 5px; cursor: pointer;">
<strong>' . $software_version['name'] . '</strong><br>
Version: ' . $software_version['version'] . '<br>
HW: ' . $software_version['hw_version'] . '
<details style="margin-top: 10px;">
<summary>Upgrade Paths</summary>
<ul>';
// Find upgrade paths
if (isset($upgrade_paths_all) && is_array($upgrade_paths_all)){
foreach ($upgrade_paths_all as $path) {
if ($path['from_version_id'] == $software_version['rowID'] || $path['to_version_id'] == $software_version['rowID']) {
$from_ver = '';
$to_ver = '';
foreach ($software_versions_all as $v) {
if ($v['rowID'] == $path['from_version_id']) $from_ver = $v['version'];
if ($v['rowID'] == $path['to_version_id']) $to_ver = $v['version'];
}
$view .= '<li>' . $from_ver . ' -> ' . $to_ver . ' (Price: ' . $path['price'] . ' ' . $path['currency'] . ')</li>';
}
}
}
$view .= '
</ul>
</details>
</div>
';
}
}
}
$view .= '
</div>
<br>
<button onclick="confirmSoftwareSelection()">Confirm Selection</button>
<button onclick="closeSoftwareSelector()">Cancel</button>
</dialog>
<script>
const softwareDialog = document.getElementById(\'softwareSelector\');
const softwarePreviewContainer = document.getElementById(\'selectedSoftwarePreview\');
const softwarePreviewID = document.getElementById(\'selectedSoftwareID\');
function openSoftwareDialog(){
softwareDialog.showModal();
document.querySelectorAll(\'#softwareGrid .software-item\').forEach(item => {item.style.border = \'1px solid #ccc\';});
}
function toggleSoftware(item) {
if (item.style.border === \'2px solid blue\') {
item.style.border = \'1px solid #ccc\';
} else {
item.style.border = \'2px solid blue\';
}
}
function confirmSoftwareSelection() {
// Get all selected software versions
const selectedSoftware = Array.from(document.querySelectorAll(\'#softwareGrid .software-item[style*="blue"]\'))
.map(item => ({
id: item.id,
name: item.querySelector(\'strong\').textContent
}));
// Update preview
let preview = \'\';
softwarePreviewContainer.innerHTML = \'\';
selectedSoftware.forEach(software => {
const previewDiv = document.createElement(\'div\');
previewDiv.textContent = software.name;
previewDiv.style.maxWidth = \'200px\';
previewDiv.style.margin = \'5px\';
previewDiv.style.padding = \'5px\';
previewDiv.style.border = \'1px solid #ccc\';
softwarePreviewContainer.appendChild(previewDiv);
preview += \'<input name="software_versions[]" form="software" type="hidden" value="\'+software.id+\'">\';
});
softwarePreviewID.innerHTML = preview;
softwareDialog.close();
}
function closeSoftwareSelector() {
softwareDialog.close();
}
</script>
';
$view .= '<div class="content-block">
<div class="block-header">
<i class="fa-solid fa-bars fa-sm"></i>'.$tab3.'
</div>
<div class="table order-table">
<table>
<tr>
<td style="width:25%;">'.$general_created.'</td>
<td>'.getRelativeTime($responses->created).'</td>
</tr>
<tr>
<td style="width:25%;">'.$general_createdby.'</td>
<td>'.$responses->createdby.'</td>
</tr>
<tr>
<td style="width:25%;">'.$general_updated.'</td>
<td>'.getRelativeTime($responses->updated).'</td>
</tr>
<tr>
<td style="width:25%;">'.$general_updatedby.'</td>
<td>'.$responses->updatedby.'</td>
</tr>
</table>
</div>
</div>
';
$view .='</div>';
//OUTPUT
echo $view;
template_footer()
?>