Viewing file: view.blade.php (13.44 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
@props([ 'inputType' => 'checkbox', 'selectionType' => 'hierarchical', ])
@if ($inputType == 'checkbox') <!-- Tree Checkbox Component --> <x-admin::tree.checkbox /> @else <!-- Tree Radio Component --> <x-admin::tree.radio /> @endif
<v-tree-view {{ $attributes->except(['input-type', 'selection-type']) }} input-type="{{ $inputType }}" selection-type="{{ $selectionType }}" > <x-admin::shimmer.tree /> </v-tree-view>
@pushOnce('scripts') <script type="module"> app.component('v-tree-view', { name: 'v-tree-view',
inheritAttrs: false,
props: { inputType: { type: String, required: false, default: 'checkbox' },
selectionType: { type: String, required: false, default: 'hierarchical' },
nameField: { type: String, required: false, default: 'permissions' },
valueField: { type: String, required: false, default: 'value' },
idField: { type: String, required: false, default: 'id' },
labelField: { type: String, required: false, default: 'name' },
childrenField: { type: String, required: false, default: 'children' },
items: { type: [Array, String, Object], required: false, default: () => ([]) },
value: { type: [Array, String, Object], required: false, default: () => ([]) },
fallbackLocale: { type: String, required: 'en', },
collapse: { type: Boolean, required: false, default: false }, },
data() { return { formattedItems: null,
formattedValues: null, }; },
created() { this.formattedItems = this.getInitialFormattedItems();
this.formattedValues = this.getInitialFormattedValues(); },
methods: { getInitialFormattedItems() { return (typeof this.items == 'string') ? JSON.parse(this.items) : this.items; },
getInitialFormattedValues() { if (this.inputType == 'radio') { if (typeof this.value == 'array') { return this.value; } else { return [this.value]; } }
return (typeof this.value == 'string') ? JSON.parse(this.value) : this.value; },
getId(item) { const timestamp = new Date().getTime().toString(36);
const id = item[this.idField];
return `${timestamp}_${id}` },
getLabel(item) { return item[this.labelField] ? item[this.labelField] : item.translations.filter((translation) => translation.locale === this.fallbackLocale)[0][this.labelField]; },
generateToggleIconComponent(props) { return this.$h('i', { ...props,
onClick: (selection) => { selection.srcElement.parentElement.classList.toggle('active');
selection.srcElement.classList.toggle('icon-down-arrow', !selection.srcElement.classList.contains('icon-down-arrow')); selection.srcElement.classList.toggle('icon-right-arrow', !selection.srcElement.classList.contains('icon-right-arrow')); }, }); },
generateFolderIconComponent(props) { return this.$h('i', { ...props, }); },
generateCheckboxComponent(props) { return this.$h(this.$resolveComponent('v-tree-checkbox'), { ...props,
onChangeInput: (item) => { this.handleCheckbox(item.value);
this.$emit('change-input', this.formattedValues); }, }); },
generateRadioComponent(props) { return this.$h(this.$resolveComponent('v-tree-radio'), { ...props,
onChangeInput: (item) => { this.$emit('change-input', this.formattedValues[0]); }, }); },
generateInputComponent(props) { switch (this.inputType) { case 'checkbox': return this.generateCheckboxComponent(props);
case 'radio': return this.generateRadioComponent(props);
default: return this.generateCheckboxComponent(props); } },
generateTreeItemComponents(items, level = 1) { let treeItems = [];
for (let key in items) { let hasChildren = Object.entries(items[key][this.childrenField]).length > 0;
treeItems.push( this.$h( 'div', { class: [ this.collapse ? '' : 'active', 'v-tree-item inline-block w-full [&>.v-tree-item]:ltr:pl-6 [&>.v-tree-item]:rtl:pr-6 [&>.v-tree-item]:hidden [&.active>.v-tree-item]:block', level === 1 && ! hasChildren ? 'ltr:!pl-5 rtl:!pr-5' : level > 1 && ! hasChildren ? 'ltr:!pl-14 rtl:!pr-14' : '', ], }, [ this.generateToggleIconComponent({ class: [ hasChildren ? 'icon-down-arrow' : '', 'text-xl rounded-md cursor-pointer transition-all hover:bg-gray-100 dark:hover:bg-gray-950' ], }),
this.generateFolderIconComponent({ class: [ hasChildren ? 'icon-folder' : 'icon-file', 'text-2xl cursor-pointer' ], }),
this.generateInputComponent({ id: this.getId(items[key]), label: this.getLabel(items[key]), name: this.nameField, value: items[key][this.valueField], }),
this.generateTreeItemComponents(items[key][this.childrenField], level + 1), ] ) ); }
return treeItems; },
generateTree() { return this.$h( 'div', { class: [ 'v-tree-item-wrapper', ], }, [ this.generateTreeItemComponents(this.formattedItems), ] ); },
searchInTree(items, value, ancestors = []) { for (let key in items) { if (items[key][this.valueField] === value) { return Object.assign(items[key], { ancestors: ancestors.reverse() }); }
const result = this.searchInTree(items[key][this.childrenField], value, [...ancestors, items[key]]);
if (result !== undefined) { return result; } }
return undefined; },
has(key) { let foundValues = this.formattedValues.filter(value => value == key);
return foundValues.length > 0; },
select(key) { if (! this.has(key)) { this.formattedValues.push(key); } },
unSelect(key) { this.formattedValues = this.formattedValues.filter((savedKey) => savedKey !== key); },
toggle(key) { this.has(key) ? this.unSelect(key) : this.select(key); },
handleCheckbox(key) { let item = this.searchInTree(this.formattedItems, key);
switch (this.selectionType) { case 'individual': this.handleIndividualSelectionType(item);
break;
case 'hierarchical': this.handleHierarchicalSelectionType(item);
break;
default: this.handleHierarchicalSelectionType(item);
break; } },
handleIndividualSelectionType(item) { this.handleCurrent(item); },
handleHierarchicalSelectionType(item) { this.handleAncestors(item);
this.handleCurrent(item);
this.handleChildren(item);
if (! this.has(item[this.valueField])) { this.unSelectAllChildren(item); } },
handleAncestors(item) { if (item.ancestors.length) { item.ancestors.forEach((ancestor) => { this.select(ancestor[this.valueField]); }); } },
handleCurrent(item) { this.toggle(item[this.valueField]); },
handleChildren(item) { let selectedChildrenCount = this.countSelectedChildren(item);
selectedChildrenCount ? this.unSelectAllChildren(item) : this.selectAllChildren(item); },
countSelectedChildren(item, selectedCount = 0) { if (typeof item[this.childrenField] === 'object') { for (let childKey in item[this.childrenField]) { if (this.has(item[this.childrenField][childKey][this.valueField])) { ++selectedCount; }
this.countSelectedChildren(item[this.childrenField][childKey], selectedCount); } }
return selectedCount; },
selectAllChildren(item) { if (typeof item[this.childrenField] === 'object') { for (let childKey in item[this.childrenField]) { this.select(item[this.childrenField][childKey][this.valueField]);
this.selectAllChildren(item[this.childrenField][childKey]); } } },
unSelectAllChildren(item) { if (typeof item[this.childrenField] === 'object') { for (let childKey in item[this.childrenField]) { this.unSelect(item[this.childrenField][childKey][this.valueField]);
this.unSelectAllChildren(item[this.childrenField][childKey]); } } }, },
render() { return this.$h('div', { class: ['v-tree-container'] }, [this.generateTree()]); } }); </script> @endPushOnce
|