group.mjs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Composables
  2. import { useProxiedModel } from "../../../composables/proxiedModel.mjs"; // Utilities
  3. import { computed, inject, provide, ref } from 'vue';
  4. import { getObjectValueByPath, propsFactory } from "../../../util/index.mjs"; // Types
  5. export const makeDataTableGroupProps = propsFactory({
  6. groupBy: {
  7. type: Array,
  8. default: () => []
  9. }
  10. }, 'DataTable-group');
  11. const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
  12. export function createGroupBy(props) {
  13. const groupBy = useProxiedModel(props, 'groupBy');
  14. return {
  15. groupBy
  16. };
  17. }
  18. export function provideGroupBy(options) {
  19. const {
  20. disableSort,
  21. groupBy,
  22. sortBy
  23. } = options;
  24. const opened = ref(new Set());
  25. const sortByWithGroups = computed(() => {
  26. return groupBy.value.map(val => ({
  27. ...val,
  28. order: val.order ?? false
  29. })).concat(disableSort?.value ? [] : sortBy.value);
  30. });
  31. function isGroupOpen(group) {
  32. return opened.value.has(group.id);
  33. }
  34. function toggleGroup(group) {
  35. const newOpened = new Set(opened.value);
  36. if (!isGroupOpen(group)) newOpened.add(group.id);else newOpened.delete(group.id);
  37. opened.value = newOpened;
  38. }
  39. function extractRows(items) {
  40. function dive(group) {
  41. const arr = [];
  42. for (const item of group.items) {
  43. if ('type' in item && item.type === 'group') {
  44. arr.push(...dive(item));
  45. } else {
  46. arr.push(item);
  47. }
  48. }
  49. return arr;
  50. }
  51. return dive({
  52. type: 'group',
  53. items,
  54. id: 'dummy',
  55. key: 'dummy',
  56. value: 'dummy',
  57. depth: 0
  58. });
  59. }
  60. // onBeforeMount(() => {
  61. // for (const key of groupedItems.value.keys()) {
  62. // opened.value.add(key)
  63. // }
  64. // })
  65. const data = {
  66. sortByWithGroups,
  67. toggleGroup,
  68. opened,
  69. groupBy,
  70. extractRows,
  71. isGroupOpen
  72. };
  73. provide(VDataTableGroupSymbol, data);
  74. return data;
  75. }
  76. export function useGroupBy() {
  77. const data = inject(VDataTableGroupSymbol);
  78. if (!data) throw new Error('Missing group!');
  79. return data;
  80. }
  81. function groupItemsByProperty(items, groupBy) {
  82. if (!items.length) return [];
  83. const groups = new Map();
  84. for (const item of items) {
  85. const value = getObjectValueByPath(item.raw, groupBy);
  86. if (!groups.has(value)) {
  87. groups.set(value, []);
  88. }
  89. groups.get(value).push(item);
  90. }
  91. return groups;
  92. }
  93. function groupItems(items, groupBy) {
  94. let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  95. let prefix = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'root';
  96. if (!groupBy.length) return [];
  97. const groupedItems = groupItemsByProperty(items, groupBy[0]);
  98. const groups = [];
  99. const rest = groupBy.slice(1);
  100. groupedItems.forEach((items, value) => {
  101. const key = groupBy[0];
  102. const id = `${prefix}_${key}_${value}`;
  103. groups.push({
  104. depth,
  105. id,
  106. key,
  107. value,
  108. items: rest.length ? groupItems(items, rest, depth + 1, id) : items,
  109. type: 'group'
  110. });
  111. });
  112. return groups;
  113. }
  114. function flattenItems(items, opened) {
  115. const flatItems = [];
  116. for (const item of items) {
  117. // TODO: make this better
  118. if ('type' in item && item.type === 'group') {
  119. if (item.value != null) {
  120. flatItems.push(item);
  121. }
  122. if (opened.has(item.id) || item.value == null) {
  123. flatItems.push(...flattenItems(item.items, opened));
  124. }
  125. } else {
  126. flatItems.push(item);
  127. }
  128. }
  129. return flatItems;
  130. }
  131. export function useGroupedItems(items, groupBy, opened) {
  132. const flatItems = computed(() => {
  133. if (!groupBy.value.length) return items.value;
  134. const groupedItems = groupItems(items.value, groupBy.value.map(item => item.key));
  135. return flattenItems(groupedItems, opened.value);
  136. });
  137. return {
  138. flatItems
  139. };
  140. }
  141. //# sourceMappingURL=group.mjs.map