Skip to content
This repository has been archived by the owner on Nov 7, 2022. It is now read-only.

fix(formula): runtime error i18n support #412

Merged
merged 1 commit into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions apps/client-web/src/docs_legacy/pages/DocumentContentPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ import { useFormulaActions } from './hooks/useFormulaActions'
import { AppError404 } from '@/routes/_shared/AppError'
import { type DocMeta, DocMetaProvider } from '../store/DocMeta'
import { MashcardEventBus, BlockMetaUpdated, ReloadDocument } from '@mashcard/schema'
import { formulaI18n } from '@mashcard/editor/src/helpers'
import { useFormulaI18n } from '@mashcard/editor/src/hooks/useFormulaI18n'

export const DocumentContentPage: FC = () => {
const { t } = useDocsI18n()
const { t: formulaT } = useFormulaI18n()
const { domain, docId, historyId } = useParams() as unknown as {
domain: string
docId?: string
Expand Down Expand Up @@ -141,8 +144,9 @@ export const DocumentContentPage: FC = () => {

useEffect(() => {
const functionClauses = generateFormulaFunctionClauses()
const formulaContext = FormulaContext.getInstance({
domain,
const formulaContext = FormulaContext.getFormulaInstance({
username: domain,
i18n: formulaI18n(formulaT),
backendActions: { commit: commitFormula },
functionClauses,
features: featureFlags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ exports[`FormulaDisplay [partial error 2] basic "=custom::ADD(1)" 2`] = `
class="mashcard-formula-borderless"
style="color: rgb(207, 31, 40);"
>
#<Error> errors.parse.not_found.function,[object Object]
#<Error> errors.parse.not_found.function {"key":"custom::ADD"}
</span>
</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,7 @@ exports[`FormulaResult chain "={a:1}.b" -> [object Object] 1`] = `
class="mashcard-formula-borderless"
style="color: rgb(207, 31, 40);"
>
#&lt;Error&gt; errors.interpret.not_found.key,[object Object]
#&lt;Error&gt; errors.interpret.not_found.key {"key":"b"}
</span>
<span
class="formula-result-ok-icon"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ exports[`FormulaValue [partial error 2] basic "=custom::ADD(1)" 1`] = `
class="mashcard-formula-borderless"
style="color: rgb(207, 31, 40);"
>
#&lt;Error&gt; errors.parse.not_found.function,[object Object]
#&lt;Error&gt; errors.parse.not_found.function {"key":"custom::ADD"}
</span>
</div>
`;
Expand Down Expand Up @@ -1063,7 +1063,7 @@ exports[`FormulaValue [partial error 2] basic "=custom::ADD(1)" 3`] = `
class="mashcard-formula-borderless"
style="color: rgb(207, 31, 40);"
>
#&lt;Error&gt; errors.parse.not_found.function,[object Object]
#&lt;Error&gt; errors.parse.not_found.function {"key":"custom::ADD"}
</span>
</div>
`;
Expand All @@ -1074,7 +1074,7 @@ exports[`FormulaValue [partial error 2] basic "=custom::ADD(1)" 4`] = `
class="mashcard-formula-borderless"
style="color: rgb(207, 31, 40);"
>
#&lt;Error&gt; errors.parse.not_found.function,[object Object]
#&lt;Error&gt; errors.parse.not_found.function {"key":"custom::ADD"}
</span>
</div>
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,12 @@ export const useFormula = ({
setReferences(e.payload.meta)
},
{
eventId: `${formulaContext?.domain}#${namespaceId},${variableId}`,
eventId: `${formulaContext?.username}#${namespaceId},${variableId}`,
subscribeId: `UseFormula#${namespaceId},${variableId}`
}
)
return () => listener.unsubscribe()
}, [formulaContext?.domain, namespaceId, variableId])
}, [formulaContext?.username, namespaceId, variableId])

React.useEffect(() => {
const listener = MashcardEventBus.subscribe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
async (variable: VariableInterface | undefined): Promise<void> => {
if (!variable) return
// TODO check no persist
const value = display(fetchResult(variable.t)).result
const value = display(fetchResult(variable.t), formulaContext!).result
const oldValue = block.text
if (value === oldValue) return
devLog('Spreadsheet cell formula updated', { cellId, value, rootId })
Expand All @@ -98,7 +98,7 @@ export const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
},
meta: null,
namespaceId: rootId,
username: formulaContext.domain,
username: formulaContext.username,
key: variable?.currentUUID ?? tableId
})
)
Expand Down Expand Up @@ -194,7 +194,9 @@ export const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
latestEditing.current = false
}

const displayResult = savedVariableT ? display(fetchResult(savedVariableT)).result : currentBlock.text
const displayResult = savedVariableT
? display(fetchResult(savedVariableT), formulaContext!).result
: currentBlock.text
const fallbackDisplayData: VariableDisplayData | undefined = displayResult
? {
definition: displayResult,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
SpreadsheetCellContainer,
SpreadsheetColumnEditable
} from './SpreadsheetView'
import { display, VariableDisplayData } from '@mashcard/formula'
import { display, SpreadsheetType, VariableDisplayData } from '@mashcard/formula'
import React from 'react'
import { FormulaDisplay } from '../../ui/Formula'
import { styled } from '@mashcard/design-system'
Expand All @@ -29,7 +29,7 @@ export interface Column {
}

export interface SpreadsheetRenderProps {
title: string
spreadsheet: SpreadsheetType
rows: Row[]
valuesMatrix: Map<string, Map<string, VariableDisplayData | undefined>>
columns: Column[]
Expand All @@ -38,7 +38,7 @@ export interface SpreadsheetRenderProps {

export const SpreadsheetRender: React.FC<SpreadsheetRenderProps> = ({
rows,
title,
spreadsheet,
columns,
valuesMatrix,
defaultSelection
Expand All @@ -56,7 +56,7 @@ export const SpreadsheetRender: React.FC<SpreadsheetRenderProps> = ({
new Map(
columns.map(c => {
const displayData = valuesMatrix.get(rowId)?.get(c.columnId)
return [c.columnId, displayData ? display(displayData.result).result : '']
return [c.columnId, displayData ? display(displayData.result, spreadsheet._formulaContext).result : '']
})
)
]
Expand Down Expand Up @@ -99,7 +99,8 @@ export const SpreadsheetRender: React.FC<SpreadsheetRenderProps> = ({
context={spreadsheetContext}
columnId={column.columnId}
columnActions={[]}
draggable={false}>
draggable={false}
>
<SpreadsheetColumnEditable
context={spreadsheetContext}
index={i}
Expand All @@ -119,7 +120,8 @@ export const SpreadsheetRender: React.FC<SpreadsheetRenderProps> = ({
<SpreadsheetCellContainer
key={column.columnId}
context={spreadsheetContext}
cellId={{ rowId: rowBlock.rowId, columnId: column.columnId }}>
cellId={{ rowId: rowBlock.rowId, columnId: column.columnId }}
>
<div className="cell">
<FormulaDisplay
displayData={valuesMatrix.get(rowBlock.rowId)?.get(column.columnId)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,28 @@ export function useFormulaSpreadsheet({
spreadsheetId,
title,
namespaceId: rootId,
username: formulaContext?.domain
username: formulaContext?.username
})
}, [formulaContext?.domain, rootId, spreadsheetId, title])
}, [formulaContext?.username, rootId, spreadsheetId, title])

React.useEffect(() => {
// TODO: remove this when switch pages
void dispatchFormulaSpreadsheetRowChange({
spreadsheetId,
namespaceId: rootId,
rows: rowData,
username: formulaContext?.domain
username: formulaContext?.username
})
}, [rootId, spreadsheetId, rowData, formulaContext?.domain])
}, [rootId, spreadsheetId, rowData, formulaContext?.username])

React.useEffect(() => {
void dispatchFormulaSpreadsheetColumnChange({
spreadsheetId,
namespaceId: rootId,
columns: columnData,
username: formulaContext?.domain
username: formulaContext?.username
})
}, [rootId, spreadsheetId, columnData, formulaContext?.domain])
}, [rootId, spreadsheetId, columnData, formulaContext?.username])

React.useEffect(() => {
if (!formulaContext) return
Expand Down Expand Up @@ -123,7 +123,7 @@ export function useFormulaSpreadsheet({

return {
deleteSpreadsheet: () => {
void dispatchFormulaSpreadsheetRemove({ id: spreadsheetId, username: formulaContext?.domain })
void dispatchFormulaSpreadsheetRemove({ id: spreadsheetId, username: formulaContext?.username })
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ describe('AutocompleteList', () => {
})

it('renders variable kind correctly', async () => {
const formulaContext = FormulaContext.getInstance({ domain: 'test' })
const formulaContext = FormulaContext.getFormulaInstance({ username: 'test' })
const interpretContext = { ctx: {}, arguments: [] }

const namespaceId = '37198be0-d10d-42dc-ae8b-20d45a95401b'
Expand Down
9 changes: 2 additions & 7 deletions packages/editor/src/components/ui/Formula/FormulaError.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FC } from 'react'
import { ErrorMessage } from '@mashcard/formula'
import { formulaI18n } from '../../../helpers'
import { useFormulaI18n } from '../../../hooks/useFormulaI18n'

export interface FormulaErrorProps {
Expand All @@ -8,13 +9,7 @@ export interface FormulaErrorProps {

export const FormulaError: FC<FormulaErrorProps> = ({ error }) => {
const { t } = useFormulaI18n()

let errorMessage: string
if (typeof error.message === 'string') {
errorMessage = t(error.message)
} else {
errorMessage = t(error.message[0], error.message[1])
}
const errorMessage = formulaI18n(t)(error.message)

return (
<>
Expand Down
8 changes: 6 additions & 2 deletions packages/editor/src/components/ui/Formula/FormulaValue.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { FC, ReactElement } from 'react'
import { resultToColorType, VariableDisplayData, display } from '@mashcard/formula'
import { cx, Icon, Tooltip } from '@mashcard/design-system'
import { SelectedType } from '../../blockViews/FormulaView'
import { getFormulaContext, SelectedType } from '../../blockViews/FormulaView'
import { FORMULA_COLOR_METAS, FORMULA_ICONS, FORMULA_STYLES } from './color'
import * as Root from './Formula.style'
import { useEditorContext } from '../../../hooks'

export interface FormulaValueProps {
displayData: VariableDisplayData
Expand All @@ -20,11 +21,14 @@ export const FormulaValue: FC<FormulaValueProps> = ({
disablePopover,
displayData: { result, type }
}) => {
const { editor } = useEditorContext()
const formulaContext = getFormulaContext(editor)

const colorType = resultToColorType(result)
const { colorCode } = FORMULA_COLOR_METAS[colorType]
const icon = FORMULA_ICONS[colorType]
const hasBorder = type === 'normal' && border
const displayResult = display(result).result
const displayResult = display(result, formulaContext!).result

if (!hasBorder) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const FormulaSpreadsheet: React.FC<FormulaSpreadsheetProps> = ({

return (
<SpreadsheetRender
title={spreadsheet.name()}
spreadsheet={spreadsheet}
valuesMatrix={valuesMatrix}
rows={rows}
columns={columns}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
import { buildTestCases, dumpDisplayResultForDisplay, makeContext } from '@mashcard/formula'
import { render } from '@testing-library/react'
import { FormulaDisplay } from '..'
import { Formula } from '../../../../extensions'
import { mockEditor } from '../../../../test'
import * as editorHooks from '../../../../hooks/useEditorContext'

const [input] = buildTestCases(['basic'])

jest.mock('../../../../hooks/useEditorContext', () => {
const { useEditorContext } = jest.requireActual('../../../../hooks/useEditorContext')
return { useEditorContext: jest.fn().mockImplementation(useEditorContext) }
})

describe('FormulaDisplay', () => {
let ctx: Awaited<ReturnType<typeof makeContext>>
beforeAll(async () => {
jest.useRealTimers()
ctx = await makeContext(input.options)
jest.clearAllTimers()

const editor = mockEditor({
extensionManager: {
extensions: [{ name: Formula.name, options: { formulaContext: ctx.formulaContext } }]
}
})

jest.spyOn(editorHooks, 'useEditorContext').mockImplementation(() => ({ editor, documentEditable: true }))
})

it.each(input.basicTestCases)('$jestTitle', async args => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { BasicNames, buildTestCases, makeContext, TestCaseInput } from '@mashcard/formula'
import { render } from '@testing-library/react'
import { Formula } from '../../../../extensions'
import { mockEditor } from '../../../../test'
import { FormulaResult } from '../FormulaResult'
import * as editorHooks from '../../../../hooks/useEditorContext'

const [input, testCases] = buildTestCases<TestCaseInput['basicTestCases'][0]>(BasicNames)

Expand All @@ -17,12 +20,25 @@ jest.mock('react-i18next', () => ({
}
}))

jest.mock('../../../../hooks/useEditorContext', () => {
const { useEditorContext } = jest.requireActual('../../../../hooks/useEditorContext')
return { useEditorContext: jest.fn().mockImplementation(useEditorContext) }
})

describe('FormulaResult', () => {
let ctx: Awaited<ReturnType<typeof makeContext>>
beforeAll(async () => {
jest.useRealTimers()
ctx = await makeContext(input.options)
jest.clearAllTimers()

const editor = mockEditor({
extensionManager: {
extensions: [{ name: Formula.name, options: { formulaContext: ctx.formulaContext } }]
}
})

jest.spyOn(editorHooks, 'useEditorContext').mockImplementation(() => ({ editor, documentEditable: true }))
})

it.each(testCases)('$jestTitle', async args => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
import { render } from '@testing-library/react'
import { buildTestCases, dumpDisplayResultForDisplay, makeContext } from '@mashcard/formula'
import { FormulaValue } from '../FormulaValue'
import { mockEditor } from '../../../../test'
import { Formula } from '../../../../extensions'
import * as editorHooks from '../../../../hooks/useEditorContext'

const [input] = buildTestCases(['basic'])

jest.mock('../../../../hooks/useEditorContext', () => {
const { useEditorContext } = jest.requireActual('../../../../hooks/useEditorContext')
return { useEditorContext: jest.fn().mockImplementation(useEditorContext) }
})

describe('FormulaValue', () => {
let ctx: Awaited<ReturnType<typeof makeContext>>
beforeAll(async () => {
jest.useRealTimers()
ctx = await makeContext(input.options)
jest.clearAllTimers()

const editor = mockEditor({
extensionManager: {
extensions: [{ name: Formula.name, options: { formulaContext: ctx.formulaContext } }]
}
})

jest.spyOn(editorHooks, 'useEditorContext').mockImplementation(() => ({ editor, documentEditable: true }))
})

it.each(input.basicTestCases)('$jestTitle', async args => {
Expand Down