UNPKG

tspace-nfs

Version:

tspace-nfs is a Network File System (NFS) and provides both server and client capabilities for accessing files over a network.

169 lines (133 loc) 6.18 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NFS-Studio</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs/loader.min.js"></script> <style> .vscode-bg { background-color: #1e1e1e; } #editor { height: calc(100vh - 64px); } </style> </head> <body class="bg-gray-100 flex flex-col h-screen"> <nav class="sticky top-0 bg-gray-300 border-gray-200 dark:bg-gray-900"> <div class="w-screen-xl flex items-center justify-between mx-auto p-4"> <div class="cursor-pointer flex items-center space-x-3 rtl:space-x-reverse" onclick="window.location.reload()"> <svg class="w-12 h-12 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"> <path stroke="currentColor" stroke-linejoin="round" stroke-width="2" d="M15 4v3a1 1 0 0 1-1 1h-3m2 10v1a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-7.13a1 1 0 0 1 .24-.65L6.7 8.35A1 1 0 0 1 7.46 8H9m-1 4H4m16-7v10a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1V7.87a1 1 0 0 1 .24-.65l2.46-2.87a1 1 0 0 1 .76-.35H19a1 1 0 0 1 1 1Z"/> </svg> <h1 class="self-center text-2xl whitespace-nowrap text-gray-800 dark:text-white"> NFS-Studio </h1> </div> </div> </nav> <div id="notify-container" class="space-y-4 fixed right-0 top-0 m-2 items-end justify-end z-50 pointer-events-none"></div> <div id="editor" class="flex-grow"></div> <div class="bg-white dark:bg-[#1e1e1e] p-4 flex justify-end"> <button class="bg-gray-300 dark:bg-gray-800 text-gray-800 dark:text-white text-[1.25rem] px-6 py-3 rounded-full" onclick="saveFile()"> Save File </button> </div> </body> <script> document.addEventListener('DOMContentLoaded', () => { const $ = (element) => document.querySelector(element) async function notify({ type, message }) { const notifyContainer = $('#notify-container') const notify = document.createElement('div'); const capitalizedType = type.charAt(0).toUpperCase() + type.slice(1); switch(type.toLowerCase()) { case 'success': notify.className = 'max-w-md text-center bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative'; break; case 'error': notify.className = 'max-w-md text-center bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative'; break; case 'info': notify.className = 'max-w-md text-center bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded relative'; break; case 'warning': notify.className = 'max-w-md text-center bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded relative'; break; default: notify.className = 'max-w-md text-center bg-gray-100 border border-gray-400 text-gray-700 px-4 py-3 rounded relative'; } notify.innerHTML = ` <strong class="font-bold">${capitalizedType}</strong> <span class="block sm:inline">${message}</span> `; notifyContainer.appendChild(notify); setTimeout(() => { notify.remove() }, 2500) } function themeToggleMode() { const theme = (localStorage.getItem('theme') ?? (document.body?.classList?.contains('dark') ? 'dark' : 'light')) const isDark = theme === 'dark' const prefixToReplace = isDark ? 'light:' : 'dark:'; const newPrefix = isDark ? 'dark:' : 'light:'; const body = document.body; body.className = body.className.split(' ').map(className => { return className.startsWith(prefixToReplace) ? className.replace(prefixToReplace, newPrefix) : className }).join(' '); const elements = document.body.getElementsByTagName('*'); for (let element of elements) { if(!element.classList) continue element.classList.forEach(className => { if (className.startsWith(prefixToReplace)) { element.classList.replace(className, className.replace(prefixToReplace, newPrefix)); } }) } } themeToggleMode() require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs' } }); require(['vs/editor/editor.main'], function() { const theme = (localStorage.getItem('theme') ?? (document.body?.classList?.contains('dark') ? 'dark' : 'light')) const editor = monaco.editor.create(document.getElementById('editor'), { language: "{{language}}", theme: `vs-${theme}`, automaticLayout: true, }); const url = window.location.href const baseUrl = `${window.location.protocol}//${window.location.host}/` const path = url.replace(baseUrl, '').replace('studio','studio/api') const filename = path.split('/').pop() fetch(`${baseUrl}${path}`) .then(response => response.text()) .then(data => { editor.setValue(data) }) .catch(err => notify({ type : 'error', message : `The file '${filename}' encountered an error '${err.message}'` })); window.saveFile = function() { const content = editor.getValue(); fetch(`${baseUrl}${path}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ content }) }) .then(response => response.text()) .then(data => { notify({ type: 'success', message : `The file '${filename}' has been updated` }) }) .catch(err => notify({ type : 'error', message : `The file '${filename}' encountered an error '${err.message}'` })); } }); }); </script> </html>