Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

175 satır
6.3 KiB

  1. import $ from 'jquery';
  2. import FilesField from './file';
  3. import { config, translations } from 'grav-form';
  4. import Sortable from 'sortablejs';
  5. const template = `
  6. <div class="dz-preview dz-file-preview">
  7. <div class="dz-details">
  8. <div class="dz-filename"><span data-dz-name></span></div>
  9. <div class="dz-size" data-dz-size></div>
  10. <img data-dz-thumbnail />
  11. </div>
  12. <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
  13. <div class="dz-success-mark"><span>✔</span></div>
  14. <div class="dz-error-mark"><span>✘</span></div>
  15. <div class="dz-error-message"><span data-dz-errormessage></span></div>
  16. <a class="dz-remove" title="${translations.PLUGIN_FORM.DELETE}" href="javascript:undefined;" data-dz-remove>${translations.PLUGIN_FORM.DELETE}</a>
  17. </div>`.trim();
  18. export default class PageMedia extends FilesField {
  19. constructor({ container = '#grav-dropzone', options = {} } = {}) {
  20. const previewTemplate = $('#dropzone-media-template').html() || template;
  21. options = Object.assign(options, { previewTemplate });
  22. super({ container, options });
  23. if (!this.container.length) { return; }
  24. this.urls = {
  25. fetch: `${this.container.data('media-url')}/task${config.param_sep}listmedia`,
  26. add: `${this.container.data('media-url')}/task${config.param_sep}addmedia`,
  27. delete: `${this.container.data('media-url')}/task${config.param_sep}delmedia`
  28. };
  29. this.dropzone.options.url = this.urls.add;
  30. if (typeof this.options.fetchMedia === 'undefined' || this.options.fetchMedia) {
  31. this.fetchMedia();
  32. }
  33. const field = $(`[name="${this.container.data('dropzone-field')}"]`);
  34. if (field.length) {
  35. this.sortable = new Sortable(this.container.get(0), {
  36. animation: 150,
  37. // forceFallback: true,
  38. setData: (dataTransfer, target) => {
  39. target = $(target);
  40. this.dropzone.disable();
  41. target.addClass('hide-backface');
  42. dataTransfer.effectAllowed = 'copy';
  43. },
  44. onSort: () => {
  45. let names = [];
  46. this.container.find('[data-dz-name]').each((index, file) => {
  47. file = $(file);
  48. const name = file.text().trim();
  49. names.push(name);
  50. });
  51. field.val(names.join(','));
  52. }
  53. });
  54. }
  55. }
  56. onDropzoneRemovedFile(file, ...extra) {
  57. if (!file.accepted || file.rejected) { return; }
  58. const form = this.container.closest('form');
  59. const unique_id = form.find('[name="__unique_form_id__"]');
  60. let url = file.removeUrl || this.urls.delete || `${location.href}.json`;
  61. let path = (url || '').match(/path:(.*)\//);
  62. let data = new FormData();
  63. data.append('filename', file.name);
  64. data.append('__form-name__', form.find('[name="__form-name__"]').val());
  65. if (unique_id.length) {
  66. data.append('__unique_form_id__', unique_id.val());
  67. }
  68. data.append('name', this.options.dotNotation);
  69. data.append('form-nonce', config.form_nonce);
  70. if (file.sessionParams) {
  71. data.append('__form-file-remover__', '1');
  72. data.append('session', file.sessionParams);
  73. }
  74. $.ajax({
  75. url,
  76. data,
  77. method: 'POST',
  78. contentType: false,
  79. processData: false,
  80. success: () => {
  81. if (!path) { return; }
  82. path = global.atob(path[1]);
  83. let input = this.container.find('[name][type="hidden"]');
  84. let data = JSON.parse(input.val() || '{}');
  85. delete data[path];
  86. input.val(JSON.stringify(data));
  87. }
  88. });
  89. }
  90. fetchMedia() {
  91. const order = this.container.closest('.form-field').find('[name="data[header][media_order]"]').val();
  92. const data = { order };
  93. let url = this.urls.fetch;
  94. $.ajax({
  95. url,
  96. method: 'POST',
  97. data,
  98. success: (response) => {
  99. if (typeof response === 'string' || response instanceof String) {
  100. return false;
  101. }
  102. response = response.results;
  103. Object.keys(response).forEach((name) => {
  104. let data = response[name];
  105. let mock = { name, size: data.size, accepted: true, extras: data };
  106. this.dropzone.files.push(mock);
  107. this.dropzone.options.addedfile.call(this.dropzone, mock);
  108. this.dropzone.options.thumbnail.call(this.dropzone, mock, data.url);
  109. });
  110. this.container.find('.dz-preview').prop('draggable', 'true');
  111. }
  112. });
  113. /*
  114. request(url, { method: 'post', body }, (response) => {
  115. let results = response.results;
  116. Object.keys(results).forEach((name) => {
  117. let data = results[name];
  118. let mock = { name, size: data.size, accepted: true, extras: data };
  119. this.dropzone.files.push(mock);
  120. this.dropzone.options.addedfile.call(this.dropzone, mock);
  121. this.dropzone.options.thumbnail.call(this.dropzone, mock, data.url);
  122. });
  123. this.container.find('.dz-preview').prop('draggable', 'true');
  124. });*/
  125. }
  126. onDropzoneSending(file, xhr, formData) {
  127. /*
  128. // Cannot call super because Safari and IE API don't implement `delete`
  129. super.onDropzoneSending(file, xhr, formData);
  130. formData.delete('task');
  131. */
  132. formData.append('name', this.options.dotNotation);
  133. formData.append('admin-nonce', config.admin_nonce);
  134. }
  135. onDropzoneComplete(file) {
  136. super.onDropzoneComplete(file);
  137. this.sortable.options.onSort();
  138. // accepted
  139. $('.dz-preview').prop('draggable', 'true');
  140. }
  141. // onDropzoneRemovedFile(file, ...extra) {
  142. // super.onDropzoneRemovedFile(file, ...extra);
  143. // this.sortable.options.onSort();
  144. // }
  145. }
  146. export let Instance = new PageMedia();