PageSourceSearch

https://optimo.ch/assets/gray_matter/modules/generic_upload-4932b3…fe8e5322be20a24fd9dae481c3c0e3dab2477283.js

js optimo.ch collected 2026-09-24 17:54:04 UTC 4,353 bytes, 149 lines download raw bytes

1// Copyright (c) 2021-2025 GrayBits LLC
2
3import * as Notification from 'gray_matter/utility/notification'
4import axios from 'axios'
5
6export default class GenericUpload{
7  constructor(e, url, options){
8    this.element = e;
9    this.url = url;
10    this.element.interface = this;
11    this.setupButtons();
12    if (!this.upload_button) return;
13    this.setupProgress();
14
15    this.file_input = e.querySelector('input[type="file"]');
16    this.file_input.addEventListener('change', (e) => this.startUploads());
17
18    if (options){
19      if (options.success) this.processSuccessfulUpload = options.success;
20      if (options.failure) this.processFailedUpload = options.failure;
21      if (options.preprocess) this.preprocessData = options.preprocess;
22    }
23  }
24
25  setupProgress(){
26    this.progress_label = this.element.querySelector('.upload_progress_label');
27    this.progress_label_initial_value = this.progress_label.innerHTML;
28    this.progress_value = this.element.querySelector('.upload_progress_value');
29    this.progress_value.style.strokeDasharray = "157.08 157.08"
30  }
31  
32  setupButtons(){
33    this.upload_button = this.element.querySelector('button.upload');
34    if (!this.upload_button) return;
35
36    this.upload_button.addEventListener('click', (e) => this.openFileBrowser(e));
37    this.setupDrop();
38  }
39
40  setupDrop(element){
41    this.upload_button.addEventListener('dragenter', (e) => this.dragHighlight(e));
42    this.upload_button.addEventListener('dragover', (e) => this.dragHighlight(e));
43    this.upload_button.addEventListener('dragleave', (e) => this.dragLeave(e));
44    this.upload_button.addEventListener('drop', (e) => this.drop(e));
45  }
46
47  dragHighlight(e){
48    e.preventDefault();
49    e.stopPropagation();
50    this.upload_button.classList.add('drop_active');
51  }
52
53  dragLeave(e){
54    e.preventDefault();
55    e.stopPropagation();
56    this.upload_button.classList.remove('drop_active');
57  }
58
59  drop(e){
60    e.preventDefault();
61    e.stopPropagation();
62    this.upload_button.classList.remove('drop_active');
63    this.uploadFiles(e.dataTransfer.files);
64  }
65
66
67  openFileBrowser(){
68    this.file_input.value = '';
69    this.file_input.click();
70  }
71
72  startUploads(){
73    if (this.file_input.files.length == 0) return;
74    
75    this.uploadFiles(this.file_input.files);
76  }
77
78  uploadFiles(files){
79    this.showProgress();
80    this.current_uploads = [];
81    this.current_loaded = [];
82    this.current_total = 0;
83    for (let i = 0; i < files.length; i++){
84      this.current_uploads.push(files[i].size);
85      this.current_loaded.push(0);
86      this.current_total += files[i].size;
87    }
88    for (let i = 0; i < files.length; i++){
89      this.startUpload(files[i], i);
90    }
91  }
92
93  async startUpload(file, index){
94    let form_data = new FormData();
95    form_data.append('file', file);
96   
97    if (this.preprocessData){
98      this.preprocessData(this, form_data);
99    }
100
101    try{
102      const response = await axios.post(this.url,
103        form_data, {
104          onUploadProgress: (e) => {
105            let i = index;
106            this.current_loaded[i] = e.loaded;
107            let total_loaded = 0;
108            for (let i = 0; i < this.current_loaded.length; i++){
109              total_loaded += this.current_loaded[i];
110            }       
111            this.setProgress(total_loaded / this.current_total);
112          }
113        }
114      );
115      if (this.processSuccessfulUpload){
116        this.processSuccessfulUpload(response);
117      }
118    } catch(error) {
119      if (this.processFailedUpload){
120        this.processFailedUpload(error, file);
121      } else {
122        if (error.response){
123          Notification.showError(error.response.data.error);
124        } else {
125          Notification.showError('Upload failed');
126        }
127      }
128    }
129    this.hideProgress();
130  }
131
132  showProgress(){
133    this.progress_value.style.strokeDashoffset = '0';
134    this.progress_label.innerHTML = '';
135    this.element.classList.add('uploading');
136    this.upload_button.disabled = true;
137  }
138
139  hideProgress(){
140    this.element.classList.remove('uploading');
141    this.progress_label.innerHTML = this.progress_label_initial_value;
142    this.upload_button.disabled = false;
143  }
144
145  setProgress(percentage){
146    this.progress_label.innerHTML = (Math.min(100 * percentage, 100)).toFixed(0) + '%';  
147    this.progress_value.style.strokeDashoffset = 157.08 * (1 - percentage);
148  }
149};

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.