-
-
Notifications
You must be signed in to change notification settings - Fork 350
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(database): basic table view grouping support (#4727)
- Loading branch information
Showing
41 changed files
with
1,583 additions
and
918 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
208 changes: 208 additions & 0 deletions
208
packages/blocks/src/database-block/common/group-by/helper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
import type { TType } from '../../logical/typesystem.js'; | ||
import type { InsertPosition } from '../../types.js'; | ||
import { insertPositionToIndex } from '../../utils/insert.js'; | ||
import type { DataViewManager } from '../data-view-manager.js'; | ||
import type { GroupBy, GroupProperty } from '../types.js'; | ||
import type { GroupByConfig } from './matcher.js'; | ||
import { groupByMatcher } from './matcher.js'; | ||
|
||
export type GroupData = { | ||
key: string; | ||
name: string; | ||
helper: GroupHelper; | ||
type: TType; | ||
value: unknown; | ||
rows: string[]; | ||
}; | ||
|
||
export class GroupHelper { | ||
constructor( | ||
private groupBy: GroupBy, | ||
config: GroupByConfig, | ||
type: TType, | ||
private viewManager: DataViewManager, | ||
private ops: { | ||
sortGroup: (keys: string[]) => string[]; | ||
sortRow: (groupKey: string, rowIds: string[]) => string[]; | ||
changeGroupSort: (keys: string[]) => void; | ||
changeRowSort: ( | ||
groupKeys: string[], | ||
groupKey: string, | ||
keys: string[] | ||
) => void; | ||
} | ||
) { | ||
this.groupMap = Object.fromEntries( | ||
config.defaultKeys(type).map(({ key, value }) => [ | ||
key, | ||
{ | ||
key, | ||
name: config.groupName(type, value), | ||
helper: this, | ||
type, | ||
value, | ||
rows: [], | ||
}, | ||
]) | ||
); | ||
this.viewManager.rows.forEach(id => { | ||
const value = this.viewManager.cellGetJsonValue(id, groupBy.columnId); | ||
const keys = config.valuesGroup(value, type); | ||
keys.forEach(({ key, value }) => { | ||
if (!this.groupMap[key]) { | ||
this.groupMap[key] = { | ||
key, | ||
name: config.groupName(type, value), | ||
helper: this, | ||
value, | ||
rows: [], | ||
type, | ||
}; | ||
} | ||
this.groupMap[key].rows.push(id); | ||
}); | ||
}); | ||
const sortedGroup = ops.sortGroup(Object.keys(this.groupMap)); | ||
sortedGroup.forEach(key => { | ||
this.groupMap[key].rows = ops.sortRow(key, this.groupMap[key].rows); | ||
}); | ||
this.groups = sortedGroup.map(key => this.groupMap[key]); | ||
} | ||
|
||
get dataType() { | ||
return this.viewManager.columnGetDataType(this.groupBy.columnId); | ||
} | ||
|
||
get column() { | ||
return this.viewManager.columnGet(this.groupBy.columnId); | ||
} | ||
|
||
get columnId() { | ||
return this.groupBy.columnId; | ||
} | ||
|
||
get type() { | ||
return this.viewManager.columnGetType(this.columnId); | ||
} | ||
|
||
get data() { | ||
return this.viewManager.columnGetData(this.columnId); | ||
} | ||
|
||
updateData = (data: NonNullable<unknown>) => { | ||
this.viewManager.columnUpdateData(this.columnId, data); | ||
}; | ||
|
||
updateValue(rows: string[], value: unknown) { | ||
rows.forEach(id => { | ||
this.viewManager.cellUpdateValue(id, this.columnId, value); | ||
}); | ||
} | ||
|
||
public readonly groups: GroupData[]; | ||
public readonly groupMap: Record<string, GroupData>; | ||
|
||
groupConfig() { | ||
return groupByMatcher.findData(v => v.name === this.groupBy.name); | ||
} | ||
|
||
defaultGroupProperty(key: string): GroupProperty { | ||
return { | ||
key, | ||
hide: false, | ||
manuallyCardSort: [], | ||
}; | ||
} | ||
|
||
addToGroup(rowId: string, key: string) { | ||
const columnId = this.columnId; | ||
const addTo = this.groupConfig()?.addToGroup ?? (value => value); | ||
const newValue = addTo( | ||
this.groupMap[key].value, | ||
this.viewManager.cellGetJsonValue(rowId, columnId) | ||
); | ||
this.viewManager.cellUpdateValue(rowId, columnId, newValue); | ||
} | ||
|
||
removeFromGroup(rowId: string, key: string) { | ||
const columnId = this.columnId; | ||
const remove = this.groupConfig()?.removeFromGroup ?? (() => undefined); | ||
const newValue = remove( | ||
this.groupMap[key].value, | ||
this.viewManager.cellGetJsonValue(rowId, columnId) | ||
); | ||
this.viewManager.cellUpdateValue(rowId, columnId, newValue); | ||
} | ||
|
||
changeCardSort(groupKey: string, cardIds: string[]) { | ||
this.ops.changeRowSort( | ||
this.groups.map(v => v.key), | ||
groupKey, | ||
cardIds | ||
); | ||
} | ||
|
||
changeGroupSort(keys: string[]) { | ||
this.ops.changeGroupSort(keys); | ||
} | ||
|
||
public moveGroupTo(groupKey: string, position: InsertPosition) { | ||
const keys = this.groups.map(v => v.key); | ||
keys.splice( | ||
keys.findIndex(key => key === groupKey), | ||
1 | ||
); | ||
const index = insertPositionToIndex(position, keys, key => key); | ||
keys.splice(index, 0, groupKey); | ||
this.changeGroupSort(keys); | ||
} | ||
|
||
moveCardTo( | ||
rowId: string, | ||
fromGroupKey: string | undefined, | ||
toGroupKey: string, | ||
position: InsertPosition | ||
) { | ||
if (fromGroupKey !== toGroupKey) { | ||
const columnId = this.columnId; | ||
const remove = this.groupConfig()?.removeFromGroup ?? (() => undefined); | ||
const group = | ||
fromGroupKey != null ? this.groupMap[fromGroupKey] : undefined; | ||
let newValue: unknown = undefined; | ||
if (group) { | ||
newValue = remove( | ||
group.value, | ||
this.viewManager.cellGetJsonValue(rowId, columnId) | ||
); | ||
} | ||
const addTo = this.groupConfig()?.addToGroup ?? (value => value); | ||
newValue = addTo(this.groupMap[toGroupKey].value, newValue); | ||
this.viewManager.cellUpdateValue(rowId, columnId, newValue); | ||
} | ||
const rows = this.groupMap[toGroupKey].rows.filter(id => id !== rowId); | ||
const index = insertPositionToIndex(position, rows, id => id); | ||
rows.splice(index, 0, rowId); | ||
this.changeCardSort(toGroupKey, rows); | ||
} | ||
get addGroup() { | ||
return this.viewManager.columnConfigManager.getColumn(this.column.type).ops | ||
.addGroup; | ||
} | ||
} | ||
export const sortByManually = <T>( | ||
arr: T[], | ||
getId: (v: T) => string, | ||
ids: string[] | ||
) => { | ||
const map = new Map(arr.map(v => [getId(v), v])); | ||
const result: T[] = []; | ||
for (const id of ids) { | ||
const value = map.get(id); | ||
if (value) { | ||
map.delete(id); | ||
result.push(value); | ||
} | ||
} | ||
result.push(...map.values()); | ||
return result; | ||
}; |
Oops, something went wrong.
c956087
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
blocksuite – ./packages/playground
blocksuite-toeverything.vercel.app
blocksuite-git-master-toeverything.vercel.app
blocksuite-five.vercel.app
c956087
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Size Report
Bundles
Packages