mirror of
https://github.com/Av0idD4rk/packmate.git
synced 2026-10-25 11:49:24 +00:00
Переписал логику добавления/изменения сервиса
This commit is contained in:
parent
eda33b665e
commit
99a46109a3
@ -7,10 +7,16 @@
|
|||||||
<li class="nav-item text-nowrap">
|
<li class="nav-item text-nowrap">
|
||||||
<router-link class="nav-link" to="/" exact>All</router-link>
|
<router-link class="nav-link" to="/" exact>All</router-link>
|
||||||
</li>
|
</li>
|
||||||
<NavbarService v-for="service in services"
|
<template v-for="service in services">
|
||||||
:key="service.name"
|
<router-link :key="service.name" tag="li" class="nav-item text-nowrap edit-button"
|
||||||
:name="service.name"
|
:to="{name:'stream', params: {servicePort: service.port}, query: this.$route.query}">
|
||||||
:port="service.port"/>
|
<a class="nav-link">{{service.name}} #{{service.port}}</a>
|
||||||
|
|
||||||
|
<a class="nav-link" style="cursor: pointer" @click.stop.prevent="editService(service)">
|
||||||
|
<i class="fas fa-pencil-alt"/>
|
||||||
|
</a>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
<li class="nav-item text-nowrap" style="padding-left: 1em;">
|
<li class="nav-item text-nowrap" style="padding-left: 1em;">
|
||||||
<div class="my-2 mr-3 navbar-cogs" style="cursor: pointer;"
|
<div class="my-2 mr-3 navbar-cogs" style="cursor: pointer;"
|
||||||
@click.stop.prevent="showAddService">
|
@click.stop.prevent="showAddService">
|
||||||
@ -24,30 +30,45 @@
|
|||||||
<i class="fas fa-cogs"/>
|
<i class="fas fa-cogs"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ServiceModal :creating="serviceModalIsCreating" :initial-service="serviceModalEditingService"
|
||||||
|
@service-update-needed="updateServices"/>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NavbarService from './NavbarService';
|
|
||||||
import PatternsDropdown from './PatternsDropdown';
|
import PatternsDropdown from './PatternsDropdown';
|
||||||
|
import ServiceModal from '../views/ServiceModal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Navbar',
|
name: 'Navbar',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
services: Array(),
|
services: Array(),
|
||||||
|
|
||||||
|
serviceModalIsCreating: true,
|
||||||
|
serviceModalEditingService: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.updateServices();
|
this.updateServices();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
editService(service) {
|
||||||
|
this.serviceModalIsCreating = false;
|
||||||
|
this.serviceModalEditingService = {};
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.serviceModalEditingService = service;
|
||||||
|
this.$bvModal.show('serviceModal');
|
||||||
|
});
|
||||||
|
},
|
||||||
showSettings() {
|
showSettings() {
|
||||||
this.$bvModal.show('settingsModal');
|
this.$bvModal.show('settingsModal');
|
||||||
console.debug('Showing settings...');
|
console.debug('Showing settings...');
|
||||||
},
|
},
|
||||||
showAddService() {
|
showAddService() {
|
||||||
this.$bvModal.show('addServiceModal');
|
this.serviceModalIsCreating = true;
|
||||||
|
this.serviceModalEditingService = {};
|
||||||
|
this.$bvModal.show('serviceModal');
|
||||||
console.debug('Showing addService...');
|
console.debug('Showing addService...');
|
||||||
},
|
},
|
||||||
updateServices() {
|
updateServices() {
|
||||||
@ -74,8 +95,8 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
ServiceModal,
|
||||||
PatternsDropdown,
|
PatternsDropdown,
|
||||||
NavbarService,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -85,6 +106,10 @@
|
|||||||
transition: all .3s;
|
transition: all .3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-button {
|
||||||
|
display: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.navbar-cogs > i {
|
.navbar-cogs > i {
|
||||||
transition: all .3s;
|
transition: all .3s;
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
<template>
|
|
||||||
<router-link tag="li" class="nav-item text-nowrap edit-button"
|
|
||||||
:to="{name:'stream', params: {servicePort: port}, query: this.$route.query}">
|
|
||||||
<a class="nav-link">{{name}} #{{port}}</a>
|
|
||||||
|
|
||||||
<a class="nav-link" style="cursor: pointer" @click.stop.prevent="editService">
|
|
||||||
<i class="fas fa-pencil-alt"/>
|
|
||||||
</a>
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'NavbarService',
|
|
||||||
props: {
|
|
||||||
name: String(),
|
|
||||||
port: Number(),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
editService() {
|
|
||||||
// Костыль: нельзя запустить BModal с аргументом
|
|
||||||
this.$store.commit('setServiceModalId', this.port);
|
|
||||||
this.$store.commit('setServiceModalName', this.name);
|
|
||||||
this.$bvModal.show('editServiceModal');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.nav-link {
|
|
||||||
transition: all .3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-button {
|
|
||||||
display: inherit;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
118
src/objectAssignDeep.js
Normal file
118
src/objectAssignDeep.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// https://github.com/saikojosh/Object-Assign-Deep/blob/master/objectAssignDeep.js
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A unified way of returning a string that describes the type of the given variable.
|
||||||
|
*/
|
||||||
|
function getTypeOf(input) {
|
||||||
|
|
||||||
|
if (input === null) {
|
||||||
|
return 'null';
|
||||||
|
} else if (typeof input === 'undefined') {
|
||||||
|
return 'undefined';
|
||||||
|
} else if (typeof input === 'object') {
|
||||||
|
return (Array.isArray(input) ? 'array' : 'object');
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof input;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Branching logic which calls the correct function to clone the given value base on its type.
|
||||||
|
*/
|
||||||
|
function cloneValue(value) {
|
||||||
|
|
||||||
|
// The value is an object so let's clone it.
|
||||||
|
if (getTypeOf(value) === 'object') {
|
||||||
|
return quickCloneObject(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The value is an array so let's clone it.
|
||||||
|
else if (getTypeOf(value) === 'array') {
|
||||||
|
return quickCloneArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any other value can just be copied.
|
||||||
|
return value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerates the given array and returns a new array, with each of its values cloned (i.e. references broken).
|
||||||
|
*/
|
||||||
|
function quickCloneArray(input) {
|
||||||
|
return input.map(cloneValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerates the properties of the given object (ignoring the prototype chain) and returns a new object, with each of
|
||||||
|
* its values cloned (i.e. references broken).
|
||||||
|
*/
|
||||||
|
function quickCloneObject(input) {
|
||||||
|
|
||||||
|
const output = {};
|
||||||
|
|
||||||
|
for (const key in input) {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(input, key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output[key] = cloneValue(input[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does the actual deep merging.
|
||||||
|
*/
|
||||||
|
function executeDeepMerge(target, _objects = [], _options = {}) {
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
arrayBehaviour: _options.arrayBehaviour || 'replace', // Can be "merge" or "replace".
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure we have actual objects for each.
|
||||||
|
const objects = _objects.map(object => object || {});
|
||||||
|
const output = target || {};
|
||||||
|
|
||||||
|
// Enumerate the objects and their keys.
|
||||||
|
for (let oindex = 0; oindex < objects.length; oindex++) {
|
||||||
|
const object = objects[oindex];
|
||||||
|
const keys = Object.keys(object);
|
||||||
|
|
||||||
|
for (let kindex = 0; kindex < keys.length; kindex++) {
|
||||||
|
const key = keys[kindex];
|
||||||
|
const value = object[key];
|
||||||
|
const type = getTypeOf(value);
|
||||||
|
const existingValueType = getTypeOf(output[key]);
|
||||||
|
|
||||||
|
if (type === 'object') {
|
||||||
|
if (existingValueType !== 'undefined') {
|
||||||
|
const existingValue = (existingValueType === 'object' ? output[key] : {});
|
||||||
|
output[key] = executeDeepMerge({}, [existingValue, quickCloneObject(value),], options);
|
||||||
|
} else {
|
||||||
|
output[key] = quickCloneObject(value);
|
||||||
|
}
|
||||||
|
} else if (type === 'array') {
|
||||||
|
if (existingValueType === 'array') {
|
||||||
|
const newValue = quickCloneArray(value);
|
||||||
|
output[key] = (options.arrayBehaviour === 'merge' ? output[key].concat(newValue) : newValue);
|
||||||
|
} else {
|
||||||
|
output[key] = quickCloneArray(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function objectAssignDeep(target, ...objects) {
|
||||||
|
return executeDeepMerge(target, objects);
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<b-modal @ok="addPattern" @cancel="reset" id="addPatternModal"
|
<b-modal @ok="addPattern" @cancel="reset" id="addPatternModal"
|
||||||
title="Add pattern"
|
title="Creating pattern"
|
||||||
cancel-title="Cancel"
|
cancel-title="Cancel"
|
||||||
centered scrollable>
|
centered scrollable>
|
||||||
<form ref="addPatternForm">
|
<form ref="addPatternForm">
|
||||||
|
|||||||
95
src/views/ServiceModal.vue
Normal file
95
src/views/ServiceModal.vue
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<template>
|
||||||
|
<b-modal id="serviceModal" size="lg"
|
||||||
|
:title="creating ? 'Creating service' : 'Editing service'"
|
||||||
|
centered scrollable @ok.prevent="submit">
|
||||||
|
<b-form ref="serviceForm">
|
||||||
|
<b-form-group label-cols-sm="4"
|
||||||
|
label="Name"
|
||||||
|
label-for="service-name">
|
||||||
|
<b-form-input id="service-name" required v-model="service.name"
|
||||||
|
@keyup.enter.stop.prevent="submit"/>
|
||||||
|
</b-form-group>
|
||||||
|
<b-form-group v-if="creating"
|
||||||
|
label-cols-sm="4"
|
||||||
|
label="Port"
|
||||||
|
label-for="service-port">
|
||||||
|
<b-form-input id="service-port" required
|
||||||
|
type="number" min="1" max="65535" v-model.number="service.port"
|
||||||
|
@keyup.enter.stop.prevent="submit"/>
|
||||||
|
</b-form-group>
|
||||||
|
<b-form-group label-cols-sm="4"
|
||||||
|
label="Decompress GZIP?"
|
||||||
|
label-for="service-ungzip">
|
||||||
|
<b-form-checkbox id="service-ungzip" required
|
||||||
|
v-model="service.ungzipHttp"/>
|
||||||
|
</b-form-group>
|
||||||
|
<b-form-group label-cols-sm="4"
|
||||||
|
label="Apply urldecode?"
|
||||||
|
label-for="service-urldecode">
|
||||||
|
<b-form-checkbox id="service-urldecode" required
|
||||||
|
v-model="service.urldecodeHttpRequests"/>
|
||||||
|
</b-form-group>
|
||||||
|
<b-form-group label-cols-sm="4"
|
||||||
|
label="Merge adjacent packets??"
|
||||||
|
label-for="service-mergeAdjacent">
|
||||||
|
<b-form-checkbox id="service-mergeAdjacent" required
|
||||||
|
v-model="service.mergeAdjacentPackets"/>
|
||||||
|
</b-form-group>
|
||||||
|
</b-form>
|
||||||
|
</b-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {objectAssignDeep,} from '../objectAssignDeep';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ServiceModal',
|
||||||
|
props: {
|
||||||
|
creating: Boolean,
|
||||||
|
|
||||||
|
initialService: {
|
||||||
|
name: String,
|
||||||
|
port: Number,
|
||||||
|
ungzipHttp: Boolean,
|
||||||
|
urldecodeHttpRequests: Boolean,
|
||||||
|
mergeAdjacentPackets: Boolean,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
service: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
initialService() {
|
||||||
|
console.debug('initialService changed, reassigning...', this.initialService);
|
||||||
|
this.service = objectAssignDeep({}, this.initialService);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit() {
|
||||||
|
if (!this.$refs.taskForm.reportValidity()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.debug('Submitting service...', this.service, this.creating);
|
||||||
|
this.$http.post('service/', this.service)
|
||||||
|
.then(response => {
|
||||||
|
console.info('Done editing/creating service', response.data);
|
||||||
|
this.$emit('service-update-needed');
|
||||||
|
this.$bvModal.hide('serviceModal');
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.$bvToast.toast(`Failed to ${this.creating ? 'create' : 'edit'} service: ${e}`, {
|
||||||
|
title: 'Error',
|
||||||
|
variant: 'danger',
|
||||||
|
});
|
||||||
|
console.error('Failed to edit/create service', e);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user