Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

341 rinda
12 KiB

  1. import $ from 'jquery';
  2. import Dropzone from 'dropzone';
  3. // import EXIF from 'exif-js';
  4. import {config, translations} from 'grav-form';
  5. // translations
  6. const Dictionary = {
  7. dictCancelUpload: translations.PLUGIN_FORM.DROPZONE_CANCEL_UPLOAD,
  8. dictCancelUploadConfirmation: translations.PLUGIN_FORM.DROPZONE_CANCEL_UPLOAD_CONFIRMATION,
  9. dictDefaultMessage: translations.PLUGIN_FORM.DROPZONE_DEFAULT_MESSAGE,
  10. dictFallbackMessage: translations.PLUGIN_FORM.DROPZONE_FALLBACK_MESSAGE,
  11. dictFallbackText: translations.PLUGIN_FORM.DROPZONE_FALLBACK_TEXT,
  12. dictFileTooBig: translations.PLUGIN_FORM.DROPZONE_FILE_TOO_BIG,
  13. dictInvalidFileType: translations.PLUGIN_FORM.DROPZONE_INVALID_FILE_TYPE,
  14. dictMaxFilesExceeded: translations.PLUGIN_FORM.DROPZONE_MAX_FILES_EXCEEDED,
  15. dictRemoveFile: translations.PLUGIN_FORM.DROPZONE_REMOVE_FILE,
  16. dictRemoveFileConfirmation: translations.PLUGIN_FORM.DROPZONE_REMOVE_FILE_CONFIRMATION,
  17. dictResponseError: translations.PLUGIN_FORM.DROPZONE_RESPONSE_ERROR
  18. };
  19. Dropzone.autoDiscover = false;
  20. const DropzoneMediaConfig = {
  21. createImageThumbnails: {thumbnailWidth: 150},
  22. addRemoveLinks: false,
  23. dictDefaultMessage: Dictionary.dictDefaultMessage,
  24. dictRemoveFileConfirmation: Dictionary.dictRemoveFileConfirmation,
  25. previewTemplate: ''
  26. };
  27. // window.EXIF = EXIF;
  28. export default class FilesField {
  29. constructor({container = '.dropzone.files-upload', options = {}} = {}) {
  30. this.container = $(container);
  31. if (!this.container.length) {
  32. return;
  33. }
  34. this.urls = {};
  35. DropzoneMediaConfig.previewTemplate = $('#dropzone-template').html();
  36. this.options = Object.assign({}, Dictionary, DropzoneMediaConfig, {
  37. klass: this,
  38. url: this.container.data('file-url-add') || config.current_url,
  39. acceptedFiles: this.container.data('media-types'),
  40. init: this.initDropzone
  41. }, this.container.data('dropzone-options'), options);
  42. this.dropzone = new Dropzone(container, this.options);
  43. this.dropzone.on('complete', this.onDropzoneComplete.bind(this));
  44. this.dropzone.on('success', this.onDropzoneSuccess.bind(this));
  45. this.dropzone.on('removedfile', this.onDropzoneRemovedFile.bind(this));
  46. this.dropzone.on('sending', this.onDropzoneSending.bind(this));
  47. this.dropzone.on('error', this.onDropzoneError.bind(this));
  48. }
  49. initDropzone() {
  50. let files = this.options.klass.container.find('[data-file]');
  51. let dropzone = this;
  52. if (!files.length) {
  53. return;
  54. }
  55. files.each((index, file) => {
  56. file = $(file);
  57. let data = file.data('file');
  58. let mock = {
  59. name: data.name,
  60. size: data.size,
  61. type: data.type,
  62. status: Dropzone.ADDED,
  63. accepted: true,
  64. url: this.options.url,
  65. removeUrl: data.remove,
  66. data
  67. };
  68. dropzone.files.push(mock);
  69. dropzone.options.addedfile.call(dropzone, mock);
  70. if (mock.type.match(/^image\//)) dropzone.options.thumbnail.call(dropzone, mock, data.path);
  71. file.remove();
  72. });
  73. }
  74. getURI() {
  75. return this.container.data('mediaUri') || '';
  76. }
  77. onDropzoneSending(file, xhr, formData) {
  78. const form = this.container.closest('form');
  79. const unique_id = form.find('[name="__unique_form_id__"]');
  80. formData.append('__form-name__', form.find('[name="__form-name__"]').val());
  81. if (unique_id.length) {
  82. formData.append('__unique_form_id__', unique_id.val());
  83. }
  84. formData.append('__form-file-uploader__', 1);
  85. formData.append('name', this.options.dotNotation);
  86. formData.append('form-nonce', config.form_nonce);
  87. formData.append('task', 'filesupload');
  88. formData.append('uri', this.getURI());
  89. }
  90. onDropzoneSuccess(file, response, xhr) {
  91. if (this.options.reloadPage) {
  92. global.location.reload();
  93. }
  94. // store params for removing file from session before it gets saved
  95. if (response.session) {
  96. file.sessionParams = response.session;
  97. file.removeUrl = this.options.url;
  98. // Touch field value to force a mutation detection
  99. const input = this.container.find('[name][type="hidden"]');
  100. const value = input.val();
  101. input.val(value + ' ');
  102. }
  103. return this.handleError({
  104. file,
  105. data: response,
  106. mode: 'removeFile',
  107. msg: `<p>${translations.PLUGIN_FORM.FILE_ERROR_UPLOAD} <strong>${file.name}</strong></p>
  108. <pre>${response.message}</pre>`
  109. });
  110. }
  111. onDropzoneComplete(file) {
  112. if (!file.accepted && !file.rejected) {
  113. let data = {
  114. status: 'error',
  115. message: `${translations.PLUGIN_FORM.FILE_UNSUPPORTED}: ${file.name.match(/\..+/).join('')}`
  116. };
  117. return this.handleError({
  118. file,
  119. data,
  120. mode: 'removeFile',
  121. msg: `<p>${translations.PLUGIN_FORM.FILE_ERROR_ADD} <strong>${file.name}</strong></p>
  122. <pre>${data.message}</pre>`
  123. });
  124. }
  125. if (this.options.reloadPage) {
  126. global.location.reload();
  127. }
  128. }
  129. onDropzoneRemovedFile(file, ...extra) {
  130. if (!file.accepted || file.rejected) {
  131. return;
  132. }
  133. const form = this.container.closest('form');
  134. const unique_id = form.find('[name="__unique_form_id__"]');
  135. let url = file.removeUrl || this.urls.delete || `${location.href}.json`;
  136. let path = (url || '').match(/path:(.*)\//);
  137. let data = new FormData();
  138. data.append('filename', file.name);
  139. data.append('__form-name__', form.find('[name="__form-name__"]').val());
  140. data.append('name', this.options.dotNotation);
  141. data.append('form-nonce', config.form_nonce);
  142. data.append('uri', this.getURI());
  143. if (file.sessionParams) {
  144. data.append('__form-file-remover__', '1');
  145. data.append('session', file.sessionParams);
  146. }
  147. if (unique_id.length) {
  148. data.append('__unique_form_id__', unique_id.val());
  149. }
  150. $.ajax({
  151. url,
  152. data,
  153. method: 'POST',
  154. contentType: false,
  155. processData: false,
  156. success: () => {
  157. if (!path) {
  158. return;
  159. }
  160. path = global.atob(path[1]);
  161. let input = this.container.find('[name][type="hidden"]');
  162. let data = JSON.parse(input.val() || '{}');
  163. delete data[path];
  164. input.val(JSON.stringify(data));
  165. }
  166. });
  167. }
  168. onDropzoneError(file, response, xhr) {
  169. let message = xhr && response.error ? response.error.message : response;
  170. $(file.previewElement).find('[data-dz-errormessage]').html(message);
  171. return this.handleError({
  172. file,
  173. data: {status: 'error'},
  174. msg: `<pre>${message}</pre>`
  175. });
  176. }
  177. handleError(options) {
  178. return true;
  179. /* let { file, data, mode, msg } = options;
  180. if (data.status !== 'error' && data.status !== 'unauthorized') { return; }
  181. switch (mode) {
  182. case 'addBack':
  183. if (file instanceof File) {
  184. this.dropzone.addFile.call(this.dropzone, file);
  185. } else {
  186. this.dropzone.files.push(file);
  187. this.dropzone.options.addedfile.call(this.dropzone, file);
  188. this.dropzone.options.thumbnail.call(this.dropzone, file, file.extras.url);
  189. }
  190. break;
  191. case 'removeFile':
  192. default:
  193. if (~this.dropzone.files.indexOf(file)) {
  194. file.rejected = true;
  195. this.dropzone.removeFile.call(this.dropzone, file, { silent: true });
  196. }
  197. break;
  198. }
  199. let modal = $('[data-remodal-id="generic"]');
  200. modal.find('.error-content').html(msg);
  201. $.remodal.lookup[modal.data('remodal')].open(); */
  202. }
  203. }
  204. /*
  205. export function UriToMarkdown(uri) {
  206. uri = uri.replace(/@3x|@2x|@1x/, '');
  207. uri = uri.replace(/\(/g, '%28');
  208. uri = uri.replace(/\)/g, '%29');
  209. return uri.match(/\.(jpe?g|png|gif|svg)$/i) ? `![](${uri})` : `[${decodeURI(uri)}](${uri})`;
  210. }
  211. */
  212. let instances = [];
  213. let cache = $();
  214. const onAddedNodes = (event, target/* , record, instance */) => {
  215. let files = $(target).find('.dropzone.files-upload');
  216. if (!files.length) {
  217. return;
  218. }
  219. files.each((index, file) => {
  220. file = $(file);
  221. if (!~cache.index(file)) {
  222. addNode(file);
  223. }
  224. });
  225. };
  226. const addNode = (container) => {
  227. container = $(container);
  228. let input = container.find('input[type="file"]');
  229. let settings = container.data('grav-file-settings') || {};
  230. if (settings.accept && ~settings.accept.indexOf('*')) {
  231. settings.accept = [''];
  232. }
  233. let options = {
  234. url: container.data('file-url-add') || (container.closest('form').attr('action') || config.current_url) + '.json',
  235. paramName: settings.paramName || 'file',
  236. dotNotation: settings.name || 'file',
  237. acceptedFiles: settings.accept ? settings.accept.join(',') : input.attr('accept') || container.data('media-types'),
  238. maxFilesize: settings.filesize || 256,
  239. maxFiles: settings.limit || null,
  240. resizeWidth: settings.resizeWidth || null,
  241. resizeHeight: settings.resizeHeight || null,
  242. resizeQuality: settings.resizeQuality || null,
  243. accept: function(file, done) {
  244. const resolution = settings.resolution;
  245. let error = '';
  246. if (!resolution) return done();
  247. if ((this.options.maxFiles != null) && (this.getAcceptedFiles().length >= this.options.maxFiles)) {
  248. done(this.options.dictMaxFilesExceeded.replace('{{maxFiles}}', this.options.maxFiles));
  249. return this.emit('maxfilesexceeded', file);
  250. }
  251. const reader = new FileReader();
  252. if (resolution.min || (!(settings.resizeWidth || settings.resizeHeight) && resolution.max)) {
  253. reader.onload = function(event) {
  254. const image = new Image();
  255. image.src = event.target.result;
  256. image.onload = function() {
  257. if (resolution.min) {
  258. Object.keys(resolution.min).forEach((attr) => {
  259. if (this[attr] < resolution.min[attr]) {
  260. error += translations.PLUGIN_FORM.RESOLUTION_MIN.replace(/{{attr}}/g, attr).replace(/{{min}}/g, resolution.min[attr]);
  261. }
  262. });
  263. }
  264. if (!(settings.resizeWidth || settings.resizeHeight)) {
  265. if (resolution.max) {
  266. Object.keys(resolution.max).forEach((attr) => {
  267. if (this[attr] > resolution.max[attr]) {
  268. error += translations.PLUGIN_FORM.RESOLUTION_MAX.replace(/{{attr}}/g, attr).replace(/{{max}}/g, resolution.max[attr]);
  269. }
  270. });
  271. }
  272. }
  273. done(error);
  274. };
  275. };
  276. reader.readAsDataURL(file);
  277. } else {
  278. return done(error);
  279. }
  280. }
  281. };
  282. cache = cache.add(container);
  283. container = container[0];
  284. instances.push(new FilesField({container, options}));
  285. };
  286. export let Instances = (() => {
  287. $(document).ready(() => {
  288. $('.dropzone.files-upload').each((i, container) => addNode(container));
  289. $('body').on('mutation._grav', onAddedNodes);
  290. });
  291. return instances;
  292. })();