1import { Controller } from '@hotwired/stimulus'; 2import * as ActiveStorage from '@rails/activestorage'; 3 4export default class extends Controller { 5 static targets = ['submitBtn', 'fileEl', 'validationMessageEl'] 6 7 connect() { 8 ActiveStorage.start(); 9 10 addEventListener('direct-upload:initialize', this.directUploadInitialize); 11 addEventListener('direct-upload:start', this.directUploadStart); 12 addEventListener("direct-upload:progress", this.directUploadProgress); 13 addEventListener("direct-upload:error", this.directUploadError); 14 addEventListener("direct-upload:end", this.directUploadEnd); 15 16 this.fileElTarget.addEventListener('change', this.fileValidator.bind(this)) 17 } 18 19 disconnect() { 20 removeEventListener('direct-upload:initialize', this.directUploadInitialize); 21 removeEventListener('direct-upload:start', this.directUploadStart); 22 removeEventListener("direct-upload:progress", this.directUploadProgress); 23 removeEventListener("direct-upload:error", this.directUploadError); 24 removeEventListener("direct-upload:end", this.directUploadEnd); 25 26 this.fileElTarget.removeEventListener('change', this.fileValidator) 27 } 28 29 fileValidator(event) { 30 const fileSizeInMb = Math.round(event.target.files[0].size / 1000 / 1000) 31 32 let validationMessages = [] 33 34 if (fileSizeInMb > 100) { 35 validationMessages.push(`File is too big (${fileSizeInMb}Mb). Limit is 100Mb.`) 36 } 37 38 if (validationMessages.length != 0) { 39 this.validationMessageElTarget.innerHTML = ` 40 <div class="alert alert-danger"> 41 ${validationMessages.join(' ')} 42 </div> 43 ` 44 45 this.submitBtnTarget.disabled = true 46 } else { 47 this.validationMessageElTarget.innerHTML = '' 48 49 this.submitBtnTarget.disabled = false 50 } 51 } 52 53 directUploadInitialize(event) { 54 const { target, detail } = event 55 const { id, file } = detail 56 57 target.insertAdjacentHTML("beforebegin", ` 58 <div id="direct-upload-${id}" class="direct-upload direct-upload--pending"> 59 <div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div> 60 <span class="direct-upload__filename">${file.name}</span> 61 </div> 62 `) 63 } 64 65 directUploadStart(event) { 66 const { id } = event.detail 67 const element = document.getElementById(`direct-upload-${id}`) 68 69 element.classList.remove('direct-upload--pending') 70 } 71 72 directUploadProgress(event) { 73 const { id, progress } = event.detail 74 const progressElement = document.getElementById(`direct-upload-progress-${id}`) 75 76 progressElement.style.width = `${progress}%` 77 } 78 79 directUploadError(event) { 80 event.preventDefault() 81 const { id, error } = event.detail 82 const element = document.getElementById(`direct-upload-${id}`) 83 84 element.classList.add('direct-upload--error') 85 element.setAttribute('title', error) 86 } 87 88 directUploadEnd(event) { 89 const { id } = event.detail 90 const element = document.getElementById(`direct-upload-${id}`) 91 92 element.classList.add('direct-upload--complete') 93 } 94};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.