summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorUdo Walter2019-02-25 07:54:40 +0100
committerUdo Walter2019-02-25 07:54:40 +0100
commit484f76be15caf517ced58930bf950ffe0d049e36 (patch)
tree139d45121ec57150e846d3987ebd486afcbe9805 /webapp
parentMerge (diff)
downloadbas-484f76be15caf517ced58930bf950ffe0d049e36.tar.gz
bas-484f76be15caf517ced58930bf950ffe0d049e36.tar.xz
bas-484f76be15caf517ced58930bf950ffe0d049e36.zip
[webapp/selectbox] new selectbox component
Diffstat (limited to 'webapp')
-rw-r--r--webapp/src/components/GroupModule.vue1
-rw-r--r--webapp/src/components/GroupModuleClientView.vue56
-rw-r--r--webapp/src/components/GroupModuleGroupView.vue70
-rw-r--r--webapp/src/components/SelectBox.vue170
4 files changed, 232 insertions, 65 deletions
diff --git a/webapp/src/components/GroupModule.vue b/webapp/src/components/GroupModule.vue
index a02fccf..0634008 100644
--- a/webapp/src/components/GroupModule.vue
+++ b/webapp/src/components/GroupModule.vue
@@ -69,6 +69,7 @@ export default {
watch: {
activeTab (index) {
const item = this.tabChain[index]
+ if (item === undefined) return
if (item.tabType !== this.$route.name.replace('GroupModule.', '') || String(item.id) !== this.$route.params.id) {
this.$router.push({
name: 'GroupModule.' + item.tabType,
diff --git a/webapp/src/components/GroupModuleClientView.vue b/webapp/src/components/GroupModuleClientView.vue
index 68298c4..f01b5c7 100644
--- a/webapp/src/components/GroupModuleClientView.vue
+++ b/webapp/src/components/GroupModuleClientView.vue
@@ -7,7 +7,8 @@
"groups": "Groups",
"ip": "IP Address",
"mac": "MAC Address",
- "uuid": "UUID"
+ "uuid": "UUID",
+ "more": "more"
},
"de": {
"name": "Name",
@@ -16,7 +17,8 @@
"groups": "Gruppen",
"ip": "IP Adresse",
"mac": "MAC Adresse",
- "uuid": "UUID"
+ "uuid": "UUID",
+ "more": "mehr"
}
}
</i18n>
@@ -40,29 +42,15 @@
</v-flex>
<v-flex>
<div class="info-box">
- <div class="body-2 info-heading">
- <v-icon>device_hub</v-icon><span>{{ $t('groups') }}</span>
- <v-menu v-if="editMode" offset-y :close-on-content-click="false" lazy>
- <v-btn slot="activator" small icon class="info-heading-button"><v-icon>edit</v-icon></v-btn>
- <v-card>
- <data-table ref="datatable" v-model="groups" :headers="headers" :items="groupList" slim :row-count="6"></data-table>
- </v-card>
- </v-menu>
- </div>
+ <div class="body-2 info-heading"><v-icon>device_hub</v-icon><span>{{ $t('groups') }}</span></div>
<div class="info-text">
- <div>
- <v-chip
- v-for="(group, index) in groupChips"
- :key="group.id"
- v-if="index <= 5"
- small
- :close="editMode"
- @input="removeGroupChip(index)"
- >
+ <select-box v-if="editMode" v-model="groups" :items="groupList"></select-box>
+ <div v-else class="chip-container">
+ <v-chip v-for="(group, index) in client.groups" :key="group.id" v-if="index < 5" small label style="width: calc(50% - 8px)">
{{ group.name || group.id }}
</v-chip>
- <span v-if="groupChips && groupChips.length > 5" class="and-more-chip">...</span>
- <span v-if="groupChips && groupChips.length === 0">-</span>
+ <span v-if="client.groups && client.groups.length > 5" class="and-more">+ {{ client.groups.length - 5 }} {{ $t('more') }}</span>
+ <span v-else-if="client.groups === undefined || client.groups.length === 0">-</span>
</div>
</div>
</div>
@@ -151,14 +139,14 @@
</template>
<script>
-import DataTable from '@/components/DataTable'
+import SelectBox from '@/components/SelectBox'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'GroupModuleClientView',
props: ['tabIndex', 'client'],
components: {
- DataTable
+ SelectBox
},
data () {
return {
@@ -179,10 +167,6 @@ export default {
configName () {
return this.$store.state.groups.configNames[this.client.configId]
},
- groupChips () {
- if (this.editMode) return this.groups
- else return this.client.groups
- },
headers () {
return [
{ key: 'name', text: this.$t('name') }
@@ -197,9 +181,6 @@ export default {
},
methods: {
...mapMutations('groups', ['setDialog']),
- removeGroupChip (index) {
- this.groups.splice(index, 1)
- },
editInfo () {
this.editMode = true
this.info.name = this.client.name
@@ -250,6 +231,19 @@ export default {
margin: 0;
}
+.chip-container {
+ display: flex;
+ flex-wrap: wrap;
+ width: 100%;
+}
+
+.and-more {
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+ margin: 4px 17px;
+}
+
.info-box {
padding: 20px;
}
diff --git a/webapp/src/components/GroupModuleGroupView.vue b/webapp/src/components/GroupModuleGroupView.vue
index f7a0151..6f78d07 100644
--- a/webapp/src/components/GroupModuleGroupView.vue
+++ b/webapp/src/components/GroupModuleGroupView.vue
@@ -13,7 +13,8 @@
"parents": "Parents",
"startIp": "Start IP",
"endIp": "End IP",
- "selectParents": "Select parents"
+ "selectParents": "Select parents",
+ "more": "more"
},
"de": {
"info": "Info",
@@ -28,7 +29,8 @@
"parents": "Übergruppen",
"startIp": "Start IP",
"endIp": "End IP",
- "selectParents": "Übergruppen auswählen"
+ "selectParents": "Übergruppen auswählen",
+ "more": "mehr"
}
}
</i18n>
@@ -52,29 +54,15 @@
</v-flex>
<v-flex>
<div class="info-box">
- <div class="body-2 info-heading">
- <v-icon>device_hub</v-icon><span>{{ $t('parents') }}</span>
- <v-menu v-if="editMode" offset-y :close-on-content-click="false" lazy>
- <v-btn slot="activator" small icon class="info-heading-button"><v-icon>edit</v-icon></v-btn>
- <v-card>
- <data-table v-model="parents" :headers="headers" :items="groupList" slim :row-count="6"></data-table>
- </v-card>
- </v-menu>
- </div>
+ <div class="body-2 info-heading"><v-icon>device_hub</v-icon><span>{{ $t('parents') }}</span></div>
<div class="info-text">
- <div>
- <v-chip
- v-for="(parent, index) in parentChips"
- :key="parent.id"
- v-if="index <= 5"
- small
- :close="editMode"
- @input="removeParentChip(index)"
- >
+ <select-box v-if="editMode" v-model="parents" :items="groupList"></select-box>
+ <div v-else class="chip-container">
+ <v-chip v-for="(parent, index) in group.parents" :key="parent.id" v-if="index < 5" small label style="width: calc(50% - 8px)">
{{ parent.name || parent.id }}
</v-chip>
- <span v-if="parentChips && parentChips.length > 5" class="and-more-chip">...</span>
- <span v-if="parentChips && parentChips.length === 0">-</span>
+ <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>
@@ -181,16 +169,24 @@
<script>
import GroupModuleGroupList from '@/components/GroupModuleGroupList'
import GroupModuleClientList from '@/components/GroupModuleClientList'
-import DataTable from '@/components/DataTable'
+import SelectBox from '@/components/SelectBox'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'GroupModuleGroupView',
- props: ['tabIndex', 'group'],
+ props: {
+ group: {
+ type: Object,
+ default: {}
+ },
+ tabIndex: {
+ type: Number
+ }
+ },
components: {
GroupModuleGroupList,
GroupModuleClientList,
- DataTable
+ SelectBox
},
data () {
return {
@@ -209,10 +205,6 @@ export default {
configName () {
return this.$store.state.groups.configNames[this.group.configId]
},
- parentChips () {
- if (this.editMode) return this.parents
- else return this.group.parents
- },
headers () {
return [
{ key: 'name', text: this.$t('name') }
@@ -237,9 +229,6 @@ export default {
addIprange () {
this.ipranges.push({ startIp: '', endIp: '' })
},
- removeParentChip (index) {
- this.parents.splice(index, 1)
- },
editInfo () {
this.editMode = true
this.info.name = this.group.name
@@ -296,8 +285,21 @@ export default {
min-height: 34px;
}
-.iprange >>> input {
- font-size: 14px;
+.iprange >>> .v-label, .iprange >>> input {
+ font-size: 14px !important;
+}
+
+.chip-container {
+ display: flex;
+ flex-wrap: wrap;
+ width: 100%;
+}
+
+.and-more {
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+ margin: 4px 17px;
}
.ip-seperator {
diff --git a/webapp/src/components/SelectBox.vue b/webapp/src/components/SelectBox.vue
new file mode 100644
index 0000000..89afc5b
--- /dev/null
+++ b/webapp/src/components/SelectBox.vue
@@ -0,0 +1,170 @@
+<i18n>
+{
+ "en": {
+ "name": "Name",
+ "more": "more"
+ },
+ "de": {
+ "name": "Name",
+ "more": "mehr"
+ }
+}
+</i18n>
+
+<template>
+ <v-menu v-model="menu" offset-y :close-on-content-click="false" lazy class="select-menu non-selectable">
+ <v-input class="v-text-field primary--text select-input" :class="{ 'v-input--is-focused': menu }" slot="activator"
+ hide-details
+ label="asdf"
+ >
+ <div class="select-input-content">
+ <div class="select-input-chips">
+ <v-chip
+ class="item-chip"
+ :style="{ width: 'calc(' + (100 / maxColumns) + '% - 8px)' }"
+ v-for="(item, index) in value"
+ :key="item[idKey]"
+ v-if="index < maxShow"
+ small
+ label
+ close
+ @input="removeItem(index)"
+ >
+ <div style="overflow: hidden; text-overflow: ellipsis;">{{ item.name || item.id }}</div>
+ </v-chip>
+ <span v-if="value.length > maxShow" class="and-more">+ {{ value.length - maxShow }} {{ $t('more') }}</span>
+ </div>
+ <v-icon :class="{ 'expand-arrow-flipped': menu }" :color="menu ? 'primary' : ''" style="margin-top: 4px">arrow_drop_down</v-icon>
+ </div>
+ </v-input>
+
+ <v-card>
+ <data-table :value="value" @input="$emit('input', $event)" :headers="headers" :items="items" slim :row-count="6"></data-table>
+ </v-card>
+ </v-menu>
+</template>
+
+<script>
+import DataTable from '@/components/DataTable'
+
+export default {
+ name: 'SelectBox',
+ components: {
+ DataTable
+ },
+ props: {
+ value: {
+ type: Array,
+ default: []
+ },
+ items: {
+ type: Array,
+ default: []
+ },
+ idKey: {
+ type: String,
+ default: 'id'
+ },
+ textKey: {
+ type: String,
+ default: 'name'
+ },
+ textHeading: {
+ type: String
+ },
+ maxColumns: {
+ type: Number,
+ default: 2
+ },
+ maxRows: {
+ type: Number,
+ default: 3
+ }
+ },
+ data () {
+ return {
+ menu: false
+ }
+ },
+ computed: {
+ maxShow () {
+ return this.maxColumns * this.maxRows - 1
+ },
+ computedTextHeading () {
+ return this.textHeading === undefined ? this.$t('name') : this.textHeading
+ },
+ headers () {
+ return [
+ { key: this.textKey, text: this.computedTextHeading }
+ ]
+ }
+ },
+ watch: {
+ value () {
+ window.dispatchEvent(new Event('resize'))
+ }
+ },
+ methods: {
+ removeItem (index) {
+ const newValue = this.value.slice(0)
+ newValue.splice(index, 1)
+ this.$emit('input', newValue)
+ },
+ test () {
+ console.log('asdf')
+ }
+ }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+.select-menu {
+ width: 100%;
+ overflow: hidden;
+}
+
+.select-input {
+ margin: 0;
+ padding: 0;
+ padding-bottom: 1px;
+}
+
+.select-input-content {
+ width: 100%;
+ display: flex;
+ align-items: flex-start;
+}
+
+.select-input-chips {
+ display: flex;
+ flex-wrap: wrap;
+ text-transform: none;
+ min-height: 34px;
+ flex: 1;
+}
+
+.item-chip >>> .v-chip__content {
+ width: 100%;
+ cursor: pointer;
+}
+
+.expand-arrow-flipped {
+ transform: rotate(180deg);
+}
+
+.and-more {
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+ margin: 4px 17px;
+}
+
+.theme--dark .and-more {
+ color: rgb(255, 255, 255);
+}
+
+.theme--light .and-more {
+ color: rgba(0, 0, 0, 0.87);
+}
+</style>