PageSourceSearch

https://survivalinternational.fr/assets/controllers/admin/pictures/upload_controller-c21572b1.js

js survivalinternational.fr collected 2026-09-25 04:09:13 UTC 3,939 bytes, 129 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2import Uppy from '@uppy/core'
3import Dashboard from '@uppy/dashboard';
4import AwsS3 from '@uppy/aws-s3';
5
6// Connects to data-controller="admin--pictures--upload"
7export default class extends Controller {
8  static targets = [
9    'fields',
10    'submitBtn',
11    'pictureReference',
12    'pictureCredit',
13    'pictureTribe',
14    'pictureCountry',
15    'pictureNote',
16    'pictureCopyright',
17    'pictureExternalUse',
18    'defaultReference',
19    'defaultCredit',
20    'defaultTribe',
21    'defaultCountry',
22    'defaultNote',
23    'defaultCopyright',
24    'defaultExternalUse'
25  ]
26  // Create unique identifier for each set of picture fields - currently just an increment.
27  // Could just generate uuid within pictures#upload_form_fields.
28  static values = { fieldNumber: Number }
29
30  connect () {
31    this.uppyNotCreated = true;
32  }
33
34  canInitUppy () {
35    let fieldsFilled = [
36      this.defaultReferenceTarget.value,
37      this.defaultCreditTarget.value
38    ].every(val => { return val !== ''; })
39    if (fieldsFilled && this['uppyNotCreated']) { this.initUppy(); }
40  }
41
42  initUppy () {
43    this.uppyNotCreated = false;
44    const uppy = new Uppy({
45      autoProceed: true,
46      restrictions: {
47        maxNumberOfFiles: 30,
48        minNumberOfFiles: 1,
49        allowedFileTypes: ["image/*"]
50      }
51    })
52    .use(Dashboard, { inline: true, height: 600, width: '100%', target: '.uppy-dashboard-elem' })
53    .use(AwsS3, {
54      shouldUseMultipart: (file) => file.size > 100 * 2 ** 20,
55      endpoint: '/',
56    })
57
58    uppy.on('upload-success', (file, response) => {
59      const fileId = decodeURIComponent(response.uploadURL).match(/cache\/(.+)/)[1];
60      // construct uploaded file data in the format that Shrine expects
61      const uploadedFileData = {
62        id: fileId,
63        storage: 'cache',
64        metadata: {
65          size: file.size,
66          filename: file.name,
67          mime_type: file.type,
68        }
69      }
70
71      const fileData = JSON.stringify(uploadedFileData);
72      this.createNestedFormFields(file, fileData);
73      if (this.submitBtnTarget.disabled === true) { this.submitBtnTarget.disabled = false; }
74    })
75  }
76
77  // This logic can likely be replace by creating a js triggered turbo_frame
78  async createNestedFormFields (file, fileData) {
79    const csrfToken = document.head.querySelector("meta[name=csrf-token]")?.content;
80    const fieldNumber = this.fieldNumberValue;
81    this.fieldNumberValue += 1;
82    await fetch(`/admin/pictures/upload_form_fields?filename=${file.name}&field_number=${fieldNumber}`,
83      {
84        headers: { 'X-CSRF-Token': csrfToken, 'Content-Type': 'application/x-www-form-urlencoded' },
85        method: 'GET'
86      }
87    ).then(response => {
88      return response.text();
89    })
90    .then(htmlString => {
91      this.fieldsTarget.innerHTML += htmlString;
92      return;
93    })
94
95    const pictureFields = document.querySelector(`[data-form-fields-file="${file.name}"]`)
96    // Add required shrine file metadata to hidden input
97    pictureFields.querySelector(`[data-form-fields-file-data]`).value = fileData;
98    // Show preview image within correct form
99    pictureFields.querySelector('img').src = file.preview;
100  }
101
102  pictureReferenceTargetConnected(element) {
103    element.value = this.defaultReferenceTarget.value;
104  }
105
106  pictureNoteTargetConnected(element) {
107    element.value = this.defaultNoteTarget.value;
108  }
109
110  pictureTribeTargetConnected(element) {
111    element.value = this.defaultTribeTarget.value;
112  }
113
114  pictureCountryTargetConnected(element) {
115    element.value = this.defaultCountryTarget.value;
116  }
117
118  pictureCopyrightTargetConnected(element) {
119    element.checked = this.defaultCopyrightTarget.checked;
120  }
121
122  pictureExternalUseTargetConnected(element) {
123    element.checked = this.defaultExternalUseTarget.checked;
124  }
125
126  pictureCreditTargetConnected(element) {
127    element.value = this.defaultCreditTarget.value;
128  }
129}

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.