diff --git a/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.sass b/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.sass new file mode 100644 index 000000000..f6f4124c7 --- /dev/null +++ b/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.sass @@ -0,0 +1,6 @@ +textarea.form-control.assurbanipal + font-size: 150% + font-family: Assurbanipal, Junicode, serif !important +textarea.form-control.neo-babylonian + font-size: 150% + font-family: Neo-Babylonian,'Adobe Blank', Junicode, serif !important diff --git a/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.test.tsx b/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.test.tsx new file mode 100644 index 000000000..7486f7c69 --- /dev/null +++ b/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.test.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import CuneiformConverterForm from 'chronology/ui/CuneiformConverter/CuneiformConverterForm' +import SignService from 'signs/application/SignService' + +jest.mock('signs/application/SignService') +const signServiceMock = new (SignService as jest.Mock< + jest.Mocked +>)() + +describe('CuneiformConverterForm', () => { + beforeEach(() => { + Object.defineProperty(window.navigator, 'clipboard', { + value: { + writeText: jest.fn().mockResolvedValue(true), + }, + writable: true, + }) + }) + + afterEach(() => { + jest.resetAllMocks() + }) + + it('renders form, options, and scenario panel correctly', () => { + render() + expect(screen.getByLabelText('Text to Convert')).toBeInTheDocument() + expect(screen.getByLabelText('Select Font')).toBeInTheDocument() + expect(screen.getByLabelText('Text to Convert')).toBeInTheDocument() + }) + it('handles input change', () => { + render() + const inputTextArea = screen.getByLabelText('Text to Convert') + fireEvent.change(inputTextArea, { target: { value: 'test text' } }) + expect(inputTextArea).toHaveValue('test text') + }) + it('handles font change', () => { + render() + const fontSelector = screen.getByLabelText('Select Font') + fireEvent.change(fontSelector, { target: { value: 'Neo-Babylonian' } }) + expect(fontSelector).toHaveValue('Neo-Babylonian') + }) + it('converts text correctly', async () => { + signServiceMock.getUnicodeFromAtf.mockResolvedValueOnce([ + { unicode: [73979] }, + ]) + render() + + const inputTextArea = screen.getByLabelText('Text to Convert') + fireEvent.change(inputTextArea, { target: { value: 'test text' } }) + + const convertButton = screen.getByText('Convert') + fireEvent.click(convertButton) + + await waitFor(() => { + expect(screen.getByLabelText('Converted Text')).toHaveValue('𒃻') + }) + }) +}) diff --git a/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.tsx b/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.tsx new file mode 100644 index 000000000..4c4f1446f --- /dev/null +++ b/src/chronology/ui/CuneiformConverter/CuneiformConverterForm.tsx @@ -0,0 +1,106 @@ +import React, { useState } from 'react' +import { Form, Button } from 'react-bootstrap' +import Bluebird from 'bluebird' +import SignService from 'signs/application/SignService' +import replaceTransliteration from 'fragmentarium/domain/replaceTransliteration' +import { displayUnicode } from 'signs/ui/search/SignsSearch' +import './CuneiformConverterForm.sass' + +function CuneiformConverterForm({ + signService, +}: { + signService: SignService +}): JSX.Element { + const [content, setContent] = useState('') + const [convertedContent, setConvertedContent] = useState('') + const [selectedFont, setSelectedFont] = useState('Assurbanipal') + + const handleChange = (event) => { + setContent(event.target.value) + } + + const handleConvert = () => { + const lines = content.split('\n') + const replacedLines = lines.map((line) => replaceTransliteration(line)) + + Promise.all( + replacedLines + .filter((line) => line.trim() !== '') + .map((line) => query(line)) + ) + .then((results) => { + const convertedText = results + .map((result) => + result + .map((entry) => + entry.unicode[0] === 9999 ? ' ' : displayUnicode(entry.unicode) + ) + .join('') + ) + .join('\n') + + setConvertedContent(convertedText) + }) + .catch((error) => { + console.error('Query Error:', error) + }) + } + + const query = (content) => { + return Bluebird.resolve(signService.getUnicodeFromAtf(content)) + } + + const handleKeyDown = (event) => { + if (event.key === 'Enter' && !event.shiftKey) { + event.preventDefault() + handleConvert() + } + } + + const handleFontChange = (event) => { + setSelectedFont(event.target.value) + } + + return ( + <> + Text to Convert + + + Enter the text you want to convert to Unicode. + + Select Font + + +

+ Converted Text + + + This is the converted Unicode text. + + + ) +} + +export default CuneiformConverterForm diff --git a/src/router/toolsRoutes.tsx b/src/router/toolsRoutes.tsx index 9896cd978..9d2299edc 100644 --- a/src/router/toolsRoutes.tsx +++ b/src/router/toolsRoutes.tsx @@ -18,15 +18,23 @@ import ListOfKings from 'chronology/ui/Kings/BrinkmanKingsTable' import _ from 'lodash' import 'about/ui/about.sass' import NotFoundPage from 'NotFoundPage' +import CuneiformConverterForm from 'chronology/ui/CuneiformConverter/CuneiformConverterForm' +import SignService from 'signs/application/SignService' -const tabIds = ['date-converter', 'list-of-kings'] as const +const tabIds = [ + 'date-converter', + 'list-of-kings', + 'cuneiform-converter', +] as const type TabId = typeof tabIds[number] const Tools = ({ markupService, + signService, activeTab, }: { markupService: MarkupService + signService: SignService activeTab: TabId }): JSX.Element => { const history = useHistory() @@ -57,6 +65,9 @@ const Tools = ({ {ListOfKings()} + + + ) @@ -64,9 +75,11 @@ const Tools = ({ export default function ToolsRoutes({ sitemap, + signService, markupService, }: { sitemap: boolean + signService: SignService markupService: MarkupService }): JSX.Element[] { return [ @@ -81,6 +94,7 @@ export default function ToolsRoutes({ > diff --git a/src/signs/application/SignService.ts b/src/signs/application/SignService.ts index bdfeecab4..d6b6907e7 100644 --- a/src/signs/application/SignService.ts +++ b/src/signs/application/SignService.ts @@ -1,5 +1,5 @@ import Bluebird from 'bluebird' -import Sign, { OrderedSign, SignQuery } from 'signs/domain/Sign' +import Sign, { OrderedSign, SignQuery, UnicodeAtf } from 'signs/domain/Sign' import SignRepository from 'signs/infrastructure/SignRepository' import { AnnotationToken } from 'fragmentarium/domain/annotation-token' @@ -39,4 +39,7 @@ export default class SignService { ): Bluebird<[OrderedSign[]]> { return this.signsRepository.findSignsByOrder(signName, sortEra) } + getUnicodeFromAtf(text: string): Bluebird { + return this.signsRepository.getUnicodeFromAtf(text) + } } diff --git a/src/signs/domain/Sign.ts b/src/signs/domain/Sign.ts index b6d978d13..6f05aba88 100644 --- a/src/signs/domain/Sign.ts +++ b/src/signs/domain/Sign.ts @@ -15,6 +15,9 @@ export interface OrderedSign { readonly unicode: readonly number[] readonly mzl: string | null } +export interface UnicodeAtf { + readonly unicode: number[] +} export interface Fossey { page: number number: number diff --git a/src/signs/infrastructure/SignRepository.ts b/src/signs/infrastructure/SignRepository.ts index b575f4b4f..bd34e3539 100644 --- a/src/signs/infrastructure/SignRepository.ts +++ b/src/signs/infrastructure/SignRepository.ts @@ -1,6 +1,6 @@ import ApiClient from 'http/ApiClient' import Promise from 'bluebird' -import Sign, { OrderedSign, SignQuery } from 'signs/domain/Sign' +import Sign, { OrderedSign, SignQuery, UnicodeAtf } from 'signs/domain/Sign' import { stringify } from 'query-string' import { AnnotationToken } from 'fragmentarium/domain/annotation-token' import { AnnotationTokenType } from 'fragmentarium/domain/annotation' @@ -89,6 +89,11 @@ class SignRepository { false ) } + getUnicodeFromAtf(text: string): Promise { + return this.apiClient.fetchJson( + `/signs/transliteration/${encodeURIComponent(text)}` + ) + } } export default SignRepository diff --git a/src/signs/ui/search/SignsSearch.tsx b/src/signs/ui/search/SignsSearch.tsx index cbe6d5793..84a831a71 100644 --- a/src/signs/ui/search/SignsSearch.tsx +++ b/src/signs/ui/search/SignsSearch.tsx @@ -23,7 +23,7 @@ function sortSigns(signs: Sign[]): Sign[] { ) } -function displayUnicode(unicode: readonly number[]): string { +export function displayUnicode(unicode: readonly number[]): string { return unicode.map((unicode) => String.fromCodePoint(unicode)).join('') }