Improvements :)
parent
7aa6a549f9
commit
84ddad027f
|
@ -125,95 +125,6 @@ function logoutEvent (event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHash (event, hash) {
|
|
||||||
event.preventDefault()
|
|
||||||
|
|
||||||
let request = new window.XMLHttpRequest()
|
|
||||||
let link
|
|
||||||
|
|
||||||
if (selectedItems.length) {
|
|
||||||
link = document.getElementById(selectedItems[0]).dataset.url
|
|
||||||
} else {
|
|
||||||
link = window.location.pathname
|
|
||||||
}
|
|
||||||
|
|
||||||
request.open('GET', `${link}?checksum=${hash}`, true)
|
|
||||||
|
|
||||||
request.onload = () => {
|
|
||||||
if (request.status >= 300) {
|
|
||||||
console.log(request.statusText)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
event.target.parentElement.innerHTML = request.responseText
|
|
||||||
}
|
|
||||||
request.onerror = (e) => console.log(e)
|
|
||||||
request.send()
|
|
||||||
}
|
|
||||||
|
|
||||||
function infoEvent (event) {
|
|
||||||
event.preventDefault()
|
|
||||||
if (event.currentTarget.classList.contains('disabled')) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let dir = false
|
|
||||||
let link
|
|
||||||
|
|
||||||
if (selectedItems.length) {
|
|
||||||
link = document.getElementById(selectedItems[0]).dataset.url
|
|
||||||
dir = document.getElementById(selectedItems[0]).dataset.dir
|
|
||||||
} else {
|
|
||||||
if (document.getElementById('listing') !== null) {
|
|
||||||
dir = true
|
|
||||||
}
|
|
||||||
|
|
||||||
link = window.location.pathname
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons.setLoading('info', false)
|
|
||||||
|
|
||||||
webdav.propfind(link)
|
|
||||||
.then((text) => {
|
|
||||||
let parser = new window.DOMParser()
|
|
||||||
let xml = parser.parseFromString(text, 'text/xml')
|
|
||||||
let clone = document.importNode(templates.info.content, true)
|
|
||||||
|
|
||||||
let value = xml.getElementsByTagName('displayname')
|
|
||||||
if (value.length > 0) {
|
|
||||||
clone.getElementById('display_name').innerHTML = value[0].innerHTML
|
|
||||||
} else {
|
|
||||||
clone.getElementById('display_name').innerHTML = xml.getElementsByTagName('D:displayname')[0].innerHTML
|
|
||||||
}
|
|
||||||
|
|
||||||
value = xml.getElementsByTagName('getcontentlength')
|
|
||||||
if (value.length > 0) {
|
|
||||||
clone.getElementById('content_length').innerHTML = value[0].innerHTML
|
|
||||||
} else {
|
|
||||||
clone.getElementById('content_length').innerHTML = xml.getElementsByTagName('D:getcontentlength')[0].innerHTML
|
|
||||||
}
|
|
||||||
|
|
||||||
value = xml.getElementsByTagName('getlastmodified')
|
|
||||||
if (value.length > 0) {
|
|
||||||
clone.getElementById('last_modified').innerHTML = value[0].innerHTML
|
|
||||||
} else {
|
|
||||||
clone.getElementById('last_modified').innerHTML = xml.getElementsByTagName('D:getlastmodified')[0].innerHTML
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir === true || dir === 'true') {
|
|
||||||
clone.querySelector('.file-only').style.display = 'none'
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelector('body').appendChild(clone)
|
|
||||||
document.querySelector('.overlay').classList.add('active')
|
|
||||||
document.querySelector('.prompt').classList.add('active')
|
|
||||||
buttons.setDone('info', true)
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
buttons.setDone('info', false)
|
|
||||||
console.log(e)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteOnSingleFile () {
|
function deleteOnSingleFile () {
|
||||||
closePrompt()
|
closePrompt()
|
||||||
buttons.setLoading('delete')
|
buttons.setLoading('delete')
|
||||||
|
@ -279,36 +190,6 @@ function deleteEvent (event) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeHelp (event) {
|
|
||||||
event.preventDefault()
|
|
||||||
|
|
||||||
document.querySelector('.help').classList.remove('active')
|
|
||||||
document.querySelector('.overlay').classList.remove('active')
|
|
||||||
}
|
|
||||||
|
|
||||||
function openHelp (event) {
|
|
||||||
closePrompt(event)
|
|
||||||
|
|
||||||
document.querySelector('.help').classList.add('active')
|
|
||||||
document.querySelector('.overlay').classList.add('active')
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('keydown', (event) => {
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
if (document.querySelector('.help.active')) {
|
|
||||||
closeHelp(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.keyCode === 46) {
|
|
||||||
deleteEvent(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.keyCode === 112) {
|
|
||||||
event.preventDefault()
|
|
||||||
openHelp(event)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * *
|
||||||
* *
|
* *
|
||||||
|
|
|
@ -159,29 +159,6 @@ listing.addDoubleTapEvent = function () {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keydown events
|
|
||||||
window.addEventListener('keydown', (event) => {
|
|
||||||
if (event.keyCode == 27) {
|
|
||||||
listing.unselectAll()
|
|
||||||
|
|
||||||
if (document.querySelectorAll('.prompt').length) {
|
|
||||||
closePrompt(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.keyCode == 113) {
|
|
||||||
listing.rename()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.ctrlKey || event.metaKey) {
|
|
||||||
switch (String.fromCharCode(event.which).toLowerCase()) {
|
|
||||||
case 's':
|
|
||||||
event.preventDefault()
|
|
||||||
window.location = '?download=true'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
listing.selectMoveFolder = function (event) {
|
listing.selectMoveFolder = function (event) {
|
||||||
if (event.target.getAttribute('aria-selected') === 'true') {
|
if (event.target.getAttribute('aria-selected') === 'true') {
|
||||||
event.target.setAttribute('aria-selected', false)
|
event.target.setAttribute('aria-selected', false)
|
||||||
|
|
|
@ -11,26 +11,6 @@
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="info-template">
|
|
||||||
<div class="prompt">
|
|
||||||
<h3>File Information</h3>
|
|
||||||
<p><strong>Display Name:</strong> <span id="display_name"></span></p>
|
|
||||||
<p><strong>Size:</strong> <span id="content_length"></span> Bytes</p>
|
|
||||||
<p><strong>Last Modified:</strong> <span id="last_modified"></span></p>
|
|
||||||
|
|
||||||
<section class="file-only">
|
|
||||||
<p><strong>MD5:</strong> <code id="md5"><a href="#" onclick="getHash(event, 'md5')">show</a></code></p>
|
|
||||||
<p><strong>SHA1:</strong> <code id="sha1"><a href="#" onclick="getHash(event, 'sha1')">show</a></code></p>
|
|
||||||
<p><strong>SHA256:</strong> <code id="sha256"><a href="#" onclick="getHash(event, 'sha256')">show</a></code></p>
|
|
||||||
<p><strong>SHA512:</strong> <code id="sha512"><a href="#" onclick="getHash(event, 'sha512')">show</a></code></p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button type="submit" onclick="closePrompt(event);" class="ok">OK</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template id="message-template">
|
<template id="message-template">
|
||||||
<div class="prompt">
|
<div class="prompt">
|
||||||
<h3></h3>
|
<h3></h3>
|
||||||
|
@ -60,28 +40,5 @@
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="help">
|
|
||||||
<h3>Help</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><strong>F1</strong> - this information</li>
|
|
||||||
<li><strong>F2</strong> - rename file</li>
|
|
||||||
<li><strong>DEL</strong> - delete selected items</li>
|
|
||||||
<li><strong>ESC</strong> - clear selection and/or close the prompt</li>
|
|
||||||
<li><strong>CTRL + S</strong> - save a file or download the directory where you are</li>
|
|
||||||
<li><strong>CTRL + Click</strong> - select multiple files or directories</li>
|
|
||||||
<li><strong>Double click</strong> - open a file or directory</li>
|
|
||||||
<li><strong>Click</strong> - select file or directory</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Not available yet</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><strong>Alt + Click</strong> - select a group of files</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button type="submit" onclick="closeHelp(event);" class="ok">OK</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
{{ end }}
|
|
@ -33,10 +33,19 @@
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
var info = {
|
var info = {
|
||||||
user: JSON.parse('{{ Marshal .User }}'),
|
user: JSON.parse('{{ Marshal .User }}'),
|
||||||
page: JSON.parse('{{ Marshal . }}'),
|
req: JSON.parse('{{ Marshal . }}'),
|
||||||
webdavURL: "{{ .WebDavURL }}",
|
webdavURL: "{{ .WebDavURL }}",
|
||||||
baseURL: "{{.BaseURL}}"
|
baseURL: "{{.BaseURL}}",
|
||||||
|
ssl: (window.location.protocol === 'https:'),
|
||||||
|
showInfo: false,
|
||||||
|
showHelp: false,
|
||||||
|
showDelete: false,
|
||||||
|
showRename: false,
|
||||||
|
listing: {
|
||||||
|
selected: [],
|
||||||
|
multiple: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<header>
|
<header>
|
||||||
<div id="first-bar">
|
<div>
|
||||||
<img src="./assets/logo.svg" alt="File Manager">
|
<img src="./assets/logo.svg" alt="File Manager">
|
||||||
<search></search>
|
<search></search>
|
||||||
</div>
|
</div>
|
||||||
<div id="second-bar">
|
<div>
|
||||||
<info-button></info-button>
|
<info-button></info-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div id="click-overlay"></div> -->
|
<!-- <div id="click-overlay"></div> -->
|
||||||
|
@ -21,12 +21,12 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<main>
|
<main>
|
||||||
<listing v-if="page.kind == 'listing'"></listing>
|
<listing v-if="req.kind == 'listing'"></listing>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<preview v-if="page.kind == 'preview'"></preview>
|
<preview v-if="req.kind == 'preview'"></preview>
|
||||||
|
|
||||||
<div class="overlay"></div>
|
|
||||||
<!-- TODO: show on listing and allowedit -->
|
<!-- TODO: show on listing and allowedit -->
|
||||||
<div class="floating">
|
<div class="floating">
|
||||||
<div tabindex="0" role="button" class="action" id="new">
|
<div tabindex="0" role="button" class="action" id="new">
|
||||||
|
@ -42,15 +42,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer>Served with <a rel="noopener noreferrer" href="https://github.com/hacdias/caddy-filemanager">File Manager</a>.</footer>
|
<info-prompt v-show="showInfo" :class="{ active: showInfo }"></info-prompt>
|
||||||
|
<help v-show="showHelp" :class="{ active: showHelp }"></help>
|
||||||
|
|
||||||
|
<div v-show="showOverlay()" class="overlay" :class="{ active: showOverlay() }"></div>
|
||||||
|
|
||||||
|
<footer>Served with <a rel="noopener noreferrer" href="https://github.com/hacdias/caddy-filemanager">File Manager</a>.</footer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Search from './components/Search'
|
import Search from './components/Search'
|
||||||
import Preview from './components/Preview'
|
import Preview from './components/Preview'
|
||||||
|
import Help from './components/Help'
|
||||||
import Listing from './components/Listing'
|
import Listing from './components/Listing'
|
||||||
import InfoButton from './components/InfoButton'
|
import InfoButton from './components/InfoButton'
|
||||||
|
import InfoPrompt from './components/InfoPrompt'
|
||||||
import css from './css.js'
|
import css from './css.js'
|
||||||
|
|
||||||
function updateColumnSizes () {
|
function updateColumnSizes () {
|
||||||
|
@ -60,9 +67,62 @@ function updateColumnSizes () {
|
||||||
items.style.width = `calc(${100 / columns}% - 1em)`
|
items.style.width = `calc(${100 / columns}% - 1em)`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener('keydown', (event) => {
|
||||||
|
// Esc!
|
||||||
|
if (event.keyCode === 27) {
|
||||||
|
window.info.showHelp = false
|
||||||
|
window.info.showInfo = false
|
||||||
|
window.info.showDelete = false
|
||||||
|
window.info.showRename = false
|
||||||
|
|
||||||
|
// Unselect all files and folders.
|
||||||
|
if (window.info.req.kind === 'listing') {
|
||||||
|
let items = document.getElementsByClassName('item')
|
||||||
|
Array.from(items).forEach(link => {
|
||||||
|
link.setAttribute('aria-selected', false)
|
||||||
|
})
|
||||||
|
|
||||||
|
window.info.listing.selected.length = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Del!
|
||||||
|
if (event.keyCode === 46) {
|
||||||
|
window.info.showDelete = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// F1!
|
||||||
|
if (event.keyCode === 112) {
|
||||||
|
event.preventDefault()
|
||||||
|
window.info.showHelp = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// F2!
|
||||||
|
if (event.keyCode === 113) {
|
||||||
|
window.info.showRename = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// CTRL + S
|
||||||
|
if (event.ctrlKey || event.metaKey) {
|
||||||
|
switch (String.fromCharCode(event.which).toLowerCase()) {
|
||||||
|
case 's':
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
if (window.info.req.kind !== 'editor') {
|
||||||
|
window.location = '?download=true'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: save file on editor!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
components: { Search, Preview, Listing, InfoButton },
|
components: { Search, Preview, Listing, InfoButton, InfoPrompt, Help },
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
updateColumnSizes()
|
updateColumnSizes()
|
||||||
window.addEventListener('resize', updateColumnSizes)
|
window.addEventListener('resize', updateColumnSizes)
|
||||||
|
@ -70,6 +130,11 @@ export default {
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
return window.info
|
return window.info
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showOverlay: function () {
|
||||||
|
return this.showInfo || this.showHelp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<div class="prompt help">
|
||||||
|
<h3>Help</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>F1</strong> - this information</li>
|
||||||
|
<li><strong>F2</strong> - rename file</li>
|
||||||
|
<li><strong>DEL</strong> - delete selected items</li>
|
||||||
|
<li><strong>ESC</strong> - clear selection and/or close the prompt</li>
|
||||||
|
<li><strong>CTRL + S</strong> - save a file or download the directory where you are</li>
|
||||||
|
<li><strong>CTRL + Click</strong> - select multiple files or directories</li>
|
||||||
|
<li><strong>Double click</strong> - open a file or directory</li>
|
||||||
|
<li><strong>Click</strong> - select file or directory</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Not available yet</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>Alt + Click</strong> - select a group of files</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit" @click="close" class="ok">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'help',
|
||||||
|
methods: {
|
||||||
|
close: function (event) {
|
||||||
|
window.info.showHelp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<button title="Info" aria-label="Info" class="action" id="info">
|
<button @click="show" title="Info" aria-label="Info" class="action" id="info">
|
||||||
<i class="material-icons">info</i>
|
<i class="material-icons">info</i>
|
||||||
<span>Info</span>
|
<span>Info</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -8,8 +8,10 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'info-button',
|
name: 'info-button',
|
||||||
data: function () {
|
methods: {
|
||||||
return window.info.page.data
|
show: function (event) {
|
||||||
|
window.info.showInfo = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
<template>
|
||||||
|
<div class="prompt">
|
||||||
|
<h3>File Information</h3>
|
||||||
|
|
||||||
|
<p v-show="listing.selected.length > 1">{{ listing.selected.length }} files selected.</p>
|
||||||
|
|
||||||
|
<p v-show="listing.selected.length < 2"><strong>Display Name:</strong> {{ name() }}</p>
|
||||||
|
<p><strong>Size:</strong> <span id="content_length"></span>{{ humanSize() }}</p>
|
||||||
|
<p v-show="listing.selected.length < 2"><strong>Last Modified:</strong> {{ humanTime() }}</p>
|
||||||
|
|
||||||
|
<section v-show="dir() && listing.selected.length === 0">
|
||||||
|
<p><strong>Number of files:</strong> {{ req.data.numFiles }}</p>
|
||||||
|
<p><strong>Number of directories:</strong> {{ req.data.numDirs }}</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section v-show="!dir()">
|
||||||
|
<p><strong>MD5:</strong> <code><a @click="checksum($event, 'md5')">show</a></code></p>
|
||||||
|
<p><strong>SHA1:</strong> <code><a @click="checksum($event, 'sha1')">show</a></code></p>
|
||||||
|
<p><strong>SHA256:</strong> <code><a @click="checksum($event, 'sha256')">show</a></code></p>
|
||||||
|
<p><strong>SHA512:</strong> <code><a @click="checksum($event, 'sha512')">show</a></code></p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit" @click="close" class="ok">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import filesize from 'filesize'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'info-prompt',
|
||||||
|
data: function () {
|
||||||
|
return window.info
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
humanSize: function () {
|
||||||
|
if (this.listing.selected.length === 0 || this.req.kind !== 'listing') {
|
||||||
|
return filesize(this.req.data.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sum = 0
|
||||||
|
|
||||||
|
for (let i = 0; i < this.listing.selected.length; i++) {
|
||||||
|
sum += this.req.data.items[this.listing.selected[i]].size
|
||||||
|
}
|
||||||
|
|
||||||
|
return filesize(sum)
|
||||||
|
},
|
||||||
|
humanTime: function () {
|
||||||
|
if (this.listing.selected.length === 0) {
|
||||||
|
return moment(this.req.data.modified).fromNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
return moment(this.req.data.items[this.listing.selected[0]]).fromNow()
|
||||||
|
},
|
||||||
|
name: function () {
|
||||||
|
if (this.listing.selected.length === 0) {
|
||||||
|
return this.req.data.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.req.data.items[this.listing.selected[0]].name
|
||||||
|
},
|
||||||
|
dir: function () {
|
||||||
|
if (this.listing.selected.length > 1) {
|
||||||
|
// Don't show when multiple selected.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.listing.selected.length === 0) {
|
||||||
|
return this.req.data.isDir
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.req.data.items[this.listing.selected[0]].isDir
|
||||||
|
},
|
||||||
|
checksum: function (event, hash) {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
let request = new window.XMLHttpRequest()
|
||||||
|
let link
|
||||||
|
|
||||||
|
if (this.listing.selected.length) {
|
||||||
|
link = this.req.data.items[this.listing.selected[0]].url
|
||||||
|
} else {
|
||||||
|
link = window.location.pathname
|
||||||
|
}
|
||||||
|
|
||||||
|
request.open('GET', `${link}?checksum=${hash}`, true)
|
||||||
|
|
||||||
|
request.onload = () => {
|
||||||
|
if (request.status >= 300) {
|
||||||
|
console.log(request.statusText)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.target.innerHTML = request.responseText
|
||||||
|
}
|
||||||
|
|
||||||
|
request.onerror = (e) => console.log(e)
|
||||||
|
request.send()
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.showInfo = false
|
||||||
|
|
||||||
|
let checksums = this.$el.querySelectorAll('a')
|
||||||
|
for (let i = 0; i < checksums.length; i++) {
|
||||||
|
checksums[i].innerHTML = 'show'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="listing"
|
<div id="listing"
|
||||||
:class="data.display"
|
:class="req.data.display"
|
||||||
@drop="drop"
|
@drop="drop"
|
||||||
@dragenter="dragEnter"
|
@dragenter="dragEnter"
|
||||||
@dragend="dragEnd">
|
@dragend="dragEnd">
|
||||||
|
@ -8,13 +8,13 @@
|
||||||
<div class="item header">
|
<div class="item header">
|
||||||
<div></div>
|
<div></div>
|
||||||
<div>
|
<div>
|
||||||
<p v-bind:class="{ active: data.sort === 'name' }" class="name"><span>Name</span>
|
<p v-bind:class="{ active: req.data.sort === 'name' }" class="name"><span>Name</span>
|
||||||
<a v-if="data.sort === 'name' && data.order != 'asc'" href="?sort=name&order=asc"><i class="material-icons">arrow_upward</i></a>
|
<a v-if="req.data.sort === 'name' && req.data.order != 'asc'" href="?sort=name&order=asc"><i class="material-icons">arrow_upward</i></a>
|
||||||
<a v-else href="?sort=name&order=desc"><i class="material-icons">arrow_downward</i></a>
|
<a v-else href="?sort=name&order=desc"><i class="material-icons">arrow_downward</i></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p v-bind:class="{ active: data.sort === 'size' }" class="size"><span>Size</span>
|
<p v-bind:class="{ active: req.data.sort === 'size' }" class="size"><span>Size</span>
|
||||||
<a v-if="data.sort === 'size' && data.order != 'asc'" href="?sort=size&order=asc"><i class="material-icons">arrow_upward</i></a>
|
<a v-if="req.data.sort === 'size' && req.data.order != 'asc'" href="?sort=size&order=asc"><i class="material-icons">arrow_upward</i></a>
|
||||||
<a v-else href="?sort=size&order=desc"><i class="material-icons">arrow_downward</i></a>
|
<a v-else href="?sort=size&order=desc"><i class="material-icons">arrow_downward</i></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -23,16 +23,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 v-if="(data.numDirs + data.numFiles) == 0" class="message">It feels lonely here :'(</h2>
|
<h2 v-if="(req.data.numDirs + req.data.numFiles) == 0" class="message">It feels lonely here :'(</h2>
|
||||||
|
|
||||||
<h2 v-if="data.numDirs > 0">Folders</h2>
|
<h2 v-if="req.data.numDirs > 0">Folders</h2>
|
||||||
<div v-if="data.numDirs > 0">
|
<div v-if="req.data.numDirs > 0">
|
||||||
<item
|
<item
|
||||||
v-for="(item, index) in data.items"
|
v-for="(item, index) in req.data.items"
|
||||||
v-if="item.isDir"
|
v-if="item.isDir"
|
||||||
:key="base64(item.name)"
|
:key="base64(item.name)"
|
||||||
:id="base64(item.name)"
|
v-bind:index="index"
|
||||||
v-bind:selected="selected"
|
|
||||||
v-bind:name="item.name"
|
v-bind:name="item.name"
|
||||||
v-bind:isDir="item.isDir"
|
v-bind:isDir="item.isDir"
|
||||||
v-bind:url="item.url"
|
v-bind:url="item.url"
|
||||||
|
@ -42,14 +41,13 @@
|
||||||
</item>
|
</item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 v-if="data.numFiles > 0">Files</h2>
|
<h2 v-if="req.data.numFiles > 0">Files</h2>
|
||||||
<div v-if="data.numFiles > 0">
|
<div v-if="req.data.numFiles > 0">
|
||||||
<item
|
<item
|
||||||
v-for="(item, index) in data.items"
|
v-for="(item, index) in req.data.items"
|
||||||
v-if="!item.isDir"
|
v-if="!item.isDir"
|
||||||
:key="base64(item.name)"
|
:key="base64(item.name)"
|
||||||
:id="base64(item.name)"
|
v-bind:index="index"
|
||||||
v-bind:selected="selected"
|
|
||||||
v-bind:name="item.name"
|
v-bind:name="item.name"
|
||||||
v-bind:isDir="item.isDir"
|
v-bind:isDir="item.isDir"
|
||||||
v-bind:url="item.url"
|
v-bind:url="item.url"
|
||||||
|
@ -73,11 +71,7 @@ import page from '../page.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'preview',
|
name: 'preview',
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return window.info
|
||||||
data: window.info.page.data,
|
|
||||||
selected: [],
|
|
||||||
multiple: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
components: { Item },
|
components: { Item },
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
|
|
|
@ -33,7 +33,10 @@ import array from '../array.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'item',
|
name: 'item',
|
||||||
props: ['name', 'isDir', 'url', 'type', 'size', 'modified', 'selected'],
|
props: ['name', 'isDir', 'url', 'type', 'size', 'modified', 'index'],
|
||||||
|
data: function () {
|
||||||
|
return window.info.listing
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
icon: function () {
|
icon: function () {
|
||||||
if (this.isDir) return 'folder'
|
if (this.isDir) return 'folder'
|
||||||
|
@ -97,22 +100,18 @@ export default {
|
||||||
})
|
})
|
||||||
|
|
||||||
this.selected.length = 0
|
this.selected.length = 0
|
||||||
|
|
||||||
// listing.handleSelectionChange()
|
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
click: function (event) {
|
click: function (event) {
|
||||||
let el = event.currentTarget
|
|
||||||
|
|
||||||
if (this.selected.length !== 0) event.preventDefault()
|
if (this.selected.length !== 0) event.preventDefault()
|
||||||
if (this.selected.indexOf(el.id) === -1) {
|
if (this.selected.indexOf(this.index) === -1) {
|
||||||
if (!event.ctrlKey && !this.multiple) this.unselectAll()
|
if (!event.ctrlKey && !this.multiple) this.unselectAll()
|
||||||
|
|
||||||
el.setAttribute('aria-selected', true)
|
this.$el.setAttribute('aria-selected', true)
|
||||||
this.selected.push(el.id)
|
this.selected.push(this.index)
|
||||||
} else {
|
} else {
|
||||||
el.setAttribute('aria-selected', false)
|
this.$el.setAttribute('aria-selected', false)
|
||||||
this.selected = array.remove(this.selected, el.id)
|
this.selected = array.remove(this.selected, this.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.handleSelectionChange()
|
// this.handleSelectionChange()
|
||||||
|
|
|
@ -23,17 +23,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import page from '../page'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'preview',
|
name: 'preview',
|
||||||
data: function () {
|
data: function () {
|
||||||
return window.info.page.data
|
return window.info.req.data
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
raw: function () {
|
raw: function () {
|
||||||
return this.url + '?raw=true'
|
return this.url + '?raw=true'
|
||||||
},
|
},
|
||||||
back: function (event) {
|
back: function (event) {
|
||||||
window.history.back()
|
let url = page.removeLastDir(window.location.pathname)
|
||||||
|
page.open(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,7 @@
|
||||||
<script>
|
<script>
|
||||||
import page from '../page'
|
import page from '../page'
|
||||||
|
|
||||||
// Remove the last directory of an url
|
var $ = window.info
|
||||||
var removeLastDirectoryPartOf = function (url) {
|
|
||||||
var arr = url.split('/')
|
|
||||||
if (arr.pop() === '') {
|
|
||||||
arr.pop()
|
|
||||||
}
|
|
||||||
return (arr.join('/'))
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = window.info.user
|
|
||||||
var ssl = window.ssl
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'search',
|
name: 'search',
|
||||||
|
@ -49,8 +39,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
reset: function () {
|
reset: function () {
|
||||||
if (user.allowCommands && user.commands.length > 0) {
|
if ($.user.allowCommands && $.user.commands.length > 0) {
|
||||||
this.box.innerHTML = `Search or use one of your supported commands: ${user.commands.join(', ')}.`
|
this.box.innerHTML = `Search or use one of your supported commands: ${$.user.commands.join(', ')}.`
|
||||||
} else {
|
} else {
|
||||||
this.box.innerHTML = 'Type and press enter to search.'
|
this.box.innerHTML = 'Type and press enter to search.'
|
||||||
}
|
}
|
||||||
|
@ -59,8 +49,8 @@ export default {
|
||||||
let value = this.input.value
|
let value = this.input.value
|
||||||
let pieces = value.split(' ')
|
let pieces = value.split(' ')
|
||||||
|
|
||||||
for (let i = 0; i < user.commands.length; i++) {
|
for (let i = 0; i < $.user.commands.length; i++) {
|
||||||
if (pieces[0] === user.commands[0]) {
|
if (pieces[0] === $.user.commands[0]) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +69,7 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.supported() || !user.allowCommands) {
|
if (!this.supported() || !$.user.allowCommands) {
|
||||||
this.box.innerHTML = 'Press enter to search.'
|
this.box.innerHTML = 'Press enter to search.'
|
||||||
} else {
|
} else {
|
||||||
this.box.innerHTML = 'Press enter to execute.'
|
this.box.innerHTML = 'Press enter to execute.'
|
||||||
|
@ -92,12 +82,12 @@ export default {
|
||||||
let url = window.location.host + window.location.pathname
|
let url = window.location.host + window.location.pathname
|
||||||
|
|
||||||
if (document.getElementById('editor')) {
|
if (document.getElementById('editor')) {
|
||||||
url = removeLastDirectoryPartOf(url)
|
url = page.removeLastDir(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
let protocol = ssl ? 'wss:' : 'ws:'
|
let protocol = $.ssl ? 'wss:' : 'ws:'
|
||||||
|
|
||||||
if (this.supported() && user.allowCommands) {
|
if (this.supported() && $.user.allowCommands) {
|
||||||
let conn = new window.WebSocket(`${protocol}//${url}?command=true`)
|
let conn = new window.WebSocket(`${protocol}//${url}?command=true`)
|
||||||
|
|
||||||
conn.onopen = () => {
|
conn.onopen = () => {
|
||||||
|
|
|
@ -16,6 +16,12 @@ header a:hover {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header img {
|
||||||
|
height: 2.5em;
|
||||||
|
margin-right: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
header>div {
|
header>div {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -32,27 +38,18 @@ header>div div {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * *
|
header > div:first-child {
|
||||||
* TOP BAR *
|
|
||||||
* * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
#first-bar {
|
|
||||||
height: 4em;
|
height: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#first-bar img {
|
header > div:last-child {
|
||||||
height: 2.5em;
|
justify-content: flex-end;
|
||||||
margin-right: 1em;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * *
|
||||||
* BOTTOM BAR *
|
* MORE?? *
|
||||||
* * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#second-bar {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
#more {
|
#more {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
.prompt {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.075);
|
||||||
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 2em;
|
||||||
|
max-width: 25em;
|
||||||
|
width: 90%;
|
||||||
|
max-height: 95%;
|
||||||
|
z-index: 99999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.active,
|
||||||
|
.prompt.active,
|
||||||
|
.help.active {
|
||||||
|
animation: .2s show forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt p {
|
||||||
|
font-size: .9em;
|
||||||
|
color: rgba(0, 0, 0, 0.8);
|
||||||
|
margin: .5em 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #dadada;
|
||||||
|
line-height: 1;
|
||||||
|
padding: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt code {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt div {
|
||||||
|
margin-top: 1em;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .cancel {
|
||||||
|
background-color: #ECEFF1;
|
||||||
|
color: #37474F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .cancel:hover {
|
||||||
|
background-color: #e9eaeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * *
|
||||||
|
* PROMPT - MOVE *
|
||||||
|
* * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
.prompt .file-list {
|
||||||
|
flex-direction: initial;
|
||||||
|
max-height: 50vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .file-list ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .file-list ul li {
|
||||||
|
width: 100%;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .file-list ul li[aria-selected=true] {
|
||||||
|
background: #2196f3 !important;
|
||||||
|
color: #fff !important;
|
||||||
|
transition: .1s ease all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .file-list ul li:hover {
|
||||||
|
background-color: #e9eaeb;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .file-list ul li:before {
|
||||||
|
content: "folder";
|
||||||
|
color: #6f6f6f;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 0 .25em;
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt .file-list ul li[aria-selected=true]:before {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help {
|
||||||
|
max-width: 24em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help ul {
|
||||||
|
padding: 0;
|
||||||
|
margin: 1em 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes show {
|
||||||
|
0% {
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
1% {
|
||||||
|
display: block;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
display: block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
@import "./fonts.css";
|
@import "./fonts.css";
|
||||||
@import "./normalize.css";
|
@import "./normalize.css";
|
||||||
@import "./header.css";
|
@import "./header.css";
|
||||||
|
@import "./prompts.css";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
|
@ -726,8 +727,7 @@ main {
|
||||||
#previewer .preview pre,
|
#previewer .preview pre,
|
||||||
#previewer .preview video,
|
#previewer .preview video,
|
||||||
#previewer .preview img {
|
#previewer .preview img {
|
||||||
/* max-height: 80vh; */
|
max-height: 100%;
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,162 +778,8 @@ main {
|
||||||
* PROMPT *
|
* PROMPT *
|
||||||
* * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.overlay,
|
|
||||||
.prompt,
|
|
||||||
.help {
|
|
||||||
opacity: 0;
|
|
||||||
z-index: -1;
|
|
||||||
transition: .1s ease opacity, z-index;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay.active,
|
|
||||||
.prompt.active,
|
|
||||||
.help.active {
|
|
||||||
z-index: 9999999;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay.active {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt,
|
|
||||||
.help {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 99999999;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.075);
|
|
||||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
|
||||||
padding: 2em;
|
|
||||||
max-width: 25em;
|
|
||||||
width: 90%;
|
|
||||||
max-height: 95%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt h3,
|
|
||||||
.help h3 {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt p,
|
|
||||||
.help p {
|
|
||||||
font-size: .9em;
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
margin: .5em 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt input {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #dadada;
|
|
||||||
line-height: 1;
|
|
||||||
padding: .3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt code {
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt div,
|
|
||||||
.help div {
|
|
||||||
margin-top: 1em;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .cancel {
|
|
||||||
background-color: #ECEFF1;
|
|
||||||
color: #37474F;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .cancel:hover {
|
|
||||||
background-color: #e9eaeb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * *
|
|
||||||
* PROMPT - MOVE *
|
|
||||||
* * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
.prompt .file-list {
|
|
||||||
flex-direction: initial;
|
|
||||||
max-height: 50vh;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .file-list ul {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .file-list ul li {
|
|
||||||
width: 100%;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .file-list ul li[aria-selected=true] {
|
|
||||||
background: #2196f3 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
transition: .1s ease all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .file-list ul li:hover {
|
|
||||||
background-color: #e9eaeb;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .file-list ul li:before {
|
|
||||||
content: "folder";
|
|
||||||
color: #6f6f6f;
|
|
||||||
vertical-align: middle;
|
|
||||||
padding: 0 .25em;
|
|
||||||
line-height: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt .file-list ul li[aria-selected=true]:before {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * *
|
|
||||||
* HELP *
|
|
||||||
* * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
.help {
|
|
||||||
max-width: 24em;
|
|
||||||
visibility: hidden;
|
|
||||||
top: -100%;
|
|
||||||
left: -100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help.active {
|
|
||||||
visibility: visible;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help ul {
|
|
||||||
padding: 0;
|
|
||||||
margin: 1em 0;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * *
|
||||||
|
|
|
@ -6,18 +6,19 @@ import App from './App'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
window.info = (window.info || window.alert('Something is wrong, please refresh!'))
|
var $ = (window.info || window.alert('Something is wrong, please refresh!'))
|
||||||
window.ssl = (window.location.protocol === 'https:')
|
|
||||||
|
|
||||||
// TODO: keep this here?
|
// TODO: keep this here?
|
||||||
document.title = window.info.page.name
|
document.title = $.req.name
|
||||||
|
|
||||||
// TODO: keep this here?
|
// TODO: keep this here?
|
||||||
window.addEventListener('popstate', (event) => {
|
window.addEventListener('popstate', (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
window.info.page.kind = ''
|
$.req.kind = ''
|
||||||
|
$.listing.selected.length = 0
|
||||||
|
$.listing.selected.multiple = false
|
||||||
|
|
||||||
let request = new window.XMLHttpRequest()
|
let request = new window.XMLHttpRequest()
|
||||||
request.open('GET', event.state.url, true)
|
request.open('GET', event.state.url, true)
|
||||||
|
@ -25,7 +26,7 @@ window.addEventListener('popstate', (event) => {
|
||||||
|
|
||||||
request.onload = () => {
|
request.onload = () => {
|
||||||
if (request.status === 200) {
|
if (request.status === 200) {
|
||||||
window.info.page = JSON.parse(request.responseText)
|
$.req = JSON.parse(request.responseText)
|
||||||
document.title = event.state.name
|
document.title = event.state.name
|
||||||
} else {
|
} else {
|
||||||
console.log(request.responseText)
|
console.log(request.responseText)
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
|
var $ = window.info
|
||||||
|
|
||||||
function open (url, history) {
|
function open (url, history) {
|
||||||
window.info.page.kind = ''
|
// Reset info
|
||||||
|
$.listing.selected.length = 0
|
||||||
|
$.listing.selected.multiple = false
|
||||||
|
$.req.kind = ''
|
||||||
|
|
||||||
let request = new window.XMLHttpRequest()
|
let request = new window.XMLHttpRequest()
|
||||||
request.open('GET', url, true)
|
request.open('GET', url, true)
|
||||||
|
@ -7,15 +12,15 @@ function open (url, history) {
|
||||||
|
|
||||||
request.onload = () => {
|
request.onload = () => {
|
||||||
if (request.status === 200) {
|
if (request.status === 200) {
|
||||||
window.info.page = JSON.parse(request.responseText)
|
$.req = JSON.parse(request.responseText)
|
||||||
|
|
||||||
if (history) {
|
if (history) {
|
||||||
window.history.pushState({
|
window.history.pushState({
|
||||||
name: window.info.page.name,
|
name: $.req.name,
|
||||||
url: url
|
url: url
|
||||||
}, window.info.page.name, url)
|
}, $.req.name, url)
|
||||||
|
|
||||||
document.title = window.info.page.name
|
document.title = $.req.name
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(request.responseText)
|
console.log(request.responseText)
|
||||||
|
@ -26,11 +31,20 @@ function open (url, history) {
|
||||||
request.send()
|
request.send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeLastDir (url) {
|
||||||
|
var arr = url.split('/')
|
||||||
|
if (arr.pop() === '') {
|
||||||
|
arr.pop()
|
||||||
|
}
|
||||||
|
return (arr.join('/'))
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
reload: () => {
|
reload: () => {
|
||||||
open(window.location.pathname, false)
|
open(window.location.pathname, false)
|
||||||
},
|
},
|
||||||
open: (url) => {
|
open: (url) => {
|
||||||
open(url, true)
|
open(url, true)
|
||||||
}
|
},
|
||||||
|
removeLastDir: removeLastDir
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
var info = window.info
|
var $ = window.info
|
||||||
|
|
||||||
function convertURL (url) {
|
function convertURL (url) {
|
||||||
return window.location.origin + url.replace(info.baseURL + '/', info.webdavURL + '/')
|
return window.location.origin + url.replace($.baseURL + '/', $.webdavURL + '/')
|
||||||
}
|
}
|
||||||
|
|
||||||
function move (oldLink, newLink) {
|
function move (oldLink, newLink) {
|
||||||
|
@ -9,8 +9,8 @@ function move (oldLink, newLink) {
|
||||||
let request = new window.XMLHttpRequest()
|
let request = new window.XMLHttpRequest()
|
||||||
|
|
||||||
oldLink = convertURL(oldLink)
|
oldLink = convertURL(oldLink)
|
||||||
newLink = newLink.replace(info.baseURL + '/', info.webdavURL + '/')
|
newLink = newLink.replace($.baseURL + '/', $.webdavURL + '/')
|
||||||
newLink = window.location.origin + newLink.substring(info.baseURL.length)
|
newLink = window.location.origin + newLink.substring($.baseURL.length)
|
||||||
|
|
||||||
request.open('MOVE', oldLink, true)
|
request.open('MOVE', oldLink, true)
|
||||||
request.setRequestHeader('Destination', newLink)
|
request.setRequestHeader('Destination', newLink)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
// editor contains the information to fill the editor template.
|
// editor contains the information to fill the editor template.
|
||||||
type editor struct {
|
type editor struct {
|
||||||
|
*fileInfo
|
||||||
Class string `json:"class"`
|
Class string `json:"class"`
|
||||||
Mode string `json:"mode"`
|
Mode string `json:"mode"`
|
||||||
Visual bool `json:"visual"`
|
Visual bool `json:"visual"`
|
||||||
|
@ -28,7 +29,7 @@ func getEditor(r *http.Request, i *fileInfo) (*editor, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Create a new editor variable and set the mode
|
// Create a new editor variable and set the mode
|
||||||
e := &editor{}
|
e := &editor{fileInfo: i}
|
||||||
e.Mode = editorMode(i.Name)
|
e.Mode = editorMode(i.Name)
|
||||||
e.Class = editorClass(e.Mode)
|
e.Class = editorClass(e.Mode)
|
||||||
|
|
||||||
|
|
11
file.go
11
file.go
|
@ -15,7 +15,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -56,10 +55,7 @@ type fileInfo struct {
|
||||||
|
|
||||||
// A listing is the context used to fill out a template.
|
// A listing is the context used to fill out a template.
|
||||||
type listing struct {
|
type listing struct {
|
||||||
// The name of the directory (the last element of the path).
|
*fileInfo
|
||||||
Name string `json:"-"`
|
|
||||||
// The full path of the request relatively to a File System.
|
|
||||||
Path string `json:"-"`
|
|
||||||
// The items (files and folders) in the path.
|
// The items (files and folders) in the path.
|
||||||
Items []fileInfo `json:"items"`
|
Items []fileInfo `json:"items"`
|
||||||
// The number of directories in the listing.
|
// The number of directories in the listing.
|
||||||
|
@ -103,7 +99,7 @@ func getInfo(url *url.URL, c *FileManager, u *User) (*fileInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getListing gets the information about a specific directory and its files.
|
// getListing gets the information about a specific directory and its files.
|
||||||
func getListing(u *User, filePath string, baseURL string) (*listing, error) {
|
func getListing(u *User, filePath string, baseURL string, i *fileInfo) (*listing, error) {
|
||||||
// Gets the directory information using the Virtual File System of
|
// Gets the directory information using the Virtual File System of
|
||||||
// the user configuration.
|
// the user configuration.
|
||||||
file, err := u.fileSystem.OpenFile(context.TODO(), filePath, os.O_RDONLY, 0)
|
file, err := u.fileSystem.OpenFile(context.TODO(), filePath, os.O_RDONLY, 0)
|
||||||
|
@ -155,8 +151,7 @@ func getListing(u *User, filePath string, baseURL string) (*listing, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &listing{
|
return &listing{
|
||||||
Name: path.Base(filePath),
|
fileInfo: i,
|
||||||
Path: filePath,
|
|
||||||
Items: fileinfos,
|
Items: fileinfos,
|
||||||
NumDirs: dirCount,
|
NumDirs: dirCount,
|
||||||
NumFiles: fileCount,
|
NumFiles: fileCount,
|
||||||
|
|
2
serve.go
2
serve.go
|
@ -64,7 +64,7 @@ func serveListing(c *requestContext, w http.ResponseWriter, r *http.Request) (in
|
||||||
|
|
||||||
c.pg.Kind = "listing"
|
c.pg.Kind = "listing"
|
||||||
|
|
||||||
listing, err = getListing(c.us, c.fi.VirtualPath, c.fm.RootURL()+r.URL.Path)
|
listing, err = getListing(c.us, c.fi.VirtualPath, c.fm.RootURL()+r.URL.Path, c.fi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorToHTTP(err, true), err
|
return errorToHTTP(err, true), err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue