amcms_filemanager 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +78 -0
- data/Rakefile +8 -0
- data/app/assets/config/amcms_filemanager_manifest.js +1 -0
- data/app/assets/images/amcms_filemanager/folder.png +0 -0
- data/app/assets/stylesheets/amcms_filemanager/application.css +34 -0
- data/app/assets/stylesheets/amcms_filemanager/filemanager.css +4 -0
- data/app/controllers/amcms_filemanager/application_controller.rb +11 -0
- data/app/controllers/amcms_filemanager/filemanager_controller.rb +93 -0
- data/app/controllers/amcms_filemanager/imagemanager_controller.rb +34 -0
- data/app/helpers/amcms_filemanager/application_helper.rb +4 -0
- data/app/helpers/amcms_filemanager/filemanager_helper.rb +4 -0
- data/app/jobs/amcms_filemanager/application_job.rb +4 -0
- data/app/lib/amcms_filemanager/filemanager.rb +181 -0
- data/app/lib/amcms_filemanager/imagemanager.rb +5 -0
- data/app/mailers/amcms_filemanager/application_mailer.rb +6 -0
- data/app/models/amcms_filemanager/application_record.rb +5 -0
- data/app/uploaders/amcms_filemanager/filemanager_uploader.rb +56 -0
- data/app/views/amcms_filemanager/filemanager/index.html.erb +168 -0
- data/app/views/layouts/amcms_filemanager/application.html.erb +497 -0
- data/config/locales/en.yml +4 -0
- data/config/routes.rb +12 -0
- data/lib/amcms_filemanager/configuration.rb +9 -0
- data/lib/amcms_filemanager/engine.rb +25 -0
- data/lib/amcms_filemanager/version.rb +3 -0
- data/lib/amcms_filemanager.rb +6 -0
- data/lib/tasks/amcms_filemanager_tasks.rake +4 -0
- 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>
|
data/config/routes.rb
ADDED