|
@@ -56,9 +56,8 @@
|
|
<label for="editor">Post Content</label>
|
|
<label for="editor">Post Content</label>
|
|
<textarea id="editor"></textarea>
|
|
<textarea id="editor"></textarea>
|
|
</div>
|
|
</div>
|
|
-
|
|
|
|
- <button class="ui basic button" id="saveButton"><i class="ui green upload icon"></i>Publish</button>
|
|
|
|
- <button class="ui blue basic button" id="saveDraftButton"><i class="ui save icon"></i>Save as Draft</button>
|
|
|
|
|
|
+ <button class="ui basic button" id="saveButton"><i class="ui green upload icon"></i> Publish</button>
|
|
|
|
+ <button class="ui blue basic button" id="saveDraftButton"><i class="ui save icon"></i> Save as Draft</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
@@ -93,310 +92,417 @@
|
|
</button>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
-
|
|
|
|
|
|
+<br><br><br>
|
|
<script>
|
|
<script>
|
|
- var currentDir = "/img"; // Initialize current path
|
|
|
|
- var pathHistory = [currentDir]; // Initialize path history
|
|
|
|
-
|
|
|
|
- $(document).ready(function() {
|
|
|
|
- // Initialize SimpleMDE
|
|
|
|
- var simplemde = new SimpleMDE({
|
|
|
|
- element: document.getElementById("editor"),
|
|
|
|
- toolbar: [
|
|
|
|
- "bold",
|
|
|
|
- "italic",
|
|
|
|
- "heading",
|
|
|
|
- "|",
|
|
|
|
- "quote",
|
|
|
|
- "unordered-list",
|
|
|
|
- "ordered-list",
|
|
|
|
- "|",
|
|
|
|
- "link",
|
|
|
|
- "image",
|
|
|
|
- {
|
|
|
|
- name: "mediaSelect",
|
|
|
|
- action: function customFunction(editor) {
|
|
|
|
- openMediaSelector(editor);
|
|
|
|
- },
|
|
|
|
- className: "fa fa-folder", // Font Awesome icon
|
|
|
|
- title: "Select Media"
|
|
|
|
|
|
+ var currentDir = "/"; // Initialize current path
|
|
|
|
+ var pathHistory = []; // Initialize path history
|
|
|
|
+ var unsafeCharacters = /[<>:"/\\|?*\x00-\x1F]/; // Regex for unsafe characters
|
|
|
|
+ if (typeof(autosaveInterval) != "undefined"){
|
|
|
|
+ clearInterval(autosaveInterval); // Clear any existing autosave interval
|
|
|
|
+ }
|
|
|
|
+ var autosaveInterval;
|
|
|
|
+ // Load draft from localStorage on page load
|
|
|
|
+ var savedTitle = localStorage.getItem('draftTitle');
|
|
|
|
+ var savedContent = localStorage.getItem('draftContent');
|
|
|
|
+
|
|
|
|
+ // Initialize SimpleMDE
|
|
|
|
+ var simplemde = new SimpleMDE({
|
|
|
|
+ element: document.getElementById("editor"),
|
|
|
|
+ toolbar: [
|
|
|
|
+ "bold",
|
|
|
|
+ "italic",
|
|
|
|
+ "heading",
|
|
|
|
+ "|",
|
|
|
|
+ "code",
|
|
|
|
+ "quote",
|
|
|
|
+ "unordered-list",
|
|
|
|
+ "ordered-list",
|
|
|
|
+ "|",
|
|
|
|
+ "link",
|
|
|
|
+ "table",
|
|
|
|
+ "horizontal-rule",
|
|
|
|
+ "image",
|
|
|
|
+ {
|
|
|
|
+ name: "mediaSelect",
|
|
|
|
+ action: function customFunction(editor) {
|
|
|
|
+ openMediaSelector(editor);
|
|
},
|
|
},
|
|
- "|",
|
|
|
|
- "preview",
|
|
|
|
- ]
|
|
|
|
- });
|
|
|
|
|
|
+ className: "fa fa-folder", // Font Awesome icon
|
|
|
|
+ title: "Select Media"
|
|
|
|
+ },
|
|
|
|
+ "|",
|
|
|
|
+ "preview",
|
|
|
|
+ ]
|
|
|
|
+ });
|
|
|
|
|
|
- // Allow vertical resize for the editor
|
|
|
|
- document.getElementById("editor").style.resize = "vertical";
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- Media Selector
|
|
|
|
-
|
|
|
|
- This function will open the media selector modal when the media button is clicked.
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- function fetchDirectoryContents(path) {
|
|
|
|
- $.ajax({
|
|
|
|
- url: `/api/fs/list?dir=${encodeURIComponent(path)}`,
|
|
|
|
- method: 'GET',
|
|
|
|
- success: function(data) {
|
|
|
|
- if (data.error == undefined){
|
|
|
|
- pathHistory.push(currentDir);
|
|
|
|
- if (path.endsWith("/")) {
|
|
|
|
- currentDir = path.slice(0, -1); // Remove trailing slash if present
|
|
|
|
- } else {
|
|
|
|
- currentDir = path; // Update current directory
|
|
|
|
- }
|
|
|
|
- $("#locationBar").val(currentDir); // Update location bar
|
|
|
|
- renderDirectoryContents(data);
|
|
|
|
- } else {
|
|
|
|
- alert("Failed to fetch directory contents: " + data.error);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- error: function() {
|
|
|
|
- alert("Error fetching directory contents.");
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
|
|
+ // Allow vertical resize for the editor
|
|
|
|
+ document.getElementById("editor").style.resize = "vertical";
|
|
|
|
|
|
- function renderDirectoryContents(contents) {
|
|
|
|
- const container = $("#mediaContent");
|
|
|
|
- container.empty();
|
|
|
|
- let folderElements = ``;
|
|
|
|
- let fileElements = ``;
|
|
|
|
- let selectableFileCounter = 0;
|
|
|
|
- contents.forEach(item => {
|
|
|
|
- if (item.IsDir) {
|
|
|
|
- folderElements += (`
|
|
|
|
- <div class="ui segment folder-item selectable" data-path="${currentDir + "/" + item.Filename}">
|
|
|
|
- <i class="yellow folder icon"></i> ${item.Filename}
|
|
|
|
- </div>
|
|
|
|
- `);
|
|
|
|
- selectableFileCounter++;
|
|
|
|
- } else if (!item.IsDir && isWebSafeFile(item.Filename)) {
|
|
|
|
- let fileIcon = getFileTypeIcons(item.Filename);
|
|
|
|
- fileElements += (`
|
|
|
|
- <div class="ui segment file-item selectable" data-path="${currentDir + "/" + item.Filename}" data-type="${getFileType(item.Filename)}">
|
|
|
|
- ${fileIcon} ${item.Filename}
|
|
|
|
- </div>
|
|
|
|
- `);
|
|
|
|
- selectableFileCounter++;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ /*
|
|
|
|
+ Media Selector
|
|
|
|
|
|
- container.append(folderElements);
|
|
|
|
- container.append(fileElements);
|
|
|
|
|
|
+ This function will open the media selector modal when the media button is clicked.
|
|
|
|
+ */
|
|
|
|
|
|
- if (selectableFileCounter == 0) {
|
|
|
|
- container.append("<div class='ui basic segment' style='pointer-events: none; user-select: none; opacity: 0.5;'><i class='ui green circle check icon'></i> No usable files / folders found</div>");
|
|
|
|
|
|
+ function fetchDirectoryContents(path) {
|
|
|
|
+ $.ajax({
|
|
|
|
+ url: `/api/fs/list?dir=${encodeURIComponent(path)}`,
|
|
|
|
+ method: 'GET',
|
|
|
|
+ success: function(data) {
|
|
|
|
+ if (data.error == undefined){
|
|
|
|
+ pathHistory.push(currentDir);
|
|
|
|
+ if (path.endsWith("/")) {
|
|
|
|
+ currentDir = path.slice(0, -1); // Remove trailing slash if present
|
|
|
|
+ } else {
|
|
|
|
+ currentDir = path; // Update current directory
|
|
|
|
+ }
|
|
|
|
+ $("#locationBar").val(currentDir); // Update location bar
|
|
|
|
+ renderDirectoryContents(data);
|
|
|
|
+ } else {
|
|
|
|
+ alert("Failed to fetch directory contents: " + data.error);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ error: function() {
|
|
|
|
+ alert("Error fetching directory contents.");
|
|
}
|
|
}
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
|
|
- // Add click handlers for folders and files
|
|
|
|
- $(".folder-item").on('dblclick', function() {
|
|
|
|
- const path = $(this).data('path');
|
|
|
|
- fetchDirectoryContents(path);
|
|
|
|
- });
|
|
|
|
|
|
+ function renderDirectoryContents(contents) {
|
|
|
|
+ const container = $("#mediaContent");
|
|
|
|
+ container.empty();
|
|
|
|
+ let folderElements = ``;
|
|
|
|
+ let fileElements = ``;
|
|
|
|
+ let selectableFileCounter = 0;
|
|
|
|
+ contents.forEach(item => {
|
|
|
|
+ if (item.IsDir) {
|
|
|
|
+ folderElements += (`
|
|
|
|
+ <div class="ui segment folder-item selectable" data-path="${currentDir + "/" + item.Filename}">
|
|
|
|
+ <i class="yellow folder icon"></i> ${item.Filename}
|
|
|
|
+ </div>
|
|
|
|
+ `);
|
|
|
|
+ selectableFileCounter++;
|
|
|
|
+ } else if (!item.IsDir && isWebSafeFile(item.Filename)) {
|
|
|
|
+ let fileIcon = getFileTypeIcons(item.Filename);
|
|
|
|
+ fileElements += (`
|
|
|
|
+ <div class="ui segment file-item selectable" data-path="${currentDir + "/" + item.Filename}" data-type="${getFileType(item.Filename)}">
|
|
|
|
+ ${fileIcon} ${item.Filename}
|
|
|
|
+ </div>
|
|
|
|
+ `);
|
|
|
|
+ selectableFileCounter++;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
|
|
- $(".folder-item").on("click", function(event) {
|
|
|
|
- const path = $(this).data('path');
|
|
|
|
- if (!event.ctrlKey) {
|
|
|
|
- // Highlight the selected folder and remove previous selection if ctrl is not held
|
|
|
|
- $(".folder-item.selected").removeClass("selected");
|
|
|
|
- }
|
|
|
|
- $(this).toggleClass("selected"); // Toggle selection for the clicked item
|
|
|
|
- });
|
|
|
|
|
|
+ container.append(folderElements);
|
|
|
|
+ container.append(fileElements);
|
|
|
|
|
|
- $(".file-item").on('dblclick', function() {
|
|
|
|
- $("#postengine_media_selector").modal("hide");
|
|
|
|
- const path = $(this).data('path');
|
|
|
|
- const type = $(this).data('type');
|
|
|
|
- addMediaFileToEditor(path, type);
|
|
|
|
- });
|
|
|
|
|
|
+ if (selectableFileCounter == 0) {
|
|
|
|
+ container.append("<div class='ui basic segment' style='pointer-events: none; user-select: none; opacity: 0.5;'><i class='ui green circle check icon'></i> No usable files / folders found</div>");
|
|
|
|
+ }
|
|
|
|
|
|
- $(".file-item").on("click", function(event) {
|
|
|
|
- const path = $(this).data('path');
|
|
|
|
- const type = $(this).data('type');
|
|
|
|
- if (!event.ctrlKey) {
|
|
|
|
- // Highlight the selected file and remove previous selection if ctrl is not held
|
|
|
|
- $(".file-item.selected").removeClass("selected");
|
|
|
|
- }
|
|
|
|
- $(this).toggleClass("selected"); // Toggle selection for the clicked item
|
|
|
|
- });
|
|
|
|
|
|
+ // Add click handlers for folders and files
|
|
|
|
+ $(".folder-item").on('dblclick', function() {
|
|
|
|
+ const path = $(this).data('path');
|
|
|
|
+ fetchDirectoryContents(path);
|
|
|
|
+ });
|
|
|
|
|
|
- //Show warning if the directory starts with /admin or /store
|
|
|
|
- if (currentDir.startsWith("/admin") || currentDir.startsWith("/store")) {
|
|
|
|
- $("#limited_access_warning").show();
|
|
|
|
- } else {
|
|
|
|
- $("#limited_access_warning").hide();
|
|
|
|
|
|
+ $(".folder-item").on("click", function(event) {
|
|
|
|
+ const path = $(this).data('path');
|
|
|
|
+ if (!event.ctrlKey) {
|
|
|
|
+ // Highlight the selected folder and remove previous selection if ctrl is not held
|
|
|
|
+ $(".folder-item.selected").removeClass("selected");
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ $(this).toggleClass("selected"); // Toggle selection for the clicked item
|
|
|
|
+ });
|
|
|
|
|
|
- // Bind event to the back button
|
|
|
|
- $('#backButton').on('click', function() {
|
|
|
|
- if (pathHistory.length > 1) {
|
|
|
|
- pathHistory.pop(); // Remove the current directory
|
|
|
|
- const previousPath = pathHistory.pop();
|
|
|
|
- fetchDirectoryContents(previousPath);
|
|
|
|
- }
|
|
|
|
|
|
+ $(".file-item").on('dblclick', function() {
|
|
|
|
+ $("#postengine_media_selector").modal("hide");
|
|
|
|
+ const path = $(this).data('path');
|
|
|
|
+ const type = $(this).data('type');
|
|
|
|
+ addMediaFileToEditor(path, type);
|
|
});
|
|
});
|
|
|
|
|
|
- // Bind event to the parent button
|
|
|
|
- $('#parentButton').on('click', function() {
|
|
|
|
- if (currentDir == "/") {
|
|
|
|
- msgbox("Already at the root directory", 3000);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- let parentPath = currentDir.split("/");
|
|
|
|
- parentPath.pop(); // Remove the last element (current directory)
|
|
|
|
- parentPath = parentPath.join("/"); // Join the remaining elements to form the parent path
|
|
|
|
- if (parentPath == ""){
|
|
|
|
- parentPath = "/"; // Set to root if empty
|
|
|
|
|
|
+ $(".file-item").on("click", function(event) {
|
|
|
|
+ const path = $(this).data('path');
|
|
|
|
+ const type = $(this).data('type');
|
|
|
|
+ if (!event.ctrlKey) {
|
|
|
|
+ // Highlight the selected file and remove previous selection if ctrl is not held
|
|
|
|
+ $(".file-item.selected").removeClass("selected");
|
|
}
|
|
}
|
|
- fetchDirectoryContents(parentPath);
|
|
|
|
|
|
+ $(this).toggleClass("selected"); // Toggle selection for the clicked item
|
|
});
|
|
});
|
|
|
|
|
|
- // Bind event to the import button
|
|
|
|
- $('#importButton').on('click', function() {
|
|
|
|
- const selectedFolders = $(".folder-item.selected");
|
|
|
|
- const selectedFiles = $(".file-item.selected");
|
|
|
|
- if (selectedFiles.length === 0 && selectedFolders.length === 0) {
|
|
|
|
- alert("No files selected for import.");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ //Show warning if the directory starts with /admin or /store
|
|
|
|
+ if (currentDir.startsWith("/admin") || currentDir.startsWith("/store")) {
|
|
|
|
+ $("#limited_access_warning").show();
|
|
|
|
+ } else {
|
|
|
|
+ $("#limited_access_warning").hide();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- selectedFolders.each(function() {
|
|
|
|
- const path = $(this).data('path');
|
|
|
|
- const type = "link";
|
|
|
|
- addMediaFileToEditor(path, type);
|
|
|
|
- });
|
|
|
|
|
|
+ // Bind event to the back button
|
|
|
|
+ $('#backButton').on('click', function() {
|
|
|
|
+ if (pathHistory.length > 1) {
|
|
|
|
+ pathHistory.pop(); // Remove the current directory
|
|
|
|
+ const previousPath = pathHistory.pop();
|
|
|
|
+ fetchDirectoryContents(previousPath);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
|
|
- selectedFiles.each(function() {
|
|
|
|
- const path = $(this).data('path');
|
|
|
|
- const type = $(this).data('type');
|
|
|
|
- addMediaFileToEditor(path, type);
|
|
|
|
- });
|
|
|
|
|
|
+ // Bind event to the parent button
|
|
|
|
+ $('#parentButton').on('click', function() {
|
|
|
|
+ if (currentDir == "/") {
|
|
|
|
+ msgbox("Already at the root directory", 3000);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ let parentPath = currentDir.split("/");
|
|
|
|
+ parentPath.pop(); // Remove the last element (current directory)
|
|
|
|
+ parentPath = parentPath.join("/"); // Join the remaining elements to form the parent path
|
|
|
|
+ if (parentPath == ""){
|
|
|
|
+ parentPath = "/"; // Set to root if empty
|
|
|
|
+ }
|
|
|
|
+ fetchDirectoryContents(parentPath);
|
|
|
|
+ });
|
|
|
|
|
|
- $("#postengine_media_selector").modal("hide");
|
|
|
|
|
|
+ // Bind event to the import button
|
|
|
|
+ $('#importButton').on('click', function() {
|
|
|
|
+ const selectedFolders = $(".folder-item.selected");
|
|
|
|
+ const selectedFiles = $(".file-item.selected");
|
|
|
|
+ if (selectedFiles.length === 0 && selectedFolders.length === 0) {
|
|
|
|
+ alert("No files selected for import.");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ selectedFolders.each(function() {
|
|
|
|
+ const path = $(this).data('path');
|
|
|
|
+ const type = "link";
|
|
|
|
+ addMediaFileToEditor(path, type);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ selectedFiles.each(function() {
|
|
|
|
+ const path = $(this).data('path');
|
|
|
|
+ const type = $(this).data('type');
|
|
|
|
+ addMediaFileToEditor(path, type);
|
|
});
|
|
});
|
|
|
|
|
|
- function isWebSafeFile(fileName) {
|
|
|
|
- const webSafeExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'webm', 'mp3', 'ogg'];
|
|
|
|
- const extension = fileName.split('.').pop().toLowerCase();
|
|
|
|
- return webSafeExtensions.includes(extension);
|
|
|
|
|
|
+ $("#postengine_media_selector").modal("hide");
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ function isWebSafeFile(fileName) {
|
|
|
|
+ const webSafeExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'webm', 'mp3', 'ogg'];
|
|
|
|
+ const extension = fileName.split('.').pop().toLowerCase();
|
|
|
|
+ return webSafeExtensions.includes(extension);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function getFileType(fileName) {
|
|
|
|
+ const extension = fileName.split('.').pop().toLowerCase();
|
|
|
|
+ if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(extension)) {
|
|
|
|
+ return 'image';
|
|
|
|
+ } else if (extension === 'webm') {
|
|
|
|
+ return 'video';
|
|
|
|
+ } else if (['mp3', 'ogg'].includes(extension)) {
|
|
|
|
+ return 'audio';
|
|
|
|
+ } else {
|
|
|
|
+ return 'unknown';
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- function getFileType(fileName) {
|
|
|
|
- const extension = fileName.split('.').pop().toLowerCase();
|
|
|
|
- if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(extension)) {
|
|
|
|
- return 'image';
|
|
|
|
- } else if (extension === 'webm') {
|
|
|
|
- return 'video';
|
|
|
|
- } else if (['mp3', 'ogg'].includes(extension)) {
|
|
|
|
- return 'audio';
|
|
|
|
- } else {
|
|
|
|
- return 'unknown';
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ function openMediaSelector(editor){
|
|
|
|
+ // Reset history
|
|
|
|
+ pathHistory = []; // Reset path history
|
|
|
|
+ fetchDirectoryContents(currentDir);
|
|
|
|
+ $("#postengine_media_selector").modal("show");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function addMediaFileToEditor(mediaLink, mediaType){
|
|
|
|
+ if (mediaType === 'image') {
|
|
|
|
+ simplemde.codemirror.replaceSelection(``);
|
|
|
|
+ } else if (mediaType === 'video') {
|
|
|
|
+ let mimeType = mediaLink.split('.').pop().toLowerCase() === 'webm' ? 'video/webm' : 'video/mp4';
|
|
|
|
+ simplemde.codemirror.replaceSelection(`<video style="background:black;" width="720" height="480" controls><source src="${mediaLink}" type="${mimeType}"></video>`);
|
|
|
|
+ } else if (mediaType === 'audio') {
|
|
|
|
+ simplemde.codemirror.replaceSelection(`<audio style="min-width: 512px;" controls><source src="${mediaLink}" type="audio/mpeg">Your browser does not support the audio element.</audio>`);
|
|
|
|
+ } else if (mediaType === 'link') {
|
|
|
|
+ let folderName = mediaLink.split("/").pop(); // Extract folder name from path
|
|
|
|
+ simplemde.codemirror.replaceSelection(`[${folderName}](${mediaLink})`);
|
|
|
|
+ } else {
|
|
|
|
+ alert("Unsupported media type!");
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ function getFileTypeIcons(fileName) {
|
|
|
|
+ const extension = fileName.split('.').pop().toLowerCase();
|
|
|
|
+ if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(extension)) {
|
|
|
|
+ return '<i class="blue file image icon"></i>';
|
|
|
|
+ } else if (extension === 'webm') {
|
|
|
|
+ return '<i class="violet file video icon"></i>';
|
|
|
|
+ } else if (['mp3', 'ogg'].includes(extension)) {
|
|
|
|
+ return '<i class="green file audio icon"></i>';
|
|
|
|
+ } else {
|
|
|
|
+ return '<i class="file icon"></i>';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- function openMediaSelector(editor){
|
|
|
|
- // Reset history
|
|
|
|
- pathHistory = []; // Reset path history
|
|
|
|
- fetchDirectoryContents(currentDir);
|
|
|
|
- $("#postengine_media_selector").modal("show");
|
|
|
|
|
|
+ /*
|
|
|
|
+ Title Validation
|
|
|
|
+
|
|
|
|
+ This function will validate the title input to ensure it does not contain unsafe characters.
|
|
|
|
+ If the title contains unsafe characters, the save button will be disabled and an alert will be shown.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ function validateTitle() {
|
|
|
|
+ const title = $('#title').val();
|
|
|
|
+ if (unsafeCharacters.test(title) || title.length > 19) {
|
|
|
|
+ msgbox("Title contains unsafe characters or is too long (max 19 characters).", 3000);
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
|
|
- function addMediaFileToEditor(mediaLink, mediaType){
|
|
|
|
- if (mediaType === 'image') {
|
|
|
|
- simplemde.codemirror.replaceSelection(``);
|
|
|
|
- } else if (mediaType === 'video') {
|
|
|
|
- let mimeType = mediaLink.split('.').pop().toLowerCase() === 'webm' ? 'video/webm' : 'video/mp4';
|
|
|
|
- simplemde.codemirror.replaceSelection(`<video style="background:black;" width="720" height="480" controls><source src="${mediaLink}" type="${mimeType}"></video>`);
|
|
|
|
- } else if (mediaType === 'audio') {
|
|
|
|
- simplemde.codemirror.replaceSelection(`<audio style="min-width: 512px;" controls><source src="${mediaLink}" type="audio/mpeg">Your browser does not support the audio element.</audio>`);
|
|
|
|
- } else if (mediaType === 'link') {
|
|
|
|
- let folderName = mediaLink.split("/").pop(); // Extract folder name from path
|
|
|
|
- simplemde.codemirror.replaceSelection(`[${folderName}](${mediaLink})`);
|
|
|
|
- } else {
|
|
|
|
- alert("Unsupported media type!");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ // Save button functionality
|
|
|
|
+ $('#saveButton').on('click', function() {
|
|
|
|
+ const title = $('#title').val();
|
|
|
|
+ const content = simplemde.value();
|
|
|
|
+
|
|
|
|
+ console.log("Title:", title);
|
|
|
|
+ console.log("Content:", content);
|
|
|
|
+
|
|
|
|
+ if (!validateTitle()){
|
|
|
|
+ return; // Exit if title is invalid
|
|
}
|
|
}
|
|
|
|
|
|
- function getFileTypeIcons(fileName) {
|
|
|
|
- const extension = fileName.split('.').pop().toLowerCase();
|
|
|
|
- if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(extension)) {
|
|
|
|
- return '<i class="blue file image icon"></i>';
|
|
|
|
- } else if (extension === 'webm') {
|
|
|
|
- return '<i class="violet file video icon"></i>';
|
|
|
|
- } else if (['mp3', 'ogg'].includes(extension)) {
|
|
|
|
- return '<i class="green file audio icon"></i>';
|
|
|
|
- } else {
|
|
|
|
- return '<i class="file icon"></i>';
|
|
|
|
- }
|
|
|
|
|
|
+ createNewPost(title, content);
|
|
|
|
+
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // Save Draft button functionality
|
|
|
|
+ $('#saveDraftButton').on('click', function() {
|
|
|
|
+ const title = $('#title').val();
|
|
|
|
+ const content = simplemde.value();
|
|
|
|
+
|
|
|
|
+ if (title.trim() === "" && content.trim() === "") {
|
|
|
|
+ alert("Cannot save an empty draft.");
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ localStorage.setItem('draftTitle', title);
|
|
|
|
+ localStorage.setItem('draftContent', content);
|
|
|
|
|
|
- // Initialize with root directory
|
|
|
|
- fetchDirectoryContents(currentDir);
|
|
|
|
|
|
+ msgbox("Draft saved");
|
|
|
|
+ });
|
|
|
|
|
|
- // Save button functionality
|
|
|
|
- $('#saveButton').on('click', function() {
|
|
|
|
- const title = $('#title').val();
|
|
|
|
- const tags = $('#tags').val();
|
|
|
|
- const content = simplemde.value();
|
|
|
|
|
|
+ // Discard Draft button functionality
|
|
|
|
+ $('#discardDraftButton').on('click', function() {
|
|
|
|
+ if (confirm("Are you sure you want to discard the draft? This action cannot be undone.")) {
|
|
|
|
+ localStorage.removeItem('draftTitle');
|
|
|
|
+ localStorage.removeItem('draftContent');
|
|
|
|
|
|
- console.log("Title:", title);
|
|
|
|
- console.log("Tags:", tags);
|
|
|
|
- console.log("Content:", content);
|
|
|
|
|
|
+ $('#title').val('');
|
|
|
|
+ simplemde.value('');
|
|
|
|
|
|
- // Add your save logic here
|
|
|
|
- alert("Content saved successfully!");
|
|
|
|
- });
|
|
|
|
|
|
+ msgbox("Draft discarded");
|
|
|
|
|
|
- // Save Draft button functionality
|
|
|
|
- $('#saveDraftButton').on('click', function() {
|
|
|
|
- const title = $('#title').val();
|
|
|
|
- const content = simplemde.value();
|
|
|
|
|
|
+ $('#loadDraftMessage').addClass('hidden');
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
|
|
- if (title.trim() === "" && content.trim() === "") {
|
|
|
|
- alert("Cannot save an empty draft.");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
|
|
- localStorage.setItem('draftTitle', title);
|
|
|
|
- localStorage.setItem('draftContent', content);
|
|
|
|
|
|
+ if (savedTitle || savedContent) {
|
|
|
|
+ $('#loadDraftMessage').removeClass('hidden');
|
|
|
|
|
|
- msgbox("Draft saved successfully!");
|
|
|
|
|
|
+ $('#loadDraftButton').on('click', function() {
|
|
|
|
+ $('#title').val(savedTitle || '');
|
|
|
|
+ simplemde.value(savedContent || '');
|
|
|
|
+ $('#loadDraftMessage').addClass('hidden');
|
|
});
|
|
});
|
|
|
|
+ }
|
|
|
|
|
|
- // Discard Draft button functionality
|
|
|
|
- $('#discardDraftButton').on('click', function() {
|
|
|
|
- if (confirm("Are you sure you want to discard the draft? This action cannot be undone.")) {
|
|
|
|
- localStorage.removeItem('draftTitle');
|
|
|
|
- localStorage.removeItem('draftContent');
|
|
|
|
|
|
+ // Autosave functionality
|
|
|
|
+ autosaveInterval = setInterval(function() {
|
|
|
|
+ if (!document.getElementById("editor")) {
|
|
|
|
+ clearInterval(autosaveInterval);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const title = $('#title').val();
|
|
|
|
+ const content = simplemde.value();
|
|
|
|
|
|
- $('#title').val('');
|
|
|
|
- simplemde.value('');
|
|
|
|
|
|
+ if (title.trim() === "" && content.trim() === "") {
|
|
|
|
+ return; // Don't save empty drafts
|
|
|
|
+ }
|
|
|
|
|
|
- msgbox("Draft discarded successfully!");
|
|
|
|
|
|
+ localStorage.setItem('draftTitle', title);
|
|
|
|
+ localStorage.setItem('draftContent', content);
|
|
|
|
+ }, 5000); // Autosave every 5 seconds
|
|
|
|
|
|
- $('#loadDraftMessage').addClass('hidden');
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ Post Create Function
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ // Function to create a new post
|
|
|
|
+ function createNewPost(title, content="# Hello World\n"){
|
|
|
|
+ if (title.trim() === "" && content.trim() === "") {
|
|
|
|
+ alert("Cannot create an empty post.");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ $("#saveButton").addClass("loading disabled");
|
|
|
|
+ //Create the markdown file at the /blog/posts folder
|
|
|
|
+ const blob = new Blob([content], { type: 'text/plain' });
|
|
|
|
+ let storeFilename = parseInt(Date.now()/1000) + "_" + title+'.md';
|
|
|
|
+ const file = new File([blob], storeFilename);
|
|
|
|
+ handleFile(file, "/site/posts", function(){
|
|
|
|
+ //Update the post index
|
|
|
|
+ updatePostIndex(function(){
|
|
|
|
+ $("#confirmNewPostBtn").removeClass("loading disabled");
|
|
|
|
+ msgbox("Post created successfully!", 3000);
|
|
|
|
+
|
|
|
|
+ switchToTab("allposts"); // Switch to the all posts tab
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ //Clear the draft
|
|
|
|
+ localStorage.removeItem('draftTitle');
|
|
|
|
+ localStorage.removeItem('draftContent');
|
|
});
|
|
});
|
|
|
|
+ }
|
|
|
|
|
|
- // Load draft from localStorage on page load
|
|
|
|
- const savedTitle = localStorage.getItem('draftTitle');
|
|
|
|
- const savedContent = localStorage.getItem('draftContent');
|
|
|
|
|
|
+ // Error handler for AJAX requests
|
|
|
|
+ function errorHandler(event) {
|
|
|
|
+ msgbox("Failed to create post: " + event.target.responseText, 3000);
|
|
|
|
+ $("#saveButton").removeClass("loading disabled");
|
|
|
|
+ }
|
|
|
|
|
|
- if (savedTitle || savedContent) {
|
|
|
|
- $('#loadDraftMessage').removeClass('hidden');
|
|
|
|
|
|
+ // Function to handle file upload
|
|
|
|
+ function handleFile(file, dir=currentPath, callback=undefined) {
|
|
|
|
+ // Perform actions with the selected file
|
|
|
|
+ var formdata = new FormData();
|
|
|
|
+ formdata.append("file1", file);
|
|
|
|
+ var ajax = new XMLHttpRequest();
|
|
|
|
+ ajax.addEventListener("load", function(event){
|
|
|
|
+ let responseText = event.target.responseText;
|
|
|
|
+ try{
|
|
|
|
+ responseText = JSON.parse(responseText);
|
|
|
|
+ if (responseText.error != undefined){
|
|
|
|
+ alert(responseText.error);
|
|
|
|
+ }
|
|
|
|
+ }catch(ex){
|
|
|
|
|
|
- $('#loadDraftButton').on('click', function() {
|
|
|
|
- $('#title').val(savedTitle || '');
|
|
|
|
- simplemde.value(savedContent || '');
|
|
|
|
- $('#loadDraftMessage').addClass('hidden');
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
+ if (callback != undefined){
|
|
|
|
+ callback();
|
|
|
|
+ }
|
|
|
|
+ }, false); // doesnt appear to ever get called even upon success
|
|
|
|
+ ajax.addEventListener("error", errorHandler, false);
|
|
|
|
+ //ajax.addEventListener("abort", abortHandler, false);
|
|
|
|
+ ajax.open("POST", "/upload?dir=" + dir);
|
|
|
|
+ ajax.send(formdata);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $(document).ready(function() {
|
|
|
|
+ // Initialize with root directory
|
|
|
|
+ fetchDirectoryContents(currentDir);
|
|
});
|
|
});
|
|
</script>
|
|
</script>
|