summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorUdo Walter2019-05-01 03:58:36 +0200
committerUdo Walter2019-05-01 03:58:36 +0200
commitb06c635f1e48855186c5c473a185a14767882f7c (patch)
tree6605bb3dff1b48d5a07558983ecae07a214d0332 /webapp
parent[webapp/ipxeBuilder] Change expansion-panels to tabs (diff)
downloadbas-b06c635f1e48855186c5c473a185a14767882f7c.tar.gz
bas-b06c635f1e48855186c5c473a185a14767882f7c.tar.xz
bas-b06c635f1e48855186c5c473a185a14767882f7c.zip
[webapp/groups] compact group view is now optional
Diffstat (limited to 'webapp')
-rw-r--r--webapp/src/components/GroupModuleGroupInfo.vue336
-rw-r--r--webapp/src/components/GroupModuleGroupView.vue448
-rw-r--r--webapp/src/store/groups.js7
3 files changed, 468 insertions, 323 deletions
diff --git a/webapp/src/components/GroupModuleGroupInfo.vue b/webapp/src/components/GroupModuleGroupInfo.vue
new file mode 100644
index 0000000..8e06a3e
--- /dev/null
+++ b/webapp/src/components/GroupModuleGroupInfo.vue
@@ -0,0 +1,336 @@
+<i18n>
+{
+ "en": {
+ "info": "Info",
+ "groups": "Groups",
+ "subgroups": "Subgroups",
+ "clients": "Clients",
+ "name": "Name",
+ "description": "Description",
+ "ipranges": "IP Ranges",
+ "config": "iPXE Config",
+ "parents": "Parents",
+ "startIp": "Start IP",
+ "endIp": "End IP",
+ "more": "more"
+ },
+ "de": {
+ "info": "Info",
+ "groups": "Groups",
+ "subgroups": "Untergruppen",
+ "clients": "Clients",
+ "name": "Name",
+ "description": "Beschreibung",
+ "ipranges": "IP Bereiche",
+ "config": "iPXE Konfiguration",
+ "parents": "Übergruppen",
+ "startIp": "Start IP",
+ "endIp": "End IP",
+ "more": "mehr"
+ }
+}
+</i18n>
+
+<template>
+ <div>
+ <v-divider></v-divider>
+ <v-card-text>
+ <v-layout wrap>
+ <v-flex lg4 sm6 xs12 order-lg1 order-xs2>
+ <v-layout column>
+ <v-flex>
+ <div class="info-box">
+ <div class="body-2 info-heading"><v-icon>label</v-icon><span>{{ $t('name') }}</span></div>
+ <div class="info-text">
+ <v-text-field v-if="editMode" class="info-input" color="primary" v-model="info.name" hide-details tabindex="1"></v-text-field>
+ <div v-else>{{ group.name || '-' }}</div>
+ </div>
+ </div>
+ </v-flex>
+ <v-flex>
+ <div class="info-box">
+ <div class="body-2 info-heading"><v-icon>device_hub</v-icon><span>{{ $t('parents') }}</span></div>
+ <div class="info-text">
+ <select-box v-if="editMode" v-model="parents" :items="groupList" class="info-input" hide-details></select-box>
+ <div v-else class="chip-container non-selectable">
+ <v-tooltip v-for="parent in firstParents" :key="parent.id" top open-delay="800">
+ <template #activator="{ on }">
+ <v-chip v-on="on" small label style="width: calc(50% - 8px)" @click="openParent(parent)">
+ <span class="chip-text">{{ parent.name || parent.id }}</span>
+ </v-chip>
+ </template>
+ <span>{{ parent.name || parent.id }}</span>
+ </v-tooltip>
+ <span v-if="group.parents && group.parents.length > 5" class="and-more">+ {{ group.parents.length - 5 }} {{ $t('more') }}</span>
+ <span v-else-if="group.parents === undefined || group.parents.length === 0">-</span>
+ </div>
+ </div>
+ </div>
+ </v-flex>
+ <v-flex>
+ <div class="info-box">
+ <div class="body-2 info-heading"><v-icon>list</v-icon><span>{{ $t('config') }}</span></div>
+ <div class="info-text">
+ <v-select v-if="editMode"
+ class="info-input"
+ clearable
+ item-text="name"
+ item-value="id"
+ :menu-props="{ offsetY: '' }"
+ hide-details
+ color="primary"
+ v-model="info.configId"
+ :items="configList"
+ ></v-select>
+ <div v-else>{{ group.config ? (group.config.name || group.config.id) : '-' }}</div>
+ </div>
+ </div>
+ </v-flex>
+ </v-layout>
+ </v-flex>
+ <v-flex lg4 sm6 xs12 order-lg2 order-xs3>
+ <div class="info-box">
+ <div class="body-2 info-heading"><v-icon>description</v-icon><span>{{ $t('description') }}</span></div>
+ <div class="info-text">
+ <v-textarea v-if="editMode" class="info-input" rows="1" auto-grow hide-details color="primary" v-model="info.description" tabindex="2"></v-textarea>
+ <div v-else style="white-space: pre-wrap;">{{ group.description || '-' }}</div>
+ </div>
+ </div>
+
+ <div class="info-box">
+ <div class="body-2 info-heading"><v-icon>settings_ethernet</v-icon><span>{{ $t('ipranges') }}</span></div>
+ <div class="info-text">
+ <div v-if="editMode">
+ <div v-for="(iprange, index) in ipranges" :key="index">
+ <div class="iprange">
+ <v-btn class="iprange-button" small icon @click="removeIprange(index)"><v-icon>remove</v-icon></v-btn>
+ <v-text-field solo flat hide-details :label="$t('startIp')" color="primary" v-model="iprange.startIp" single-line></v-text-field>
+ <span class="ip-seperator">-</span>
+ <v-text-field solo flat hide-details :label="$t('endIp')" color="primary" v-model="iprange.endIp" single-line></v-text-field>
+ </div>
+ <v-divider></v-divider>
+ </div>
+ <div class="iprange-add-wrapper">
+ <v-btn class="iprange-button" small icon @click="addIprange"><v-icon>add</v-icon></v-btn>
+ </div>
+ </div>
+ <div v-else>
+ <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 && group.ipranges.length === 0">-</div>
+ </div>
+ </div>
+ </div>
+ </v-flex>
+ <v-flex lg4 xs12 order-lg3 order-xs1 class="text-xs-right">
+ <div class="info-box">
+ <div v-if="!editMode">
+ <v-btn color="error" flat @click="deleteGroup" class="info-buttons">
+ <v-icon left>delete</v-icon>{{ $t('delete') }}
+ </v-btn>
+ <v-btn color="primary" flat @click="editInfo" class="info-buttons">
+ <v-icon left>create</v-icon>{{ $t('edit') }}
+ </v-btn>
+ </div>
+ <div v-else>
+ <v-btn color="primary" flat @click="cancelEdit" class="info-buttons">{{ $t('cancel') }}</v-btn>
+ <v-btn color="primary" @click="saveData" class="info-buttons" tabindex="3">
+ <v-icon left>save</v-icon>{{ $t('save') }}
+ </v-btn>
+ </div>
+ </div>
+ </v-flex>
+ </v-layout>
+ </v-card-text>
+ </div>
+</template>
+
+<script>
+import SelectBox from '@/components/SelectBox'
+import { mapState, mapMutations } from 'vuex'
+
+export default {
+ name: 'GroupModuleGroupInfo',
+ props: {
+ group: {
+ type: Object,
+ default: () => {}
+ },
+ tabIndex: {
+ type: Number
+ }
+ },
+ components: {
+ SelectBox
+ },
+ data () {
+ return {
+ editMode: false,
+ info: {
+ name: '',
+ description: '',
+ configId: null
+ },
+ parents: [],
+ ipranges: []
+ }
+ },
+ computed: {
+ ...mapState('groups', ['groupList', 'configList']),
+ firstParents () {
+ return this.group.parents ? this.group.parents.slice(0, 5) : []
+ }
+ },
+ watch: {
+ group (newValue, oldValue) {
+ if (newValue.id === 'create') this.editInfo()
+ else if (newValue.id !== oldValue.id) this.editMode = false
+ }
+ },
+ methods: {
+ ...mapMutations('groups', ['setDialog', 'setActiveTab', 'adjustTabSlider', 'deleteFromTabChain']),
+ 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.parents = this.group.parents ? this.group.parents.slice(0) : []
+ this.ipranges = this.group.ipranges ? this.group.ipranges.slice(0) : []
+ },
+ cancelEdit () {
+ this.editMode = false
+ if (this.group.id === 'create') {
+ this.deleteFromTabChain({ index: this.tabIndex, count: 1 })
+ this.setActiveTab(this.tabIndex - 1)
+ }
+ },
+ saveData () {
+ this.info.configId = this.info.configId === undefined ? null : this.info.configId
+ this.ipranges = this.ipranges.filter(iprange => iprange.startIp && iprange.endIp)
+ this.adjustTabSlider()
+ this.$store.dispatch('groups/saveGroup', {
+ id: this.group.id,
+ data: this.info,
+ parents: this.parents,
+ ipranges: this.ipranges,
+ tabIndex: this.tabIndex,
+ callback: this.updateUrl
+ })
+ this.editMode = false
+ },
+ deleteGroup () {
+ this.setDialog({ show: true, info: { action: 'delete', type: 'group', selected: [this.group] } })
+ },
+ updateUrl (id) {
+ this.$router.replace({
+ name: 'GroupModule.group',
+ params: { id, noReload: true }
+ })
+ },
+ openParent (parent) {
+ this.$store.dispatch('groups/loadGroup', { id: parent.id, name: parent.name, tabIndex: this.tabIndex, asParent: true, switchTab: true })
+ }
+ },
+ created () {
+ if (this.group.id === 'create') this.editInfo()
+ }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+.info-buttons {
+ margin: 0;
+}
+
+.iprange {
+ display: flex;
+ align-items: center;
+ min-height: 34px;
+}
+
+.iprange-add-wrapper {
+ height: 32px;
+ display: flex;
+ align-items: center;
+}
+
+.iprange >>> .v-text-field.v-text-field--solo .v-input__control {
+ min-height: 32px;
+}
+
+.iprange >>> .v-label, .iprange >>> input {
+ font-size: 14px;
+}
+
+.chip-container {
+ display: flex;
+ flex-wrap: wrap;
+ width: 100%;
+}
+
+.chip-container >>> .v-chip__content {
+ width: 100%;
+ cursor: pointer;
+}
+
+.chip-text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.and-more {
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+ margin: 4px 17px;
+}
+
+.ip-seperator {
+ padding: 0 10px;
+}
+
+.iprange-button {
+ margin: 0 8px 0 0;
+}
+
+.info-box {
+ padding: 20px;
+}
+
+.info-input {
+ margin: 0;
+ padding: 0 0 1px 0;
+ overflow: hidden;
+}
+
+.info-heading {
+ display: flex;
+ align-items: center;
+ margin-bottom: 10px;
+}
+
+.info-heading > span {
+ margin-left: 10px;
+}
+
+.info-text {
+ overflow-x: auto;
+ margin-left: 34px;
+ font-family: 'Roboto Mono';
+ min-height: 34px;
+ display: flex;
+ align-items: center;
+}
+</style>
diff --git a/webapp/src/components/GroupModuleGroupView.vue b/webapp/src/components/GroupModuleGroupView.vue
index 04b0be0..fe1017e 100644
--- a/webapp/src/components/GroupModuleGroupView.vue
+++ b/webapp/src/components/GroupModuleGroupView.vue
@@ -5,196 +5,129 @@
"showall": "All",
"groups": "Groups",
"subgroups": "Subgroups",
- "clients": "Clients",
- "name": "Name",
- "description": "Description",
- "ipranges": "IP Ranges",
- "config": "iPXE Config",
- "parents": "Parents",
- "startIp": "Start IP",
- "endIp": "End IP",
- "selectParents": "Select parents",
- "more": "more"
+ "clients": "Clients"
},
"de": {
"info": "Info",
"showall": "Alle",
"groups": "Groups",
"subgroups": "Untergruppen",
- "clients": "Clients",
- "name": "Name",
- "description": "Beschreibung",
- "ipranges": "IP Bereiche",
- "config": "iPXE Konfiguration",
- "parents": "Übergruppen",
- "startIp": "Start IP",
- "endIp": "End IP",
- "selectParents": "Übergruppen auswählen",
- "more": "mehr"
+ "clients": "Clients"
}
}
</i18n>
<template>
- <v-card style="margin-top: 24px">
- <v-tabs v-model="activeTab" grow hide-slider>
- <v-tab v-if="group.id !== 0" class="groupview-tab" :class="(group.id !== 0 && activeTab === 0) ? 'primary--text' : ''">
- <v-icon :color="(group.id !== 0 && activeTab === 0) ? 'primary' : ''">list_alt</v-icon>
- <span class="hidden-xs-only ml-2">Info</span>
- </v-tab>
- <v-tab v-if="group.id !== 'create'" class="groupview-tab" :class="activeTab === (group.id === 0 ? 0 : 1) ? 'primary--text' : ''">
- <v-icon class="mr-2" :color="activeTab === (group.id === 0 ? 0 : 1) ? 'primary' : ''">category</v-icon>
- {{ group.subgroups ? group.subgroups.length : 0 }}
- <span class="hidden-xs-only ml-1">{{ group.id > 0 ? $t('subgroups') : $t('groups') }}</span>
- </v-tab>
- <v-tab v-if="group.id !== 'create'" class="groupview-tab" :class="activeTab === (group.id === 0 ? 1 : 2) ? 'primary--text' : ''">
- <v-icon class="mr-2" :color="activeTab === (group.id === 0 ? 1 : 2) ? 'primary' : ''">computer</v-icon>
- {{ group.clients ? group.clients.length : 0 }}
- <span class="hidden-xs-only ml-1">{{ $t('clients') }}</span>
- </v-tab>
-
- <v-switch
- v-if="group.id !== 'create'"
- :input-value="group.tabShowAll"
- @change="setShowAll"
- class="show-toggle"
- :label="$t('showall')"
- hide-details
- color="primary"
- ></v-switch>
-
- <v-tabs-items touchless>
- <v-tab-item v-if="group.id !== 0" lazy :transition="false" :reverse-transition="false">
- <v-divider></v-divider>
- <v-card-text>
- <v-layout wrap>
- <v-flex lg4 sm6 xs12 order-lg1 order-xs2>
- <v-layout column>
- <v-flex>
- <div class="info-box">
- <div class="body-2 info-heading"><v-icon>label</v-icon><span>{{ $t('name') }}</span></div>
- <div class="info-text">
- <v-text-field v-if="editMode" class="info-input" color="primary" v-model="info.name" hide-details tabindex="1"></v-text-field>
- <div v-else>{{ group.name || '-' }}</div>
- </div>
- </div>
- </v-flex>
- <v-flex>
- <div class="info-box">
- <div class="body-2 info-heading"><v-icon>device_hub</v-icon><span>{{ $t('parents') }}</span></div>
- <div class="info-text">
- <select-box v-if="editMode" v-model="parents" :items="groupList" class="info-input" hide-details></select-box>
- <div v-else class="chip-container non-selectable">
- <v-tooltip v-for="parent in firstParents" :key="parent.id" top open-delay="800">
- <template #activator="{ on }">
- <v-chip v-on="on" small label style="width: calc(50% - 8px)" @click="openParent(parent)">
- <span class="chip-text">{{ parent.name || parent.id }}</span>
- </v-chip>
- </template>
- <span>{{ parent.name || parent.id }}</span>
- </v-tooltip>
- <span v-if="group.parents && group.parents.length > 5" class="and-more">+ {{ group.parents.length - 5 }} {{ $t('more') }}</span>
- <span v-else-if="group.parents === undefined || group.parents.length === 0">-</span>
- </div>
- </div>
- </div>
- </v-flex>
- <v-flex>
- <div class="info-box">
- <div class="body-2 info-heading"><v-icon>list</v-icon><span>{{ $t('config') }}</span></div>
- <div class="info-text">
- <v-select v-if="editMode"
- class="info-input"
- clearable
- item-text="name"
- item-value="id"
- :menu-props="{ offsetY: '' }"
- hide-details
- color="primary"
- v-model="info.configId"
- :items="configList"
- ></v-select>
- <div v-else>{{ group.config ? (group.config.name || group.config.id) : '-' }}</div>
- </div>
- </div>
- </v-flex>
- </v-layout>
- </v-flex>
- <v-flex lg4 sm6 xs12 order-lg2 order-xs3>
- <div class="info-box">
- <div class="body-2 info-heading"><v-icon>description</v-icon><span>{{ $t('description') }}</span></div>
- <div class="info-text">
- <v-textarea v-if="editMode" class="info-input" rows="1" auto-grow hide-details color="primary" v-model="info.description" tabindex="2"></v-textarea>
- <div v-else style="white-space: pre-wrap;">{{ group.description || '-' }}</div>
- </div>
- </div>
-
- <div class="info-box">
- <div class="body-2 info-heading"><v-icon>settings_ethernet</v-icon><span>{{ $t('ipranges') }}</span></div>
- <div class="info-text">
- <div v-if="editMode">
- <div v-for="(iprange, index) in ipranges" :key="index">
- <div class="iprange">
- <v-btn class="iprange-button" small icon @click="removeIprange(index)"><v-icon>remove</v-icon></v-btn>
- <v-text-field solo flat hide-details :label="$t('startIp')" color="primary" v-model="iprange.startIp" single-line></v-text-field>
- <span class="ip-seperator">-</span>
- <v-text-field solo flat hide-details :label="$t('endIp')" color="primary" v-model="iprange.endIp" single-line></v-text-field>
- </div>
- <v-divider></v-divider>
- </div>
- <div class="iprange-add-wrapper">
- <v-btn class="iprange-button" small icon @click="addIprange"><v-icon>add</v-icon></v-btn>
- </div>
- </div>
- <div v-else>
- <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 && group.ipranges.length === 0">-</div>
- </div>
- </div>
- </div>
- </v-flex>
- <v-flex lg4 xs12 order-lg3 order-xs1 class="text-xs-right">
- <div class="info-box">
- <div v-if="!editMode">
- <v-btn color="error" flat @click="deleteGroup" class="info-buttons">
- <v-icon left>delete</v-icon>{{ $t('delete') }}
- </v-btn>
- <v-btn color="primary" flat @click="editInfo" class="info-buttons">
- <v-icon left>create</v-icon>{{ $t('edit') }}
- </v-btn>
- </div>
- <div v-else>
- <v-btn color="primary" flat @click="cancelEdit" class="info-buttons">{{ $t('cancel') }}</v-btn>
- <v-btn color="primary" @click="saveData" class="info-buttons" tabindex="3">
- <v-icon left>save</v-icon>{{ $t('save') }}
- </v-btn>
- </div>
- </div>
- </v-flex>
- </v-layout>
- </v-card-text>
- </v-tab-item>
- <v-tab-item v-if="group.id !== 'create'" lazy :transition="false" :reverse-transition="false">
- <group-module-group-list :tabIndex="tabIndex" :groupId="group.id" :groups="group.subgroups || []" />
- </v-tab-item>
- <v-tab-item v-if="group.id !== 'create'" lazy :transition="false" :reverse-transition="false">
- <group-module-client-list :tabIndex="tabIndex" :groupId="group.id" :clients="group.clients || []" />
- </v-tab-item>
- </v-tabs-items>
- </v-tabs>
- </v-card>
+ <div>
+ <div v-if="!settings.collapsedView">
+
+ <v-card v-if="group.id !== 0" style="margin-top: 24px">
+ <div class="header-div">
+ <div class="header-div-text">
+ <v-icon class="mr-2">list_alt</v-icon>
+ <span>Info</span>
+ </div>
+ <v-btn v-if="group.id !== 'create'" icon @click="toggleCollapsedView" :class="{ 'upside-down': settings.collapsedView }">
+ <v-icon>expand_less</v-icon>
+ </v-btn>
+ <v-switch
+ v-if="group.id !== 'create'"
+ :input-value="group.tabShowAll"
+ @change="setShowAll"
+ class="show-toggle"
+ :label="$t('showall')"
+ hide-details
+ color="primary"
+ ></v-switch>
+ </div>
+ <group-module-group-info :tabIndex="tabIndex" :group="group" />
+ </v-card>
+
+ <v-card v-if="group.id !== 'create'" style="margin-top: 24px">
+ <div class="header-div">
+ <div class="header-div-text">
+ <v-icon class="mr-2">category</v-icon>
+ {{ group.subgroups ? group.subgroups.length : 0 }}
+ <span class="ml-1">{{ group.id > 0 ? $t('subgroups') : $t('groups') }}</span>
+ </div>
+ <v-btn v-if="group.id === 0" icon @click="toggleCollapsedView" :class="{ 'upside-down': settings.collapsedView }">
+ <v-icon>expand_less</v-icon>
+ </v-btn>
+ <v-switch
+ v-if="group.id === 0"
+ :input-value="group.tabShowAll"
+ @change="setShowAll"
+ class="show-toggle"
+ :label="$t('showall')"
+ hide-details
+ color="primary"
+ ></v-switch>
+ </div>
+ <group-module-group-list :tabIndex="tabIndex" :groupId="group.id" :groups="group.subgroups || []" />
+ </v-card>
+
+ <v-card v-if="group.id !== 'create'" style="margin-top: 24px">
+ <div class="header-div">
+ <div class="header-div-text">
+ <v-icon class="mr-2">computer</v-icon>
+ {{ group.clients ? group.clients.length : 0 }}
+ <span class="ml-1">{{ $t('clients') }}</span>
+ </div>
+ </div>
+ <group-module-client-list :tabIndex="tabIndex" :groupId="group.id" :clients="group.clients || []" />
+ </v-card>
+ </div>
+
+ <v-card v-else style="margin-top: 24px">
+ <v-tabs v-model="activeTab" grow hide-slider>
+ <v-tab v-if="group.id !== 0" class="groupview-tab" :class="(group.id !== 0 && activeTab === 0) ? 'primary--text' : ''">
+ <v-icon :color="(group.id !== 0 && activeTab === 0) ? 'primary' : ''">list_alt</v-icon>
+ <span class="hidden-xs-only ml-2">Info</span>
+ </v-tab>
+ <v-tab v-if="group.id !== 'create'" class="groupview-tab" :class="activeTab === (group.id === 0 ? 0 : 1) ? 'primary--text' : ''">
+ <v-icon class="mr-2" :color="activeTab === (group.id === 0 ? 0 : 1) ? 'primary' : ''">category</v-icon>
+ {{ group.subgroups ? group.subgroups.length : 0 }}
+ <span class="hidden-xs-only ml-1">{{ group.id > 0 ? $t('subgroups') : $t('groups') }}</span>
+ </v-tab>
+ <v-tab v-if="group.id !== 'create'" class="groupview-tab" :class="activeTab === (group.id === 0 ? 1 : 2) ? 'primary--text' : ''">
+ <v-icon class="mr-2" :color="activeTab === (group.id === 0 ? 1 : 2) ? 'primary' : ''">computer</v-icon>
+ {{ group.clients ? group.clients.length : 0 }}
+ <span class="hidden-xs-only ml-1">{{ $t('clients') }}</span>
+ </v-tab>
+
+ <v-btn v-if="group.id !== 'create'" icon @click="toggleCollapsedView">
+ <v-icon>expand_more</v-icon>
+ </v-btn>
+ <v-switch
+ v-if="group.id !== 'create'"
+ :input-value="group.tabShowAll"
+ @change="setShowAll"
+ class="show-toggle"
+ :label="$t('showall')"
+ hide-details
+ color="primary"
+ ></v-switch>
+
+ <v-tabs-items touchless>
+ <v-tab-item v-if="group.id !== 0" lazy :transition="false" :reverse-transition="false">
+ <group-module-group-info :tabIndex="tabIndex" :group="group" />
+ </v-tab-item>
+ <v-tab-item v-if="group.id !== 'create'" lazy :transition="false" :reverse-transition="false">
+ <group-module-group-list :tabIndex="tabIndex" :groupId="group.id" :groups="group.subgroups || []" />
+ </v-tab-item>
+ <v-tab-item v-if="group.id !== 'create'" lazy :transition="false" :reverse-transition="false">
+ <group-module-client-list :tabIndex="tabIndex" :groupId="group.id" :clients="group.clients || []" />
+ </v-tab-item>
+ </v-tabs-items>
+ </v-tabs>
+ </v-card>
+ </div>
</template>
<script>
+import GroupModuleGroupInfo from '@/components/GroupModuleGroupInfo'
import GroupModuleGroupList from '@/components/GroupModuleGroupList'
import GroupModuleClientList from '@/components/GroupModuleClientList'
-import SelectBox from '@/components/SelectBox'
import { mapState, mapMutations } from 'vuex'
export default {
@@ -209,40 +142,22 @@ export default {
}
},
components: {
+ GroupModuleGroupInfo,
GroupModuleGroupList,
- GroupModuleClientList,
- SelectBox
+ GroupModuleClientList
},
data () {
return {
activeTab: 0,
- editMode: false,
- showAllClicked: false,
- info: {
- name: '',
- description: '',
- configId: null
- },
- parents: [],
- ipranges: []
+ showAllClicked: false
}
},
computed: {
- ...mapState('groups', ['groupList', 'configList']),
- headers () {
- return [
- { key: 'name', text: this.$t('name') }
- ]
- },
- firstParents () {
- return this.group.parents ? this.group.parents.slice(0, 5) : []
- }
+ ...mapState('groups', ['groupList', 'configList', 'settings'])
},
watch: {
group (newValue, oldValue) {
- if (newValue.id === 'create') this.editInfo()
- else if (newValue.id !== oldValue.id) this.editMode = false
- else if (!oldValue.isPlaceholder) return
+ if (!oldValue.isPlaceholder) return
if (newValue.subgroups.length) this.activeTab = (this.group.id === 0 ? 0 : 1)
else if (newValue.clients.length) this.activeTab = (this.group.id === 0 ? 1 : 2)
@@ -250,62 +165,16 @@ export default {
}
},
methods: {
- ...mapMutations('groups', ['setDialog', 'setActiveTab', 'adjustTabSlider', 'deleteFromTabChain']),
+ ...mapMutations('groups', ['setDialog', 'setActiveTab', 'adjustTabSlider', 'deleteFromTabChain', 'setCollapsedView']),
setShowAll (value) {
this.showAllClicked = true
this.$store.commit('groups/setShowAll', { index: this.tabIndex, value })
this.$store.dispatch('groups/loadGroup', { id: this.group.id, tabIndex: this.tabIndex })
},
- 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.parents = this.group.parents ? this.group.parents.slice(0) : []
- this.ipranges = this.group.ipranges ? this.group.ipranges.slice(0) : []
- },
- cancelEdit () {
- this.editMode = false
- if (this.group.id === 'create') {
- this.deleteFromTabChain({ index: this.tabIndex, count: 1 })
- this.setActiveTab(this.tabIndex - 1)
- }
- },
- saveData () {
- this.info.configId = this.info.configId === undefined ? null : this.info.configId
- this.ipranges = this.ipranges.filter(iprange => iprange.startIp && iprange.endIp)
- this.adjustTabSlider()
- this.$store.dispatch('groups/saveGroup', {
- id: this.group.id,
- data: this.info,
- parents: this.parents,
- ipranges: this.ipranges,
- tabIndex: this.tabIndex,
- callback: this.updateUrl
- })
- this.editMode = false
- },
- deleteGroup () {
- this.setDialog({ show: true, info: { action: 'delete', type: 'group', selected: [this.group] } })
- },
- updateUrl (id) {
- this.$router.replace({
- name: 'GroupModule.group',
- params: { id, noReload: true }
- })
- },
- openParent (parent) {
- this.$store.dispatch('groups/loadGroup', { id: parent.id, name: parent.name, tabIndex: this.tabIndex, asParent: true, switchTab: true })
+ toggleCollapsedView () {
+ this.setCollapsedView(!this.settings.collapsedView)
+ console.log(this.settings)
}
- },
- created () {
- if (this.group.id === 'create') this.editInfo()
}
}
</script>
@@ -325,87 +194,20 @@ export default {
align-items: center;
}
-.info-buttons {
- margin: 0;
-}
-
-.iprange {
- display: flex;
- align-items: center;
- min-height: 34px;
-}
-
-.iprange-add-wrapper {
- height: 32px;
- display: flex;
- align-items: center;
-}
-
-.iprange >>> .v-text-field.v-text-field--solo .v-input__control {
- min-height: 32px;
-}
-
-.iprange >>> .v-label, .iprange >>> input {
- font-size: 14px;
-}
-
-.chip-container {
- display: flex;
- flex-wrap: wrap;
- width: 100%;
-}
-
-.chip-container >>> .v-chip__content {
- width: 100%;
- cursor: pointer;
-}
-
-.chip-text {
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.and-more {
- font-size: 13px;
- display: flex;
- align-items: center;
- margin: 4px 17px;
-}
-
-.ip-seperator {
- padding: 0 10px;
-}
-
-.iprange-button {
- margin: 0 8px 0 0;
-}
-
-.info-box {
- padding: 20px;
-}
-
-.info-input {
- margin: 0;
- padding: 0 0 1px 0;
- overflow: hidden;
-}
-
-.info-heading {
+.header-div {
+ user-select: none;
+ padding-left: 16px;
+ height: 48px;
+ font-weight: bold;
display: flex;
+ flex-direction: row;
align-items: center;
- margin-bottom: 10px;
-}
-
-.info-heading > span {
- margin-left: 10px;
}
-.info-text {
- overflow-x: auto;
- margin-left: 34px;
- font-family: 'Roboto Mono';
- min-height: 34px;
+.header-div > .header-div-text {
+ flex: 1;
display: flex;
+ flex-direction: row;
align-items: center;
}
</style>
diff --git a/webapp/src/store/groups.js b/webapp/src/store/groups.js
index 24f58d3..0f5e756 100644
--- a/webapp/src/store/groups.js
+++ b/webapp/src/store/groups.js
@@ -4,6 +4,9 @@ import axios from 'axios'
export default {
namespaced: true,
state: {
+ settings: {
+ collapsedView: localStorage.getItem('settings.groups.collapsedView') === 'true'
+ },
groupList: [],
clientList: [],
configList: [],
@@ -16,6 +19,10 @@ export default {
adjustTabSlider: false
},
mutations: {
+ setCollapsedView (state, value) {
+ state.settings.collapsedView = value
+ localStorage.setItem('settings.groups.collapsedView', value)
+ },
setGroupList: (state, list) => { state.groupList = list },
setClientList: (state, list) => { state.clientList = list },
setConfigList: (state, list) => { state.configList = list },