Files
sshwifty-udp-telnet-http/ui/widgets/connect_known.vue
2021-03-02 21:32:54 +08:00

353 lines
8.3 KiB
Vue

<!--
// Sshwifty - A Web SSH client
//
// Copyright (C) 2019-2021 Ni Rui <nirui@gmx.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<template>
<div id="connect-known-list" :class="{ reloaded: reloaded }">
<div
v-if="knownList.length <= 0 && presets <= 0"
id="connect-known-list-empty"
>
No known remote available
</div>
<div v-else>
<div v-if="knownList.length > 0" id="connect-known-list-list">
<h3>Connected before</h3>
<ul class="hlst lstcl1">
<li v-for="(known, kk) in knownList" :key="kk">
<div class="labels">
<span
class="type"
:style="'background-color: ' + known.data.color"
>
{{ known.data.type }}
</span>
<a
class="opt link"
href="javascript:;"
@click="launcher(known, $event)"
>
{{ known.copyStatus }}
</a>
<a
v-if="!known.data.session"
class="opt del"
href="javascript:;"
@click="remove(known.data.uid)"
>
Remove
</a>
<a
v-else
class="opt clr"
href="javascript:;"
title="Clear session data"
@click="clearSession(known.data.uid)"
>
Clear
</a>
</div>
<div class="lst-wrap" @click="select(known.data)">
<h4
:title="known.data.title"
:class="{ highlight: known.data.session }"
>
{{ known.data.title }}
</h4>
Last: {{ known.data.last.toLocaleString() }}
</div>
</li>
</ul>
</div>
<div
v-if="presets.length > 0"
id="connect-known-list-presets"
:class="{
'last-planel': knownList.length > 0,
}"
>
<h3>Presets</h3>
<ul class="hlst lstcl2">
<li
v-for="(preset, pk) in presets"
:key="pk"
:class="{ disabled: presetDisabled(preset) }"
>
<div class="lst-wrap" @click="selectPreset(preset)">
<div class="labels">
<span
class="type"
:style="'background-color: ' + preset.command.color()"
>
{{ preset.command.name() }}
</span>
</div>
<h4 :title="preset.preset.title()">
{{ preset.preset.title() }}
</h4>
</div>
</li>
</ul>
<div v-if="restrictedToPresets" id="connect-known-list-presets-alert">
The operator has restricted the outgoing connections. You can only
connect to remotes from the pre-defined presets.
</div>
</div>
</div>
<div id="connect-known-list-import">
Tip: You can
<a href="javascript:;" @click="importHosts">import</a> and
<a href="javascript:;" @click="exportHosts">export</a>
known remotes from and to a file.
</div>
</div>
</template>
<script>
import "./connect_known.css";
export default {
props: {
presets: {
type: Array,
default: () => [],
},
restrictedToPresets: {
type: Boolean,
default: () => false,
},
knowns: {
type: Array,
default: () => [],
},
launcherBuilder: {
type: Function,
default: () => [],
},
knownsExport: {
type: Function,
default: () => [],
},
knownsImport: {
type: Function,
default: () => [],
},
},
data() {
return {
knownList: [],
reloaded: false,
busy: false,
};
},
watch: {
knowns(newVal) {
// Only play reload animation when we're adding data into the records,
// not reducing
const playReloaded = newVal.length > this.knownList.length;
this.reload(newVal);
if (!playReloaded) {
return;
}
const self = this;
self.reloaded = true;
setTimeout(() => {
self.reloaded = false;
}, 500);
},
},
mounted() {
this.reload(this.knowns);
},
methods: {
reload(knownList) {
this.knownList = [];
for (let i in knownList) {
this.knownList.unshift({
data: knownList[i],
copying: false,
copyStatus: "Copy link",
});
}
},
select(known) {
if (this.busy) {
return;
}
this.$emit("select", known);
},
presetDisabled(preset) {
if (!this.restrictedToPresets || preset.preset.host().length > 0) {
return false;
}
return true;
},
selectPreset(preset) {
if (this.busy || this.presetDisabled(preset)) {
return;
}
this.$emit("select-preset", preset);
},
async launcher(known, ev) {
if (known.copying || this.busy) {
return;
}
ev.preventDefault();
this.busy = true;
known.copying = true;
known.copyStatus = "Copying";
let lnk = this.launcherBuilder(known.data);
try {
await navigator.clipboard.writeText(lnk);
(() => {
known.copyStatus = "Copied!";
})();
} catch (e) {
(() => {
known.copyStatus = "Failed";
ev.target.setAttribute("href", lnk);
})();
}
setTimeout(() => {
known.copyStatus = "Copy link";
known.copying = false;
}, 2000);
this.busy = false;
},
remove(uid) {
if (this.busy) {
return;
}
this.$emit("remove", uid);
},
clearSession(uid) {
if (this.busy) {
return;
}
this.$emit("clear-session", uid);
},
exportHosts() {
let el = null;
try {
const dataStr = JSON.stringify(this.knownsExport());
el = document.createElement("a");
el.setAttribute(
"href",
"data:text/plain;charset=utf-8," + btoa(dataStr)
);
el.setAttribute("target", "_blank");
el.setAttribute("download", "sshwifty.known-remotes.txt");
el.setAttribute(
"style",
"overflow: hidden; opacity: 0; width: 1px; height: 1px; top: -1px;" +
"left: -1px; position: absolute;"
);
document.body.appendChild(el);
el.click();
} catch (e) {
alert("Unable to export known remotes: " + e);
}
if (el === null) {
return;
}
document.body.removeChild(el);
},
importHosts() {
const self = this;
let el = null;
try {
el = document.createElement("input");
el.setAttribute("type", "file");
el.setAttribute(
"style",
"overflow: hidden; opacity: 0; width: 1px; height: 1px; top: -1px;" +
"left: -1px; position: absolute;"
);
el.addEventListener("change", (ev) => {
const t = ev.target;
if (t.files.length <= 0) {
return;
}
t.disabled = "disabled";
let r = new FileReader();
r.onload = () => {
try {
self.knownsImport(JSON.parse(atob(r.result)));
} catch (e) {
alert("Unable to import known remotes due to error: " + e);
}
};
r.readAsText(t.files[0], "utf-8");
});
document.body.appendChild(el);
el.click();
} catch (e) {
alert("Unable to load known remotes data due to error: " + e);
}
if (el === null) {
return;
}
document.body.removeChild(el);
},
},
};
</script>