amcms_filemanager 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +78 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/amcms_filemanager_manifest.js +1 -0
  6. data/app/assets/images/amcms_filemanager/folder.png +0 -0
  7. data/app/assets/stylesheets/amcms_filemanager/application.css +34 -0
  8. data/app/assets/stylesheets/amcms_filemanager/filemanager.css +4 -0
  9. data/app/controllers/amcms_filemanager/application_controller.rb +11 -0
  10. data/app/controllers/amcms_filemanager/filemanager_controller.rb +93 -0
  11. data/app/controllers/amcms_filemanager/imagemanager_controller.rb +34 -0
  12. data/app/helpers/amcms_filemanager/application_helper.rb +4 -0
  13. data/app/helpers/amcms_filemanager/filemanager_helper.rb +4 -0
  14. data/app/jobs/amcms_filemanager/application_job.rb +4 -0
  15. data/app/lib/amcms_filemanager/filemanager.rb +181 -0
  16. data/app/lib/amcms_filemanager/imagemanager.rb +5 -0
  17. data/app/mailers/amcms_filemanager/application_mailer.rb +6 -0
  18. data/app/models/amcms_filemanager/application_record.rb +5 -0
  19. data/app/uploaders/amcms_filemanager/filemanager_uploader.rb +56 -0
  20. data/app/views/amcms_filemanager/filemanager/index.html.erb +168 -0
  21. data/app/views/layouts/amcms_filemanager/application.html.erb +497 -0
  22. data/config/locales/en.yml +4 -0
  23. data/config/routes.rb +12 -0
  24. data/lib/amcms_filemanager/configuration.rb +9 -0
  25. data/lib/amcms_filemanager/engine.rb +25 -0
  26. data/lib/amcms_filemanager/version.rb +3 -0
  27. data/lib/amcms_filemanager.rb +6 -0
  28. data/lib/tasks/amcms_filemanager_tasks.rake +4 -0
  29. metadata +127 -0
@@ -0,0 +1,168 @@
1
+ <div id="amcms-filemanager-container" data-routes="<%= @config[:routes].to_json %>" data-type="<%= @config[:type] %>">
2
+ <nav class="navbar fixed-top navbar-expand-lg navbar-light bg-light mb-3 fm">
3
+ <div class="collapse navbar-collapse">
4
+ <ul class="navbar-nav me-auto mb-2 mb-lg-0">
5
+ <li class="nav-item dropdown">
6
+ <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
7
+ <i class="bi bi-plus-lg"></i>
8
+ </a>
9
+ <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
10
+ <li id="fm-mkdir-item">
11
+ <a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#createFolderModal" href="#">
12
+ <i class="bi bi-folder-plus"></i>
13
+ Create Folder
14
+ </a>
15
+ </li>
16
+ <li id="fm-upload-item">
17
+ <a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#uploadModal" href="#">
18
+ <i class="bi bi-cloud-arrow-up"></i>
19
+ Upload
20
+ </a>
21
+ </li>
22
+ </ul>
23
+ </li>
24
+ <li class="nav-item"><a class="nav-link" id="pwd-display"></a></li>
25
+ </ul>
26
+ <ul class="navbar-nav ms-auto" id="file-list-type">
27
+ <% if @config[:type] == 'image' %>
28
+ <li class="nav-item">
29
+ <a class="nav-link active" aria-current="page" href="#" id="thumbnail-view-btn" onclick="switchViewHandler(this, 'thumbnail')">
30
+ <i class="bi bi-grid-fill"></i>
31
+ Thumbnails
32
+ </a>
33
+ </li>
34
+ <% end %>
35
+ <li class="nav-item">
36
+ <a class="nav-link<%= @config[:type] == 'file' ? ' active' : '' %>" aria-current="page" href="#" id="list-view-btn" onclick="switchViewHandler(this, 'list')">
37
+ <i class="bi bi-list-ul"></i>
38
+ List
39
+ </a>
40
+ </li>
41
+ </ul>
42
+ </div>
43
+ </nav>
44
+ <div class="fm-file-panel">
45
+ <div class="row" style="padding: 0 15px;">
46
+ <div id="fm-directory-structure" class="col-md-3 ">
47
+ <ul id="fm-directories-list" class="list-group position-static">
48
+
49
+ </ul>
50
+ </div>
51
+ <div id="fm-directory-listing" class="col-md-9" style="overflow: auto">
52
+ <div class="row" id="fm-file-list">
53
+
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ <!-- Create Folder Modal -->
59
+ <div class="modal fade" id="createFolderModal" tabindex="-1" aria-labelledby="createFolderModalLabel" aria-hidden="true">
60
+ <div class="modal-dialog">
61
+ <div class="modal-content">
62
+ <div class="modal-header">
63
+ <h5 class="modal-title" id="createFolderModalLabel">Create Folder</h5>
64
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
65
+ </div>
66
+ <div class="modal-body">
67
+ <form id="fm-new-folder-form">
68
+ <input type="text" name="item_name" id="new-folder-name" class="form-control" placeholder="Folder Name">
69
+ </form>
70
+ </div>
71
+ <div class="modal-footer">
72
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
73
+ <button type="button" class="btn btn-primary" onclick="createDirectory()">Create</button>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ <!-- Rename Item Modal -->
79
+ <div class="modal fade" id="renameItemModal" tabindex="-1" aria-labelledby="renameItemModalLabel" aria-hidden="true">
80
+ <div class="modal-dialog">
81
+ <div class="modal-content">
82
+ <div class="modal-header">
83
+ <h5 class="modal-title" id="renameItemModalLabel">Rename Item</h5>
84
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
85
+ </div>
86
+ <div class="modal-body">
87
+ <form id="fm-rename-item-form">
88
+ <input type="text" name="item_name" id="new-filename" class="form-control" placeholder="Rename">
89
+ <input type="hidden" name="original_filename" id="original-filename">
90
+ </form>
91
+ </div>
92
+ <div class="modal-footer">
93
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
94
+ <button type="button" class="btn btn-primary" onclick="renameFilename()">Rename</button>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ <!-- Warning Modal -->
100
+ <div class="modal" tabindex="-1" id="fmModal" aria-labelledby="fmModal" aria-hidden="true">
101
+ <div class="modal-dialog">
102
+ <div class="modal-content">
103
+ <div class="modal-header alert" id="fm-modal-header">
104
+ <h5 class="modal-title fm-modal-title">Title</h5>
105
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
106
+ </div>
107
+ <div class="modal-body fm-modal-body">
108
+ </div>
109
+ <div class="modal-footer fm-modal-footer">
110
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
111
+ <div class="fm-modal-footer-buttons"></div>
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ <!-- Upload Modal -->
117
+ <div class="modal fade" tabindex="-1" id="uploadModal" aria-labelledby="uploadModalLabel" aria-hidden="true">
118
+ <div class="modal-dialog modal-lg">
119
+ <div class="modal-content">
120
+ <div class="modal-header alert" id="fm-upload-header">
121
+ <h5 class="modal-title upload-modal-title">Upload Files</h5>
122
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
123
+ </div>
124
+ <div class="modal-body upload-modal-body">
125
+ <form action="<%= filemanager_upload_path(type: @config[:type]) %>" class="dropzone" id="fm-uploader">
126
+ <%= hidden_field_tag :authenticity_token, form_authenticity_token %>
127
+ <input type="hidden" name="dir" id="upload_to_dir">
128
+ </form>
129
+ </div>
130
+ <div class="modal-footer upload-modal-footer">
131
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ <!-- Resize Image Modal -->
138
+ <div class="modal fade" id="resizeImageModal" tabindex="-1" aria-labelledby="resizeImageModalLabel" aria-hidden="true">
139
+ <div class="modal-dialog modal-fullscreen modal-dialog-scrollable">
140
+ <div class="modal-content">
141
+ <div class="modal-header">
142
+ <h5 class="modal-title" id="imageResizeModalLabel">Resize Image</h5>
143
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
144
+ </div>
145
+ <div class="modal-body">
146
+ <div class="row">
147
+ <div class="col-8" id="image-preview-panel">
148
+ <img src="" alt="" id="original_image">
149
+ </div>
150
+ <div class="col-4">
151
+ <form id="fm-resize-image-form">
152
+ <h6>Image Details</h6>
153
+ <div id="image-info-container">
154
+ </div>
155
+ </form>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ <div class="modal-footer">
160
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
161
+ <button type="button" class="btn btn-secondary" onclick="resizeImageHandler(true)">Resize and Save Copy</button>
162
+ <button type="button" class="btn btn-primary" onclick="resizeImageHandler(false)">Resize and Save</button>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ </div>
167
+
168
+ </div>
@@ -0,0 +1,497 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Amcms filemanager</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/dropzone.min.css" integrity="sha512-jU/7UFiaW5UBGODEopEqnbIAHOI8fO6T99m7Tsmqs2gkdujByJfkCbbfPSN4Wlqlb9TGnsuC0YgUgWkRBK7B9A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
11
+ <%= stylesheet_link_tag "amcms_filemanager/application", media: "all" %>
12
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
13
+ <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
14
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.js" integrity="sha512-oQq8uth41D+gIH/NJvSJvVB85MFk1eWpMK6glnkg6I7EdMqC1XVkW7RxLheXwmFdG03qScCM7gKS/Cx3FYt7Tg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
15
+ </head>
16
+ <body>
17
+ <%= yield %>
18
+
19
+ <script>
20
+ const csrf = document.querySelector("meta[name='csrf-token']").getAttribute("content");
21
+ const mkdirModal = new bootstrap.Modal(document.getElementById('createFolderModal'));
22
+ const renameItemModal = new bootstrap.Modal(document.getElementById('renameItemModal'));
23
+ const resizeImageModal = new bootstrap.Modal(document.getElementById('resizeImageModal'));
24
+ let pwd = '';
25
+ const type = document.getElementById('amcms-filemanager-container').getAttribute('data-type');
26
+
27
+ Dropzone.options.fmUploader = {
28
+ init: function() {
29
+ this.on("complete", file => {
30
+ changeDirectory(pwd)
31
+ });
32
+ }
33
+ };
34
+
35
+ getTargetOrigin = () => {
36
+ // return wilcard(*) if debug on and testing locally
37
+ // if (allowDebugOrigin && window.location.origin.match(regex)) return "*";
38
+ //
39
+ // // since we're not testing locally, return required origin
40
+ // return targetOrigin;
41
+ return '*';
42
+ }
43
+
44
+ const routes = (path) => {
45
+ const config = document.getElementById('amcms-filemanager-container');
46
+ const routes = JSON.parse(config.dataset.routes);
47
+ return routes[path];
48
+ };
49
+
50
+ sendMessage = (filename) => {
51
+
52
+ window.parent.postMessage(
53
+ {
54
+ mceAction: "customAction",
55
+ data: {
56
+ location: filename
57
+ }
58
+ },
59
+ getTargetOrigin()
60
+ );
61
+ };
62
+
63
+ directoryListing = (response) => {
64
+ html = activeView() === 'thumbnail-view-btn' && type == 'image' ? thumbnailListing(response) : listViewLiisting(response);
65
+ document.getElementById('fm-file-list').innerHTML = html;
66
+ }
67
+
68
+ thumbnailListing = (response) => {
69
+ let html = '';
70
+ for (const file of response.data.files) {
71
+ const onClick = file.directory ? `changeDirectory('${file.filepath}')` : `sendMessage('${file.filepath}')`;
72
+
73
+ html += `<div class="col-md-3 mb-3">
74
+ <div class="card text-center d-flex mb-3">
75
+ <div class="row align-items-center item-name">
76
+ <a
77
+ data-filename="${file.filename}"
78
+ data-filepath="${file.filepath}"
79
+ data-directory="${file.directory}"
80
+ data-size="${file.size}"
81
+ data-date-modified="${file.date_modified}"
82
+ class="fm-${file.directory ? 'folder' : 'file'}-item"
83
+ onClick="${onClick}"
84
+ >
85
+ <img
86
+ src="${file.directory ? '/assets/amcms_filemanager/folder.png' : file.filepath}"
87
+ alt="${file.filename}"
88
+ class="fm-image-thumbnail"
89
+ style="border: none; max-width: 90%"
90
+ >
91
+ </a>
92
+ </div>
93
+ </div>
94
+ <div class="btn-group d-flex w-100 mb-3">
95
+ <button type="button" class="btn btn-sm btn-primary item-name" style="width:85%" onclick="${onClick}">${file.filename}</button>
96
+ <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" style="width:15%" data-bs-toggle="dropdown" aria-expanded="false">
97
+ <span class="visually-hidden">Toggle Dropdown</span>
98
+ </button>
99
+ <ul class="dropdown-menu dropdown-menu-end">
100
+ ${fileMenuOptions(file)}
101
+ </ul>
102
+ </div>
103
+ </div>`;
104
+ }
105
+ return html;
106
+ };
107
+
108
+ listViewLiisting = (response) => {
109
+ let html = '<ul class="list-group list-group-flush">';
110
+ for (const file of response.data.files) {
111
+ const onClick = file.directory ? `changeDirectory('${file.filepath}')` : `sendMessage('${file.filepath}')`;
112
+ const fileCopyMenuItem = !file.directory ? `<li><a class="dropdown-item" data-filepath="${file.filepath}" data-filename="${file.filename}" href="#" onclick="copyFileHandler(this)"><i class="bi bi-copy"></i> Copy</a></li>` : '';
113
+ html += `
114
+ <li class="list-group-item">
115
+ <div class="row">
116
+ <div class="col">
117
+ <a onclick="${onClick}">
118
+ <i class="bi bi-${file.directory ? 'folder-fill' : 'file-earmark-text-fill'}"></i>
119
+ ${file.filename}
120
+ </a>
121
+ </div>
122
+ <div class="col text-end">
123
+ ${file.directory ? '' : file.size}
124
+ </div>
125
+ <div class="col col-auto text-end">
126
+ ${file.date_modified}
127
+ <div class="btn-group" role="group">
128
+ <button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"></button>
129
+ <ul class="dropdown-menu">
130
+ ${fileMenuOptions(file)}
131
+ </ul>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </li>
136
+ `;
137
+ }
138
+ html += `</ul>`
139
+ return html;
140
+ };
141
+
142
+ directories = (response) => {
143
+ // console.log(response.data.root_directory);
144
+ let html = '';
145
+ if (pwd != response.data.parent_directory) {
146
+ html += `<li class="list-group-item">
147
+ <div onclick="changeDirectory('${response.data.parent_directory}', '${routes('cd_path')}')" class="w-100">
148
+ <i class="bi bi-folder-fill"></i>
149
+ ..
150
+ </div>
151
+ </li>`;
152
+ }
153
+ html += `<li class="list-group-item">
154
+ <div onclick="changeDirectory('${pwd}', '${routes('cd_path')}')" class="w-100">
155
+ <i class="bi bi-folder-fill"></i>
156
+ ${response.data.pwd_name}
157
+ </div>
158
+ <ul class="list-group">
159
+ `;
160
+ for (const file of response.data.files) {
161
+ if (file.directory) {
162
+ html += `
163
+ <li class="list-group-item">
164
+ <div onclick="changeDirectory('${file.filepath}')" class="w-100">
165
+ <i class="bi bi-folder-fill"></i>
166
+ ${file.filename}
167
+ </div>
168
+ </li>
169
+ `;
170
+ }
171
+ }
172
+ html += '</ul></li>';
173
+ document.getElementById('fm-directories-list').innerHTML = html;
174
+ document.getElementById('pwd-display').innerHTML = `/${pwd}`;
175
+ }
176
+
177
+ activeView = () => {
178
+ return document.querySelector('#file-list-type .nav-link.active').id;
179
+ };
180
+
181
+ fileMenuOptions = (file) => {
182
+ const fileCopyMenuItem = !file.directory ? `<li><a class="dropdown-item" data-filepath="${file.filepath}" data-filename="${file.filename}" href="#" onclick="copyFileHandler(this)"><i class="bi bi-copy"></i> Copy</a></li>` : '';
183
+ const filedownloadMenuItem = !file.directory ? `<li><a class="dropdown-item" data-filename="${file.filename}" href="${file.filepath}" target="_blank"><i class="bi bi-download"></i> Download</a></li>` : '';
184
+ const imageResizeMenuItem = file.image ? `<li><a class="dropdown-item" data-filepath="${file.filepath}" href="# " onclick="openImageDialogHandler(this)"><i class="bi bi-arrows-move"></i> Resize</a></li>` : '';
185
+ html = fileCopyMenuItem;
186
+ html += `
187
+ <li><a class="dropdown-item" data-filepath="${file.filepath}" data-filename="${file.filename}" href="#" onclick="openRenameDialogHandler(this)"><i class="bi bi-pencil"></i> Rename</a></li>
188
+ <li><a class="dropdown-item" data-filepath="${file.filepath}" href="#" onclick="deleteFileHandler(this)"><i class="bi bi-trash"></i> Delete</a></li>`
189
+ html += imageResizeMenuItem;
190
+ html += filedownloadMenuItem;
191
+ return html;
192
+ }
193
+
194
+ switchViewHandler = (e, listType) => {
195
+ e.classList.add('active');
196
+ deSelectedListClass = `#${listType == 'thumbnail' ? 'list' : 'thumbnail'}-view-btn`;
197
+ document.querySelector(deSelectedListClass).classList.remove('active');
198
+ changeDirectory(pwd);
199
+ };
200
+
201
+ copyFileHandler = (e) => {
202
+ const filepath = e.getAttribute('data-filepath');
203
+ axios.post(
204
+ routes('copy_path'),
205
+ {
206
+ item_name: filepath
207
+ },
208
+ {
209
+ headers: {
210
+ 'Content-Type': 'application/json',
211
+ 'X-CSRF-Token': csrf
212
+ }
213
+ }
214
+ )
215
+ .then(function(response) {
216
+ if(response.data.success) {
217
+ mkdirModal.hide();
218
+ document.getElementById('new-folder-name').value = '';
219
+ changeDirectory(pwd);
220
+ } else {
221
+ fmModalDialog(response.data.message);
222
+ }
223
+ });
224
+ };
225
+
226
+ createDirectory = () => {
227
+ const directoryName = document.getElementById('new-folder-name').value;
228
+ if (directoryName === null || directoryName === '') {
229
+ fmModalDialog(
230
+ {
231
+ title: 'Error',
232
+ body: 'Please enter a folder name',
233
+ status: 'danger'
234
+ }
235
+ )
236
+ return ;
237
+ }
238
+ axios.post(
239
+ routes('mkdir_path'),
240
+ {
241
+ pwd: pwd,
242
+ item_name: directoryName
243
+ },
244
+ {
245
+ headers: {
246
+ 'Content-Type': 'application/json',
247
+ 'X-CSRF-Token': csrf
248
+ }
249
+ }
250
+ )
251
+ .then(function(response) {
252
+ if(response.data.success) {
253
+ mkdirModal.hide();
254
+ document.getElementById('new-folder-name').value = '';
255
+ changeDirectory(pwd);
256
+ } else {
257
+ fmModalDialog(response.data.message);
258
+ }
259
+ });
260
+ };
261
+
262
+ changeDirectory = (filePath) => {
263
+ axios.get(`${routes('cd_path')}?type=${type}&cd=${filePath}`)
264
+ .then(function (response) {
265
+ // handle success
266
+ pwd = response.data.pwd;
267
+ document.getElementById('upload_to_dir').value = pwd
268
+ directoryListing(response);
269
+ directories(response);
270
+ })
271
+ .catch(function (error) {
272
+ // handle error
273
+ console.log(error);
274
+ })
275
+ .then(function () {
276
+ // always executed
277
+ });
278
+ }
279
+
280
+ fmModalDialog = (content) => {
281
+ const fmModal = new bootstrap.Modal(document.getElementById('fmModal'));
282
+ let header = document.getElementById('fm-modal-header');
283
+ header.className = 'modal-header'
284
+
285
+ if(content.status !== undefined || content.status) {
286
+ header.classList.add("alert");
287
+ header.classList.add(`alert-${content.status}`);
288
+ }
289
+ document.querySelector('.fm-modal-title').innerHTML = content.title
290
+ document.querySelector('.fm-modal-body').innerHTML = content.body;
291
+
292
+ fmModalDialogButtons(content.buttons);
293
+
294
+ fmModal.show();
295
+ }
296
+
297
+ fmModalDialogButtons = (buttons) => {
298
+ if(buttons === undefined) return;
299
+
300
+ let btnContainer = document.querySelector('.fm-modal-footer-buttons');
301
+ btnContainer.innerHTML = '';
302
+ for (const btn of buttons) {
303
+ let node = document.createElement('button');
304
+ let textNode = document.createTextNode(btn.name);
305
+ node.appendChild(textNode);
306
+ node.classList.add('btn');
307
+ node.classList.add(`btn-${btn.type}`);
308
+ node.onclick = btn.onclick;
309
+ node.setAttribute('data-bs-dismiss', 'modal');
310
+ btnContainer.appendChild(node);
311
+ }
312
+ }
313
+
314
+ deleteFileHandler = (e) => {
315
+ const filepath = e.getAttribute('data-filepath');
316
+ fmModalDialog({
317
+ title: 'Please confirm',
318
+ body: 'Are you sure you wish to delete this item?',
319
+ buttons: [
320
+ { name: 'Ok', onclick: () => { deleteFile(`${filepath}`) }, type: 'primary' }
321
+ ]
322
+ });
323
+ }
324
+
325
+ deleteFile = (file) => {
326
+ axios.delete(
327
+ routes('rm_path'),
328
+ {
329
+ data: { file: file },
330
+ headers: {
331
+ 'Content-Type': 'application/json',
332
+ 'X-CSRF-Token': csrf
333
+ }
334
+ },
335
+ ).then(function (response) {
336
+ changeDirectory(pwd);
337
+ })
338
+ .catch(function (error) {
339
+ console.log(error);
340
+ })
341
+ }
342
+
343
+ openImageDialogHandler = (e) => {
344
+ document.getElementById('original_image').src = e.getAttribute('data-filepath');
345
+ document.getElementById('original_image').setAttribute('width', '');
346
+ document.getElementById('original_image').setAttribute('height', '');
347
+
348
+ const filepath = encodeURIComponent(e.getAttribute('data-filepath'));
349
+
350
+ axios.get(
351
+ routes('image_info_path').replace(':id', filepath),
352
+ {
353
+ },
354
+ {
355
+ headers: {
356
+ 'Content-Type': 'application/json',
357
+ 'X-CSRF-Token': csrf
358
+ }
359
+ }
360
+ )
361
+ .then(function(response) {
362
+ if(response.status === 200) {
363
+ html = `
364
+ <table class="table table-striped">
365
+ <tr>
366
+ <td>File:</td>
367
+ <td>
368
+ <input type="hidden" id="orig_file_path" value="${response.data.filepath}">
369
+ ${response.data.filepath}
370
+ </td>
371
+ </tr>
372
+ <tr>
373
+ <td>Width:</td>
374
+ <td>
375
+ <input type="hidden" id="original_image_width" value="${response.data.width}">
376
+ <input type="text" name="image_width_text" id="image_width_text" onblur="changeImageHeight('width')" value="${response.data.width}"> px
377
+ </td>
378
+ </tr>
379
+ <tr>
380
+ <td>Height:</td>
381
+ <td>
382
+ <input type="hidden" id="original_image_height" value="${response.data.height}">
383
+ <input type="text" name="image_height_text" id="image_height_text" onblur="changeImageHeight('height')" value="${response.data.height}"> px
384
+ </td>
385
+ </tr>
386
+ </table>
387
+ `;
388
+ document.getElementById('image-info-container').innerHTML = html;
389
+ } else {
390
+
391
+ }
392
+ });
393
+
394
+ resizeImageModal.show();
395
+ };
396
+
397
+ changeImageHeight = (attrib) => {
398
+ const oWidth = document.getElementById("original_image_width").value
399
+ const oHeight = document.getElementById("original_image_height").value;
400
+ let nWidth, nHeight;
401
+
402
+ const ratio = oWidth / oHeight;
403
+
404
+ if(attrib === 'width') {
405
+ nWidth = document.getElementById("image_width_text").value
406
+ nHeight = nWidth / ratio;
407
+ document.getElementById("image_height_text").value = Math.round(nHeight);
408
+ }
409
+ else {
410
+ nHeight = document.getElementById("image_height_text").value;
411
+ nWidth = nHeight * ratio;
412
+ document.getElementById("image_width_text").value = Math.round(nWidth);
413
+ }
414
+
415
+ document.getElementById('original_image').setAttribute('width', nWidth);
416
+ document.getElementById('original_image').setAttribute('height', nHeight);
417
+ };
418
+
419
+ resizeImageHandler = (copy) => {
420
+ const filepath = encodeURIComponent(document.getElementById('orig_file_path').value);
421
+ axios.put(
422
+ routes('image_info_path').replace(':id', filepath),
423
+ {
424
+ width: document.getElementById("image_width_text").value,
425
+ height: document.getElementById("image_height_text").value,
426
+ copy
427
+ },
428
+ {
429
+ headers: {
430
+ 'Content-Type': 'application/json',
431
+ 'X-CSRF-Token': csrf
432
+ }
433
+ }
434
+ )
435
+ .then(function(response) {
436
+ if(response.data.success) {
437
+ resizeImageModal.hide();
438
+ changeDirectory(pwd);
439
+ } else {
440
+
441
+ }
442
+ })
443
+ .catch(function (error) {
444
+ console.log(error);
445
+ });
446
+ };
447
+
448
+ openRenameDialogHandler = (e) => {
449
+ document.getElementById('new-filename').value = e.getAttribute('data-filename');
450
+ document.getElementById('original-filename').value = e.getAttribute('data-filename');
451
+ renameItemModal.show();
452
+ }
453
+
454
+ renameFilename = () => {
455
+ const newFilename = document.getElementById('new-filename').value;
456
+ if (newFilename === null || newFilename === '') {
457
+ fmModalDialog(
458
+ {
459
+ title: 'Error',
460
+ body: 'Please enter a filename',
461
+ status: 'danger'
462
+ }
463
+ )
464
+ return ;
465
+ }
466
+ axios.put(
467
+ routes('rename_path'),
468
+ {
469
+ pwd: pwd,
470
+ original_filename: document.getElementById('original-filename').value,
471
+ item_name: newFilename
472
+ },
473
+ {
474
+ headers: {
475
+ 'Content-Type': 'application/json',
476
+ 'X-CSRF-Token': csrf
477
+ }
478
+ }
479
+ )
480
+ .then(function(response) {
481
+ if(response.data.success) {
482
+ renameItemModal.hide();
483
+ document.getElementById('new-filename').value = '';
484
+ changeDirectory(pwd);
485
+ } else {
486
+ fmModalDialog(response.data.message);
487
+ }
488
+ })
489
+ .catch(function (error) {
490
+ console.log(error);
491
+ });
492
+ }
493
+
494
+ changeDirectory('');
495
+ </script>
496
+ </body>
497
+ </html>
@@ -0,0 +1,4 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ extension_whitelist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ AmcmsFilemanager::Engine.routes.draw do
2
+ get :filemanager, to: 'filemanager#index'
3
+ namespace :filemanager do
4
+ get :change_directory
5
+ post :mkdir
6
+ post :copy
7
+ post :upload
8
+ put :rename
9
+ delete :destroy
10
+ end
11
+ resources :imagemanager
12
+ end