Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 94 additions & 6 deletions assets/controllers/bulk_import_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { generateCsrfHeaders } from "./csrf_protection_controller"

export default class extends Controller {
static targets = ["progressBar", "progressText"]
static values = {
static values = {
jobId: Number,
partId: Number,
researchUrl: String,
researchAllUrl: String,
markCompletedUrl: String,
markSkippedUrl: String,
markPendingUrl: String
markPendingUrl: String,
quickApplyUrl: String,
quickApplyAllUrl: String
}

connect() {
Expand Down Expand Up @@ -119,13 +121,11 @@ export default class extends Controller {

async markSkipped(event) {
const partId = event.currentTarget.dataset.partId
const reason = prompt('Reason for skipping (optional):') || ''


try {
const url = this.markSkippedUrlValue.replace('__PART_ID__', partId)
const data = await this.fetchWithErrorHandling(url, {
method: 'POST',
body: JSON.stringify({ reason })
method: 'POST'
})

if (data.success) {
Expand Down Expand Up @@ -321,6 +321,94 @@ export default class extends Controller {
}
}

async quickApply(event) {
event.preventDefault()
event.stopPropagation()

const partId = event.currentTarget.dataset.partId
const providerKey = event.currentTarget.dataset.providerKey
const providerId = event.currentTarget.dataset.providerId
const button = event.currentTarget
const originalHtml = button.innerHTML

button.disabled = true
button.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Applying...'

try {
const url = this.quickApplyUrlValue.replace('__PART_ID__', partId)
const data = await this.fetchWithErrorHandling(url, {
method: 'POST',
body: JSON.stringify({ providerKey, providerId })
}, 60000)

if (data.success) {
this.updateProgressDisplay(data)
this.showSuccessMessage(data.message || 'Part updated successfully')
sessionStorage.setItem('bulkImportScrollPosition', window.scrollY.toString())
window.location.reload()
} else {
this.showErrorMessage(data.error || 'Quick apply failed')
button.innerHTML = originalHtml
button.disabled = false
}
} catch (error) {
console.error('Error in quick apply:', error)
this.showErrorMessage(error.message || 'Quick apply failed')
button.innerHTML = originalHtml
button.disabled = false
}
}

async quickApplyAll(event) {
event.preventDefault()
event.stopPropagation()

if (!confirm('This will apply the top search result to all pending parts without individual review. Continue?')) {
return
}

const button = event.currentTarget
const spinner = document.getElementById('quick-apply-all-spinner')
const originalHtml = button.innerHTML

button.disabled = true
if (spinner) {
spinner.style.display = 'inline-block'
}

try {
const data = await this.fetchWithErrorHandling(this.quickApplyAllUrlValue, {
method: 'POST'
}, 300000)

if (data.success) {
this.updateProgressDisplay(data)

let message = data.message || 'Bulk apply completed'
if (data.errors && data.errors.length > 0) {
message += '\nErrors:\n' + data.errors.join('\n')
}

this.showSuccessMessage(message)
sessionStorage.setItem('bulkImportScrollPosition', window.scrollY.toString())
window.location.reload()
} else {
this.showErrorMessage(data.error || 'Bulk apply failed')
button.innerHTML = originalHtml
button.disabled = false
}
} catch (error) {
console.error('Error in quick apply all:', error)
this.showErrorMessage(error.message || 'Bulk apply failed')
button.innerHTML = originalHtml
button.disabled = false
} finally {
if (spinner) {
spinner.style.display = 'none'
}
}
}

showSuccessMessage(message) {
this.showToast('success', message)
}
Expand Down
19 changes: 19 additions & 0 deletions assets/controllers/field_mapping_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ export default class extends Controller {
newFieldSelect.addEventListener('change', this.updateFieldOptions.bind(this))
}

// Auto-increment priority based on existing mappings
const nextPriority = this.getNextPriority()
const priorityInput = newRow.querySelector('input[name*="[priority]"]')
if (priorityInput) {
priorityInput.value = nextPriority
}

this.updateFieldOptions()
this.updateAddButtonState()
}
Expand Down Expand Up @@ -119,6 +126,18 @@ export default class extends Controller {
}
}

getNextPriority() {
const priorityInputs = this.tbodyTarget.querySelectorAll('input[name*="[priority]"]')
let maxPriority = 0
priorityInputs.forEach(input => {
const val = parseInt(input.value, 10)
if (!isNaN(val) && val > maxPriority) {
maxPriority = val
}
})
return Math.min(maxPriority + 1, 10)
}

handleFormSubmit(event) {
if (this.hasSubmitButtonTarget) {
this.submitButtonTarget.disabled = true
Expand Down
Loading
Loading