فهرست منبع

updated products api+

Harshit Pathak 3 ماه پیش
والد
کامیت
4190364819

+ 6 - 0
content_quality_tool_public/static/css/attr-extraction.css

@@ -210,3 +210,9 @@ td.thumb-cell { width: 60px; }
     width: 3rem;
     height: 3rem;
 }
+
+.select-attr {
+  margin-left: 10px;
+  font-size: 0.9em;
+  color: #666;
+}

+ 54 - 0
content_quality_tool_public/static/js/attr-extraction.js

@@ -29,6 +29,8 @@ document.addEventListener('DOMContentLoaded', () => {
         console.log("data",data);
         // --- Wire up ---
         PRODUCT_BASE = data;
+        PRODUCT_BASE = PRODUCT_BASE.map((d)=>{return {...d,mandatoryAttributes:["color","size"]}});
+        console.log("PRODUCT_BASE",PRODUCT_BASE);
         if(PRODUCT_BASE.length > 0){
             $('#paginationBar').style.display = 'block';
         }
@@ -146,6 +148,58 @@ function createProductCard(p) {
     const long = el('div', 'desc'); long.innerHTML = p.product_long_description || ''; long.style.marginTop = '4px';
     mid.appendChild(name); mid.appendChild(desc); mid.appendChild(badges); mid.appendChild(long);
 
+
+    // const rightAttribute = el('label', 'select');
+
+    // // Main checkbox: "Select"
+    // const cb_attribute = document.createElement('input');
+    // cb_attribute.type = 'checkbox';
+    // cb_attribute.checked = selectedIds.has(p.item_id);
+    // cb_attribute.addEventListener('change', () => {
+    //   setChecked(p.item_id, cb_attribute.checked);
+    //   row.classList.toggle('selected', cb_attribute.checked);
+    // });
+    // const lbl_attribute = el('span');
+    // lbl_attribute.textContent = 'Select';
+
+    // rightAttribute.appendChild(cb_attribute);
+    // rightAttribute.appendChild(lbl_attribute);
+
+    // // --- New checkbox for mandatory attributes ---
+    // if (p.mandatoryAttributes && p.mandatoryAttributes.length > 0) {
+    //   const attrLabel = el('label', 'select-attr');
+    //   const attrCb = document.createElement('input');
+    //   attrCb.type = 'checkbox';
+    //   attrCb.checked = false;  // Not selected by default
+
+    //   attrCb.addEventListener('change', () => {
+    //     if (attrCb.checked) {
+    //       // Select the main checkbox
+    //       cb_attribute.checked = true;
+    //       setChecked(p.item_id, true);
+    //       row.classList.add('selected');
+    //     } else {
+    //       // Optionally uncheck main if attrCb is unchecked
+    //       // (optional logic)
+    //     }
+    //   });
+
+    //   const attrSpan = el('span');
+    //   attrSpan.textContent = `Select mandatory (${p.mandatoryAttributes.join(', ')})`;
+
+    //   attrLabel.appendChild(attrCb);
+    //   attrLabel.appendChild(attrSpan);
+
+    //   rightAttribute.appendChild(attrLabel);
+    // }
+
+    const secondRight = el('label', 'select');
+    const cbSeond = document.createElement('input'); cbSeond.type = 'checkbox'; cbSeond.checked = selectedIds.has(p.item_id);
+    cbSeond.addEventListener('change', () => { setChecked(p.item_id, cbSeond.checked); row.classList.toggle('selected', cbSeond.checked); });
+    const lblsecond = el('span'); lblsecond.textContent = 'Select';
+    secondRight.appendChild(cbSeond); secondRight.appendChild(lblsecond);
+
+    
     const right = el('label', 'select');
     const cb = document.createElement('input'); cb.type = 'checkbox'; cb.checked = selectedIds.has(p.item_id);
     cb.addEventListener('change', () => { setChecked(p.item_id, cb.checked); row.classList.toggle('selected', cb.checked); });

+ 180 - 26
content_quality_tool_public/templates/product-attributes.html

@@ -83,36 +83,75 @@
                     </div>
                 </div>
                 <div class="row">
+                    <!-- upload attributes -->
+                    <div class="col-md-12">
+                        <div class="card mb-4">
+                            <div class="card-header">
+                                <h5 class="card-title">Upload Attributes</h5>
+                            </div> 
+                            <div class="card-body p-0">
+                                <form id="uploadForm" method="POST"  enctype="multipart/form-data"> <!--begin::Body-->
+                                    {% csrf_token %}
+                                    <div class="card-body">
+                                        
+                                        <div class="form-group row mb-3">
+                                            <label for="file" class="col-sm-2 col-form-label">Select Input
+                                                File <span class="text-danger">*</span></label>
+                                            <div class="col-sm-6">
+                                                <div class="input-group mb-3"> 
+                                                    <input type="file" class="form-control"
+                                                        id="fileInput" name="file" required
+                                                        >
+                                            </div>
+                                        </div>
+
+                                        <div class="form-group row mb-3 ">
+                                            <label for="file" class="col-sm-2 col-form-label"></label>
+                                            <div class="col-sm-6">
+                                                <button type="submit" class="btn btn-primary" id="submitBtn" disabled>Upload</button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                                
+                                <div id="responseMessage" class="mt-3"></div>
+
+                            </div>
+                        </div> <!-- /.card -->
+                    </div>
+                     <!-- upload attributes end -->
                     <div class="col-md-12">
                         <div class="card mb-4">
-                            <!-- Add Button -->
                              <div class="card-header">
                                 <div class="d-flex justify-content-between align-items-center mb-3">
-                                    <h2>Manage Records</h2>
-                                    <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addModal">Add New</button>
+                                    <h3>Manage Attributes</h3>
+                                    <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addProductTypeModal">Add New Product Type</button>
+                                    <button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#addProductAttributeModal">Add New Attribute</button>
                                 </div>
                             </div>
                             <div class="card-body">
-                                <!-- Table View -->
                                 <table class="table table-bordered table-striped" cellspacing="0" width="100%" id="product-attribute-list">
                                     <thead class="table-dark" >
                                     <tr>
                                         <th>ID</th>
-                                        <th>Name</th>
-                                        <th>Email</th>
+                                        <th>Product Type</th>
+                                        <th>Product Attribute List</th>
                                         <th>Actions</th>
                                     </tr>
                                     </thead>
                                     <tbody id="dataBody">
                                     <tr>
                                         <td>1</td>
-                                        <td>John Doe</td>
-                                        <td>john@example.com</td>
+                                        <td>Canvas Art Prints</td>
+                                        <td><ul>
+                                                <li>color</li>
+                                                <li>Shade</li>
+                                            </ul>
+                                        </td>
                                         <td>
-                                        <button class="btn btn-sm btn-warning" data-bs-toggle="modal" data-bs-target="#editModal">Edit</button>
+                                        <button class="btn btn-sm btn-warning" data-bs-toggle="modal"  data-bs-target="#editModal">Edit</button>
                                         </td>
                                     </tr>
-                                    <!-- More rows can be added dynamically -->
                                     </tbody>
                                 </table>
                             </div>
@@ -121,22 +160,45 @@
                 </div>
 
 
-                <!-- Add Modal -->
-                <div class="modal fade" id="addModal" tabindex="-1" aria-labelledby="addModalLabel" aria-hidden="true">
+                <div class="modal fade" id="addProductTypeModal" tabindex="-1" aria-labelledby="addProductTypeModal" aria-hidden="true">
                 <div class="modal-dialog">
                     <form class="modal-content">
                     <div class="modal-header">
-                        <h5 class="modal-title" id="addModalLabel">Add New Record</h5>
+                        <h5 class="modal-title" id="addTypeModalLabel">Add Product Type</h5>
                         <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                     </div>
                     <div class="modal-body">
                         <div class="mb-3">
-                        <label for="addName" class="form-label">Name</label>
+                        <label for="addProductTypeName" class="form-label">Name</label>
                         <input type="text" class="form-control" id="addName" required>
                         </div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="submit" class="btn btn-success">Save</button>
+                    </div>
+                    </form>
+                </div>
+                </div>
+
+                <div class="modal fade" id="addProductAttributeModal" tabindex="-1" aria-labelledby="addProductAttributeModal" aria-hidden="true">
+                <div class="modal-dialog">
+                    <form class="modal-content">
+                    <div class="modal-header">
+                        <h5 class="modal-title" id="addAttributeModalLabel">Add Product Attribute</h5>
+                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+                    </div>
+                    <div class="modal-body">
+                        <div class="mb-3">
+                            <label for="addProductType" class="form-label">Product Type</label>
+                            <select name="productType" class="form-control" id="productType" aria-describedby="Select Product Type">
+                                <option value="">Select Product Type</option>
+                                <option value="color">Color</option>
+                                <option value="shade">Shade</option>
+                            </select>
+                        </div>
                         <div class="mb-3">
-                        <label for="addEmail" class="form-label">Email</label>
-                        <input type="email" class="form-control" id="addEmail" required>
+                            <label for="addAttributeName" class="form-label">Name</label>
+                            <input type="text" class="form-control" id="addAttributeName" required>
                         </div>
                     </div>
                     <div class="modal-footer">
@@ -146,23 +208,26 @@
                 </div>
                 </div>
 
-                <!-- Edit Modal -->
                 <div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
                 <div class="modal-dialog">
                     <form class="modal-content">
                     <div class="modal-header">
-                        <h5 class="modal-title" id="editModalLabel">Edit Record</h5>
+                        <h5 class="modal-title" id="editModalLabel">Edit Product Attribute</h5>
                         <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                     </div>
                     <div class="modal-body">
                         <input type="hidden" id="editId">
                         <div class="mb-3">
-                        <label for="editName" class="form-label">Name</label>
-                        <input type="text" class="form-control" id="editName" required>
+                        <label for="editProductType" class="form-label">Product Type</label>
+                            <select name="editProductType[]" class="form-control" id="editProductType" aria-describedby="Select Product Type" multiple>
+                                <option value="">Select Product Type</option>
+                                <option value="color">Color</option>
+                                <option value="shade">Shade</option>
+                            </select>
                         </div>
                         <div class="mb-3">
-                        <label for="editEmail" class="form-label">Email</label>
-                        <input type="email" class="form-control" id="editEmail" required>
+                            <label for="editAttributeName" class="form-label">Name</label>
+                            <input type="text" class="form-control" id="editAttributeName" required>
                         </div>
                     </div>
                     <div class="modal-footer">
@@ -216,10 +281,6 @@
             }
         });
         $(document).ready(function () {
-            $('.select2').select2({
-                theme: 'bootstrap4',
-                placeholder: 'Select Competitors'
-            });
             $('#product-attribute-list').DataTable();
         });
     </script> <!--end::OverlayScrollbars Configure--> <!-- OPTIONAL SCRIPTS --> <!-- apexcharts -->
@@ -228,6 +289,99 @@
 </script>
 
 </body><!--end::Body-->
+<script>
+$(document).ready(function () {
+    $('#product-attribute-list').on('click', '.btn-warning', function () {
+        var $row = $(this).closest('tr');
+        
+        // Extract the Product Attribute List (list items inside <ul>)
+        var selectedAttributes = [];
+        $row.find('td:nth-child(3) ul li').each(function () {
+            selectedAttributes.push($(this).text().trim().toLowerCase());
+        });
+
+        // Clear previous selection
+        $('#editProductType option').prop('selected', false);
 
+        // Select the ones that match
+        $('#editProductType option').each(function () {
+            if (selectedAttributes.includes($(this).val().toLowerCase())) {
+                $(this).prop('selected', true);
+            }
+        });
+
+        // Also update attribute name if needed
+        var attributeName = selectedAttributes.length ? selectedAttributes[0] : '';
+        $('#editAttributeName').val(attributeName);
+    });
+});
+</script>
+
+<script>
+    $(document).ready(function () {
+        $('#editProductType').select2({
+            dropdownParent: $('#editModal'), // important for modal
+            placeholder: 'Select product attributes'
+        });
+    });
+    
+    document.addEventListener('DOMContentLoaded', function () {
+        const form = document.getElementById('uploadForm');
+        const fileInput = document.getElementById('fileInput');
+        const submitBtn = document.getElementById('submitBtn');
+        const responseDiv = document.getElementById('responseMessage');
+
+        // Enable submit button when file is selected
+        fileInput.addEventListener('change', function () {
+            submitBtn.disabled = fileInput.files.length === 0;
+        });
+
+        // Handle form submission
+        form.addEventListener('submit', function (e) {
+            e.preventDefault();
+            $('#full-page-loader').show();
+            // Disable button during upload
+            submitBtn.disabled = true;
+            submitBtn.textContent = 'Uploading...';
+
+            const formData = new FormData(form);
+
+            fetch('/attr/products/upload-attributes/', {
+                method: 'POST',
+                body: formData,
+                headers: {
+                    'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
+                }
+            })
+            .then(response => response.json())
+            .then(data => {
+                // if (data.success) {
+                    responseDiv.innerHTML = `<div class="alert alert-success">✅ ${data.message}</div>`;
+                    fileInput.value = ''; // Clear file input
+                    submitBtn.disabled = true; // Keep disabled until new file selected
+                    $('#full-page-loader').hide();
+                // } else {
+                //     responseDiv.innerHTML = `<div class="alert alert-danger">❌ ${data.error}</div>`;
+                //     submitBtn.disabled = false;
+                //     $('#full-page-loader').hide();
+                // }
+            })
+            .catch(error => {
+                responseDiv.innerHTML = `<div class="alert alert-danger">❌ Upload failed: ${error}</div>`;
+                submitBtn.disabled = false;
+                $('#full-page-loader').hide();
+            })
+            .finally(() => {
+                submitBtn.textContent = 'Upload';
+                $('#full-page-loader').hide();
+
+                // Remove message after 5 seconds
+                setTimeout(() => {
+                    responseDiv.innerHTML = '';
+                }, 3000);
+            });
+        });
+    });
+</script>
 </html>
 

+ 7 - 1
content_quality_tool_public/templates/sidebar.html

@@ -27,7 +27,13 @@
                 <li class="nav-item"> <a href="{% url 'attribute-extraction' %}" class="nav-link {% if request.path == '/attribute-extraction/' %}active{% endif %}"> <i
                             class="nav-icon bi bi-scissors"></i>
                         <p>Attribute Extraction</p>
-                    </a> </li>        
+                    </a> </li> 
+                    
+                
+                <li class="nav-item"> <a href="{% url 'product-attributes' %}" class="nav-link {% if request.path == '/product-attributes/' %}active{% endif %}"> <i
+                            class="nav-icon bi bi-tag"></i>
+                        <p>Product Attributes</p>
+                    </a> </li>     
                 
 
             </ul> <!--end::Sidebar Menu-->