Skip to content

Commit

Permalink
Implement kings as service (WiP)
Browse files Browse the repository at this point in the history
  • Loading branch information
khoidt committed Feb 6, 2024
1 parent 28e393c commit 0f9030d
Show file tree
Hide file tree
Showing 26 changed files with 502 additions and 153 deletions.
7 changes: 7 additions & 0 deletions src/chronology/application/DateSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,22 @@ import {
import useDateSelectionState, {
DateEditorStateProps,
} from 'chronology/application/DateSelectionState'
import KingsService from './KingsService'

type Props = {
dateProp?: MesopotamianDate
updateDate: (date?: MesopotamianDate, index?: number) => Bluebird<Fragment>
inList?: boolean
index?: number
saveDateOverride?: (updatedDate?: MesopotamianDate, index?: number) => void
kingsService: KingsService
}

interface DateEditorProps extends DateEditorStateProps {
target: React.MutableRefObject<null>
isSaving: boolean
isDisplayed: boolean
kingsService: KingsService
}

export function DateEditor({
Expand All @@ -41,6 +44,7 @@ export function DateEditor({
setIsDisplayed,
setIsSaving,
saveDateOverride,
kingsService,
}: DateEditorProps): JSX.Element {
const state = useDateSelectionState({
date,
Expand All @@ -50,6 +54,7 @@ export function DateEditor({
setIsDisplayed,
setIsSaving,
saveDateOverride,
kingsService,
})

const dateOptionsInput = DateOptionsInput({ ...state })
Expand Down Expand Up @@ -114,6 +119,7 @@ export default function DateSelection({
inList = false,
index,
saveDateOverride,
kingsService,
}: Props): JSX.Element {
const target = useRef(null)
const [isDisplayed, setIsDisplayed] = useState(false)
Expand Down Expand Up @@ -149,6 +155,7 @@ export default function DateSelection({
setDate={setDate}
index={index}
saveDateOverride={saveDateOverride}
kingsService={kingsService}
/>
)

Expand Down
35 changes: 21 additions & 14 deletions src/chronology/application/DateSelectionMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DateFieldDto, MonthFieldDto } from 'fragmentarium/domain/FragmentDtos'
import { Fragment } from 'fragmentarium/domain/fragment'
import { DateSelectionStateParams } from './DateSelectionState'
import { EponymDateField, KingDateField } from 'chronology/domain/DateBase'
import KingsService from './KingsService'

interface SaveDateParams {
date?: MesopotamianDate
Expand Down Expand Up @@ -45,20 +46,26 @@ export function saveDateDefault({
}
}

export function getDate(params: DateSelectionStateParams): MesopotamianDate {
return MesopotamianDate.fromJson({
year: getYear(params),
month: getMonth(params),
day: getDay(params),
king: getKing(params),
eponym: getEponym(params),
isSeleucidEra: params.isSeleucidEra,
isAssyrianDate: params.isAssyrianDate,
ur3Calendar:
params.ur3Calendar && params.isCalendarFieldDisplayed
? params.ur3Calendar
: undefined,
})
export function getDate(
params: DateSelectionStateParams,
kingsService: KingsService
): MesopotamianDate {
return MesopotamianDate.fromJson(
{
year: getYear(params),
month: getMonth(params),
day: getDay(params),
king: getKing(params),
eponym: getEponym(params),
isSeleucidEra: params.isSeleucidEra,
isAssyrianDate: params.isAssyrianDate,
ur3Calendar:
params.ur3Calendar && params.isCalendarFieldDisplayed
? params.ur3Calendar
: undefined,
},
kingsService
)
}

function getYear(params: DateSelectionStateParams): DateFieldDto {
Expand Down
24 changes: 20 additions & 4 deletions src/chronology/application/DateSelectionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,26 @@ import { MesopotamianDate } from 'chronology/domain/Date'
import { EponymDateField, Ur3Calendar } from 'chronology/domain/DateBase'
import { KingDateField } from 'chronology/domain/DateBase'
import usePromiseEffect from 'common/usePromiseEffect'
import { Eponym } from 'chronology/ui/DateEditor/Eponyms'
import { useState } from 'react'
import Bluebird from 'bluebird'
import { Fragment } from 'fragmentarium/domain/fragment'
import {
getDate,
saveDateDefault,
} from 'chronology/application/DateSelectionMethods'
import KingsService from './KingsService'

// ToDo:
// - Test `isNotInBrinkman`
// - Exclude empty dates and make it impossible to save them
// - If year, month, and day are empty and not broken or undertain, do not display ∅.∅.∅, instead display only the name of the king.
// - If day, month or year are not given, do not calculate the exact date, instead only the year.
// - Accession year: year 0 of the king belongs with the last year of the prev. king
// - Address date converter issues:
// 1. January & February (both Gregorian & Julian) drifts upon change,
// 2. Check dates around 1 BCE / CE,
// 3. Fix errors with first and last ruler
// - Instead of PGC, give the Julian date by default and show an info icon. When hovering over the icon, the user will get the PGC date.

export interface DateEditorStateProps {
date?: MesopotamianDate
Expand All @@ -19,6 +31,7 @@ export interface DateEditorStateProps {
setIsSaving: React.Dispatch<React.SetStateAction<boolean>>
index?: number
saveDateOverride?: (updatedDate?: MesopotamianDate, index?: number) => void
kingsService: KingsService
}

interface YearStateParams {
Expand Down Expand Up @@ -74,7 +87,7 @@ interface KingAndEponymDateParams extends KingAndEponymBrokenUncertainParams {
king?: KingDateField
eponym?: EponymDateField
setKing: React.Dispatch<React.SetStateAction<KingDateField | undefined>>
setEponym: React.Dispatch<React.SetStateAction<Eponym | undefined>>
setEponym: React.Dispatch<React.SetStateAction<EponymDateField | undefined>>
}

interface AdditionalDateStateParams
Expand All @@ -88,7 +101,9 @@ export interface DateSelectionStateParams
extends YearStateParams,
MonthStateParams,
DayStateParams,
AdditionalDateStateParams {}
AdditionalDateStateParams {
kingsService: KingsService
}

export interface DateSelectionState extends DateSelectionStateParams {
getDate: () => MesopotamianDate
Expand Down Expand Up @@ -241,6 +256,7 @@ export default function useDateSelectionState(
...useMonthState(date),
...useDayState(date),
...useAdditionalDateParams(date),
kingsService: props.kingsService,
}
const _saveDate = (updatedDate) =>
saveDateDefault({
Expand All @@ -250,7 +266,7 @@ export default function useDateSelectionState(
updatedDate,
})

const _getDate = () => getDate(stateParams)
const _getDate = () => getDate(stateParams, props.kingsService)

return {
...stateParams,
Expand Down
58 changes: 58 additions & 0 deletions src/chronology/application/KingsService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Promise from 'bluebird'
import KingsRepository from 'chronology/infrastructure/KingsRepository'
import { King } from 'chronology/ui/BrinkmanKings/BrinkmanKings'

export interface kingsSearch {
fetchAll(query: string): Promise<readonly King[]>
}

export default class KingsService implements kingsSearch {
private readonly kingsRepository: KingsRepository
private _kings: King[] = []
kingOptions: Array<{ label: string; value: King }> = []

constructor(kingsRepository: KingsRepository) {
this.kingsRepository = kingsRepository
}

static async createAndInitialize(
kingsRepository: KingsRepository
): Promise<KingsService> {
const service = new KingsService(kingsRepository)
await service.initializeKings()
return service
}

get kings(): King[] {
return this._kings
}

private async initializeKings(): Promise<void> {
try {
this._kings = await this.fetchAll()
this.kingOptions = this.getKingOptions()
} catch (error) {
console.error('Failed to initialize kingsCollection', error)
}
}

fetchAll(): Promise<King[]> {
return this.kingsRepository.fetchAll()
}

private getKingOptions(): Array<{ label: string; value: King }> {
return this.kings
.filter((king) => !['16', '17'].includes(king.dynastyNumber))
.map((king) => {
return {
label: this.getKingSelectLabel(king),
value: king,
}
})
}

private getKingSelectLabel(king: King): string {
const kingYears = king.date ? ` (${king.date})` : ''
return `${king.name}${kingYears}, ${king.dynastyName}`
}
}
9 changes: 7 additions & 2 deletions src/chronology/domain/Date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import { MesopotamianDateDto } from 'fragmentarium/domain/FragmentDtos'
import _ from 'lodash'
import { romanize } from 'romans'
import { MesopotamianDateBase } from 'chronology/domain/DateBase'
import KingsService from 'chronology/application/KingsService'

export class MesopotamianDate extends MesopotamianDateBase {
static fromJson(dateJSON: MesopotamianDateDto): MesopotamianDate {
static fromJson(
dateJson: MesopotamianDateDto,
kingsService: KingsService
): MesopotamianDate {
const {
year,
month,
Expand All @@ -14,8 +18,9 @@ export class MesopotamianDate extends MesopotamianDateBase {
isSeleucidEra,
isAssyrianDate,
ur3Calendar,
} = dateJSON
} = dateJson
return new MesopotamianDate(
kingsService,
year,
month,
day,
Expand Down
8 changes: 6 additions & 2 deletions src/chronology/domain/DateBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Eponym } from 'chronology/ui/DateEditor/Eponyms'
import DateConverter from 'chronology/domain/DateConverter'
import data from 'chronology/domain/dateConverterData.json'
import _ from 'lodash'
import KingsService from 'chronology/application/KingsService'

export interface DateField {
value: string
Expand Down Expand Up @@ -40,6 +41,7 @@ export enum Ur3Calendar {
}

export class MesopotamianDateBase {
kingsService: KingsService
year: DateField
month: MonthField
day: DateField
Expand All @@ -50,6 +52,7 @@ export class MesopotamianDateBase {
ur3Calendar?: Ur3Calendar

constructor(
kingsService: KingsService,
year: DateField,
month: MonthField,
day: DateField,
Expand All @@ -59,6 +62,7 @@ export class MesopotamianDateBase {
isAssyrianDate?: boolean,
ur3Calendar?: Ur3Calendar
) {
this.kingsService = kingsService
this.year = year
this.month = month
this.day = day
Expand Down Expand Up @@ -188,7 +192,7 @@ export class MesopotamianDateBase {
day: number,
isApproximate: boolean
): string {
const converter = new DateConverter()
const converter = new DateConverter({ ...this })
converter.setToSeBabylonianDate(year, month, day)
return this.insertDateApproximation(converter.toDateString(), isApproximate)
}
Expand All @@ -203,7 +207,7 @@ export class MesopotamianDateBase {
(key) => data.rulerToBrinkmanKings[key] === this.king?.orderGlobal
)
if (kingName) {
const converter = new DateConverter()
const converter = new DateConverter({ ...this })
converter.setToMesopotamianDate(kingName, year, month, day)
return this.insertDateApproximation(
converter.toDateString(),
Expand Down
8 changes: 5 additions & 3 deletions src/chronology/domain/DateConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ import {
King,
findKingByOrderGlobal,
} from 'chronology/ui/BrinkmanKings/BrinkmanKings'
import KingsService from 'chronology/application/KingsService'

export default class DateConverter extends DateConverterBase {
checks: DateConverterChecks = new DateConverterChecks()
earliestDate: CalendarProps
latestDate: CalendarProps
kingsService: KingsService

constructor() {
constructor({ kingsService }: { kingsService: KingsService }) {
super()
this.setToEarliestDate()
this.kingsService = kingsService
this.earliestDate = { ...this.calendar }
this.setToLatestDate()
this.latestDate = { ...this.calendar }
Expand Down Expand Up @@ -49,7 +51,7 @@ export default class DateConverter extends DateConverterBase {
ruler = ruler ?? this.calendar?.ruler
if (ruler) {
const orderGlobal = data.rulerToBrinkmanKings[ruler]
return findKingByOrderGlobal(orderGlobal)
return findKingByOrderGlobal(orderGlobal, this.kingsService.kings)
}
return null
}
Expand Down
15 changes: 15 additions & 0 deletions src/chronology/infrastructure/KingsRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { King } from 'chronology/ui/BrinkmanKings/BrinkmanKings'
import Promise from 'bluebird'
import ApiClient from 'http/ApiClient'

export default class KingsRepository {
private readonly apiClient: ApiClient

constructor(apiClient: ApiClient) {
this.apiClient = apiClient
}

fetchAll(): Promise<King[]> {
return this.apiClient.fetchJson('/kings-all', false)
}
}
14 changes: 14 additions & 0 deletions src/chronology/ui/BrinkmanKings/BrinkmanKings.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { render, screen } from '@testing-library/react'
import BrinkmanKingsTable from 'chronology/ui/BrinkmanKings/BrinkmanKings'

/*
jest.doMock('chronology/domain/BrinkmanKings.json', () => ({
__esModule: true,
default: [],
}))
*/
jest.mock('chronology/domain/BrinkmanKings.json', () => [], { virtual: true })

test('Snapshot', () => {
expect(BrinkmanKingsTable()).toMatchSnapshot()
})

test('Displays only kings from Brinkman in table', () => {
render(BrinkmanKingsTable())
expect(screen.getByText('Maništušu')).not.toBeInTheDocument()
})
Loading

0 comments on commit 0f9030d

Please sign in to comment.