<!doctype html> <html> <head> <title>Direktil Local Server</title> <style> @import url('./style.css'); @import url('./app.css'); </style> <script src="js/jsonpatch.min.js" crossorigin="anonymous"></script> <script src="js/app.js" type="module" defer></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 id="uiHash">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="setToken"> <input type="password" v-model="forms.setToken" required placeholder="Token" /> <input type="submit" value="set token"/> </form> </template> <template v-else> <div v-if="state.Clusters" id="clusters"> <h2>Clusters</h2> <div class="sheets"> <Cluster v-for="c in state.Clusters" :cluster="c" :token="session.token" :state="state" /> </div> </div> <div v-if="state.Hosts" id="hosts"> <h2>Hosts</h2> <div class="sheets"> <Host v-for="h in state.Hosts" :host="h" :token="session.token" :state="state" /> </div> </div> <h2>Admin actions</h2> <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> </div> </body> </html>