OverviewFilesCommitsIssuesDocsReleasesPeers

pear-git-v3 / lib / web / static / pgv3-upload.js

74 lines · javascript ref:
/**
 * pgv3 file upload handler.
 *
 * Intercepts form submissions that have a file input. If a file is selected:
 * 1. Reads the file as an ArrayBuffer
 * 2. POSTs the raw bytes to /api/upload
 * 3. Gets the content hash back
 * 4. Injects the hash into a hidden `images` field on the form
 * 5. Lets the form submit proceed normally (with the hash included)
 *
 * Works on any form with class="pgv3-upload-form". The form must contain:
 *   <input type="file" name="attachment">
 *   <input type="hidden" name="images" value="">
 *
 * The hidden field accumulates comma-separated hashes if multiple uploads
 * are done before submitting.
 */

document.addEventListener('DOMContentLoaded', () => {
  const forms = document.querySelectorAll('.pgv3-upload-form')

  for (const form of forms) {
    const fileInput = form.querySelector('input[type="file"]')
    const imagesField = form.querySelector('input[name="images"]')
    const preview = form.querySelector('.upload-preview')

    if (!fileInput || !imagesField) continue

    // When a file is selected, upload it immediately and show a preview
    fileInput.addEventListener('change', async () => {
      const file = fileInput.files[0]
      if (!file) return

      // Show uploading state
      if (preview) preview.textContent = `uploading ${file.name}...`

      try {
        const response = await fetch(((document.body && document.body.dataset.prefix) || '') + '/api/upload', {
          method: 'POST',
          body: file,
          credentials: 'same-origin'
        })

        if (!response.ok) {
          const err = await response.text()
          throw new Error(err)
        }

        const result = await response.json()

        // Append hash to the hidden images field
        const existing = imagesField.value ? imagesField.value.split(',').filter(Boolean) : []
        existing.push(result.hash)
        imagesField.value = existing.join(',')

        // Show success
        if (preview) {
          const pfx = (document.body && document.body.dataset.prefix) || ''
          const img = file.type.startsWith('image/')
            ? `<img src="${pfx}/files/raw?path=${encodeURIComponent(result.path)}" style="max-width:200px;max-height:150px;border-radius:4px;margin-top:0.3rem">`
            : ''
          preview.innerHTML = `attached: ${file.name} (${result.hash.slice(0, 12)}…)${img}`
        }

        // Clear the file input so the form doesn't try to upload the raw file
        fileInput.value = ''
      } catch (err) {
        if (preview) preview.textContent = `upload failed: ${err.message}`
        console.error('[pgv3-upload]', err)
      }
    })
  }
})