Move connect and network edit views to vue.

This commit is contained in:
Richard Lewis 2019-03-01 15:29:00 +02:00 committed by Pavel Djundik
parent c4a3108dc0
commit 5a3ad194e8
9 changed files with 305 additions and 243 deletions

View File

@ -26,6 +26,8 @@ import NetworkList from "./NetworkList.vue";
import Chat from "./Chat.vue"; import Chat from "./Chat.vue";
import SignIn from "./Windows/SignIn.vue"; import SignIn from "./Windows/SignIn.vue";
import Settings from "./Windows/Settings.vue"; import Settings from "./Windows/Settings.vue";
import NetworkEdit from "./Windows/NetworkEdit.vue";
import Connect from "./Windows/Connect.vue";
import Help from "./Windows/Help.vue"; import Help from "./Windows/Help.vue";
import Changelog from "./Windows/Changelog.vue"; import Changelog from "./Windows/Changelog.vue";
@ -37,6 +39,8 @@ export default {
Chat, Chat,
SignIn, SignIn,
Settings, Settings,
NetworkEdit,
Connect,
Help, Help,
Changelog, Changelog,
}, },

View File

@ -0,0 +1,241 @@
<template>
<div
id="connect"
class="window"
role="tabpanel"
aria-label="Connect">
<div class="header">
<button
class="lt"
aria-label="Toggle channel list" />
</div>
<form
class="container"
method="post"
action=""
:data-event="defaults.uuid ? 'network:edit' : 'network:new'"
@submit.prevent="onSubmit"
>
<div class="row">
<div class="col-sm-12">
<h1 class="title">
<template v-if="defaults.uuid">
<input
type="hidden"
name="uuid"
:value="defaults.uuid">
Edit {{ defaults.name }}
</template>
<template v-else>
<template v-if="config.public">The Lounge - </template>
Connect
<template v-if="!config.displayNetwork">
<template v-if="config.lockNetwork">
to {{ defaults.name }}
</template>
</template>
</template>
</h1>
</div>
<template v-if="config.displayNetwork">
<div>
<div class="col-sm-12">
<h2>Network settings</h2>
</div>
<div class="col-sm-3">
<label for="connect:name">Name</label>
</div>
<div class="col-sm-9">
<input
id="connect:name"
class="input"
name="name"
:value="defaults.name"
maxlength="100">
</div>
<div class="col-sm-3">
<label for="connect:host">Server</label>
</div>
<div class="col-sm-6 col-xs-8">
<input
id="connect:host"
class="input"
name="host"
:value="defaults.host"
aria-label="Server address"
maxlength="255"
required
:disabled="config.lockNetwork ? true : false"
>
</div>
<div class="col-sm-3 col-xs-4">
<div class="port">
<input
class="input"
type="number"
min="1"
max="65535"
name="port"
:value="defaults.port"
aria-label="Server port"
:disabled="config.lockNetwork ? true : false"
>
</div>
</div>
<div class="clearfix" />
<div class="col-sm-9 col-sm-offset-3">
<label class="tls">
<input
type="checkbox"
name="tls"
:checked="defaults.tls ? true : false"
:disabled="config.lockNetwork ? true : false"
>
Use secure connection (TLS)
</label>
</div>
<div class="col-sm-9 col-sm-offset-3">
<label class="tls">
<input
type="checkbox"
name="rejectUnauthorized"
:checked="defaults.rejectUnauthorized ? true : false"
:disabled="config.lockNetwork ? true : false"
>
Only allow trusted certificates
</label>
</div>
<div class="clearfix" />
</div>
</template>
<div class="col-sm-12">
<h2>User preferences</h2>
</div>
<div class="col-sm-3">
<label for="connect:nick">Nick</label>
</div>
<div class="col-sm-9">
<input
id="connect:nick"
class="input nick"
name="nick"
:value="defaults.nick"
maxlength="100"
required>
</div>
<template v-if="!config.useHexIp">
<div class="col-sm-3">
<label for="connect:username">Username</label>
</div>
<div class="col-sm-9">
<input
id="connect:username"
class="input username"
name="username"
:value="defaults.username"
maxlength="512">
</div>
</template>
<div class="col-sm-3">
<label for="connect:password">Password</label>
</div>
<div class="col-sm-9 password-container">
<RevealPassword v-slot:default="slotProps">
<input
id="connect:password"
v-model="defaults.password"
class="input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="password"
maxlength="512">
</RevealPassword>
</div>
<div class="col-sm-3">
<label for="connect:realname">Real name</label>
</div>
<div class="col-sm-9">
<input
id="connect:realname"
class="input"
name="realname"
:value="defaults.realname"
maxlength="512">
</div>
<template v-if="defaults.uuid">
<div class="col-sm-3">
<label for="connect:commands">Commands</label>
</div>
<div class="col-sm-9">
<textarea
id="connect:commands"
class="input"
name="commands"
placeholder="One raw command per line, each command will be executed on new connection"
:value="defaults.commands ? defaults.commands.join('\n') : ''"
/>
</div>
<div class="col-sm-9 col-sm-offset-3">
<button
type="submit"
class="btn"
:disabled="disabled ? true : false"
>Save</button>
</div>
</template>
<template v-else>
<div class="col-sm-3">
<label for="connect:channels">Channels</label>
</div>
<div class="col-sm-9">
<input
id="connect:channels"
class="input"
name="join"
:value="defaults.join">
</div>
<div class="col-sm-9 col-sm-offset-3">
<button
type="submit"
class="btn"
:disabled="disabled ? true : false"
>Connect</button>
</div>
</template>
</div>
</form>
</div>
</template>
<script>
import RevealPassword from "./RevealPassword.vue";
export default {
name: "NetworkForm",
components: {
RevealPassword,
},
props: {
handleSubmit: Function,
defaults: Object,
disabled: Boolean,
},
data() {
return {
config: this.$root.serverConfiguration,
};
},
methods: {
onSubmit(event) {
const formData = new FormData(event.target);
const data = {};
for (const item of formData.entries()) {
data[item[0]] = item[1];
}
this.handleSubmit(data);
},
},
};
</script>

View File

@ -0,0 +1,31 @@
<template>
<NetworkForm
:handle-submit="handleSubmit"
:defaults="$root.serverConfiguration.defaults"
:disabled="disabled"
/>
</template>
<script>
const socket = require("../../js/socket");
import NetworkForm from "../NetworkForm.vue";
export default {
name: "Connect",
components: {
NetworkForm,
},
data() {
return {
disabled: false,
};
},
methods: {
handleSubmit(data) {
this.disabled = true;
socket.emit("network:new", data);
},
},
};
</script>

View File

@ -1,242 +1,40 @@
<template> <template>
<div <NetworkForm
id="connect" v-if="$store.state.currentNetworkConfig"
class="window" :handle-submit="handleSubmit"
role="tabpanel" :defaults="$store.state.currentNetworkConfig"
aria-label="Connect"> :disabled="disabled"
<div class="header"> />
<button
class="lt"
aria-label="Toggle channel list" />
</div>
<form
class="container"
method="post"
action=""
data-event="{{#if defaults.uuid}}network:edit{{else}}network:new{{/if}}">
<div class="row">
<div class="col-sm-12">
<h1 class="title">
{{#if defaults.uuid}}
<input
type="hidden"
name="uuid"
value="{{defaults.uuid}}">
Edit {{ defaults.name }}
{{else}}
{{#if public}}The Lounge - {{/if}}
Connect
{{#unless displayNetwork}}
{{#if lockNetwork}}
to {{ defaults.name }}
{{/if}}
{{/unless}}
{{/if}}
</h1>
</div>
{{#if displayNetwork}}
<div>
<div class="col-sm-12">
<h2>Network settings</h2>
</div>
<div class="col-sm-3">
<label for="connect:name">Name</label>
</div>
<div class="col-sm-9">
<input
id="connect:name"
class="input"
name="name"
value="{{defaults.name}}"
maxlength="100">
</div>
<div class="col-sm-3">
<label for="connect:host">Server</label>
</div>
<div class="col-sm-6 col-xs-8">
<input
id="connect:host"
class="input"
name="host"
value="{{defaults.host}}"
aria-label="Server address"
maxlength="255"
required
{{#if
lockNetwork}}disabled{{
if}}>
</div>
<div class="col-sm-3 col-xs-4">
<div class="port">
<input
class="input"
type="number"
min="1"
max="65535"
name="port"
value="{{defaults.port}}"
aria-label="Server port"
{{#if
lockNetwork}}disabled{{
if}}>
</div>
</div>
<div class="clearfix" />
<div class="col-sm-9 col-sm-offset-3">
<label class="tls">
<input
type="checkbox"
name="tls"
{{#if
defaults.tls}}checked{{
if}}
{{#if
lockNetwork}}disabled{{
if}}>
Use secure connection (TLS)
</label>
</div>
<div class="col-sm-9 col-sm-offset-3">
<label class="tls">
<input
type="checkbox"
name="rejectUnauthorized"
{{#if
defaults.rejectUnauthorized}}checked{{
if}}
{{#if
lockNetwork}}disabled{{
if}}>
Only allow trusted certificates
</label>
</div>
<div class="clearfix" />
</div>
{{/if}}
<div class="col-sm-12">
<h2>User preferences</h2>
</div>
<div class="col-sm-3">
<label for="connect:nick">Nick</label>
</div>
<div class="col-sm-9">
<input
id="connect:nick"
class="input nick"
name="nick"
value="{{defaults.nick}}"
maxlength="100"
required>
</div>
{{#unless useHexIp}}
<div class="col-sm-3">
<label for="connect:username">Username</label>
</div>
<div class="col-sm-9">
<input
id="connect:username"
class="input username"
name="username"
value="{{defaults.username}}"
maxlength="512">
</div>
{{/unless}}
<div class="col-sm-3">
<label for="connect:password">Password</label>
</div>
<div class="col-sm-9 password-container">
<input
id="connect:password"
class="input"
type="password"
name="password"
value="{{defaults.password}}"
maxlength="512">
{{> ../reveal-password}}
</div>
<div class="col-sm-3">
<label for="connect:realname">Real name</label>
</div>
<div class="col-sm-9">
<input
id="connect:realname"
class="input"
name="realname"
value="{{defaults.realname}}"
maxlength="512">
</div>
{{#if defaults.uuid}}
<div class="col-sm-3">
<label for="connect:commands">Commands</label>
</div>
<div class="col-sm-9">
<textarea
id="connect:commands"
class="input"
name="commands"
placeholder="One raw command per line, each command will be executed on new connection">{{~#each defaults.commands~}}{{ ~this }}
{{/each~}}</textarea>
</div>
<div class="col-sm-9 col-sm-offset-3">
<button
type="submit"
class="btn">Save</button>
</div>
{{else}}
<div class="col-sm-3">
<label for="connect:channels">Channels</label>
</div>
<div class="col-sm-9">
<input
id="connect:channels"
class="input"
name="join"
value="{{defaults.join}}">
</div>
<div class="col-sm-9 col-sm-offset-3">
<button
type="submit"
class="btn">Connect</button>
</div>
{{/if}}
</div>
</form>
</div>
</template> </template>
<script> <script>
const storage = require("../../js/localStorage"); const $ = require("jquery");
import socket from "../../js/socket"; const socket = require("../../js/socket");
import RevealPassword from "../RevealPassword.vue";
import NetworkForm from "../NetworkForm.vue";
export default { export default {
name: "NetworkEdit", name: "NetworkEdit",
components: { components: {
RevealPassword, NetworkForm,
}, },
data() { data() {
return { return {
inFlight: false, disabled: false,
errorShown: false,
}; };
}, },
methods: { methods: {
onSubmit(event) { handleSubmit(data) {
event.preventDefault(); this.disabled = true;
socket.emit("network:edit", data);
this.inFlight = true; const sidebar = $("#sidebar");
this.errorShown = false; // TODO: move networks to vuex and update state when the network info comes in
const network = this.$root.networks.find((n) => n.uuid === data.uuid);
network.name = network.channels[0].name = data.name;
const values = { sidebar.find(`.network[data-uuid="${data.uuid}"] .chan.lobby .name`)
user: this.$refs.username.value, .click();
password: this.$refs.password.value,
};
storage.set("user", values.user);
socket.emit("auth", values);
}, },
}, },
}; };

View File

@ -302,6 +302,7 @@
<h2>Change password</h2> <h2>Change password</h2>
</div> </div>
<div class="col-sm-12 password-container"> <div class="col-sm-12 password-container">
<!-- TODO: use revealPassword -->
<label <label
for="old_password_input" for="old_password_input"
class="sr-only">Enter current password</label> class="sr-only">Enter current password</label>

View File

@ -287,7 +287,6 @@ function addFocusItem() {
function addEditNetworkItem() { function addEditNetworkItem() {
function edit(itemData) { function edit(itemData) {
socket.emit("network:get", itemData); socket.emit("network:get", itemData);
$('button[data-target="#connect"]').trigger("click");
} }
addContextMenuItem({ addContextMenuItem({

View File

@ -2,7 +2,6 @@
const $ = require("jquery"); const $ = require("jquery");
const socket = require("../socket"); const socket = require("../socket");
const templates = require("../../views");
const sidebar = $("#sidebar"); const sidebar = $("#sidebar");
const {vueApp, initChannel, findChannel} = require("../vue"); const {vueApp, initChannel, findChannel} = require("../vue");
@ -58,20 +57,7 @@ socket.on("channel:state", function(data) {
}); });
socket.on("network:info", function(data) { socket.on("network:info", function(data) {
$("#connect") vueApp.$store.commit("currentNetworkConfig", data.defaults);
.html(templates.windows.connect(data)) vueApp.$store.commit("activeWindow", "NetworkEdit");
.find("form") vueApp.activeChannel = null;
.on("submit", function() {
const uuid = $(this)
.find("input[name=uuid]")
.val();
const newName = $(this)
.find("#connect\\:name")
.val();
const network = vueApp.networks.find((n) => n.uuid === uuid);
network.name = network.channels[0].name = newName;
sidebar.find(`.network[data-uuid="${uuid}"] .chan.lobby .name`).click();
});
}); });

View File

@ -19,5 +19,8 @@ export default new Vuex.Store({
activeWindow(state, payload) { activeWindow(state, payload) {
state.activeWindow = payload; state.activeWindow = payload;
}, },
} currentNetworkConfig(state, payload) {
state.currentNetworkConfig = payload;
},
},
}); });

View File

@ -2,7 +2,6 @@
const $ = require("jquery"); const $ = require("jquery");
const escape = require("css.escape"); const escape = require("css.escape");
const viewport = $("#viewport");
const {vueApp} = require("./vue"); const {vueApp} = require("./vue");
var serverHash = -1; // eslint-disable-line no-var var serverHash = -1; // eslint-disable-line no-var