add frontend project

This commit is contained in:
amar
2023-05-30 08:32:18 +02:00
parent 2a564bba38
commit ac3429868a
33 changed files with 12787 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
<template>
<div>
<ValidationObserver
ref="observer"
v-slot="{ handleSubmit, validated, invalid }"
>
<v-form @submit.prevent="onSubmit">
<v-row>
<v-col lg="6" md="6" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Hostname"
>
<v-text-field
v-model="host.data.device_name"
:error-messages="errors"
color="primary"
outlined
label="Hostname"
prepend-inner-icon="mdi-subtitles-outline"
></v-text-field>
</ValidationProvider>
</v-col>
<v-col lg="6" md="6" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Ip address"
>
<v-text-field
v-model="host.hostname"
:error-messages="errors"
color="primary"
outlined
label="Ip address"
prepend-inner-icon="mdi-router-network"
></v-text-field>
</ValidationProvider>
</v-col>
<v-col lg="6" md="6" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Model"
>
<v-text-field
v-model="host.data.device_model"
:error-messages="errors"
color="primary"
outlined
label="Model"
prepend-inner-icon="mdi-cog-sync-outline"
></v-text-field>
</ValidationProvider>
</v-col>
<v-col lg="6" md="6" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Type"
>
<v-select
v-model="host.data.device_type"
:items="['router', 'routeur_switch']"
outlined
:error-messages="errors"
color="primary"
label="Type"
prepend-inner-icon="mdi-devices"
></v-select>
</ValidationProvider>
</v-col>
<v-col lg="6" md="6" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Locality"
>
<v-text-field
v-model="host.data.locality"
:error-messages="errors"
color="primary"
outlined
label="Locality"
prepend-inner-icon="mdi-map-marker-radius-outline"
></v-text-field>
</ValidationProvider>
</v-col>
<v-col lg="6" md="6" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Building"
>
<v-text-field
v-model="host.data.building"
:error-messages="errors"
color="primary"
outlined
label="Building"
prepend-inner-icon="mdi-office-building-marker-outline"
></v-text-field>
</ValidationProvider>
</v-col>
<v-col lg="8" md="8" cols="12">
<ValidationProvider
v-slot="{ errors, valid }"
rules="required"
name="Room"
>
<v-text-field
v-model="host.data.room"
:error-messages="errors"
color="primary"
outlined
label="Room"
prepend-inner-icon="mdi-domain"
></v-text-field>
</ValidationProvider>
</v-col>
</v-row>
<div class="text-center">
<v-btn
:disabled="invalid"
color="primary"
class="white--text"
x-large
:loading="loading"
@click="add"
outlined
>
Add <v-icon right dark> mdi-check </v-icon>
</v-btn>
</div>
</v-form>
</ValidationObserver>
</div>
</template>
<script>
export default {
data() {
return {
loading: false,
host: {
hostname: null,
data: {
device_type: null,
device_name: null,
device_model: null,
locality: "cisco",
building: null,
room: null,
},
},
};
},
mounted() {},
methods: {
add() {
this.loading = true;
this.$store
.dispatch("inventory/post", { data: this.host })
.then((response) => {
this.loading = false;
this.$emit("onSubmit");
})
.catch((error) => {
this.loading = false;
console.log("error", error);
});
},
},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,103 @@
<template>
<UiCard title="Device informations" icon="server" :flat="false">
<template #headerActions>
<div class="text-center">
<v-btn
v-show="!loading"
@click="$emit('refresh')"
color="primary"
outlined
>
Refresh
</v-btn>
</div>
<div class="text-center" v-show="!loading">
<v-icon size="100" color="primary">mdi-remote-desktop</v-icon>
<br />
<span class="text-h5 text-center" v-if="!!item">
{{ item.hostname }}
</span>
</div>
</template>
<template #content>
<div class="text-center">
<v-progress-circular
:size="70"
:width="7"
color="primary"
indeterminate
v-show="loading"
></v-progress-circular>
</div>
<v-divider class="mb-4" v-show="!loading"></v-divider>
<v-row
justify="center"
align="center"
class="text-center"
v-if="!!item"
v-show="!loading"
>
<v-col cols="12" class="text-capitalize">
<v-icon color="primary"> mdi-webpack </v-icon>
<span class="font-weight-bold">FQDN :</span>
{{ item.fqdn }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-office-building-cog-outline </v-icon>
<span class="font-weight-bold">vendor :</span>
{{ item.vendor }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-cog-sync-outline </v-icon>
<span class="font-weight-bold">Model :</span>
{{ item.model }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-barcode </v-icon>
<span class="font-weight-bold">Serial number :</span>
<span class="text-capitalize">
{{ item.serial_number }}
</span>
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-clock-outline </v-icon>
<span class="font-weight-bold">Up time :</span>
<span class="text-capitalize">
{{ item.uptime }}
</span>
</v-col>
<v-col cols="12">
<v-icon color="primary"> mdi-code-tags </v-icon>
<span class="font-weight-bold">OS version :</span>
<span class="text-capitalize">
{{ item.os_version }}
</span>
</v-col>
</v-row>
</template>
</UiCard>
</template>
<script>
export default {
props: {
item: {
type: Object,
default: null,
},
loading: {
type: Boolean,
default: false,
},
},
data() {
return {};
},
mounted() {},
methods: {},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,94 @@
<template>
<UiCard :title="deviceName" icon="server" :flat="false" v-if="!!item">
<template #headerActions>
<div class="text-center" v-show="!loading">
<v-icon
size="100"
v-if="item.data.device_type === 'router'"
color="primary"
>mdi-router</v-icon
>
<v-icon size="100" v-else color="primary">mdi-border-outside</v-icon>
<br />
<span class="text-h5 text-center">{{ item.hostname }}</span>
</div>
</template>
<template #content>
<div class="text-center">
<v-progress-circular
:size="70"
:width="7"
color="primary"
indeterminate
v-show="loading"
></v-progress-circular>
</div>
<div v-show="!loading">
<v-divider class="mb-4"></v-divider>
<v-row justify="center" align="center" class="text-center">
<v-col cols="3" class="text-capitalize">
<v-icon color="primary"> mdi-map-marker-radius-outline </v-icon>
<span class="font-weight-bold">Location :</span>
{{ item.data.locality }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary">
mdi-office-building-marker-outline
</v-icon>
<span class="font-weight-bold">Building :</span>
{{ item.data.building }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-domain </v-icon>
<span class="font-weight-bold">Room :</span>
{{ item.data.room }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-devices </v-icon>
<span class="font-weight-bold">Type :</span>
<span v-if="item.data.device_type == 'router'">Router</span>
<span v-if="item.data.device_type == 'switch_router'">Router</span>
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-cog-sync-outline </v-icon>
<span class="font-weight-bold">Model :</span>
{{ item.data.device_model }}
</v-col>
<v-col lg="4" md="4" cols="12">
<v-icon color="primary"> mdi-cog-sync-outline </v-icon>
<span class="font-weight-bold">OS :</span>
<span class="text-capitalize">
{{ item.groups[0] }}
</span>
</v-col>
</v-row>
</div>
</template>
</UiCard>
</template>
<script>
export default {
props: {
item: {
type: Object,
default: null,
},
deviceName: {
type: String,
default: null,
},
loading: {
type: Boolean,
default: false,
},
},
data() {
return {};
},
mounted() {},
methods: {},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,135 @@
<template>
<UiCard title="Devices interfaces" icon="connection" :flat="false">
<template #headerActions>
<div class="text-center">
<v-btn
@click="$emit('refresh')"
color="primary"
outlined
v-show="!loading"
>
Refresh
</v-btn>
</div>
<div class="text-center" v-show="!loading">
<v-icon size="100" color="primary">mdi-connection</v-icon>
<br />
<span class="text-h5 text-center" v-if="!!items">
{{ deviceName }}
</span>
</div>
</template>
<template #content>
<div class="text-center">
<v-progress-circular
:size="70"
:width="7"
color="primary"
indeterminate
v-show="loading"
></v-progress-circular>
</div>
<v-divider class="mb-4" v-show="!loading"></v-divider>
<div v-if="!!items" v-show="!loading">
<v-row justify="end">
<v-col cols="4">
<v-text-field
v-if="items.length > 1"
v-model="search"
color="secondary"
append-icon="mdi-magnify"
label="search an interface..."
single-line
hide-details
></v-text-field>
</v-col>
</v-row>
<v-data-table
hide-default-footer
class="row-pointer"
:search="search"
:headers="headers"
:items="items"
:items-per-page="100"
>
<template #[`item.is_up`]="{ item }">
<v-tooltip bottom>
<template #activator="{ on, attrs }">
<v-btn
v-bind="attrs"
icon
color="error"
v-on="on"
@click="onDelete(item)"
>
<v-icon size="65" :color="item.is_up ? 'success' : 'error'">
mdi-circle-small
</v-icon>
</v-btn>
</template>
<span>
<span v-if="item.is_up">IS UP</span>
<span v-else>IS DOWN</span>
</span>
</v-tooltip>
</template>
</v-data-table>
</div>
</template>
</UiCard>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: null,
},
loading: {
type: Boolean,
default: false,
},
deviceName: {
type: String,
default: false,
},
},
data() {
return {
search: "",
headers: [
{
text: "Name",
value: "name",
align: "center",
},
{
text: "Description",
value: "description",
align: "center",
},
{
text: "Admin status",
value: "is_enabled",
align: "center",
},
{
text: "Status",
value: "is_up",
align: "center",
},
{
text: "Mac address",
value: "mac_addresss",
align: "center",
},
],
};
},
mounted() {},
methods: {},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,104 @@
<template>
<UiCard title="Configured interfaces" icon="connection" :flat="false">
<template #headerActions>
<div class="text-center">
<v-btn
@click="$emit('refresh')"
color="primary"
outlined
v-show="!loading"
>
Refresh
</v-btn>
</div>
<div class="text-center" v-show="!loading">
<v-icon size="100" color="primary">mdi-connection</v-icon>
<br />
<span class="text-h5 text-center" v-if="!!items">
{{ deviceName }}
</span>
</div>
</template>
<template #content>
<div class="text-center">
<v-progress-circular
:size="70"
:width="7"
color="primary"
indeterminate
v-show="loading"
></v-progress-circular>
</div>
<v-divider class="mb-4" v-show="!loading"></v-divider>
<div v-if="!!items" v-show="!loading">
<v-row justify="end">
<v-col cols="4">
<v-text-field
v-if="items.length > 1"
v-model="search"
color="secondary"
append-icon="mdi-magnify"
label="search an interface..."
single-line
hide-details
></v-text-field>
</v-col>
</v-row>
<v-data-table
hide-default-footer
class="row-pointer"
:search="search"
:headers="headers"
:items="items"
:items-per-page="100"
>
</v-data-table>
</div>
</template>
</UiCard>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: null,
},
loading: {
type: Boolean,
default: false,
},
deviceName: {
type: String,
default: false,
},
},
data() {
return {
search:"",
headers: [
{
text: "Name",
value: "name",
align: "center",
},
{
text: "Ip address",
value: "ip",
align: "center",
},
{
text: "Prefix length",
value: "prefix_length",
align: "center",
},
],
};
},
mounted() {},
methods: {},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,132 @@
<template>
<UiCard
title="Devices snapshots"
icon="content-save-cog-outline"
:flat="false"
>
<template #headerActions>
<div class="text-center">
<v-btn
@click="$emit('createSnapshot')"
color="primary"
outlined
v-show="!loading"
>
Make a snapshot
</v-btn>
<v-btn
@click="$emit('refresh')"
color="primary"
outlined
v-show="!loading"
>
Refresh
</v-btn>
</div>
<div class="text-center" v-show="!loading">
<v-icon size="100" color="primary">mdi-content-save-cog-outline</v-icon>
<br />
<span class="text-h5 text-center" v-if="!!items">
{{ deviceName }}
</span>
</div>
</template>
<template #content>
<div class="text-center">
<v-progress-circular
:size="70"
:width="7"
color="primary"
indeterminate
v-show="loading"
></v-progress-circular>
</div>
<v-divider class="mb-4" v-show="!loading"></v-divider>
<div v-if="!!items" v-show="!loading">
<v-row justify="end">
<v-col cols="4">
<v-text-field
v-if="items.length > 1"
v-model="search"
color="secondary"
append-icon="mdi-magnify"
label="search a snapshot..."
single-line
hide-details
></v-text-field>
</v-col>
</v-row>
<v-data-table
hide-default-footer
class="row-pointer"
:search="search"
:headers="headers"
:items="items"
:items-per-page="100"
>
<template #[`item.actions`]="{ item }">
<v-tooltip bottom>
<template #activator="{ on, attrs }">
<v-btn v-bind="attrs" icon v-on="on" link :href="'http://192.168.1.36:5000/snapshots/'+item.file">
<v-icon> mdi-cloud-download-outline </v-icon>
</v-btn>
</template>
<span> Download </span>
</v-tooltip>
</template>
</v-data-table>
</div>
</template>
</UiCard>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: null,
},
loading: {
type: Boolean,
default: false,
},
deviceName: {
type: String,
default: false,
},
},
data() {
return {
search: "",
headers: [
{
text: "Name",
value: "file",
align: "center",
},
{
text: "Path",
value: "path",
align: "center",
},
{
text: "At",
value: "at",
align: "center",
},
{
text: "Actions",
value: "actions",
align: "center",
},
],
};
},
mounted() {},
methods: {},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,152 @@
<template>
<div>
<v-row justify="center">
<v-col lg="6" md="12" cols="12">
<UiCard title="Show commands SHELL" icon="console" :flat="false">
<template #content>
<v-textarea
outlined
name="input-7-4"
label="Show commands"
v-model="showCommands"
></v-textarea>
<div class="text-center">
<v-btn
outlined
color="primary"
@click="sendShowCommands"
:loading="loadingShowCommands"
>
Send <v-icon>mdi-arrange-send-to-back</v-icon>
</v-btn>
</div>
</template>
</UiCard>
</v-col>
<v-col lg="6" md="12" cols="12">
<UiCard title="Config commands SHELL" icon="console" :flat="false">
<template #content>
<v-textarea
outlined
name="input-7-4"
label="Config commands"
v-model="configCommands"
></v-textarea>
<div class="text-center">
<v-btn
outlined
color="primary"
@click="sendConfigCommands"
:loading="loadingConfigCommands"
>
Send <v-icon>mdi-arrange-send-to-back</v-icon>
</v-btn>
<v-alert
dense
text
type="success"
class="my-5"
v-if="!!configResult && !configError"
>
Configuration deployed!
</v-alert>
<v-alert dense outlined type="error" class="my-5" v-if="configError">
Error config could not be deployed...
</v-alert>
</div>
</template>
</UiCard>
</v-col>
<v-col cols="12">
<div v-if="!!result" class="text-center">
<v-textarea
:value="result"
height="280"
outlined
color="primary"
label="Output"
></v-textarea>
</div>
</v-col>
</v-row>
</div>
</template>
<script>
export default {
data() {
return {
loadingShowCommands: false,
selectedDeviceName: null,
showCommands: null,
configCommands: null,
loadingConfigCommands: null,
result: null,
configResult: null,
configError:false,
};
},
mounted() {
//this.getDevices();
this.selectedDeviceName = this.$route.params.name;
},
methods: {
getDeviceByName() {
this.loading = true;
this.$store
.dispatch("inventory/getByName", { name: this.$route.params.name })
.then((response) => {
this.loading = false;
this.device = response.data.device;
})
.catch((error) => {
this.loading = false;
console.log("error", error);
});
},
sendShowCommands() {
const data = { mode: "enable", commands: this.showCommands.split("\n") };
this.loadingShowCommands = true;
this.$store
.dispatch("inventory/config", {
name: this.$route.params.name,
data: data,
})
.then((response) => {
this.loadingShowCommands = false;
this.result = response.data.result
.map((item) => {
return item.result;
})
.join("\n\n\n");
})
.catch((error) => {
this.loadingShowCommands = false;
console.log("error", error);
});
},
sendConfigCommands() {
const data = {
mode: "config",
commands: this.configCommands.split("\n"),
};
this.loadingConfigCommands = true;
this.configError = false
this.$store
.dispatch("inventory/config", {
name: this.$route.params.name,
data: data,
})
.then((response) => {
this.loadingConfigCommands = false;
this.configResult = response.data.result;
})
.catch((error) => {
this.configError = true
this.loadingConfigCommands = false;
console.log("error", error);
});
},
},
};
</script>

View File

@@ -0,0 +1,131 @@
<template>
<div>
<v-row justify="end">
<v-col cols="3">
<v-text-field
v-if="items.length > 1"
v-model="search"
color="secondary"
append-icon="mdi-magnify"
label="search a device..."
single-line
hide-details
></v-text-field>
</v-col>
</v-row>
<v-data-table
hide-default-footer
class="row-pointer"
:search="search"
:headers="headers"
:items="items"
:items-per-page="100"
>
<template #[`item.data`]="{ item }">
<span class="text-capitalize">
{{ item.data.locality }} - {{ item.data.building }}
</span>
</template>
<template #[`item.data.device_type`]="{ item }">
<span v-if="item.data.device_type == 'router_switch'">
Ethernet switch router - {{ item.data.device_model }}
</span>
<span v-if="item.data.device_type == 'router'">
Router - {{ item.data.device_model }}
</span>
</template>
<template #[`item.actions`]="{ item }">
<v-tooltip bottom>
<template #activator="{ on, attrs }">
<v-btn
v-bind="attrs"
icon
color="secondary"
v-on="on"
@click="onView(item)"
>
<v-icon> mdi-magnify </v-icon>
</v-btn>
</template>
<span> Detail </span>
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ on, attrs }">
<v-btn
v-bind="attrs"
icon
color="error"
v-on="on"
@click="onDelete(item)"
>
<v-icon> mdi-delete-circle-outline </v-icon>
</v-btn>
</template>
<span> Delete this device </span>
</v-tooltip>
</template>
<template #no-data> No data .... </template>
<template #no-results> No data ....</template>
</v-data-table>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: null,
},
},
data() {
return {
search: "",
headers: [
{
text: "Hostname",
value: "name",
align: "center",
},
{
text: "Ip address",
value: "hostname",
align: "center",
},
{
text: "Type",
value: "data.device_type",
align: "center",
},
{
text: "Location",
value: "data",
align: "center",
},
{
text: "Actions",
value: "actions",
align: "center",
},
],
};
},
mounted() {},
methods: {
onView(item) {
this.$emit("onAction", { item, action: "show" });
},
onDelete(item) {
this.$emit("onAction", { item, action: "delete" });
},
},
};
</script>
<style scoped>
.row-pointer >>> tbody tr :hover {
cursor: pointer;
}
</style>