[Extensions UI] Install extensions deps from the UI.
- Added `Install` button - Added interactive output panel
This commit is contained in:
parent
033317e0a7
commit
a652bd9df8
5 changed files with 171 additions and 9 deletions
|
@ -45,5 +45,6 @@ export default {
|
|||
padding: 0.5em;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,9 +1,43 @@
|
|||
<template>
|
||||
<div class="install-container">
|
||||
<div class="install-cmd-container">
|
||||
<CopyButton :text="installCmd" />
|
||||
<pre><code v-html="highlightedInstallCmd" /></pre>
|
||||
</div>
|
||||
<section class="top">
|
||||
<header>
|
||||
<h2>Dependencies</h2>
|
||||
</header>
|
||||
|
||||
<div class="body">
|
||||
<div class="container install-cmd-container">
|
||||
<CopyButton :text="installCmd" />
|
||||
<pre><code v-html="highlightedInstallCmd" /></pre>
|
||||
</div>
|
||||
|
||||
<div class="buttons install-btn" v-if="installCmd?.length">
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
:disabled="installRunning"
|
||||
@click="installExtension">
|
||||
<i class="fas fa-download" /> Install
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="bottom" v-if="installRunning || installOutput">
|
||||
<header>
|
||||
<h2>Output</h2>
|
||||
</header>
|
||||
|
||||
<div class="body">
|
||||
<div class="container install-output" ref="installOutput">
|
||||
<CopyButton :text="installOutput" />
|
||||
<pre><code v-text="installOutput" /><div
|
||||
class="loading-container"
|
||||
v-if="installRunning">
|
||||
<Loading />
|
||||
</div></pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -12,14 +46,18 @@ import 'highlight.js/lib/common'
|
|||
import 'highlight.js/styles/stackoverflow-dark.min.css'
|
||||
import hljs from "highlight.js"
|
||||
import CopyButton from "@/components/elements/CopyButton"
|
||||
import Loading from "@/components/Loading"
|
||||
import Utils from "@/Utils"
|
||||
|
||||
export default {
|
||||
name: "Install",
|
||||
mixins: [Utils],
|
||||
emit: ['install-start', 'install-end'],
|
||||
components: {
|
||||
CopyButton,
|
||||
Loading,
|
||||
},
|
||||
|
||||
props: {
|
||||
extension: {
|
||||
type: Object,
|
||||
|
@ -27,6 +65,14 @@ export default {
|
|||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
installRunning: false,
|
||||
installOutput: null,
|
||||
pendingCommands: 0,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
installCmd() {
|
||||
const cmd = this.extension.deps.install_cmd.join('\n').trim()
|
||||
|
@ -47,29 +93,142 @@ export default {
|
|||
)
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
wsProcess(path) {
|
||||
try {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
const url = `${protocol}://${location.host}${path}`
|
||||
const ws = new WebSocket(url)
|
||||
|
||||
ws.onmessage = this.onMessage
|
||||
ws.onerror = this.onError
|
||||
ws.onclose = this.onClose
|
||||
} catch (err) {
|
||||
console.error('Websocket initialization error') // TODO notify
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
},
|
||||
|
||||
onMessage(msg) {
|
||||
if (!this.installOutput)
|
||||
this.installOutput = ''
|
||||
|
||||
this.installOutput += msg.data
|
||||
},
|
||||
|
||||
onClose() {
|
||||
this.installRunning = false
|
||||
this.$emit('install-end', this.extension)
|
||||
},
|
||||
|
||||
onError(error) {
|
||||
console.error('Websocket error') // TODO notify
|
||||
console.error(error)
|
||||
},
|
||||
|
||||
installExtension() {
|
||||
this.installRunning = true
|
||||
this.installOutput = ''
|
||||
this.$emit('install-start', this.extension)
|
||||
|
||||
const cmd = (this.extension.deps.install_cmd || []).join(';\n')
|
||||
this.request('shell.exec', {
|
||||
cmd: cmd,
|
||||
ws: true,
|
||||
}).then((output) => {
|
||||
this.wsProcess(output.ws_path)
|
||||
}).catch((err) => {
|
||||
console.error(err) // TODO notify
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$watch('installOutput', () => {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.installOutput.focus()
|
||||
this.$refs.installOutput.scrollTop = this.$refs.installOutput.scrollHeight
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "common.scss";
|
||||
|
||||
$header-height: 3.5em;
|
||||
|
||||
.install-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.install-cmd-container {
|
||||
section {
|
||||
&.top {
|
||||
height: 33.3333% !important;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
height: 66.6666% !important;
|
||||
}
|
||||
|
||||
header {
|
||||
height: $header-height;
|
||||
padding-left: 0.5em;
|
||||
border-top: 1px solid $border-color-1;
|
||||
border-bottom: 1px solid $border-color-1;
|
||||
}
|
||||
|
||||
.body {
|
||||
height: calc(100% - #{$header-height});
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.3em;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
pre {
|
||||
height: 50%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
.install-btn {
|
||||
width: 100%;
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
|
||||
button {
|
||||
border-radius: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
:deep(.loading) {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,6 +3,7 @@ pre {
|
|||
margin: 0;
|
||||
background: $code-dark-bg;
|
||||
color: $code-dark-fg;
|
||||
font-size: 0.9em;
|
||||
padding: 0.5em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ $scrollbar-thumb-bg: #a5a2a2 !default;
|
|||
$row-shadow: 0 0 1px 0.5px #cfcfcf !default;
|
||||
|
||||
//// Code blocks
|
||||
$code-dark-bg: #090909 !default;
|
||||
$code-dark-fg: #f0f0f0 !default;
|
||||
$code-dark-bg: rgb(11, 11, 13) !default;
|
||||
$code-dark-fg: rgb(243, 243, 250) !default;
|
||||
$code-light-bg: #f2f0e9 !default;
|
||||
$code-light-fg: #090909 !default;
|
||||
|
|
|
@ -36,6 +36,7 @@ module.exports = {
|
|||
proxy: {
|
||||
'^/ws/events': wsProxy,
|
||||
'^/ws/requests': wsProxy,
|
||||
'^/ws/shell': wsProxy,
|
||||
'^/execute': httpProxy,
|
||||
'^/auth': httpProxy,
|
||||
'^/camera/': httpProxy,
|
||||
|
|
Loading…
Reference in a new issue