-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AfO Register #398
AfO Register #398
Changes from 11 commits
6b090e8
bc7e1fe
fd947c1
2749a66
ced19e9
5d3aacd
526e661
029b34d
104f699
81b8fce
162e4fd
89b0fdf
b556376
2810b19
bf4a4b2
71a947a
669b57a
5d30646
48f9a91
3a26c4b
75d2217
b16cc16
6b06553
c5832c5
8f01369
fa10ed7
0d95895
599ad57
7a929a3
93adcf7
dcee39c
43c19d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { testDelegation, TestData } from 'test-support/utils' | ||
import AfoRegisterRepository from 'afo-register/infrastructure/AfoRegisterRepository' | ||
import AfoRegisterRecord from 'afo-register/domain/Record' | ||
import { stringify } from 'query-string' | ||
import ApiClient from 'http/ApiClient' | ||
|
||
jest.mock('http/ApiClient') | ||
const apiClient = new (ApiClient as jest.Mock<jest.Mocked<ApiClient>>)() | ||
|
||
const afoRegisterRepository = new AfoRegisterRepository(apiClient) | ||
|
||
const resultStub = { | ||
afoNumber: 'AfO 1', | ||
page: '2', | ||
text: 'some text', | ||
textNumber: '5', | ||
discussedBy: '', | ||
discussedByNotes: '', | ||
linesDiscussed: '', | ||
} | ||
|
||
const query = { afoNumber: resultStub.afoNumber, page: resultStub.page } | ||
const entry = new AfoRegisterRecord(resultStub) | ||
|
||
const testData: TestData<AfoRegisterRepository>[] = [ | ||
new TestData( | ||
'search', | ||
[ | ||
stringify({ | ||
afoNumber: 'AfO 1', | ||
page: '2', | ||
}), | ||
], | ||
apiClient.fetchJson, | ||
[entry], | ||
[`/afo-register?${stringify(query)}`, false], | ||
Promise.resolve([resultStub]) | ||
), | ||
] | ||
describe('afoRegisterService', () => | ||
testDelegation(afoRegisterRepository, testData)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Promise from 'bluebird' | ||
import AfoRegisterRecord, { | ||
AfoRegisterRecordSuggestion, | ||
} from 'afo-register/domain/Record' | ||
import AfoRegisterRepository from 'afo-register/infrastructure/AfoRegisterRepository' | ||
|
||
export interface afoRegisterSearch { | ||
search(query: string): Promise<readonly AfoRegisterRecord[]> | ||
searchSuggestions( | ||
query: string | ||
): Promise<readonly AfoRegisterRecordSuggestion[]> | ||
} | ||
|
||
export default class AfoRegisterService implements afoRegisterSearch { | ||
private readonly afoRegisterRepository: AfoRegisterRepository | ||
|
||
constructor(afoRegisterRepository: AfoRegisterRepository) { | ||
this.afoRegisterRepository = afoRegisterRepository | ||
} | ||
|
||
search(query: string): Promise<readonly AfoRegisterRecord[]> { | ||
return this.afoRegisterRepository.search(query) | ||
} | ||
|
||
searchSuggestions( | ||
query: string | ||
): Promise<readonly AfoRegisterRecordSuggestion[]> { | ||
return this.afoRegisterRepository.searchSuggestions(query) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import AfoRegisterRecord from 'afo-register/domain/Record' | ||
import { fragmentFactory } from 'test-support/fragment-fixtures' | ||
|
||
describe('AfoRegisterRecord', () => { | ||
const mockRecord = { | ||
afoNumber: '123', | ||
page: '456', | ||
text: 'Sample text', | ||
textNumber: '789', | ||
linesDiscussed: 'Some lines', | ||
discussedBy: 'John Doe', | ||
discussedByNotes: 'Notes by John', | ||
} | ||
|
||
const fragment1 = fragmentFactory.build({ | ||
traditionalReferences: ['Sample text 789'], | ||
number: 'Fragment001', | ||
}) | ||
|
||
const fragment2 = fragmentFactory.build({ | ||
traditionalReferences: [], | ||
number: 'Fragment002', | ||
}) | ||
|
||
describe('constructor', () => { | ||
describe('constructor', () => { | ||
it('should initialize properties correctly', () => { | ||
const record = new AfoRegisterRecord(mockRecord) | ||
expect(record.afoNumber).toEqual('123') | ||
expect(record.page).toEqual('456') | ||
expect(record.text).toEqual('Sample text') | ||
expect(record.textNumber).toEqual('789') | ||
expect(record.linesDiscussed).toEqual('Some lines') | ||
expect(record.discussedBy).toEqual('John Doe') | ||
expect(record.discussedByNotes).toEqual('Notes by John') | ||
}) | ||
}) | ||
}) | ||
|
||
describe('Converts to Markdown string', () => { | ||
it('Returns the correct markdown string with fragments', () => { | ||
const record = new AfoRegisterRecord(mockRecord) | ||
const result = record.toMarkdownString([fragment1, fragment2]) | ||
expect(result).toEqual( | ||
'Sample text 789(Fragment001), Some lines: John Doe Notes by John<small class="text-black-50 ml-3">[123, 456]</small>' | ||
) | ||
}) | ||
|
||
it('Handles sup tags correctly', () => { | ||
const recordWithSup = new AfoRegisterRecord({ | ||
...mockRecord, | ||
text: 'Sample^text^', | ||
}) | ||
const result = recordWithSup.toMarkdownString([fragment1, fragment2]) | ||
expect(result).toContain('<sup>text</sup>') | ||
}) | ||
}) | ||
|
||
describe('Finds link to fragment', () => { | ||
it('should return the correct link to fragment', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
const record = new AfoRegisterRecord(mockRecord) | ||
const result = record.findLinkToFragment([fragment1, fragment2]) | ||
expect(result).toEqual('Fragment001') | ||
}) | ||
|
||
it('Returns empty string if no matching fragments', () => { | ||
const record = new AfoRegisterRecord(mockRecord) | ||
const result = record.findLinkToFragment([fragment2]) | ||
expect(result).toEqual('') | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { immerable } from 'immer' | ||
import { Fragment } from 'fragmentarium/domain/fragment' | ||
|
||
interface RecordData { | ||
readonly afoNumber: string | ||
readonly page: string | ||
readonly text: string | ||
readonly textNumber: string | ||
readonly linesDiscussed?: string | ||
readonly discussedBy?: string | ||
readonly discussedByNotes?: string | ||
} | ||
|
||
export class AfoRegisterRecordSuggestion { | ||
[immerable] = true | ||
|
||
readonly text: string | ||
readonly textNumbers: string[] | ||
|
||
constructor({ | ||
text, | ||
textNumbers, | ||
}: { | ||
readonly text: string | ||
readonly textNumbers: string[] | ||
}) { | ||
this.text = text | ||
this.textNumbers = textNumbers | ||
} | ||
} | ||
|
||
export default class AfoRegisterRecord { | ||
[immerable] = true | ||
|
||
readonly afoNumber: string | ||
readonly page: string | ||
readonly text: string | ||
readonly textNumber: string | ||
readonly linesDiscussed?: string | ||
readonly discussedBy?: string | ||
readonly discussedByNotes?: string | ||
|
||
constructor({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 3 locations. Consider refactoring. |
||
afoNumber, | ||
page, | ||
text, | ||
textNumber, | ||
linesDiscussed, | ||
discussedBy, | ||
discussedByNotes, | ||
}: RecordData) { | ||
this.afoNumber = afoNumber | ||
this.page = page | ||
this.text = text | ||
this.textNumber = textNumber | ||
this.linesDiscussed = linesDiscussed | ||
this.discussedBy = discussedBy | ||
this.discussedByNotes = discussedByNotes | ||
} | ||
|
||
toMarkdownString(fragments: Fragment[]): string { | ||
let result = this.text + (this.textNumber ? ' ' + this.textNumber : '') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recently made a little helper function |
||
const linkToFragment = this.findLinkToFragment(fragments) | ||
if (linkToFragment) result += `(${linkToFragment})` | ||
if (this.linesDiscussed) result += ', ' + this.linesDiscussed | ||
if (this.discussedBy) result += ': ' + this.discussedBy | ||
if (this.discussedByNotes) result += ' ' + this.discussedByNotes | ||
|
||
result += `<small class="text-black-50 ml-3">${`[${this.afoNumber}, ${this.page}]`}</small>` | ||
|
||
result = result.replace(/\^([^^]+)\^/g, '<sup>$1</sup>') | ||
return result | ||
} | ||
|
||
findLinkToFragment(fragments: Fragment[]): string { | ||
const reference = this.text + ' ' + this.textNumber | ||
const matchingFragments = fragments.filter((fragment) => | ||
fragment.traditionalReferences.includes(reference) | ||
) | ||
if (matchingFragments.length === 0) return '' | ||
return matchingFragments.map((fragment) => fragment.number).join(', ') | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import AfoRegisterRecord from 'afo-register/domain/Record' | ||
import ApiClient from 'http/ApiClient' | ||
import AfoRegisterRepository from './AfoRegisterRepository' | ||
import Promise from 'bluebird' | ||
import { testDelegation, TestData } from 'test-support/utils' | ||
|
||
jest.mock('http/ApiClient') | ||
|
||
const apiClient = new (ApiClient as jest.Mock<jest.Mocked<ApiClient>>)() | ||
const afoRegisterRepository = new AfoRegisterRepository(apiClient) | ||
const query = '{"afoNumber": "AfO 12", "page": "321"}' | ||
const resultStub = { | ||
afoNumber: 'AfO 12', | ||
page: '321', | ||
text: 'text', | ||
textNumber: 'text number', | ||
linesDiscussed: '', | ||
discussedBy: '', | ||
discussedByNotes: '', | ||
} | ||
const entry = new AfoRegisterRecord(resultStub) | ||
|
||
const testData: TestData<AfoRegisterRepository>[] = [ | ||
new TestData( | ||
'search', | ||
[query], | ||
apiClient.fetchJson, | ||
[entry], | ||
[`/afo-register?${query}`, false], | ||
Promise.resolve([resultStub]) | ||
), | ||
] | ||
|
||
describe('AfoRegisterRepository', () => | ||
testDelegation(afoRegisterRepository, testData)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import AfoRegisterRecord, { | ||
AfoRegisterRecordSuggestion, | ||
} from 'afo-register/domain/Record' | ||
import Promise from 'bluebird' | ||
import ApiClient from 'http/ApiClient' | ||
|
||
function createAfoRegisterRecord(data) { | ||
return new AfoRegisterRecord(data) | ||
} | ||
|
||
function createAfoRegisterRecordSuggestion(data) { | ||
return new AfoRegisterRecordSuggestion(data) | ||
} | ||
|
||
export default class AfoRegisterRepository { | ||
private readonly apiClient: ApiClient | ||
|
||
constructor(apiClient: ApiClient) { | ||
this.apiClient = apiClient | ||
} | ||
|
||
search(query: string): Promise<AfoRegisterRecord[]> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
return this.apiClient | ||
.fetchJson(`/afo-register?${query}`, false) | ||
.then((result) => result.map(createAfoRegisterRecord)) | ||
} | ||
|
||
searchSuggestions(query: string): Promise<AfoRegisterRecordSuggestion[]> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
return this.apiClient | ||
.fetchJson(`/afo-register/suggestions?text_query=${query}`, false) | ||
.then((result) => result.map(createAfoRegisterRecordSuggestion)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import React from 'react' | ||
import _ from 'lodash' | ||
|
||
import withData from 'http/withData' | ||
|
||
import AfoRegisterRecord from 'afo-register/domain/Record' | ||
import AfoRegisterService from 'afo-register/application/AfoRegisterService' | ||
import { LiteratureRedirectBox } from 'common/LiteratureRedirectBox' | ||
import { AfoRegisterQuery } from './AfoRegisterSearchForm' | ||
import { stringify } from 'query-string' | ||
import MarkdownAndHtmlToHtml from 'common/MarkdownAndHtmlToHtml' | ||
|
||
export const AfoRegisterRedirectBox = ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
<LiteratureRedirectBox | ||
authors="Hirsch, H.; Hunger, H.; Jursa, M.; Weszeli, M.; et al." | ||
book="Archiv für Orientforschung (Register Assyriologie)" | ||
notelink="" | ||
subtitle="25 (1974/1977) – 54 (2021)" | ||
note="By permission from the AfO Redaktion" | ||
link="https://orientalistik.univie.ac.at/publikationen/afo/register/" | ||
icon="pointer__hover my-2 fas fa-external-link-square-alt" | ||
/> | ||
) | ||
|
||
function afoRegisterSearch({ data }: { data: readonly AfoRegisterRecord[] }) { | ||
return ( | ||
<> | ||
<ol className="afoRegisterSearch"> | ||
{data.map((record, index) => ( | ||
<li key={`li-${index}`} className="afoRegisterSearch__record"> | ||
<MarkdownAndHtmlToHtml | ||
key={`md-${index}`} | ||
markdownAndHtml={record.toMarkdownString([])} | ||
/> | ||
</li> | ||
))} | ||
</ol> | ||
{data.length > 0 && AfoRegisterRedirectBox} | ||
</> | ||
) | ||
} | ||
|
||
export default withData< | ||
unknown, | ||
{ | ||
afoRegisterService: AfoRegisterService | ||
query: AfoRegisterQuery | ||
}, | ||
readonly AfoRegisterRecord[] | ||
>( | ||
afoRegisterSearch, | ||
(props) => props.afoRegisterService.search(stringify(props.query)), | ||
{ | ||
watch: (props) => [props.query], | ||
filter: (props) => !_.isEmpty(props.query), | ||
defaultData: () => [], | ||
} | ||
) |
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.
Similar blocks of code found in 2 locations. Consider refactoring.