summaryrefslogtreecommitdiffstats
path: root/webapp/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/src/components')
-rw-r--r--webapp/src/components/GroupModule.vue13
-rw-r--r--webapp/src/components/GroupModuleClientView.vue32
-rw-r--r--webapp/src/components/GroupModuleGroupView.vue103
3 files changed, 117 insertions, 31 deletions
diff --git a/webapp/src/components/GroupModule.vue b/webapp/src/components/GroupModule.vue
index cd487b0..a02fccf 100644
--- a/webapp/src/components/GroupModule.vue
+++ b/webapp/src/components/GroupModule.vue
@@ -11,8 +11,8 @@
<v-container fill-height>
<v-layout>
<v-flex class="tabs-wrapper" xl10 offset-xl1 lg12>
- <v-card class="tabbar-card">
- <v-tabs :value="activeTab" @change="setActiveTab" :dark="tabsDark" :color="tabsColor" :slider-color="tabsSliderColor">
+ <v-card class="tabbar-card" style="display: flex; justify-content: space-between">
+ <v-tabs :value="activeTab" @change="setActiveTab" :dark="tabsDark" :color="tabsColor" :slider-color="tabsSliderColor" style="overflow-x: hidden">
<template v-for="(item, index) in tabChain">
<v-icon v-if="item.id > 0 || item.id === 'create'" :key="'arrow' + index">keyboard_arrow_right</v-icon>
<v-tab ripple :key="'tab' + index">
@@ -22,6 +22,7 @@
</v-tab>
</template>
</v-tabs>
+ <v-btn icon :loading="reloading" @click="reload"><v-icon>refresh</v-icon></v-btn>
</v-card>
<v-tabs-items :value="activeTab" @input="setActiveTab" touchless style="padding-bottom: 20px">
<v-tab-item v-for="(item, index) in tabChain" :key="index">
@@ -39,7 +40,7 @@
import GroupModuleGroupView from '@/components/GroupModuleGroupView'
import GroupModuleClientView from '@/components/GroupModuleClientView'
import GroupModuleDialog from '@/components/GroupModuleDialog'
-import { mapState, mapGetters, mapMutations } from 'vuex'
+import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
name: 'GroupModule',
@@ -60,7 +61,10 @@ export default {
},
computed: {
...mapGetters(['tabsDark', 'tabsColor', 'tabsSliderColor']),
- ...mapState('groups', ['tabChain', 'activeTab', 'groupList', 'clientList'])
+ ...mapState('groups', ['tabChain', 'activeTab', 'groupList', 'clientList']),
+ reloading () {
+ return this.tabChain.some(tab => tab.loading)
+ }
},
watch: {
activeTab (index) {
@@ -75,6 +79,7 @@ export default {
},
methods: {
...mapMutations('groups', ['setActiveTab', 'setTab']),
+ ...mapActions('groups', ['reload']),
loadItem (routeName, id) {
const type = routeName.replace('GroupModule.', '')
if (id === 'create') {
diff --git a/webapp/src/components/GroupModuleClientView.vue b/webapp/src/components/GroupModuleClientView.vue
index bc7ea10..b78b2ed 100644
--- a/webapp/src/components/GroupModuleClientView.vue
+++ b/webapp/src/components/GroupModuleClientView.vue
@@ -27,7 +27,7 @@
<v-card>
<v-card-text>
<v-layout wrap>
- <v-flex lg4 md6 xs12 order-lg1 order-xs2>
+ <v-flex lg4 sm6 xs12 order-lg1 order-xs2>
<v-layout column>
<v-flex>
<v-text-field v-if="editMode" prepend-icon="label" class="info-input" :label="$t('name')" color="primary" v-model="info.name"></v-text-field>
@@ -42,13 +42,14 @@
v-if="editMode"
class="info-input"
:items="$store.state.groups.groupList"
- v-model="groupIds"
+ v-model="groups"
:menu-props="{ offsetY: '' }"
:label="$t('groups')"
color="primary"
multiple
item-value="id"
item-text="name"
+ return-object
small-chips
deletable-chips
>
@@ -74,7 +75,7 @@
</v-flex>
</v-layout>
</v-flex>
- <v-flex lg4 md6 xs12 order-lg2 order-xs3>
+ <v-flex lg4 sm6 xs12 order-lg2 order-xs3>
<v-textarea prepend-icon="description" v-if="editMode" rows="1" auto-grow class="info-input" :label="$t('description')" color="primary" v-model="info.description"></v-textarea>
<div v-else class="info-input">
<div class="body-2 info-heading"><v-icon>description</v-icon><span>{{ $t('description') }}</span></div>
@@ -96,21 +97,21 @@
</v-flex>
</v-layout>
<v-layout wrap>
- <v-flex lg4 md6 xs12>
+ <v-flex lg4 sm6 xs12>
<v-text-field prepend-icon="language" v-if="editMode" class="info-input" :label="$t('ip')" color="primary" v-model="info.ip"></v-text-field>
<div v-else class="info-input">
<div class="body-2 info-heading"><v-icon>language</v-icon><span>{{ $t('ip') }}</span></div>
<div class="info-text">{{ client.ip || '-' }}</div>
</div>
</v-flex>
- <v-flex lg4 md6 xs12>
+ <v-flex lg4 sm6 xs12>
<v-text-field prepend-icon="memory" v-if="editMode" class="info-input" :label="$t('mac')" color="primary" v-model="info.mac"></v-text-field>
<div v-else class="info-input">
<div class="body-2 info-heading"><v-icon>memory</v-icon><span>{{ $t('mac') }}</span></div>
<div class="info-text">{{ client.mac || '-' }}</div>
</div>
</v-flex>
- <v-flex lg4 md6 xs12>
+ <v-flex lg4 sm6 xs12>
<v-text-field prepend-icon="fingerprint" v-if="editMode" class="info-input" :label="$t('uuid')" color="primary" v-model="info.uuid"></v-text-field>
<div v-else class="info-input">
<div class="body-2 info-heading"><v-icon>fingerprint</v-icon><span>{{ $t('uuid') }}</span></div>
@@ -138,7 +139,7 @@ export default {
mac: '',
uuid: ''
},
- groupIds: []
+ groups: []
}
},
computed: {
@@ -156,9 +157,6 @@ export default {
}
},
methods: {
- removeGroup (id) {
- this.groupIds.splice(this.groupIds.indexOf(id), 1)
- },
editInfo () {
this.editMode = true
this.info.name = this.client.name
@@ -167,7 +165,7 @@ export default {
this.info.ip = this.client.ip
this.info.mac = this.client.mac
this.info.uuid = this.client.uuid
- this.groupIds = this.client.groups ? this.client.groups.map(x => x.id) : []
+ this.groups = this.client.groups || []
},
cancelEdit () {
this.editMode = false
@@ -181,7 +179,7 @@ export default {
this.$store.dispatch('groups/saveClient', {
id: this.client.id,
data: this.info,
- groupIds: this.groupIds,
+ groups: this.groups,
tabIndex: this.tabIndex,
callback: this.updateUrl
})
@@ -205,17 +203,25 @@ export default {
.info-buttons {
margin: 0;
}
+
.info-input {
- margin: 20px;
+ padding: 20px;
+}
+
+.info-input >>> input, .info-input >>> textarea {
+ font-family: 'Roboto Mono';
}
+
.info-heading {
display: flex;
align-items: center;
margin-bottom: 10px;
}
+
.info-heading > span {
margin-left: 10px;
}
+
.info-text {
margin-left: 34px;
font-family: 'Roboto Mono';
diff --git a/webapp/src/components/GroupModuleGroupView.vue b/webapp/src/components/GroupModuleGroupView.vue
index 7418928..5403b61 100644
--- a/webapp/src/components/GroupModuleGroupView.vue
+++ b/webapp/src/components/GroupModuleGroupView.vue
@@ -8,8 +8,11 @@
"clients": "Clients",
"name": "Name",
"description": "Description",
+ "ipranges": "IP Ranges",
"config": "iPXE Config",
- "parents": "Parents"
+ "parents": "Parents",
+ "startIp": "Start IP",
+ "endIp": "End IP"
},
"de": {
"info": "Info",
@@ -19,8 +22,11 @@
"clients": "Clienten",
"name": "Name",
"description": "Beschreibung",
+ "ipranges": "IP Bereiche",
"config": "iPXE Konfiguration",
- "parents": "Übergruppen"
+ "parents": "Übergruppen",
+ "startIp": "Start IP",
+ "endIp": "End IP"
}
}
</i18n>
@@ -31,7 +37,7 @@
<v-card v-if="group.id !== 0">
<v-card-text>
<v-layout wrap>
- <v-flex lg4 md6 xs12 order-lg1 order-xs2>
+ <v-flex lg4 sm6 xs12 order-lg1 order-xs2>
<v-layout column>
<v-flex>
<v-text-field prepend-icon="label" v-if="editMode" class="info-input" :label="$t('name')" color="primary" v-model="info.name"></v-text-field>
@@ -46,13 +52,14 @@
v-if="editMode"
class="info-input"
:items="$store.state.groups.groupList"
- v-model="parentIds"
+ v-model="parents"
:menu-props="{ offsetY: '' }"
:label="$t('parents')"
color="primary"
multiple
item-value="id"
item-text="name"
+ return-object
small-chips
deletable-chips
>
@@ -78,11 +85,39 @@
</v-flex>
</v-layout>
</v-flex>
- <v-flex lg4 md6 xs12 order-lg2 order-xs3>
+ <v-flex lg4 sm6 xs12 order-lg2 order-xs3>
<v-textarea prepend-icon="description" v-if="editMode" rows="1" auto-grow class="info-input" :label="$t('description')" color="primary" v-model="info.description"></v-textarea>
<div v-else class="info-input">
<div class="body-2 info-heading"><v-icon>description</v-icon><span>{{ $t('description') }}</span></div>
- <div class="info-text">{{ group.description || '-' }}</div>
+ <pre class="info-text">{{ group.description || '-' }}</pre>
+ </div>
+
+ <div v-if="editMode" class="info-input">
+ <div class="body-2 info-heading">
+ <v-icon>settings_ethernet</v-icon><span>{{ $t('ipranges') }}</span>
+ <v-btn small icon @click="addIprange"><v-icon>add</v-icon></v-btn>
+ </div>
+ <div>
+ <div v-for="(iprange, index) in ipranges" class="iprange" :key="index">
+ <v-btn small icon class="remove-iprange" @click="removeIprange(index)"><v-icon>remove</v-icon></v-btn>
+ <v-text-field :label="$t('startIp')" color="primary" v-model="iprange.startIp"></v-text-field>
+ <span>-</span>
+ <v-text-field :label="$t('endIp')" color="primary" v-model="iprange.endIp"></v-text-field>
+ </div>
+ </div>
+ </div>
+ <div v-else class="info-input">
+ <div class="body-2 info-heading"><v-icon>settings_ethernet</v-icon><span>{{ $t('ipranges') }}</span></div>
+ <div class="info-text ipranges-nonedit">
+ <table>
+ <tr v-for="(iprange, index) in group.ipranges" :key="index">
+ <td class="text-xs-right">{{ iprange.startIp }}</td>
+ <td class="ip-seperator">-</td>
+ <td>{{ iprange.endIp }}</td>
+ </tr>
+ </table>
+ <div v-if="group.ipranges.length === 0">-</div>
+ </div>
</div>
</v-flex>
<v-flex lg4 xs12 order-lg3 order-xs1 class="text-xs-right">
@@ -114,9 +149,9 @@
></v-switch></div>
</v-layout>
<v-subheader>{{ group.id > 0 ? $t('subgroups') : $t('groups') }}</v-subheader>
- <group-module-group-list :tabIndex="tabIndex" :groupId="group.id" :groups="group.subgroups" />
+ <group-module-group-list :tabIndex="tabIndex" :groupId="group.id" :groups="group.subgroups || []" />
<v-subheader>{{ $t('clients') }}</v-subheader>
- <group-module-client-list :tabIndex="tabIndex" :groupId="group.id" :clients="group.clients" />
+ <group-module-client-list :tabIndex="tabIndex" :groupId="group.id" :clients="group.clients || []" />
</template>
</div>
</template>
@@ -140,7 +175,8 @@ export default {
description: '',
configId: null
},
- parentIds: []
+ parents: [],
+ ipranges: [{ startIp: '', endIp: '' }]
}
},
computed: {
@@ -162,15 +198,19 @@ export default {
this.$store.commit('groups/setShowAll', { index: this.tabIndex, value })
this.$store.dispatch('groups/loadGroup', { id: this.group.id, tabIndex: this.tabIndex, reload: true })
},
- removeParent (id) {
- this.parentIds.splice(this.parentIds.indexOf(id), 1)
+ removeIprange (index) {
+ this.ipranges.splice(index, 1)
+ },
+ addIprange () {
+ this.ipranges.push({ startIp: '', endIp: '' })
},
editInfo () {
this.editMode = true
this.info.name = this.group.name
this.info.description = this.group.description
this.info.configId = this.group.configId
- this.parentIds = this.group.parents ? this.group.parents.map(x => x.id) : []
+ this.parents = this.group.parents.slice(0) || []
+ this.ipranges = this.group.ipranges.slice(0) || [{ startIp: '', endIp: '' }]
},
cancelEdit () {
this.editMode = false
@@ -184,7 +224,8 @@ export default {
this.$store.dispatch('groups/saveGroup', {
id: this.group.id,
data: this.info,
- parentIds: this.parentIds,
+ parents: this.parents,
+ ipranges: this.ipranges,
tabIndex: this.tabIndex,
callback: this.updateUrl
})
@@ -208,21 +249,55 @@ export default {
.info-buttons {
margin: 0;
}
+
+.iprange {
+ display: flex;
+ align-items: center;
+}
+
+.ipranges-nonedit {
+ overflow-x: auto;
+}
+
+.ipranges-nonedit .ip-seperator {
+ padding: 0 10px;
+}
+
+.iprange > .remove-iprange {
+ margin: 0 8px 0 -2px;
+}
+
+.iprange >>> input {
+ font-size: 14px;
+}
+
+.iprange > span {
+ margin: 0 10px;
+}
+
.info-input {
- margin: 20px;
+ padding: 10px 20px;
}
+
+.info-input >>> input, .info-input >>> textarea {
+ font-family: 'Roboto Mono';
+}
+
.info-heading {
display: flex;
align-items: center;
margin-bottom: 10px;
}
+
.info-heading > span {
margin-left: 10px;
}
+
.info-text {
margin-left: 34px;
font-family: 'Roboto Mono';
}
+
.show-toggle {
margin-top: 20px;
margin-right: 20px;