Skip to content

Commit

Permalink
fix: improve initial state logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mesqueeb committed Sep 4, 2023
1 parent c872985 commit 07568d6
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 45 deletions.
58 changes: 35 additions & 23 deletions packages/ui/src/components/MagnetarTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import {
import {
calcCollection,
carbonCopyMap,
columnsToInitialOrderByState,
filtersAndColumnsToInitialState,
filterStateToClauses,
filtersToInitialState,
getRequiredOrderByBasedOnFilters,
mapUnshift,
orderByStateToClauses,
Expand Down Expand Up @@ -55,35 +54,48 @@ function muiLabel(label: MUILabel): string {
// const emit = defineEmits<{}>()
const fetchState = ref<'ok' | 'end' | 'fetching' | { error: string }>('ok')
const initialFilterState = ((): FiltersState => {
const map = filtersToInitialState(props.filters)
const initialState = ((): {
filtersState: FiltersState
orderByState: OrderByState
} => {
const { filtersState, orderByState } = filtersAndColumnsToInitialState({
columns: props.columns,
filters: props.filters,
})
if (props.filtersState) {
for (const [index, state] of props.filtersState) {
map.set(index, state)
filtersState.set(index, state)
}
}
return map
return {
filtersState,
orderByState: props.orderByState || orderByState,
}
})()
const initialOrderByState: OrderByState =
props.orderByState || columnsToInitialOrderByState(props.columns, initialFilterState)
const filtersState = ref<FiltersState>(carbonCopyMap(initialFilterState))
const orderByState = ref<OrderByState>(carbonCopyMap(initialOrderByState))
const filtersState = ref<FiltersState>(carbonCopyMap(initialState.filtersState))
const orderByState = ref<OrderByState>(carbonCopyMap(initialState.orderByState))
const currentFilters = computed(() => filterStateToClauses(filtersState.value, props.filters))
const currentOrderBy = computed(() => orderByStateToClauses(orderByState.value))
const initialStateActive = computed<boolean>(
() =>
filtersState.value.size === initialFilterState.size &&
orderByState.value.size === initialOrderByState.size &&
[...filtersState.value.entries()].every(
([key, value]) => initialFilterState.get(key) === value
) &&
[...orderByState.value.entries()].every(
([key, value]) => initialOrderByState.get(key) === value
)
)
/**
* This will always be true in case there was no initialState
*/
const initialStateActive = computed<boolean>(() => {
const initialFilters = initialState.filtersState
const initialOrderBy = initialState.orderByState
if (!initialFilters.size && !initialOrderBy.size) {
return true
}
return (
filtersState.value.size === initialFilters.size &&
orderByState.value.size === initialOrderBy.size &&
[...filtersState.value.entries()].every(([key, value]) => initialFilters.get(key) === value) &&
[...orderByState.value.entries()].every(([key, value]) => initialOrderBy.get(key) === value)
)
})
const hasSomeFilterOrOrderby = computed<boolean>(
() => !!filtersState.value.size || !!orderByState.value.size
)
Expand All @@ -99,8 +111,8 @@ function clearAllRecords(): void {
}
function resetState(): void {
filtersState.value = carbonCopyMap(initialFilterState)
orderByState.value = carbonCopyMap(initialOrderByState)
filtersState.value = carbonCopyMap(initialState.filtersState)
orderByState.value = carbonCopyMap(initialState.orderByState)
clearAllRecords()
fetchMore()
}
Expand Down
64 changes: 42 additions & 22 deletions packages/ui/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@ export function whereClausesEqual(where1?: WhereClause, where2?: WhereClause): b
)
}

export function filtersToInitialState(filters: MUIFilter<Record<string, any>>[]): FiltersState {
export function filtersAndColumnsToInitialState(params: {
columns: MUIColumn<any>[]
filters: MUIFilter<Record<string, any>>[]
}): {
filtersState: FiltersState
orderByState: OrderByState
} {
const { columns, filters } = params
// remember, see `FiltersState` for instructions how to save the state.
return filters.reduce<FiltersState>((map, f, i) => {
const _filtersState = filters.reduce<FiltersState>((map, f, i) => {
if (f.type === 'radio' || f.type === 'select') {
const firstChecked = f.options?.find((o) => o.checked)
if (firstChecked) map.set(i, firstChecked.where)
Expand All @@ -55,6 +62,39 @@ export function filtersToInitialState(filters: MUIFilter<Record<string, any>>[])
}
return map
}, new Map())

// maybe we needed to clear other filters, let's do that for the first filter we find that needs it
const entryThatClearsOtherFilters = [..._filtersState.entries()].find(([filterIndex]) => {
const filter = filters[filterIndex]
return filter?.clearOtherFilters
})
const filtersState = entryThatClearsOtherFilters
? new Map([entryThatClearsOtherFilters])
: _filtersState

// maybe we needed to clear other orderBy, let's do that for the first filter we find that needs it
const entryThatClearsOtherOrderBy = [...filtersState.entries()].find(([filterIndex]) => {
const filter = filters[filterIndex]
return filter?.clearOrderBy
})

const _orderByState = entryThatClearsOtherOrderBy
? new Map()
: sort(columns)
// sort columns by sortable.position
.asc((c) => (isPlainObject(c.sortable) ? c.sortable.position : -1))
// then grab each column's sortable.orderBy and save as "direction" in a map
.reduce<OrderByState>((map, column) => {
if (isPlainObject(column.sortable) && column.sortable.orderBy && column.fieldPath) {
map.set(column.fieldPath, column.sortable.orderBy)
}
return map
}, new Map())

const newEntries = getRequiredOrderByBasedOnFilters(filtersState)
const orderByState = newEntries.length ? mapUnshift(_orderByState, ...newEntries) : _orderByState

return { filtersState, orderByState }
}

/**
Expand Down Expand Up @@ -98,26 +138,6 @@ export function getRequiredOrderByBasedOnFilters(
}, [])
}

export function columnsToInitialOrderByState(
columns: MUIColumn<any>[],
initialFilterState: FiltersState
): OrderByState {
const orderByState = sort(columns)
// sort columns by sortable.position
.asc((c) => (isPlainObject(c.sortable) ? c.sortable.position : -1))
// then grab each column's sortable.orderBy and save as "direction" in a map
.reduce<OrderByState>((map, column) => {
if (isPlainObject(column.sortable) && column.sortable.orderBy && column.fieldPath) {
map.set(column.fieldPath, column.sortable.orderBy)
}
return map
}, new Map())

const newEntries = getRequiredOrderByBasedOnFilters(initialFilterState)
if (newEntries.length) return mapUnshift(orderByState, ...newEntries)
return orderByState
}

/** Clears JavaScript reference pointers */
export function carbonCopyMap<T extends Map<any, any>>(map: T): T {
let newMap = new Map() as T
Expand Down

0 comments on commit 07568d6

Please sign in to comment.