146 lines
6.3 KiB
HTML
146 lines
6.3 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>Direktil Local Server</title>
|
|
<base href="/ui/" />
|
|
|
|
<link rel="icon" href="favicon.ico" />
|
|
|
|
|
|
|
|
<style>@import url('/ui/style.css');@import url('/ui/app.css');</style>
|
|
<script src="/ui/jsonpatch.min-942279a1c4209cc2.js" integrity="sha384-GcPrkRS12jtrElEkbJcrZ8asvvb9s3mc+CUq9UW/8bL4L0bpkmh9M+oFnWN6qLq2"></script>
|
|
<script src="/ui/app-7f4645e84eaae7ce.js" defer integrity="sha384-31uiQnXVSPLDq61o+chfyKRkSdkmzv023M7KafOo+0xRw5AM70BUFyYO6yo0kPiZ" type="module"></script>
|
|
<script src="/ui/Downloads-c9374f19f52c46d.js" integrity="sha384-WQIkCSxlUkvu4jFIWwS3bESMaazGwwnBn9dyvB7nItz3L8BmusRMsJACzfJa7sC4"></script>
|
|
<script src="/ui/GetCopy-7e3c9678f9647d40.js" integrity="sha384-LzxUXylxE/t25HyTch8y2qvKcehvP2nqCo37swIBGEKZZUzHVJVQrS5UJDWNskTA"></script>
|
|
<script src="/ui/Cluster-703dcdca97841304.js" integrity="sha384-ifGpq/GB1nDfqczm5clTRtcfnc9UMkT+SptMyS3UG9Di3xoKORtOGGjmK5RnJx+v"></script>
|
|
<script src="/ui/Host-61916516a854adff.js" integrity="sha384-/wh3KrC0sb4MT7ekO2U84rswxI42WSH/0jB4dbDaaGaGhX60xTEZHFsdQAf7UgTG"></script>
|
|
<body>
|
|
|
|
<div id="app">
|
|
<header>
|
|
<div id="logo">
|
|
<img src="favicon.ico" />
|
|
<span>Direktil Local Server</span>
|
|
</div>
|
|
<div class="utils">
|
|
<span id="login-hdr" v-if="session.token">
|
|
Logged in
|
|
<button class="link" @click="copyText(session.token)">🗐</button>
|
|
</span>
|
|
|
|
<span>server <code>{{ serverVersion || '-----' }}</code></span>
|
|
<span>ui <code>{{ uiHash || '-----' }}</code></span>
|
|
|
|
<span :class="publicState ? 'green' : 'red'">🗲</span>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="error" v-if="error">
|
|
<button class="btn-close" @click="error=null">×</button>
|
|
<div class="code" v-if="error.code">{{ error.code }}</div>
|
|
<div class="message">{{ error.message }}</div>
|
|
</div>
|
|
|
|
<template v-if="!publicState">
|
|
<p>Not connected.</p>
|
|
</template>
|
|
|
|
<template v-else-if="publicState.Store.New">
|
|
<p>Store is new.</p>
|
|
<p>Option 1: initialize a new store</p>
|
|
<form @submit="unlockStore">
|
|
<input type="text" v-model="forms.store.name" name="name" placeholder="Name" /><br/>
|
|
<input type="password" v-model="forms.store.pass1" name="passphrase" required placeholder="Passphrase" />
|
|
<input type="password" v-model="forms.store.pass2" required placeholder="Passphrase confirmation" />
|
|
<input type="submit" value="initialize" :disabled="!forms.store.pass1 || forms.store.pass1 != forms.store.pass2" />
|
|
</form>
|
|
<p>Option 2: upload a previously downloaded store</p>
|
|
<form @submit="uploadStore">
|
|
<input type="file" ref="storeUpload" />
|
|
<input type="submit" value="upload" />
|
|
</form>
|
|
</template>
|
|
|
|
<template v-else-if="!publicState.Store.Open">
|
|
<p>Store is not open.</p>
|
|
<form @submit="unlockStore">
|
|
<input type="password" name="passphrase" v-model="forms.store.pass1" required placeholder="Passphrase" />
|
|
<input type="submit" value="unlock" :disabled="!forms.store.pass1" />
|
|
</form>
|
|
</template>
|
|
|
|
<template v-else-if="!state">
|
|
<p v-if="!session.token">Not logged in.</p>
|
|
<p v-else>Invalid token</p>
|
|
|
|
<form @submit="unlockStore">
|
|
<input type="password" v-model="forms.store.pass1" required placeholder="Passphrase" />
|
|
<input type="submit" value="log in"/>
|
|
</form>
|
|
</template>
|
|
|
|
<template v-else>
|
|
<div style="float:right;"><input type="search" placeholder="Filter" v-model="viewFilter"/></div>
|
|
<p class="view-links"><span v-for="v in views" @click="view = v" :class="{selected: view.type==v.type && view.name==v.name}">{{v.title}}</span></p>
|
|
|
|
<h2 v-if="view">{{view.title}}</h2>
|
|
|
|
<div v-if="view.type == 'cluster'" id="clusters">
|
|
<Cluster :cluster="viewObj" :token="session.token" :state="state" />
|
|
</div>
|
|
|
|
<div v-if="view.type == 'host'" id="hosts">
|
|
<Host :host="viewObj" :token="session.token" :state="state" />
|
|
</div>
|
|
|
|
<div v-if="view.type == 'actions' && view.name == 'admin'">
|
|
<h3>Config</h3>
|
|
<form @submit="uploadConfig">
|
|
<input type="file" ref="configUpload" required />
|
|
<input type="submit" value="upload config" />
|
|
</form>
|
|
|
|
<h3>Store</h3>
|
|
<p><a :href="'/public/store.tar?token='+state.Store.DownloadToken" target="_blank">Download</a></p>
|
|
<form @submit="storeAddKey" action="/store/add-key">
|
|
<p>Add an unlock phrase:</p>
|
|
<input type="text" v-model="forms.store.name" name="name" required placeholder="Name" /><br/>
|
|
<input type="password" v-model="forms.store.pass1" name="passphrase" autocomplete="new-password" required placeholder="Phrase" />
|
|
<input type="password" v-model="forms.store.pass2" autocomplete="new-password" required placeholder="Phrase confirmation" />
|
|
<input type="submit" value="add unlock phrase" :disabled="!forms.store.pass1 || forms.store.pass1 != forms.store.pass2" />
|
|
</form>
|
|
<form @submit="storeDelKey" action="/store/delete-key">
|
|
<p>Remove an unlock phrase:</p>
|
|
<input type="text" v-model="forms.delKey.name" name="name" required placeholder="Name" />
|
|
<input type="submit" value="remove unlock phrase" />
|
|
|
|
<p v-if="state.Store.KeyNames">Available names:
|
|
<template v-for="k,i in state.Store.KeyNames">{{i?", ":""}}<code @click="forms.delKey.name=k">{{k}}</code></template>.</p>
|
|
</form>
|
|
|
|
<template v-if="any(state.HostTemplates) || any(hostsFromTemplate)">
|
|
<h3>Hosts from template</h3>
|
|
<form @submit="hostFromTemplateAdd" action="" v-if="any(state.HostTemplates)">
|
|
<p>Add a host from template instance:</p>
|
|
<input type="text" v-model="forms.hostFromTemplate.name" required placeholder="Name" />
|
|
<select v-model="forms.hostFromTemplate.Template" required>
|
|
<option v-for="name in state.HostTemplates" :value="name">{{name}}</option>
|
|
</select>
|
|
<input type="text" v-model="forms.hostFromTemplate.IP" required placeholder="IP" />
|
|
<input type="submit" value="add instance" />
|
|
</form>
|
|
<form @submit="hostFromTemplateDel" action="" v-if="any(hostsFromTemplate)">
|
|
<p>Remove a host from template instance:</p>
|
|
<select v-model="forms.hostFromTemplateDel" required>
|
|
<option v-for="h in hostsFromTemplate" :value="h.Name">{{h.Name}}</option>
|
|
</select>
|
|
<input type="submit" value="delete instance" :disabled="!forms.hostFromTemplateDel" />
|
|
</form>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</body>
|
|
</html>
|