142 lines
3.7 KiB
JavaScript
142 lines
3.7 KiB
JavaScript
// Composables
|
|
import { useProxiedModel } from "../../../composables/proxiedModel.mjs"; // Utilities
|
|
import { computed, inject, provide, ref } from 'vue';
|
|
import { getObjectValueByPath, propsFactory } from "../../../util/index.mjs"; // Types
|
|
export const makeDataTableGroupProps = propsFactory({
|
|
groupBy: {
|
|
type: Array,
|
|
default: () => []
|
|
}
|
|
}, 'DataTable-group');
|
|
const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
|
|
export function createGroupBy(props) {
|
|
const groupBy = useProxiedModel(props, 'groupBy');
|
|
return {
|
|
groupBy
|
|
};
|
|
}
|
|
export function provideGroupBy(options) {
|
|
const {
|
|
groupBy,
|
|
sortBy
|
|
} = options;
|
|
const opened = ref(new Set());
|
|
const sortByWithGroups = computed(() => {
|
|
return groupBy.value.map(val => ({
|
|
...val,
|
|
order: val.order ?? false
|
|
})).concat(sortBy.value);
|
|
});
|
|
function isGroupOpen(group) {
|
|
return opened.value.has(group.id);
|
|
}
|
|
function toggleGroup(group) {
|
|
const newOpened = new Set(opened.value);
|
|
if (!isGroupOpen(group)) newOpened.add(group.id);else newOpened.delete(group.id);
|
|
opened.value = newOpened;
|
|
}
|
|
function extractRows(items) {
|
|
function dive(group) {
|
|
const arr = [];
|
|
for (const item of group.items) {
|
|
if ('type' in item && item.type === 'group') {
|
|
arr.push(...dive(item));
|
|
} else {
|
|
arr.push(item);
|
|
}
|
|
}
|
|
return arr;
|
|
}
|
|
return dive({
|
|
type: 'group',
|
|
items,
|
|
id: 'dummy',
|
|
key: 'dummy',
|
|
value: 'dummy',
|
|
depth: 0
|
|
});
|
|
}
|
|
|
|
// onBeforeMount(() => {
|
|
// for (const key of groupedItems.value.keys()) {
|
|
// opened.value.add(key)
|
|
// }
|
|
// })
|
|
|
|
const data = {
|
|
sortByWithGroups,
|
|
toggleGroup,
|
|
opened,
|
|
groupBy,
|
|
extractRows,
|
|
isGroupOpen
|
|
};
|
|
provide(VDataTableGroupSymbol, data);
|
|
return data;
|
|
}
|
|
export function useGroupBy() {
|
|
const data = inject(VDataTableGroupSymbol);
|
|
if (!data) throw new Error('Missing group!');
|
|
return data;
|
|
}
|
|
function groupItemsByProperty(items, groupBy) {
|
|
if (!items.length) return [];
|
|
const groups = new Map();
|
|
for (const item of items) {
|
|
const value = getObjectValueByPath(item.raw, groupBy);
|
|
if (!groups.has(value)) {
|
|
groups.set(value, []);
|
|
}
|
|
groups.get(value).push(item);
|
|
}
|
|
return groups;
|
|
}
|
|
function groupItems(items, groupBy) {
|
|
let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
let prefix = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'root';
|
|
if (!groupBy.length) return [];
|
|
const groupedItems = groupItemsByProperty(items, groupBy[0]);
|
|
const groups = [];
|
|
const rest = groupBy.slice(1);
|
|
groupedItems.forEach((items, value) => {
|
|
const key = groupBy[0];
|
|
const id = `${prefix}_${key}_${value}`;
|
|
groups.push({
|
|
depth,
|
|
id,
|
|
key,
|
|
value,
|
|
items: rest.length ? groupItems(items, rest, depth + 1, id) : items,
|
|
type: 'group'
|
|
});
|
|
});
|
|
return groups;
|
|
}
|
|
function flattenItems(items, opened) {
|
|
const flatItems = [];
|
|
for (const item of items) {
|
|
// TODO: make this better
|
|
if ('type' in item && item.type === 'group') {
|
|
if (item.value != null) {
|
|
flatItems.push(item);
|
|
}
|
|
if (opened.has(item.id) || item.value == null) {
|
|
flatItems.push(...flattenItems(item.items, opened));
|
|
}
|
|
} else {
|
|
flatItems.push(item);
|
|
}
|
|
}
|
|
return flatItems;
|
|
}
|
|
export function useGroupedItems(items, groupBy, opened) {
|
|
const flatItems = computed(() => {
|
|
if (!groupBy.value.length) return items.value;
|
|
const groupedItems = groupItems(items.value, groupBy.value.map(item => item.key));
|
|
return flattenItems(groupedItems, opened.value);
|
|
});
|
|
return {
|
|
flatItems
|
|
};
|
|
}
|
|
//# sourceMappingURL=group.mjs.map
|