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.
- 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