add v-field-select

This commit is contained in:
Nitwel
2020-09-11 14:18:05 +02:00
committed by rijkvanzanten
parent 8b1b23b919
commit 81faa88c62
7 changed files with 196 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ import VDivider from './v-divider';
import VError from './v-error';
import VFancySelect from './v-fancy-select';
import VFieldTemplate from './v-field-template';
import VFieldSelect from './v-field-select';
import VForm from './v-form';
import VHover from './v-hover/';
import VIcon from './v-icon/';
@@ -64,6 +65,7 @@ Vue.component('v-divider', VDivider);
Vue.component('v-error', VError);
Vue.component('v-fancy-select', VFancySelect);
Vue.component('v-field-template', VFieldTemplate);
Vue.component('v-field-select', VFieldSelect);
Vue.component('v-form', VForm);
Vue.component('v-hover', VHover);
Vue.component('v-icon', VIcon);

View File

@@ -0,0 +1,37 @@
<template>
<v-list-item
v-if="field.children === undefined"
@click="$emit('add', `${parent ? parent + '.' : ''}${field.field}`)"
>
<v-list-item-content>{{ field.name }}</v-list-item-content>
</v-list-item>
<v-list-group v-else>
<template #activator>{{ field.name }}</template>
<field-list-item
v-for="childField in field.children"
:key="childField.field"
:parent="`${parent ? parent + '.' : ''}${field.field}`"
:field="childField"
@add="$emit('add', $event)"
/>
</v-list-group>
</template>
<script lang="ts">
import { defineComponent, PropType } from '@vue/composition-api';
import { FieldTree } from './types';
export default defineComponent({
name: 'field-list-item',
props: {
field: {
type: Object as PropType<FieldTree>,
required: true,
},
parent: {
type: String,
default: null,
},
},
});
</script>

View File

@@ -0,0 +1,4 @@
import VFieldSelect from './v-field-select.vue';
export default VFieldSelect;
export { VFieldSelect };

View File

@@ -0,0 +1 @@
# Field Select

View File

@@ -0,0 +1,7 @@
import { TranslateResult } from 'vue-i18n';
export type FieldTree = {
field: string;
name: string | TranslateResult;
children?: FieldTree[];
};

View File

@@ -0,0 +1,138 @@
<template>
<div class="v-field-select">
<draggable v-model="activeFields" handle=".drag-handle" :set-data="hideDragImage">
<div
v-for="(field, index) in activeFields"
:key="index"
:value="field.field"
:label="field.name"
class="field"
>
<v-icon @click.stop="removeField(field.field)" name="close" />
<span class="name">{{ field.name }}</span>
<v-icon @click.stop name="drag_handle" class="drag-handle" />
</div>
</draggable>
<v-menu attached v-model="menuActive" v-show="selectableFields.length > 0">
<template #activator="{ toggle }">
<div class="field" @click="toggle">
<v-icon name="add" />
<span class="name">Add field</span>
</div>
</template>
<v-list dense>
<field-list-item @add="addField" v-for="field in selectableFields" :key="field.field" :field="field" />
</v-list>
</v-menu>
</div>
</template>
<script lang="ts">
import { defineComponent, toRefs, ref, watch, onMounted, onUnmounted, PropType, computed } from '@vue/composition-api';
import FieldListItem from './field-list-item.vue';
import { useFieldsStore } from '@/stores';
import { Field } from '@/types/';
import Draggable from 'vuedraggable';
import useFieldTree from '@/composables/use-field-tree';
import useCollection from '@/composables/use-collection';
import { FieldTree } from '../v-field-template/types';
import hideDragImage from '@/utils/hide-drag-image';
export default defineComponent({
components: { FieldListItem, Draggable },
props: {
disabled: {
type: Boolean,
default: false,
},
value: {
type: Array as PropType<string[]>,
default: null,
},
collection: {
type: String,
required: true,
},
},
setup(props, { emit }) {
const fieldsStore = useFieldsStore();
const menuActive = ref(false);
const { collection } = toRefs(props);
const { tree } = useFieldTree(collection);
const { info, primaryKeyField, fields: fieldsInCollection, sortField } = useCollection(collection);
const _value = computed({
get() {
return props.value;
},
set(newVal: string[]) {
emit('input', newVal);
},
});
const treeFlattened = computed(() => {
const fields: FieldTree[] = [];
const stack: FieldTree[] = tree.value;
while (stack.length > 0) {
const field = stack.shift();
if (field === undefined) continue;
fields.push(field);
if (field.children === undefined) continue;
stack.push(...field.children);
}
return fields;
});
const activeFields = computed({
get() {
const list = _value.value.map((field) => fieldsInCollection.value.find((f) => f.field === field));
const filteredList: Field[] = [];
list.forEach((field) => {
if (field !== undefined) filteredList.push(field);
});
return filteredList;
},
set(newVal: Field[]) {
_value.value = newVal.map((field) => field.field);
},
});
const selectableFields = computed(() => {
return fieldsInCollection.value.filter((field) => _value.value.includes(field.field) === false);
});
return { tree, menuActive, addField, activeFields, removeField, selectableFields, hideDragImage };
function removeField(field: string) {
_value.value = _value.value.filter((f) => f !== field);
}
function addField(field: string) {
const newArray = _value.value;
newArray.push(field);
_value.value = newArray;
}
},
});
</script>
<style lang="scss" scoped>
.field {
display: flex;
justify-content: space-between;
.name {
flex: 1;
padding: 0 5px;
}
.v-icon {
--v-icon-color: var(--foreground-subdued);
}
}
</style>

View File

@@ -1,6 +1,11 @@
<template>
<div class="layout-tabular">
<portal to="layout-options">
<div class="layout-option">
<div class="option-label">Test</div>
<v-field-select :collection="collection" v-model="selectedFields" />
</div>
<div class="layout-option">
<div class="option-label">{{ $t('layouts.tabular.spacing') }}</div>
<v-select
@@ -211,6 +216,7 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const selectedFields = ref(['title']);
const table = ref<Vue | null>(null);
const mainElement = inject('main-element', ref<Element | null>(null));
@@ -290,6 +296,7 @@ export default defineComponent({
activeFilterCount,
refresh,
resetPresetAndRefresh,
selectedFields,
};
async function resetPresetAndRefresh() {