Запилил просмотр пакетов в стриме, добавил создание сервисов

This commit is contained in:
saber-nyan 2019-05-04 01:08:10 +03:00
parent 26643a92e3
commit a37457a08f
No known key found for this signature in database
GPG Key ID: 7B069E9C295E6B4A
6 changed files with 173 additions and 25 deletions

View File

@ -0,0 +1,98 @@
<template>
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<form>
<div class="form-group">
<label for="inputServiceName">Имя сервиса</label>
<input type="text" class="form-control" id="inputServiceName" v-model="service.name">
</div>
<div class="form-group">
<label for="inputServicePort">Порт</label>
<input type="number" class="form-control" id="inputServicePort" v-model="service.port">
</div>
<button type="submit" @click.prevent="sendNewService()" class="btn btn-primary" style="margin-right: 10px;">
Сохранить
</button>
<button type="submit" @click.prevent="$emit('close')" class="btn btn-secondary">
Закрыть
</button>
</form>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "AddServiceModal",
data: function () {
return {
escapeKeyCallback: (e) => {
if (e.key === 'Escape') this.$emit('close');
},
service: {
name: '',
port: 0,
},
}
},
mounted() {
document.addEventListener('keyup', this.$data.escapeKeyCallback);
},
beforeDestroy() {
document.removeEventListener('keyup', this.$data.escapeKeyCallback);
},
methods: {
sendNewService() {
console.debug(`creating service name: ${this.service.name}, port: ${this.service.port}`);
const instance = axios.create({
baseURL: this.$store.state.apiUrl,
auth: {
username: this.$store.state.apiLogin,
password: this.$store.state.apiPassword,
},
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
});
instance.post('/service/', this.service)
.then(this.$emit('serviceAddDone'))
.catch(error => console.error('Failed to add service', error));
},
},
}
</script>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0 auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
transition: all .3s ease;
font-family: Helvetica, Arial, sans-serif;
}
</style>

View File

@ -1,16 +1,18 @@
<template>
<main class="col-md-9 ml-sm-auto col-lg-10 px-4">
<Packet v-for="packet in packets"
:key="packet.id"
:id="packet.id"
:content="packet.content"
:timestamp="packet.timestamp"></Packet>
<infinite-loading @infinite="infiniteHandler"></infinite-loading>
</main>
</template>
<script>
import Packet from "@/components/Packet.vue";
import InfiniteLoading from "vue-infinite-loading";
import axios from "axios";
export default {
name: 'Content',
@ -18,25 +20,60 @@ export default {
data: function () {
return {
packets: [
{
id: 39,
timestamp: 1556555231394,
content: 'wuAAUEtPbKUAAAAAoAL///jUAAACBAW0BAIIChMcPpEAAAAAAQMDBw==',
},
{
id: 40,
timestamp: 1556555231392,
content: 'AFDC4CVNkpxLT2ymoBJxIIKHAAACBAW0BAIICoTZHMUTHD6RAQMDBw==',
},
{
id: 41,
timestamp: 1556555231396,
content: '0KLQtdGB0YLQvtCy0LDRjyDRgdGC0YDQvtC60LAuLi4=',
},
// {
// id: 39,
// timestamp: 1556555231394,
// content: 'wuAAUEtPbKUAAAAAoAL///jUAAACBAW0BAIIChMcPpEAAAAAAQMDBw==',
// },
// {
// id: 40,
// timestamp: 1556555231392,
// content: 'AFDC4CVNkpxLT2ymoBJxIIKHAAACBAW0BAIICoTZHMUTHD6RAQMDBw==',
// },
// {
// id: 41,
// timestamp: 1556555231396,
// content: '0KLQtdGB0YLQvtCy0LDRjyDRgdGC0YDQvtC60LAuLi4=',
// },
],
}
},
components: {Packet,},
methods: {
infiniteHandler($state) {
if (!this.streamId) return $state.complete();
console.debug('getting next portion of packets...');
const instance = axios.create({
baseURL: this.$store.state.apiUrl,
auth: {
username: this.$store.state.apiLogin,
password: this.$store.state.apiPassword,
},
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
});
instance.post(`/packet/${this.streamId}`, {
fetchLatest: true,
direction: 'ASC',
startingFrom: this.packets.length,
pageSize: 50,
}).then(response => {
const data = response.data;
if (data.length === 0) return $state.complete();
if (data[0] && this.packets[0] && data[0].id === this.packets[0].id) {
$state.complete();
} else {
this.packets.push(...data);
$state.loaded();
}
}).catch(error => {
console.error('Failed to load new portion of packets', error);
return $state.error();
})
},
},
components: {Packet, InfiniteLoading,},
}
</script>

View File

@ -11,7 +11,7 @@
:name="service.name"></CtfService>
<li class="nav-item" style="margin-left: 10px;">
<button type="button" class="btn btn-link">
<button type="button" class="btn btn-link" @click="$emit('addServiceButtonClicked')">
<svg id="i-plus" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16"
fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">

View File

@ -6,6 +6,7 @@
v-for="stream in streams"
:key="stream.id"
:id="stream.id"
:servicePort="stream.service.port"
:time="stream.startTimestamp"></Stream>
<infinite-loading @infinite="infiniteHandler"></infinite-loading>
</ul>
@ -23,7 +24,6 @@ export default {
props: ['servicePort', 'streamId',],
data: function () {
return {
key: this.$route.path,
streams: [
// {
// id: 111,
@ -34,7 +34,7 @@ export default {
},
methods: {
infiniteHandler($state) {
console.debug('getting next portion of streams...', $state);
console.debug('getting next portion of streams...');
const instance = axios.create({
baseURL: this.$store.state.apiUrl,
auth: {
@ -52,10 +52,12 @@ export default {
startingFrom: this.streams.length,
pageSize: 50,
}).then(response => {
if (response.data[0] && this.streams[0] && response.data[0].id === this.streams[0].id) { // FIXME: проверка довольно колхозная
const data = response.data;
if (data.length === 0) return $state.complete();
if (data[0] && this.streams[0] && data[0].id === this.streams[0].id) { // FIXME: проверка довольно колхозная
$state.complete();
} else {
this.streams.push(...response.data);
this.streams.push(...data);
$state.loaded();
}
}).catch((error) => {

View File

@ -1,6 +1,6 @@
<template>
<li class="nav-item">
<router-link class="nav-link" active-class="active" :to="{ name: 'home', params: { servicePort: $route.params.servicePort, streamId: id} }">
<router-link class="nav-link" active-class="active" :to="{ name: 'home', params: { servicePort: servicePort, streamId: id} }">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
#{{id}}<br/>
{{new Date(time * 1000).toLocaleDateString('ru-RU', {month: '2-digit', day: '2-digit', hour:'2-digit', minute: '2-digit', second: '2-digit'})}}
@ -11,7 +11,7 @@
<script>
export default {
name: "Stream",
props: ['id', 'time',],
props: ['id', 'time', 'servicePort',],
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<div>
<Navbar @settingsButtonClicked="showSettingsModal = true"></Navbar>
<Navbar @settingsButtonClicked="showSettingsModal = true" @addServiceButtonClicked="showAddServiceModal = true" ref="navbar"></Navbar>
<div class="container-fluid">
<div class="row">
<Sidebar :servicePort="servicePort" :streamId="streamId"></Sidebar>
@ -11,6 +11,9 @@
<transition name="modal">
<SettingsModal v-if="showSettingsModal" @close="showSettingsModal = false"></SettingsModal>
</transition>
<transition name="modal">
<AddServiceModal v-if="showAddServiceModal" @serviceAddDone="reloadNavbar(); showAddServiceModal = false" @close="showAddServiceModal = false"></AddServiceModal>
</transition>
</div>
</template>
@ -20,16 +23,24 @@ import SettingsModal from "@/components/SettingsModal.vue";
import Navbar from "@/components/Navbar.vue";
import Sidebar from "@/components/Sidebar.vue";
import Content from "@/components/Content.vue";
import AddServiceModal from "../components/AddServiceModal";
export default {
name: 'Home',
data: function () {
return {
showSettingsModal: false,
showAddServiceModal: false,
}
},
props: ['servicePort', 'streamId',],
methods: {
reloadNavbar() {
this.$refs.navbar.getCtfServices();
},
},
components: {
AddServiceModal,
SettingsModal,
Navbar,
Sidebar,