in frontend/apps/quantgrid/src/app/hooks/useManualEditDSL/useManualEditDSL.ts [29:1170]
export function useManualEditDSL() {
const {
projectName,
sheetContent,
parsedSheet,
projectSheets,
openStatusModal,
} = useContext(ProjectContext);
const {
updateDSL,
findTableField,
findTable,
findLastTableField,
findFieldOnLeftOrRight,
findContext,
} = useDSLUtils();
const { gridApi, gridService } = useContext(SpreadsheetContext);
const { append, appendTo } = useContext(UndoRedoContext);
const { addOverride, removeOverride, renameOverrideField } =
useOverridesManualEditDSL();
const renameTable = useCallback(
(oldName: string, newName: string) => {
if (!sheetContent || !parsedSheet) return;
if (oldName === newName) return;
const targetTable = findTable(oldName);
if (!targetTable?.dslTableNamePlacement) return;
const { end, start } = targetTable.dslTableNamePlacement;
const uniqueNewTableName = createUniqueName(
newName.includes(' ') ? `'${newName}'` : newName,
getAllTableNames(projectSheets)
);
const updatedSheetContent =
sheetContent.substring(0, start) +
uniqueNewTableName +
sheetContent.substring(end);
updateDSL(updatedSheetContent);
append(
`Rename table "${oldName}" to "${uniqueNewTableName}"`,
updatedSheetContent
);
},
[append, findTable, parsedSheet, projectSheets, sheetContent, updateDSL]
);
const moveTable = useCallback(
(tableName: string, rowDelta: number, colDelta: number) => {
if (!sheetContent) return;
const targetTable = findTable(tableName);
if (!targetTable) return;
const placementDecorator = targetTable.decorators.find(
({ decoratorName }) => decoratorName === 'placement'
);
let dsl = sheetContent;
if (placementDecorator) {
if (rowDelta === 0 && colDelta === 0) return;
const { start, end } = placementDecorator.dslPlacement;
const [startRow, startCol] = placementDecorator.params[0] as [
number,
number
];
dsl =
sheetContent.substring(0, start) +
`!placement(${startRow + rowDelta}, ${startCol + colDelta})` +
sheetContent.substring(end + 1);
append(
`Move table "${tableName}" to (${startRow + rowDelta}, ${
startCol + colDelta
})`,
dsl
);
} else {
if (!targetTable.dslTableNamePlacement) return;
dsl =
sheetContent.substring(
0,
targetTable.dslTableNamePlacement.start - tableKeywordLength
) +
`!placement(${1 + rowDelta}, ${1 + colDelta})\r\ntable ` +
sheetContent.substring(targetTable.dslTableNamePlacement.start);
append(
`Move table "${tableName}" to (${rowDelta + 1}, ${colDelta + 1})`,
dsl
);
}
updateDSL(dsl);
},
[append, findTable, sheetContent, updateDSL]
);
const moveTableTo = useCallback(
(tableName: string, row: number, col: number) => {
if (!sheetContent) return;
const targetTable = findTable(tableName);
if (!targetTable) return;
const placementDecorator = targetTable.decorators.find(
({ decoratorName }) => decoratorName === 'placement'
);
let dsl = sheetContent;
if (placementDecorator) {
const { start, end } = placementDecorator.dslPlacement;
const [startRow, startCol] = placementDecorator.params[0] as [
number,
number
];
if (row === startRow && col === startCol) return;
dsl =
sheetContent.substring(0, start) +
`!placement(${row}, ${col})` +
sheetContent.substring(end + 1);
append(`Move table "${tableName}" to (${row}, ${col})`, dsl);
} else {
if (!targetTable.dslTableNamePlacement) return;
dsl =
sheetContent.substring(
0,
targetTable.dslTableNamePlacement.start - tableKeywordLength
) +
`!placement(${row}, ${col})\r\ntable ` +
sheetContent.substring(targetTable.dslTableNamePlacement.start);
append(`Move table "${tableName}" to (${row}, ${col})`, dsl);
}
updateDSL(dsl);
},
[append, findTable, sheetContent, updateDSL]
);
const renameField = useCallback(
(tableName: string, oldName: string, newName: string) => {
if (!sheetContent) return;
const targetTable = findTable(tableName);
const targetField = findTableField(tableName, oldName);
if (!targetTable || !targetField?.dslFieldNamePlacement) return;
const { end, start } = targetField.dslFieldNamePlacement;
const sanitizedNewName = newName.replace(/[[\]]/g, '');
if (sanitizedNewName === oldName) return;
const fields = targetTable.fields.map((field) => field.key.fieldName);
const uniqueNewFieldName = createUniqueName(sanitizedNewName, fields);
let updatedSheetContent = renameOverrideField(
tableName,
oldName,
uniqueNewFieldName
);
if (updatedSheetContent) {
updatedSheetContent =
updatedSheetContent.substring(0, start) +
`[${uniqueNewFieldName}]` +
updatedSheetContent.substring(end);
} else {
updatedSheetContent =
sheetContent.substring(0, start) +
`[${uniqueNewFieldName}]` +
sheetContent.substring(end);
}
updateDSL(updatedSheetContent);
append(
`Rename field [${oldName}] to [${uniqueNewFieldName}] in table "${tableName}"`,
updatedSheetContent
);
},
[
append,
findTable,
findTableField,
renameOverrideField,
sheetContent,
updateDSL,
]
);
const editExpression = useCallback(
(tableName: string, fieldName: string, expression: string) => {
const context = findContext(tableName, fieldName);
if (!context || !context.field) return;
const { table, sheetContent, field } = context;
let targetField: ParsedField | undefined = field;
if (field?.isDynamic) {
targetField = table.fields.find(
(f) => f.key.fieldName === dynamicFieldName
);
}
if (
!targetField?.dslFieldNamePlacement ||
!targetField.expressionMetadata
)
return;
const { end, start } = targetField.expressionMetadata;
const sanitizedExpression = expression.trimStart().startsWith('=')
? expression.trimStart().replace('=', '').trimStart()
: expression;
const updatedSheetContent =
sheetContent.substring(0, start) +
sanitizedExpression +
sheetContent.substring(end + 1);
if (
verifyDslHasSameSetTablesAndFields(sheetContent, updatedSheetContent)
) {
openStatusModal('Incorrect expression');
return false;
}
updateDSL(updatedSheetContent);
append(
`Update expression of field [${fieldName}] in table "${tableName}"`,
updatedSheetContent
);
return true;
},
[append, findContext, openStatusModal, updateDSL]
);
const deleteTable = useCallback(
(tableName: string) => {
const context = findContext(tableName);
if (!context || !projectName) return;
const { table, sheetContent, sheetName } = context;
if (!table?.dslPlacement) return;
const { startOffset, stopOffset } = table.dslPlacement;
const updatedSheetContent =
sheetContent.substring(0, startOffset) +
sheetContent.substring(stopOffset + 1).replace('\r\n', '');
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Delete table "${tableName}"`,
updatedSheetContent
);
},
[projectName, appendTo, updateDSL, findContext]
);
const deleteField = useCallback(
(tableName: string, fieldName: string) => {
const context = findContext(tableName, fieldName);
if (!context || !projectName) return;
const { table, sheetContent, sheetName, field } = context;
if (!field) return;
let targetField: ParsedField | undefined = field;
if (field?.isDynamic) {
targetField = table.fields.find(
(f) => f.key.fieldName === dynamicFieldName
);
}
if (!targetField?.dslPlacement) return;
const { start, end } = targetField.dslPlacement;
const updatedSheetContent =
sheetContent.substring(0, start) +
sheetContent
.substring(end + 1)
.replace('\r\n', '')
.trimStart();
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Delete field [${fieldName}] from table "${tableName}"`,
updatedSheetContent
);
},
[findContext, projectName, updateDSL, appendTo]
);
const deleteSelectedFieldOrTable = useCallback(() => {
if (
!gridApi ||
!gridService ||
!sheetContent ||
gridApi?.isCellEditorOpen()
)
return;
const selection = gridApi.selection$.getValue();
if (!selection) return;
const { startCol, endCol, startRow, endRow } = selection;
const tableStructure = gridService.getTableStructure();
const tableMeta = findTableInSelection(tableStructure, selection);
if (!tableMeta) return;
const { tableName } = tableMeta;
const tableHeaderRowSelected =
startRow === tableMeta.startRow || endRow === tableMeta.startRow;
const entireTableHeaderSelected =
startCol === tableMeta.startCol && endCol === tableMeta.endCol;
if (tableHeaderRowSelected && entireTableHeaderSelected) {
deleteTable(tableName);
return;
}
if (startCol !== endCol) return;
const table = findTable(tableName);
if (!table) return;
let field = table.getFieldByIndex(startCol - tableMeta.startCol);
if (!field) return;
if (field.isDynamic) {
field = findTableField(tableName, dynamicFieldName);
if (!field) return;
}
const { fieldName } = field.key;
if (
startRow <= tableMeta.startRow + 1 ||
endRow <= tableMeta.startRow + 1
) {
deleteField(tableName, fieldName);
} else {
const cell = gridService?.getCellValue(startRow, startCol);
if (!cell || cell.overrideIndex === undefined || cell.value === undefined)
return;
removeOverride(tableName, fieldName, cell.overrideIndex, cell.value);
}
}, [
deleteField,
deleteTable,
findTable,
findTableField,
gridApi,
gridService,
removeOverride,
sheetContent,
]);
const swapFields = useCallback(
(
tableName: string,
rightFieldName: string,
leftFieldName: string,
direction: HorizontalDirection
) => {
const rfContext = findContext(tableName, rightFieldName);
const lfContext = findContext(tableName, leftFieldName);
if (!rfContext || !lfContext || !projectName) return;
if (!rfContext.sheetContent) return;
const { sheetContent, sheetName } = rfContext;
let rightField = rfContext.field || null;
let leftField = lfContext.field || null;
if (rightField?.isDynamic && leftField?.isDynamic) {
if (direction === 'left') {
leftField = findFieldOnLeftOrRight(
tableName,
rightFieldName,
direction
);
rightField = findTableField(tableName, dynamicFieldName);
} else {
rightField = findFieldOnLeftOrRight(
tableName,
leftFieldName,
direction
);
leftField = findTableField(tableName, dynamicFieldName);
}
if (!leftField || !rightField) return;
} else if (rightField?.isDynamic) {
rightField = findTableField(tableName, dynamicFieldName);
} else if (leftField?.isDynamic) {
leftField = findTableField(tableName, dynamicFieldName);
}
if (!rightField?.dslPlacement || !leftField?.dslPlacement) return;
const { start: rightStart, end: rightEnd } = rightField.dslPlacement;
const { start: leftStart, end: leftEnd } = leftField.dslPlacement;
const updatedSheetContent =
sheetContent.substring(0, leftStart) +
sheetContent.substring(rightStart, rightEnd + 1) +
sheetContent.substring(leftEnd + 1, rightStart) +
sheetContent.substring(leftStart, leftEnd + 1) +
sheetContent.substring(rightEnd + 1);
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Swap fields [${rightFieldName}] and [${leftFieldName}] in table "${tableName}"`,
updatedSheetContent
);
},
[
appendTo,
findContext,
findFieldOnLeftOrRight,
findTableField,
projectName,
updateDSL,
]
);
const swapFieldsHandler = useCallback(
(tableName: string, fieldName: string, direction: HorizontalDirection) => {
const context = findContext(tableName, fieldName);
if (!context) return;
const { table } = context;
const { fields } = table;
let rightFieldName = '';
let leftFieldName = '';
for (let i = 0; i < fields.length; i++) {
const field = fields[i];
if (field.key.fieldName === fieldName) {
if (direction === 'left') {
if (i === 0) return;
rightFieldName = field.key.fieldName;
leftFieldName = fields[i - 1].key.fieldName;
} else {
if (i === fields.length - 1) return;
rightFieldName = fields[i + 1].key.fieldName;
leftFieldName = field.key.fieldName;
}
}
}
if (rightFieldName && leftFieldName) {
swapFields(tableName, rightFieldName, leftFieldName, direction);
}
},
[findContext, swapFields]
);
const addField = useCallback(
(tableName: string, fieldText: string) => {
if (!sheetContent) return;
const targetTable = findTable(tableName);
const targetField = findLastTableField(tableName);
if (!targetTable) return;
let updatedSheetContent = sheetContent;
const { fieldName, fieldDsl } = generateFieldExpressionFromText(
fieldText,
targetTable
);
if (targetField?.dslPlacement) {
const { end, start } = targetField.dslPlacement;
const spacesMatch = sheetContent
.substring(0, start)
.replaceAll('\r\n', '')
.match(/\s+$/);
const spacesCount = spacesMatch ? spacesMatch[0].length : 0;
updatedSheetContent =
sheetContent.substring(0, end + 1) +
'\r\n' +
' '.repeat(spacesCount) +
fieldDsl +
sheetContent.substring(end + 1);
} else if (targetTable.dslPlacement) {
const { stopOffset } = targetTable.dslPlacement;
updatedSheetContent =
sheetContent.substring(0, stopOffset + 1) +
'\r\n' +
spaces +
fieldDsl +
sheetContent.substring(stopOffset + 1);
}
if (
verifyDslHasSameSetTablesAndNewField(
sheetContent,
updatedSheetContent,
tableName
)
) {
openStatusModal('Incorrect expression');
return false;
}
updateDSL(updatedSheetContent);
append(
`Add [${fieldName}] to table "${targetTable.tableName}"`,
updatedSheetContent
);
return true;
},
[
append,
findLastTableField,
findTable,
openStatusModal,
sheetContent,
updateDSL,
]
);
const createDerivedTable = useCallback(
(tableName: string) => {
const context = findContext(tableName);
if (!context || !projectName) return;
const { table, sheetContent, sheetName } = context;
const { fields } = table;
const newName = createUniqueName(
`${tableName}_derived`,
getAllTableNames(projectSheets)
);
const derivedName = newName.includes(' ') ? `'${newName}'` : newName;
const sourceName = tableName.includes(' ') ? `'${tableName}'` : tableName;
const sourceField = `${spaces}dim [source] = ${sourceName}`;
const derivedFields = fields
.map(
(f: ParsedField) =>
`${spaces}${f.key.fullFieldName} = [source]${f.key.fullFieldName}`
)
.join('\r\n');
const [row, col] = table.getPlacement();
const newCol = col + fields.length + 1;
const derivedTable = `!placement(${row}, ${newCol})\r\ntable ${derivedName}\r\n${sourceField}\r\n${derivedFields}`;
const updatedSheetContent = sheetContent + '\r\n\r\n' + derivedTable;
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Add derived table "${derivedName}"`,
updatedSheetContent
);
},
[findContext, projectName, projectSheets, updateDSL, appendTo]
);
const createTable = useCallback(
(col: number, row: number, value: string) => {
if (!parsedSheet) return;
const tableName = createUniqueName(
defaultTableName,
getAllTableNames(projectSheets)
);
const { fieldDsl } = generateFieldExpressionFromText(value);
const tableDsl = `!placement(${row}, ${col})\r\ntable ${tableName}\r\n${spaces}${fieldDsl}`;
const updatedSheetContent = sheetContent
? sheetContent + '\r\n\r\n' + tableDsl
: tableDsl;
updateDSL(updatedSheetContent);
append(`Add table "${tableName}"`, updatedSheetContent);
},
[append, projectSheets, parsedSheet, sheetContent, updateDSL]
);
const createDimensionTable = useCallback(
(col: number, row: number, value: string) => {
if (!parsedSheet) return;
const tables = value.split(':');
if (tables.length < 2) return;
const newTableName = createUniqueName(
tables[0] || defaultTableName,
getAllTableNames(projectSheets)
);
const fields = tables
.slice(1)
.map(
(table, index) =>
`${spaces}dim [source${index + 1}] = ${table.trim()}`
)
.join('\r\n');
const dimTable = `!placement(${row}, ${col})\r\ntable ${newTableName}\r\n${fields}`;
const updatedSheetContent = sheetContent
? sheetContent + '\r\n\r\n' + dimTable
: dimTable;
updateDSL(updatedSheetContent);
append(`Add dimension table "${newTableName}"`, updatedSheetContent);
},
[append, projectSheets, parsedSheet, sheetContent, updateDSL]
);
const createDimensionalTableFromFormula = useCallback(
(
col: number,
row: number,
formula: string,
schema: string[],
keys: string[]
) => {
if (!parsedSheet) return;
const formulaParts = formula.split(':');
if (formulaParts.length !== 2) return;
const newTableName = createUniqueName(
formulaParts[0] || defaultTableName,
getAllTableNames(projectSheets)
);
const sourceField = `${spaces}dim [source] = ${formulaParts[1]}`;
const tableFields = ['source'];
const fields = schema
.map((f) => {
const uniqueFieldName = createUniqueName(f, tableFields);
tableFields.push(uniqueFieldName);
const key = keys.includes(f) ? 'key ' : '';
return `${spaces}${key}[${uniqueFieldName}] = [source][${f}]`;
})
.join('\r\n');
const requiresPlacement = row === 0 || col === 0;
let dimTable = `table ${newTableName}\r\n${sourceField}\r\n${fields}`;
if (!requiresPlacement) {
dimTable = `!placement(${row}, ${col})\r\n${dimTable}`;
}
let updatedSheetContent = sheetContent
? sheetContent + '\r\n\r\n' + dimTable
: dimTable;
if (requiresPlacement) {
updatedSheetContent = autoTablePlacement(updatedSheetContent);
}
updateDSL(updatedSheetContent);
append(`Add dimension table "${newTableName}"`, updatedSheetContent);
},
[append, parsedSheet, projectSheets, sheetContent, updateDSL]
);
const createDimensionalTableFromSchema = useCallback(
(
col: number,
row: number,
tableName: string,
fieldName: string,
keyValues: string,
formula: string,
schema: string[],
keys: string[]
) => {
if (!sheetContent || !parsedSheet) return;
const targetTable = findTable(tableName);
if (!targetTable) return;
const sanitizedKayValues = keyValues.replaceAll(`"`, '');
const newTableName = createUniqueName(
`${tableName}_(${sanitizedKayValues})[${fieldName}]`,
getAllTableNames(projectSheets)
);
const sourceField = `${spaces}dim [source] = ${formula}`;
const tableFields = ['source'];
const fields = schema
.map((f) => {
const uniqueFieldName = createUniqueName(f, tableFields);
tableFields.push(uniqueFieldName);
const key = keys.includes(f) ? 'key ' : '';
return `${spaces}${key}[${uniqueFieldName}] = [source][${f}]`;
})
.join('\r\n');
const newTable = `!placement(${row}, ${col})\r\ntable '${newTableName}'\r\n${sourceField}\r\n${fields}`;
const updatedSheetContent = sheetContent + '\r\n\r\n' + newTable;
updateDSL(updatedSheetContent);
append(`Add dimension table "${newTableName}"`, updatedSheetContent);
},
[append, findTable, parsedSheet, projectSheets, sheetContent, updateDSL]
);
const removeDimension = useCallback(
(tableName: string, fieldName: string) => {
const context = findContext(tableName, fieldName);
if (!context || !projectName) return;
const { sheetContent, sheetName, field } = context;
if (!sheetContent || !field?.dslDimensionPlacement) return;
const { start, end } = field.dslDimensionPlacement;
const updatedSheetContent =
sheetContent.substring(0, start) +
sheetContent.substring(end + 1).trimStart();
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Remove dimension [${fieldName}] from table "${tableName}"`,
updatedSheetContent
);
},
[appendTo, findContext, projectName, updateDSL]
);
const addDimension = useCallback(
(tableName: string, fieldName: string) => {
const context = findContext(tableName, fieldName);
if (!context || !projectName) return;
const { sheetContent, sheetName, field } = context;
if (!sheetContent || !field?.dslFieldNamePlacement || field.isDim) return;
const { start } = field.dslFieldNamePlacement;
const updatedSheetContent =
sheetContent.substring(0, start) +
'dim ' +
sheetContent.substring(start).trimStart();
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Add dimension [${fieldName}] to table "${tableName}"`,
updatedSheetContent
);
},
[appendTo, findContext, projectName, updateDSL]
);
const addKey = useCallback(
(tableName: string, fieldName: string) => {
const context = findContext(tableName, fieldName);
if (!context || !projectName) return;
const { sheetContent, sheetName, field } = context;
if (!sheetContent || !field?.dslPlacement || field.isKey) return;
const { start } = field.dslPlacement;
const updatedSheetContent =
sheetContent.substring(0, start) +
'key ' +
sheetContent.substring(start).trimStart();
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Add key [${fieldName}] to table "${tableName}"`,
updatedSheetContent
);
},
[appendTo, findContext, projectName, updateDSL]
);
const removeKey = useCallback(
(tableName: string, fieldName: string) => {
const context = findContext(tableName, fieldName);
if (!context || !projectName) return;
const { sheetContent, sheetName, field } = context;
if (!sheetContent || !field?.dslKeyPlacement) return;
const { start, end } = field.dslKeyPlacement;
const updatedSheetContent =
sheetContent.substring(0, start) +
sheetContent.substring(end + 1).trimStart();
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Remove key [${fieldName}] from table "${tableName}"`,
updatedSheetContent
);
},
[appendTo, findContext, projectName, updateDSL]
);
const createManualTable = useCallback(
(col: number, row: number, value: string) => {
if (!parsedSheet) return;
const tableName = createUniqueName(
defaultTableName,
getAllTableNames(projectSheets)
);
const fieldDsl = `${spaces}[Field1] = NA`;
const overrideValue = !isNaN(parseFloat(value))
? value.trim()
: `"${value.trim()}"`;
const overridesDsl = `override\r\n[Field1]\r\n${overrideValue}`;
const tableDsl = `!manual()\r\n!placement(${Math.max(
0,
row - 2
)}, ${col})\r\ntable ${tableName}\r\n${fieldDsl}\r\n${overridesDsl}`;
const updatedSheetContent = sheetContent
? sheetContent + '\r\n\r\n' + tableDsl
: tableDsl;
updateDSL(updatedSheetContent);
append(`Add manual table "${tableName}"`, updatedSheetContent);
},
[append, projectSheets, parsedSheet, sheetContent, updateDSL]
);
const addTableRow = useCallback(
(col: number, row: number, tableName: string, value: string) => {
if (!sheetContent) return;
const targetTable = findTable(tableName);
if (!targetTable || !targetTable.isManual())
return createManualTable(col, row, value);
const [startRow, startCol] = targetTable.getPlacement();
const targetField = targetTable.fields.find(
(f, index) => index === col - startCol
);
if (!targetField) return;
return addOverride(
tableName,
targetField.key.fieldName,
row - startRow - 2,
value
);
},
[addOverride, createManualTable, findTable, sheetContent]
);
const chartResize = useCallback(
(tableName: string, cols: number, rows: number) => {
const context = findContext(tableName);
if (!context || !projectName) return;
const { sheetContent, sheetName, table } = context;
if (!sheetContent) return;
const sizeDecorator = table.decorators.find(
({ decoratorName }) => decoratorName === 'size'
);
let updatedSheetContent = sheetContent;
if (sizeDecorator) {
const { start, end } = sizeDecorator.dslPlacement;
const currentSize = sizeDecorator.params[0] as [number, number];
if (currentSize[0] === rows && currentSize[1] === cols) return;
updatedSheetContent =
sheetContent.substring(0, start) +
`!size(${rows}, ${cols})` +
sheetContent.substring(end + 1);
} else {
if (!table.dslTableNamePlacement) return;
updatedSheetContent =
sheetContent.substring(
0,
table.dslTableNamePlacement.start - tableKeywordLength
) +
`!size(${rows}, ${cols})\r\ntable ` +
sheetContent.substring(table.dslTableNamePlacement.start);
}
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Resize chart [${tableName}] to (${rows}, ${cols})`,
updatedSheetContent
);
},
[appendTo, findContext, projectName, updateDSL]
);
const addChart = useCallback(
(tableName: string) => {
const context = findContext(tableName);
if (!context || !projectName) return;
const { table, sheetContent, sheetName } = context;
if (!table?.dslPlacement || !table.dslTableNamePlacement) return;
const { stopOffset } = table.dslPlacement;
const { end } = table.dslTableNamePlacement;
const chartTableName = createUniqueName(
`${tableName}_chart`,
getAllTableNames(projectSheets)
);
const [row, col] = table.getPlacement();
const newCol = col + table.fields.length + 1;
const decorators = table.decorators
.filter(
(d) =>
d.decoratorName !== 'visualization' &&
d.decoratorName !== 'size' &&
d.decoratorName !== 'placement'
)
.map((d) => `!${d.decoratorName}(${d.params.join(',')})\r\n`);
const chartTable =
'table ' + chartTableName + sheetContent.substring(end, stopOffset + 1);
const updatedSheetContent =
sheetContent +
`\r\n\r\n!visualization("line-chart")\r\n` +
`!placement(${row},${newCol})\r\n` +
decorators +
chartTable;
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Add chart "${chartTableName}"`,
updatedSheetContent
);
},
[findContext, projectName, projectSheets, updateDSL, appendTo]
);
const convertToChart = useCallback(
(tableName: string) => {
const context = findContext(tableName);
if (!context || !projectName) return;
const { table, sheetContent, sheetName } = context;
const chartDecorator = table.decorators.find(
({ decoratorName }) => decoratorName === 'visualization'
);
if (chartDecorator || !table.dslTableNamePlacement) return;
const { start } = table.dslTableNamePlacement;
const updatedSheetContent =
sheetContent.substring(0, start - tableKeywordLength) +
`!visualization("line-chart")\r\ntable ` +
sheetContent.substring(start);
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Convert table "${tableName}" to chart`,
updatedSheetContent
);
},
[projectName, appendTo, updateDSL, findContext]
);
const convertToTable = useCallback(
(tableName: string) => {
const context = findContext(tableName);
if (!context || !projectName) return;
const { table, sheetContent, sheetName } = context;
const chartDecorator = table.decorators.find(
({ decoratorName }) => decoratorName === 'visualization'
);
if (
!chartDecorator ||
!table.dslPlacement ||
!table.dslTableNamePlacement
)
return;
const { startOffset } = table.dslPlacement;
const { start } = table.dslTableNamePlacement;
const decorators = table.decorators
.filter(
(d) =>
d.decoratorName !== 'visualization' && d.decoratorName !== 'size'
)
.map((d) => `!${d.decoratorName}(${d.params.join(',')})\r\n`);
const updatedSheetContent =
sheetContent.substring(0, startOffset) +
decorators +
'table ' +
sheetContent.substring(start);
updateDSL(updatedSheetContent, sheetName);
appendTo(
projectName,
sheetName,
`Convert chart "${tableName}" to table`,
updatedSheetContent
);
},
[projectName, appendTo, updateDSL, findContext]
);
return {
addChart,
addDimension,
addField,
addKey,
addTableRow,
chartResize,
convertToChart,
convertToTable,
createDerivedTable,
createDimensionTable,
createDimensionalTableFromFormula,
createDimensionalTableFromSchema,
createManualTable,
createTable,
deleteField,
deleteSelectedFieldOrTable,
deleteTable,
editExpression,
moveTable,
moveTableTo,
removeDimension,
removeKey,
renameField,
renameTable,
swapFields,
swapFieldsHandler,
};
}