Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
farmaazon committed Jan 27, 2025
1 parent 45dd855 commit 7b21c0e
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type {
ProcessDataFromClipboardParams,
RowDragEndEvent,
} from 'ag-grid-enterprise'
import { ComponentInstance, computed, proxyRefs, ref } from 'vue'
import { ComponentInstance, computed, proxyRefs, ref, watch, watchEffect } from 'vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
import { z } from 'zod'
import TableHeader, { HeaderParams } from './WidgetTableEditor/TableHeader.vue'
Expand Down Expand Up @@ -67,7 +67,7 @@ const { rowData, columnDefs, moveColumn, moveRow, pasteFromClipboard } = useTabl
// === Edit Handlers ===
const { editedCell, gridEventHandlers, headerEventHandlers } = useTableEditHandler(
const { handler, editedCell, gridEventHandlers, headerEventHandlers } = useTableEditHandler(
() => grid.value?.gridApi,
columnDefs,
(hooks) => {
Expand All @@ -88,6 +88,18 @@ const { editedCell, gridEventHandlers, headerEventHandlers } = useTableEditHandl
},
)
watch(
() => props.input.value,
() => grid.value?.gridApi?.refreshCells(),
)
// const rowDataSuppressed = ref<typeof rowData.value>([])
// watchEffect(() => {
// if (!handler.isActive() || true) {
// rowDataSuppressed.value = rowData.value
// }
// })
// === Resizing ===
const graphNav = injectGraphNavigator()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ function emitEditEnd() {
watch(inputElement, (newVal, oldVal) => {
if (newVal != null) {
// Whenever input field appears, focus and select text
// Whenever input field appears, put text, focus and select
// We don't do that through props, because we don't want updates.
newVal.value = props.displayName
newVal.focus()
newVal.select()
}
Expand Down Expand Up @@ -115,12 +117,14 @@ function onMouseRightClick(event: MouseEvent) {
v-if="editing"
ref="inputElement"
class="ag-input-field-input ag-text-field-input"
:value="displayName"
@change="acceptNewName"
@keydown.arrow-left.stop
@keydown.arrow-right.stop
@keydown.arrow-up.stop
@keydown.arrow-down.stop
@keydown.tab.prevent="{
// We prevent default, because switching edit on tab is handled by the widget edit
// handlers
}"
/>
<span
v-else
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { NEW_COLUMN_ID } from '@/components/GraphEditor/widgets/WidgetTableEditor/tableInputArgument'
import { InteractionHandler } from '@/providers/interactionHandler'
import { WidgetInput } from '@/providers/widgetRegistry'
import { WidgetEditHandler, WidgetEditHooks } from '@/providers/widgetRegistry/editHandler'
import { ToValue } from '@/util/reactivity'
import {
CellEditingStartedEvent,
CellEditingStoppedEvent,
CellPosition,
StartEditingCellParams,
} from 'ag-grid-enterprise'
import { CellEditingStoppedEvent, CellPosition, StartEditingCellParams } from 'ag-grid-enterprise'
import { computed, ref, toValue, watch } from 'vue'

export interface EditedCell {
Expand Down Expand Up @@ -90,21 +83,28 @@ export function useTableEditHandler(
handler.start()
}
},
cellEditingStopped() {
cellEditingStopped(event: { rowIndex: number | undefined; column: { getColId(): string } }) {
console.error(event)
const api = toValue(gridApi)
if (!api?.getEditingCells().length && handler.isActive()) {
if (
event.rowIndex === editedCell.value?.rowIndex &&
event.column.getColId() === editedCell.value?.colKey &&
!api?.getEditingCells().length &&
handler.isActive()
) {
handler.end()
}
},
rowDataUpdated() {
console.error('Row data updated!', editedCell.value)
syncGridWithEditedCell()
},
keydown(event: KeyboardEvent) {
const handler =
event.code === 'Tab' ? tabPressed
: event.code === 'Enter' ? enterPressed
: undefined
if (handler?.() === false) {
if (handler && handler() !== false) {
event.stopPropagation()
}
},
Expand Down Expand Up @@ -132,6 +132,7 @@ export function useTableEditHandler(
}

function tabPressed() {
console.log('Tab pressed when edited', editedCell.value)
// When cell is edited, AgGrid handles tab correctly.
if (editedCell.value == null || editedCell.value.rowIndex !== 'header') return false
const currentIndex = columnIndexById.value.get(editedCell.value.colKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { assert } from '@/util/assert'
import { Ast } from '@/util/ast'
import { findIndexOpt } from '@/util/data/array'
import { Err, Ok, type Result, transposeResult, unwrapOrWithLog } from '@/util/data/result'
import { arrayEquals } from '@/util/equals'
import { qnLastSegment, type QualifiedName } from '@/util/qualifiedName'
import type { ToValue } from '@/util/reactivity'
import { cachedGetter, type ToValue } from '@/util/reactivity'
import type { ColDef } from 'ag-grid-enterprise'
import * as iter from 'enso-common/src/utilities/data/iter'
import { computed, toValue } from 'vue'
import { a } from 'vitest/dist/chunks/suite.BJU7kdY9.js'
import { computed, ref, toValue, watch, watchEffect } from 'vue'
import type { ColumnSpecificParams } from './TableHeader.vue'

/** Id of a fake column with "Add new column" option. */
Expand Down Expand Up @@ -154,6 +156,11 @@ export function useTableInputArgument(
return unwrapOrWithLog(cols, [], errorMessagePreamble)
})

const columnHeaders = cachedGetter(
() => Array.from(columns.value, (col) => ({ id: col.id, name: col.name.rawTextContent })),
(a, b) => arrayEquals(a, b, (a, b) => a.id === b.id && a.name === b.name),
)

const rowCount = computed(() =>
columns.value.reduce((soFar, col) => Math.max(soFar, col.data.length), 0),
)
Expand Down Expand Up @@ -183,7 +190,7 @@ export function useTableInputArgument(

function mayAddNewColumn(
rowCount_: number = rowCount.value,
colCount: number = columns.value.length,
colCount: number = columnHeaders.value.length,
): boolean {
return rowCount_ * (colCount + 1) <= CELLS_LIMIT
}
Expand Down Expand Up @@ -278,59 +285,70 @@ export function useTableInputArgument(
},
})

const newColumnDef = computed<ColumnDef>(() => ({
colId: NEW_COLUMN_ID,
headerName: '',
valueGetter: () => null,
editable: false,
resizable: false,
suppressNavigable: true,
width: 40,
maxWidth: 40,
headerComponentParams: {
columnParams: {
type: 'newColumn',
enabled: mayAddNewColumn(),
newColumnRequested: () => {
const edit = graph.startEdit()
fixColumns(edit)
addColumn(edit, `${DEFAULT_COLUMN_PREFIX}${columns.value.length + 1}`)
onUpdate({ edit, directInteraction: true })
const newColumnDef = computed<ColumnDef>(
() => (
console.error('Updating newColumnDef'),
{
colId: NEW_COLUMN_ID,
headerName: '',
valueGetter: () => null,
editable: false,
resizable: false,
suppressNavigable: true,
width: 40,
maxWidth: 40,
headerComponentParams: {
columnParams: {
type: 'newColumn',
enabled: mayAddNewColumn(),
newColumnRequested: () => {
const edit = graph.startEdit()
fixColumns(edit)
addColumn(edit, `${DEFAULT_COLUMN_PREFIX}${columns.value.length + 1}`)
onUpdate({ edit, directInteraction: true })
},
},
},
},
},
mainMenuItems: ['autoSizeThis', 'autoSizeAll'],
contextMenuItems: [removeRowMenuItem],
lockPosition: 'right',
cellClass: 'newColumnCell',
}))

const rowIndexColumnDef = computed<ColumnDef>(() => ({
colId: ROW_INDEX_COLUMN_ID,
headerName: ROW_INDEX_HEADER,
valueGetter: ({ data }: { data: RowData | undefined }) => data?.index,
editable: false,
resizable: false,
suppressNavigable: true,
headerComponentParams: { columnParams: { type: 'rowIndexColumn' } },
mainMenuItems: ['autoSizeThis', 'autoSizeAll'],
contextMenuItems: [removeRowMenuItem],
cellClass: 'rowIndexCell',
lockPosition: 'left',
rowDrag: ({ data }: { data: RowData | undefined }) =>
data?.index != null && data.index < rowCount.value,
}))
mainMenuItems: ['autoSizeThis', 'autoSizeAll'],
contextMenuItems: [removeRowMenuItem],
lockPosition: 'right',
cellClass: 'newColumnCell',
}
),
)

const rowIndexColumnDef = computed<ColumnDef>(
() => (
console.error('Updating rowIndexColumnDef'),
{
colId: ROW_INDEX_COLUMN_ID,
headerName: ROW_INDEX_HEADER,
valueGetter: ({ data }: { data: RowData | undefined }) => data?.index,
editable: false,
resizable: false,
suppressNavigable: true,
headerComponentParams: { columnParams: { type: 'rowIndexColumn' } },
mainMenuItems: ['autoSizeThis', 'autoSizeAll'],
contextMenuItems: [removeRowMenuItem],
cellClass: 'rowIndexCell',
lockPosition: 'left',
rowDrag: ({ data }: { data: RowData | undefined }) =>
data?.index != null && data.index < rowCount.value,
}
),
)

const columnDefs = computed(() => {
console.error('Updating columnDefs')
const cols: ColumnDef[] = Array.from(
columns.value,
(col) =>
columnHeaders.value,
(col, i) =>
({
colId: col.id,
headerName: col.name.rawTextContent,
headerName: col.name,
valueGetter: ({ data }: { data: RowData | undefined }) => {
if (data == null) return undefined
const ast = toValue(input).value.module.tryGet(data.cells[col.data.id])
const ast = toValue(input).value.module.tryGet(data.cells[columns.value[i]!.data.id])
if (ast == null) return null
const value = cellValueConversion.astToAgGrid(ast as Ast.Expression)
if (!value.ok) {
Expand All @@ -342,15 +360,16 @@ export function useTableInputArgument(
return value.value
},
valueSetter: ({ data, newValue }: { data: RowData; newValue: any }): boolean => {
const astId = data?.cells[col.data.id]
const astId = data?.cells[col.id]
const edit = graph.startEdit()
fixColumns(edit)
if (data.index === rowCount.value) {
addRow(edit, (colId) => (colId === col.data.id ? newValue : null))
addRow(edit, (colId) => (colId === col.id ? newValue : null))
} else {
const newValueAst = convertWithImport(newValue, edit)
if (astId != null) edit.replaceValue(astId, newValueAst)
else edit.getVersion(col.data).set(data.index, newValueAst)
// TODO
else edit.getVersion(columns.value[i]!.data).set(data.index, newValueAst)
}
onUpdate({ edit, directInteraction: true })
return true
Expand All @@ -361,7 +380,7 @@ export function useTableInputArgument(
nameSetter: (newName: string) => {
const edit = graph.startEdit()
fixColumns(edit)
edit.getVersion(col.name).setRawTextContent(newName)
edit.getVersion(columns.value[i]!.name).setRawTextContent(newName)
onUpdate({ edit, directInteraction: true })
},
},
Expand All @@ -386,25 +405,42 @@ export function useTableInputArgument(
return cols
})

const rowData = computed(() => {
const rows: RowData[] = []
for (const col of columns.value) {
for (const [rowIndex, value] of col.data.enumerate()) {
const row: RowData = rows.at(rowIndex) ?? { index: rowIndex, cells: {} }
assert(rowIndex <= rows.length)
if (rowIndex === rows.length) {
rows.push(row)
}
if (value?.id) {
row.cells[col.data.id] = value?.id
const rowData = ref<RowData[]>([])

watch(
columns,
(columns) => {
console.log('Update rowData if needed')
for (const col of columns) {
for (const [rowIndex, value] of col.data.enumerate()) {
const row: RowData = rowData.value.at(rowIndex) ?? { index: rowIndex, cells: {} }
assert(rowIndex <= rowData.value.length)
if (rowIndex === rowData.value.length) {
rowData.value.push(row)
}
if (value?.id && row.cells[col.data.id] != value.id) {
row.cells[col.data.id] = value.id
} else if (!value?.id && row.cells[col.data.id]) {
delete row.cells[col.data.id]
}
}
}
}
if (mayAddNewRow()) {
rows.push({ index: rows.length, cells: {} })
}
return rows
})
const expectedRowNumber = rowCount.value + (mayAddNewRow() ? 1 : 0)
if (expectedRowNumber < rowData.value.length) {
rowData.value.splice(expectedRowNumber)
} else if (expectedRowNumber > rowData.value.length) {
const toAdd = expectedRowNumber - rowData.value.length
rowData.value.splice(
rowData.value.length,
0,
...Array(toAdd).fill({ index: rowCount.value, cells: {} }),
)
}
},
{ immediate: true },
)

watch(rowData, () => console.error('Updating rowData'), { flush: 'sync' })

const nothingImport = computed(() => requiredImportsByFQN(suggestions, NOTHING_PATH, true))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import type {
GetRowIdFunc,
GridApi,
GridReadyEvent,
ICellEditorComp,
IHeaderComp,
IHeaderParams,
MenuItemDef,
Expand Down Expand Up @@ -317,14 +318,15 @@ const vueHost = new VueHost()
const mappedComponents = computed(() => {
if (!props.components) return
const retval: Record<string, new () => IHeaderComp> = {}
const retval: Record<string, new () => IHeaderComp | ICellEditorComp> = {}
for (const [key, comp] of Object.entries(props.components)) {
class ComponentWrapper implements IHeaderComp {
private readonly container: HTMLElement = document.createElement('div')
private handle: VueComponentHandle | undefined
init(params: IHeaderParams) {
this.handle = vueHost.register(h(comp, params), this.container)
console.log('init')
this.handle = vueHost.register(h(comp, params), this.container, params.column.getColId())
}
getGui() {
Expand All @@ -337,6 +339,7 @@ const mappedComponents = computed(() => {
}
destroy() {
console.log('destroy')
this.handle?.unregister()
}
}
Expand Down

0 comments on commit 7b21c0e

Please sign in to comment.