forked from platypush/platypush
[UI] FileEditor improvements.
- Switched to dark mode (I couldn't find any decent light theme combination that works with the Platypush UI). - Support passing static `content` and `content-type` rather than only a `file`. - Pass the `with-save` property from `EditorModal` to `Editor`.
This commit is contained in:
parent
010b52ed19
commit
575c0ab730
2 changed files with 88 additions and 37 deletions
|
@ -33,7 +33,7 @@
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import hljs from 'highlight.js';
|
import hljs from 'highlight.js';
|
||||||
import 'highlight.js/styles/intellij-light.css';
|
import 'highlight.js/styles/night-owl.min.css'
|
||||||
|
|
||||||
import FloatingButton from "@/components/elements/FloatingButton";
|
import FloatingButton from "@/components/elements/FloatingButton";
|
||||||
import Highlighter from "./Highlighter";
|
import Highlighter from "./Highlighter";
|
||||||
|
@ -51,7 +51,16 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
file: {
|
file: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
},
|
||||||
|
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
|
||||||
|
contentType: {
|
||||||
|
type: String,
|
||||||
|
default: 'plaintext',
|
||||||
},
|
},
|
||||||
|
|
||||||
isNew: {
|
isNew: {
|
||||||
|
@ -114,41 +123,43 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async loadFile() {
|
async loadFile() {
|
||||||
this.setUrlArgs({file: this.file})
|
if (!this.text?.length) {
|
||||||
if (this.isNew) {
|
this.setUrlArgs({file: this.file})
|
||||||
this.content = ''
|
if (this.isNew) {
|
||||||
this.initialContentHash = 0
|
this.content = ''
|
||||||
this.highlightedContent = ''
|
this.initialContentHash = 0
|
||||||
this.info = {}
|
this.highlightedContent = ''
|
||||||
this.type = this.getLanguageType({path: this.file})
|
this.info = {}
|
||||||
return
|
this.type = this.getLanguageType({path: this.file})
|
||||||
}
|
return
|
||||||
|
|
||||||
this.loading = true
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.info = (
|
|
||||||
await this.request('file.info', {files: [this.file]})
|
|
||||||
)[this.file] || {}
|
|
||||||
|
|
||||||
this.type = this.getLanguageType(this.info)
|
|
||||||
this.content = (
|
|
||||||
await axios.get(`/file?path=${encodeURIComponent(this.file)}`)
|
|
||||||
).data
|
|
||||||
|
|
||||||
if (typeof this.content === 'object') {
|
|
||||||
this.content = JSON.stringify(this.content, null, 2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initialContentHash = this.content.hashCode()
|
this.loading = true
|
||||||
} catch (e) {
|
|
||||||
this.notify({
|
try {
|
||||||
error: true,
|
this.info = (
|
||||||
text: e.message,
|
await this.request('file.info', {files: [this.file]})
|
||||||
title: 'Failed to load file',
|
)[this.file] || {}
|
||||||
})
|
|
||||||
} finally {
|
this.type = this.getLanguageType(this.info)
|
||||||
this.loading = false
|
this.content = (
|
||||||
|
await axios.get(`/file?path=${encodeURIComponent(this.file)}`)
|
||||||
|
).data
|
||||||
|
|
||||||
|
if (typeof this.content === 'object') {
|
||||||
|
this.content = JSON.stringify(this.content, null, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialContentHash = this.content.hashCode()
|
||||||
|
} catch (e) {
|
||||||
|
this.notify({
|
||||||
|
error: true,
|
||||||
|
text: e.message,
|
||||||
|
title: 'Failed to load file',
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedLine) {
|
if (this.selectedLine) {
|
||||||
|
@ -270,6 +281,11 @@ export default {
|
||||||
window.removeEventListener('beforeunload', this.beforeUnload)
|
window.removeEventListener('beforeunload', this.beforeUnload)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
convertType(type) {
|
||||||
|
const parts = type.split('/')
|
||||||
|
return parts[parts.length - 1]
|
||||||
|
},
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.setUrlArgs({file: null, line: null})
|
this.setUrlArgs({file: null, line: null})
|
||||||
this.removeBeforeUnload()
|
this.removeBeforeUnload()
|
||||||
|
@ -278,6 +294,14 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
contentType() {
|
||||||
|
if (!this.contentType?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.type = this.convertType(this.contentType)
|
||||||
|
},
|
||||||
|
|
||||||
file() {
|
file() {
|
||||||
this.loadFile()
|
this.loadFile()
|
||||||
},
|
},
|
||||||
|
@ -323,6 +347,10 @@ export default {
|
||||||
this.$refs.selectedLine.style.top = `${offset}px`
|
this.$refs.selectedLine.style.top = `${offset}px`
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
text() {
|
||||||
|
this.content = this.text
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -334,6 +362,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.content = this.text
|
||||||
|
this.type = this.convertType(this.contentType)
|
||||||
this.loadFile()
|
this.loadFile()
|
||||||
this.addBeforeUnload()
|
this.addBeforeUnload()
|
||||||
this.addKeyListener()
|
this.addKeyListener()
|
||||||
|
@ -354,6 +384,11 @@ export default {
|
||||||
$line-numbers-width: 2.5em;
|
$line-numbers-width: 2.5em;
|
||||||
|
|
||||||
.file-editor {
|
.file-editor {
|
||||||
|
--body-bg: #080808;
|
||||||
|
--body-fg: #f8f8f2;
|
||||||
|
--line-numbers-bg: #282a36;
|
||||||
|
--line-numbers-fg: #6272a4;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -366,6 +401,8 @@ $line-numbers-width: 2.5em;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
background: var(--body-bg);
|
||||||
|
color: var(--body-fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-highlight-loading {
|
.editor-highlight-loading {
|
||||||
|
@ -412,6 +449,8 @@ $line-numbers-width: 2.5em;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
background: var(--line-numbers-bg);
|
||||||
|
color: var(--line-numbers-fg);
|
||||||
|
|
||||||
.line-number {
|
.line-number {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -444,7 +483,7 @@ $line-numbers-width: 2.5em;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
color: rgba(0, 0, 0, 0);
|
color: rgba(0, 0, 0, 0);
|
||||||
caret-color: black;
|
caret-color: var(--body-fg);
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
:file="file"
|
:file="file"
|
||||||
:is-new="isNew"
|
:is-new="isNew"
|
||||||
:line="line"
|
:line="line"
|
||||||
|
:text="text"
|
||||||
|
:content-type="contentType"
|
||||||
|
:with-save="withSave"
|
||||||
@save="$emit('save', $event)"
|
@save="$emit('save', $event)"
|
||||||
v-if="file" />
|
v-if="file" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +44,16 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
file: {
|
file: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
},
|
||||||
|
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
|
||||||
|
contentType: {
|
||||||
|
type: String,
|
||||||
|
default: 'text/plain',
|
||||||
},
|
},
|
||||||
|
|
||||||
isNew: {
|
isNew: {
|
||||||
|
|
Loading…
Reference in a new issue