From 708d26d5611b01a159716216054c248ddacca26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemek=20Wi=C4=99ch?= Date: Tue, 12 May 2026 00:33:42 +0200 Subject: [PATCH] Add Immediate Family section to person details in side panel --- docs/IMMEDIATE_FAMILY_SECTION_DESIGN.md | 87 +++++++ docs/README.md | 1 + docs/SCREENSHOT_TESTS_DESIGN.md | 4 + src/index.css | 10 +- src/sidepanel/details/README.md | 2 + src/sidepanel/details/details.tsx | 2 + src/sidepanel/details/events.tsx | 28 +-- src/sidepanel/details/immediate-family.tsx | 218 ++++++++++++++++++ src/sidepanel/details/person-link.tsx | 31 +++ src/translations/bg.json | 11 +- src/translations/cs.json | 11 +- src/translations/de.json | 11 +- src/translations/fr.json | 11 +- src/translations/it.json | 11 +- src/translations/pl.json | 11 +- src/translations/ru.json | 11 +- tests/details_visual.spec.ts | 66 ++++++ .../details-events-sources-visual-linux.png | Bin 19750 -> 19786 bytes .../details-immediate-family-visual-linux.png | Bin 0 -> 16879 bytes 19 files changed, 492 insertions(+), 34 deletions(-) create mode 100644 docs/IMMEDIATE_FAMILY_SECTION_DESIGN.md create mode 100644 src/sidepanel/details/immediate-family.tsx create mode 100644 src/sidepanel/details/person-link.tsx create mode 100644 tests/details_visual.spec.ts-snapshots/details-immediate-family-visual-linux.png diff --git a/docs/IMMEDIATE_FAMILY_SECTION_DESIGN.md b/docs/IMMEDIATE_FAMILY_SECTION_DESIGN.md new file mode 100644 index 0000000..b4ebd17 --- /dev/null +++ b/docs/IMMEDIATE_FAMILY_SECTION_DESIGN.md @@ -0,0 +1,87 @@ +# Immediate Family Section Design + +## Problem + +Topola Viewer renders an interactive graphical family tree centered on a selected individual, displaying connected nodes for ancestors, descendants, and spouses. However, as family structures expand or users zoom in for detail, directly related family members frequently flow off the visible screen boundaries, requiring tedious canvas manipulation to locate and select them. To improve navigation efficiency and provide clear relational context at a glance, the application needs a dedicated layout block in the side panel that consolidates and displays the focused person's parents, spouses, and children. Providing these primary relationships as direct clickable links ensures users can rapidly transition focus between immediate family members regardless of their current viewport position on the graphical canvas. + +## Technical Plan + +To introduce the immediate family view without disrupting existing features, the implementation introduces a focused visual component that acts as an intermediary between the raw genealogy data and the user interface. + +The system relies on three primary components working together: +1. **Genealogy Data Store**: The core repository containing all parsed individuals and family records. It provides lookup utilities to resolve cross-references between children and their parents or spouses. +2. **Immediate Family Component**: A dedicated new interface element embedded directly inside the side panel. It queries the data store for the currently selected person, extracts their primary set of parents, and groups all associated children under their respective spouses or partners. +3. **Navigation Module**: When a user clicks on any parent, spouse, or child link within the new block, this module updates the application's active web address with the chosen relative's identifier. This action instantly re-centers both the side panel and the primary visual tree onto the newly selected family member. + +## Alternatives + +During the initial design discussions, several alternative implementation strategies were evaluated and ultimately ruled out to ensure optimal user experience and maintainability: + +### 1. Integrating Relationships into the Event Timeline +* **Concept**: Interweave parents and children directly into the chronologically sorted lifecycle event list (e.g., rendering children as "Child Born" timeline events and placing parents near the target person's birth event). +* **Reason for Rejection**: Structural relationships are fundamentally distinct from point-in-time events. Forcing them into an event-driven layout scatters family members across the full vertical height of the panel, creating severe timeline clutter and undermining the core goal of rapid navigation. + +### 2. Removing the Timeline Spouse Link +* **Concept**: Strip out the standalone spouse navigation link from the chronological marriage event entries to prevent duplicating the link in both the timeline and the new Immediate Family block. +* **Reason for Rejection**: Detaching the spouse link from the timeline breaks historical context, separating the marriage ceremony record from the actual partner involved. Maintaining both preserves event completeness while establishing a centralized navigation block. + +### 3. Rendering a Flat List of Children +* **Concept**: Consolidate all children into a single flat list ordered strictly by birth date, omitting spousal boundaries. +* **Reason for Rejection**: Fails to represent blended families clearly. Explicitly grouping children under their respective spouse or partner headers makes full-sibling versus half-sibling structures immediately obvious to the user. + +### 4. Uniformly Showing or Hiding Unknown Spouses +* **Concept**: Apply a blanket rule to either always display an "Unknown Spouse" header for single-parent records or entirely hide unknown headers across all scenarios. +* **Reason for Rejection**: Always showing the header adds unnecessary visual noise to standard single-family layouts. Always hiding it obscures complex relationship boundaries when an individual has children across multiple partners where some partner names are unrecorded. The conditional approach dynamically cleans up single-family displays while preserving vital structural boundaries for multi-partner families. + +### 5. Supporting Multiple Sets of Parents Immediately +* **Concept**: Query all associated `FAMC` records to display biological, adoptive, and foster parent sets side-by-side from day one. +* **Reason for Rejection**: Introduces substantial UI complexity for labeling pedigree types (`PEDI` sub-tags) and requires wider structural refactoring of active focus state handling across the core canvas layout. Deferring to a single primary parent set keeps the initial feature scope robust and achievable. + +## Detailed Implementation + +Executing this feature requires clean extensions across the side panel architecture. To maintain high code quality and ensure strict boundaries, the implementation avoids modifying shared core state or event logic directly, instead isolating rendering responsibilities into modular layers. + +Below is the exhaustive file-by-file breakdown enumerating every file that will be created or modified, accompanied by detailed implementation step guidelines and specific technical rationale. + +### 1. Component Creation +#### [NEW] [immediate-family.tsx](../src/sidepanel/details/immediate-family.tsx) +* **Rationale**: Encapsulating the new feature inside a dedicated component file separates concerns, avoids bloating the orchestration component ([details.tsx](../src/sidepanel/details/details.tsx)), and centralizes specialized rendering logic for single parent sets, childless spouses, conditional unknown headers, and chronologically sorted child groupings. +* **Implementation Steps**: + 1. **Imports**: Import React elements, Semantic UI layout wrappers (`Item`, `Header`), navigation routing dependencies (`Link`, `useLocation` from `react-router`, `query-string`), localization wrappers (`FormattedMessage`, `useIntl` from `react-intl`), and GEDCOM utility functions from `../../util/gedcom_util` ([dereference](../src/util/gedcom_util.ts#L171-L183), [getName](../src/util/gedcom_util.ts#L292-L302), [pointerToId](../src/util/gedcom_util.ts#L42-L44), [resolveDate](../src/util/gedcom_util.ts#L339-L342)). + 2. **Relative Link Helper**: Define an internal component (e.g., `RelativeLink`) that renders an individual relative profile as a ``. It extracts the target relative's plain ID directly from the raw sub-entry string via `pointerToId(subEntry.data)` before dereferencing to prevent runtime crashes on broken references. It parses `location.search` using `useLocation()`, sets the `indi` query parameter to the target ID, stringifies the search parameters, routes to `/view`, and outputs the resolved display name via `getName` (falling back to localized unknown string if undefined). + 3. **Parents Block Renderer**: Implement a rendering method that extracts the active individual's tree array. Find the first sub-entry where `tag === 'FAMC'`. Guard against `undefined` if parents are unrecorded. Safely dereference this pointer against the repository's family mapping array to locate the parental family record. Scan the resolved family entry for all `HUSB` and `WIFE` sub-entries. Extract plain IDs via `pointerToId(subEntry.data)` and dereference each against the repository's individual mapping array to resolve profile records. Conditionally output localized sub-headers (e.g., "Father", "Mother") accompanied by clickable `RelativeLink` instances only for present parent records. + 4. **Spouses and Children Block Renderer**: Implement a rendering method that iterates over all `FAMS` tags within the active individual's tree. Dereference each entry to fetch its corresponding family record. For each family record, extract the partner/spouse pointers (`HUSB` or `WIFE` tags ensuring `!subEntry.data.includes(props.indi)` to prevent extracting the focused person as their own spouse) and extract all child records (`CHIL`). + 5. **Child Record Dereferencing and Sorting**: Explicitly dereference each extracted `CHIL` sub-entry against `gedcom.indis` to access child profile records. Extract their birth dates using `resolveDate` and sort the children array chronologically by birth date before outputting to ensure correct relational flow. + 6. **Conditional Unknown Spouse Logic**: Prior to outputting headers, evaluate the total length of the mapped `FAMS` array. Guard against incomplete/empty family entries by suppressing groups containing neither a valid spouse pointer nor children. If a spouse profile pointer is absent and total `FAMS` equals `1`, suppress the spouse header output. If a spouse pointer is absent and total valid `FAMS` groups exceed `1`, output a visible "Spouse: Unknown" block header to clearly define half-sibling boundaries. + 7. **Sequential Group Output**: Output each valid spousal family group as an encapsulated sub-block. Render childless spouses as complete standalone items. Output the resolved, sorted children collection as relative links below their respective spouse/partner header. + 8. **Container Wrapper**: Export the primary `ImmediateFamily` component wrapper. If active parent, spouse, or child nodes exist, wrap the consolidated layout blocks inside a single Semantic UI `` container structured with ``. If no immediate family members exist, return `null` to prevent empty dividers in the side panel DOM. + +### 2. Orchestration Layer Modification +#### [MODIFY] [details.tsx](../src/sidepanel/details/details.tsx) +* **Rationale**: Acts as the root layout orchestrator for the side panel info tab. Needs to import and render the new view block near the top of the component flow to guarantee primary relational links are visible above the fold without requiring users to scroll past massive event timelines. +* **Implementation Steps**: + 1. Import the `ImmediateFamily` component from `./immediate-family`. + 2. Locate the main [Details](../src/sidepanel/details/details.tsx#L338-L387) component export function. + 3. Identify the execution block rendering `{getSectionForEachMatchingEntry(entries, props.gedcom, ['OBJE'], imageDetails)}` (line 350-355). + 4. Directly below this block, and strictly *before* the `` timeline rendering execution line, embed `` directly within the `` flow. Rely on the component's internal conditional logic to render the outer item bounds. + +### 3. Registry and Documentation Updates +#### [MODIFY] [README.md](../src/sidepanel/details/README.md) +* **Rationale**: Functions as the official index cataloging all available component views within the side panel details sub-package. Documenting the new file preserves architectural readability. +* **Implementation Steps**: + 1. Locate the alphabetical files registry list. + 2. Insert a descriptive entry for `immediate-family.tsx`, explaining its role as a dedicated side panel module for grouping and displaying parents, spouses, and children as rapid-navigation links. + +### 4. Localization Contracts +#### [MODIFY] Translation JSON Files (`src/translations/*.json`) +* **Rationale**: Guarantees that every new UI header label introduced by the feature supports multi-language localization cleanly across all supported international environments. +* **Implementation Steps**: + 1. Establish explicit string descriptor keys to be mapped across all JSON locale files (e.g., `src/translations/en.json`, `de.json`, `pl.json`, `fr.json`, `it.json`, etc.) to avoid production fallback leakage: + * `"family.immediate_family": "Immediate Family"` + * `"family.parents": "Parents"` + * `"family.father": "Father"` + * `"family.mother": "Mother"` + * `"family.spouse": "Spouse"` + * `"family.unknown_spouse": "Unknown Spouse"` + * `"family.children": "Children"` + 2. Ensure corresponding `` invocations inside `immediate-family.tsx` reference these specific string descriptor keys. diff --git a/docs/README.md b/docs/README.md index 6bb4017..b0baae7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ While new features *may* follow this methodology to ensure robust design validat ## Design Documents Registry * **[DOCKER_DESIGN.md](DOCKER_DESIGN.md)**: Docker container packaging, lightweight Caddy web server configuration, and GitHub Actions publishing pipelines. +* **[IMMEDIATE_FAMILY_SECTION_DESIGN.md](IMMEDIATE_FAMILY_SECTION_DESIGN.md)**: Side panel block consolidating parents, spouses, and children for efficient off-screen tree navigation. * **[PLAYWRIGHT_DESIGN.md](PLAYWRIGHT_DESIGN.md)**: Playwright E2E testing architecture, Vite development/preview server lifecycle integration, tracking blocker interceptors, and embedded iframe communication. * **[SCREENSHOT_TESTS_DESIGN.md](SCREENSHOT_TESTS_DESIGN.md)**: Pixel-perfect visual regression testing infrastructure, animation stabilization, sandbox environment/DOM sanitization, and isolated Playwright projects. * **[WEBMCP_DESIGN.md](WEBMCP_DESIGN.md)**: Model Context Protocol (MCP) bridge and TS tool registration for AI agent interaction. diff --git a/docs/SCREENSHOT_TESTS_DESIGN.md b/docs/SCREENSHOT_TESTS_DESIGN.md index f7213de..ac67aae 100644 --- a/docs/SCREENSHOT_TESTS_DESIGN.md +++ b/docs/SCREENSHOT_TESTS_DESIGN.md @@ -106,6 +106,10 @@ This section defines the granular, step-by-step implementation steps and enumera * Mock `**/family.ged` containing complex nested fact (`FACT`), source (`SOUR`), and note (`NOTE`) trees. * Select the individual and wait for `#sidebar` to load. * Assert sidebar visual representation: `expect(page.locator('#sidebar')).toHaveScreenshot('details-events-sources.png')`. + * **Immediate Family Rendering Test:** + * Mock `**/family.ged` containing an individual with explicit parental links (`FAMC`) and multi-partner spousal families (`FAMS`) to display biological parents, spouses, and chronologically sorted children blocks. + * Select the individual and wait for `#sidebar` to load. + * Assert sidebar visual representation: `expect(page.locator('#sidebar')).toHaveScreenshot('details-immediate-family.png')`. #### Step 5: Configurations Integration Spec (`tests/config_visual.spec.ts`) 1. Define a test block tagged `@visual` with a locked browser window viewport size of `1280x720` via `playwright.config.ts`. diff --git a/src/index.css b/src/index.css index 8ba8595..8874cb4 100644 --- a/src/index.css +++ b/src/index.css @@ -162,7 +162,7 @@ div.zoom { .details .item-header .header { text-transform: uppercase; - margin: 0; + margin: 0 0 8px 0; min-width: 40%; } @@ -335,6 +335,14 @@ div.zoom { white-space: pre; } +.parents-block { + margin-bottom: 7px; +} + +.children-block { + display: flex; +} + @media (max-width: 450px) { /* Hide the title from the top bar when the viewport is too small to display it alongside the search box. */ diff --git a/src/sidepanel/details/README.md b/src/sidepanel/details/README.md index 7cb015c..4d00cc3 100644 --- a/src/sidepanel/details/README.md +++ b/src/sidepanel/details/README.md @@ -9,8 +9,10 @@ This directory contains React components for displaying detailed information abo - [details.tsx](details.tsx): The main component that orchestrates the display of all details for an individual, including name, images, events, facts, notes, and sources. - [event-extras.tsx](event-extras.tsx): Displays additional content for events (images, notes, sources, files) in a tabbed interface. - [events.tsx](events.tsx): Handles the logic and display for all events related to an individual, sorting them by date and grouping them by life stages. +- [immediate-family.tsx](immediate-family.tsx): A dedicated side panel module for grouping and displaying parents, spouses, and children as rapid-navigation links. - [linkify-new-tab.tsx](linkify-new-tab.tsx): A helper component that wraps content and makes URLs clickable, opening them in a new tab. - [multiline-text.tsx](multiline-text.tsx): Helper component to display multi-line text with linkified URLs. +- [person-link.tsx](person-link.tsx): Component that renders a clickable link to navigate to a person's profile view. - [sources.tsx](sources.tsx): Displays a list of sources cited for an entry. - [translated-tag.tsx](translated-tag.tsx): Component to translate GEDCOM tags into human-readable labels. - [wrapped-image.tsx](wrapped-image.tsx): Component to display images with loading placeholders, error fallback, and a click-to-enlarge modal. diff --git a/src/sidepanel/details/details.tsx b/src/sidepanel/details/details.tsx index b5e20b1..16d35d1 100644 --- a/src/sidepanel/details/details.tsx +++ b/src/sidepanel/details/details.tsx @@ -14,6 +14,7 @@ import { import {Config, Ids} from '../config/config'; import {AdditionalFiles, FileEntry} from './additional-files'; import {ALL_SUPPORTED_EVENT_TYPES, Events} from './events'; +import {ImmediateFamily} from './immediate-family'; import {MultilineText} from './multiline-text'; import {Sources} from './sources'; import {TranslatedTag} from './translated-tag'; @@ -353,6 +354,7 @@ export function Details(props: Props) { ['OBJE'], imageDetails, )} + {props.config.id === Ids.SHOW ? getSectionForId(props.indi) : null} {getSectionForEachMatchingEntry( diff --git a/src/sidepanel/details/events.tsx b/src/sidepanel/details/events.tsx index 9eabf9b..ac04b2a 100644 --- a/src/sidepanel/details/events.tsx +++ b/src/sidepanel/details/events.tsx @@ -1,8 +1,6 @@ import flatMap from 'array.prototype.flatmap'; import {GedcomEntry} from 'parse-gedcom'; -import queryString from 'query-string'; -import {FormattedMessage, IntlShape, useIntl} from 'react-intl'; -import {Link, useLocation} from 'react-router'; +import {IntlShape, useIntl} from 'react-intl'; import {Header, Item} from 'semantic-ui-react'; import {DateOrRange, getDate} from 'topola'; import {calcAge} from '../../util/age_util'; @@ -13,39 +11,17 @@ import { getData, getFileName, getImageFileEntry, - getName, getNonImageFileEntry, mapToSource, - pointerToId, resolveDate, resolveType, Source, } from '../../util/gedcom_util'; import {FileEntry} from './additional-files'; import {EventExtras, Image} from './event-extras'; +import {PersonLink} from './person-link'; import {TranslatedTag} from './translated-tag'; -function PersonLink(props: {person: GedcomEntry}) { - const location = useLocation(); - - const name = getName(props.person); - - const search = queryString.parse(location.search); - search['indi'] = pointerToId(props.person.pointer); - - return ( - - - {name ? ( - name - ) : ( - - )} - - - ); -} - interface Props { gedcom: GedcomData; indi: string; diff --git a/src/sidepanel/details/immediate-family.tsx b/src/sidepanel/details/immediate-family.tsx new file mode 100644 index 0000000..293ef04 --- /dev/null +++ b/src/sidepanel/details/immediate-family.tsx @@ -0,0 +1,218 @@ +import {GedcomEntry} from 'parse-gedcom'; +import {FormattedMessage} from 'react-intl'; +import {Header, Item} from 'semantic-ui-react'; +import {getDate} from 'topola'; +import {compareDates} from '../../util/date_util'; +import {GedcomData, pointerToId, resolveDate} from '../../util/gedcom_util'; +import {PersonLink} from './person-link'; + +interface Props { + gedcom: GedcomData; + indi: string; +} + +function mapSpousalFamily( + familyRecord: GedcomEntry, + gedcom: GedcomData, + indi: string, +) { + const spouseSubEntry = familyRecord.tree?.find( + (sub) => + ['HUSB', 'WIFE'].includes(sub.tag) && pointerToId(sub.data) !== indi, + ); + const spouseId = spouseSubEntry + ? pointerToId(spouseSubEntry.data) + : undefined; + const spouseRecord = spouseId ? gedcom.indis[spouseId] : undefined; + + const chilSubEntries = + familyRecord.tree?.filter((sub) => sub.tag === 'CHIL') || []; + + const validChildren = chilSubEntries.filter( + (childSub) => !!gedcom.indis[pointerToId(childSub.data)], + ); + + // Pre-parse dates to avoid redundant O(N log N) parsing inside sort comparator + const mappedChildren = validChildren.map((childSub) => { + const childEntry = gedcom.indis[pointerToId(childSub.data)]; + const birt = childEntry?.tree.find((sub) => sub.tag === 'BIRT'); + const dateSub = birt ? resolveDate(birt) : undefined; + const parsedDate = dateSub ? getDate(dateSub.data) : undefined; + return { + childEntry, + parsedDate, + }; + }); + + const sortedChildren = mappedChildren + .sort((a, b) => compareDates(a.parsedDate, b.parsedDate)) + .map((item) => item.childEntry); + + return { + familyId: pointerToId(familyRecord.pointer), + spouseTag: spouseSubEntry?.tag, + spouseRecord, + children: sortedChildren, + }; +} + +/** + * Renders the immediate family section of a person, displaying their parents, + * spouses, and children. + */ +export function ImmediateFamily(props: Props) { + const personEntry = props.gedcom.indis[props.indi]; + if (!personEntry) { + return null; + } + + const entries = personEntry.tree; + + // --- Parents Block Renderer --- + const famcEntry = entries.find((sub) => sub.tag === 'FAMC'); + const parentalFamily = famcEntry + ? props.gedcom.fams[pointerToId(famcEntry.data)] + : undefined; + + const isParentalFamilyValid = parentalFamily?.tag === 'FAM'; + + const husbEntry = isParentalFamilyValid + ? parentalFamily?.tree.find((sub) => sub.tag === 'HUSB') + : undefined; + const wifeEntry = isParentalFamilyValid + ? parentalFamily?.tree.find((sub) => sub.tag === 'WIFE') + : undefined; + + const fatherId = husbEntry ? pointerToId(husbEntry.data) : undefined; + const fatherRecord = fatherId ? props.gedcom.indis[fatherId] : undefined; + + const motherId = wifeEntry ? pointerToId(wifeEntry.data) : undefined; + const motherRecord = motherId ? props.gedcom.indis[motherId] : undefined; + + const hasParents = fatherRecord || motherRecord; + + // --- Spouses and Children Block Renderer --- + const famsEntries = entries.filter((sub) => sub.tag === 'FAMS'); + const spousalFamilies = famsEntries.map( + (entry) => props.gedcom.fams[pointerToId(entry.data)], + ); + + const mappedFamilies = spousalFamilies.map((familyRecord) => + mapSpousalFamily(familyRecord, props.gedcom, props.indi), + ); + + const validMappedFamilies = mappedFamilies.filter( + (group) => group.spouseRecord || group.children.length > 0, + ); + + const totalValidFams = validMappedFamilies.length; + const hasSpousesOrChildren = totalValidFams > 0; + + if (!hasParents && !hasSpousesOrChildren) { + return null; + } + + return ( + + +
+
+ +
+
+ {hasParents && ( +
+ {fatherRecord && ( +
+ + + + : +
+ )} + {motherRecord && ( +
+ + + + : +
+ )} +
+ )} + + {validMappedFamilies.map((group) => { + const showUnknownSpouse = !group.spouseRecord && totalValidFams > 1; + return ( +
+ {group.spouseRecord ? ( +
+ + {group.spouseTag === 'HUSB' ? ( + + ) : ( + + )} + + : +
+ ) : showUnknownSpouse ? ( +
+ + + +
+ ) : null} + + {group.children.length > 0 && ( +
+
+ + {group.children.length === 1 ? ( + + ) : ( + + )} + + :  +
+
+ {group.children.map((child) => ( +
+ +
+ ))} +
+
+ )} +
+ ); + })} +
+
+ ); +} diff --git a/src/sidepanel/details/person-link.tsx b/src/sidepanel/details/person-link.tsx new file mode 100644 index 0000000..4cf6d86 --- /dev/null +++ b/src/sidepanel/details/person-link.tsx @@ -0,0 +1,31 @@ +import {GedcomEntry} from 'parse-gedcom'; +import queryString from 'query-string'; +import {FormattedMessage} from 'react-intl'; +import {Link, useLocation} from 'react-router'; +import {getName, pointerToId} from '../../util/gedcom_util'; + +interface Props { + person: GedcomEntry; +} + +/** + * Renders a clickable link to an individual's profile view, preserving existing query parameters. + */ +export function PersonLink(props: Props) { + const location = useLocation(); + + const name = getName(props.person); + + const search = queryString.parse(location.search); + search['indi'] = pointerToId(props.person.pointer); + + return ( + + {name ? ( + name + ) : ( + + )} + + ); +} diff --git a/src/translations/bg.json b/src/translations/bg.json index 683a6c0..89f27ff 100644 --- a/src/translations/bg.json +++ b/src/translations/bg.json @@ -134,5 +134,14 @@ "extras.images": "Изображение", "extras.notes": "Бележки", "extras.sources": "Източници", - "extras.files": "Допълнителни файлове" + "extras.files": "Допълнителни файлове", + "family.immediate_family": "Най-близко семейство", + "family.parents": "Родители", + "family.father": "Баща", + "family.mother": "Майка", + "family.husband": "Съпруг", + "family.wife": "Съпруга", + "family.unknown_spouse": "Неизвестен съпруг/а", + "family.children": "Деца", + "family.child": "Дете" } diff --git a/src/translations/cs.json b/src/translations/cs.json index acdd258..a1a1072 100644 --- a/src/translations/cs.json +++ b/src/translations/cs.json @@ -134,5 +134,14 @@ "extras.images": "Obrázky", "extras.notes": "Poznámky", "extras.sources": "Zdroje", - "extras.files": "Další soubory" + "extras.files": "Další soubory", + "family.immediate_family": "Nejbližší rodina", + "family.parents": "Rodiče", + "family.father": "Otec", + "family.mother": "Matka", + "family.husband": "Manžel", + "family.wife": "Manželka", + "family.unknown_spouse": "Neznámý manžel/ka", + "family.children": "Děti", + "family.child": "Dítě" } diff --git a/src/translations/de.json b/src/translations/de.json index ad53fdb..2a97c5e 100644 --- a/src/translations/de.json +++ b/src/translations/de.json @@ -134,5 +134,14 @@ "extras.images": "Bilder", "extras.notes": "Notizen", "extras.sources": "Quellen", - "extras.files": "Weitere Dateien" + "extras.files": "Weitere Dateien", + "family.immediate_family": "Engere Familie", + "family.parents": "Eltern", + "family.father": "Vater", + "family.mother": "Mutter", + "family.husband": "Ehemann", + "family.wife": "Ehefrau", + "family.unknown_spouse": "Unbekannter Ehepartner", + "family.children": "Kinder", + "family.child": "Kind" } diff --git a/src/translations/fr.json b/src/translations/fr.json index 1af1f57..4ac4129 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -134,5 +134,14 @@ "extras.images": "Images", "extras.notes": "Notes", "extras.sources": "Sources", - "extras.files": "Fichiers supplémentaires" + "extras.files": "Fichiers supplémentaires", + "family.immediate_family": "Famille proche", + "family.parents": "Parents", + "family.father": "Père", + "family.mother": "Mère", + "family.husband": "Mari", + "family.wife": "Femme", + "family.unknown_spouse": "Conjoint inconnu", + "family.children": "Enfants", + "family.child": "Enfant" } diff --git a/src/translations/it.json b/src/translations/it.json index 59cbd6f..fdc4235 100644 --- a/src/translations/it.json +++ b/src/translations/it.json @@ -134,5 +134,14 @@ "extras.images": "Immagini", "extras.notes": "Appunti", "extras.sources": "Fonti", - "extras.files": "File aggiuntivi" + "extras.files": "File aggiuntivi", + "family.immediate_family": "Famiglia stretta", + "family.parents": "Genitori", + "family.father": "Padre", + "family.mother": "Madre", + "family.husband": "Marito", + "family.wife": "Moglie", + "family.unknown_spouse": "Coniuge sconosciuto", + "family.children": "Figli", + "family.child": "Figlio" } diff --git a/src/translations/pl.json b/src/translations/pl.json index 0dc2373..2fd1d6a 100644 --- a/src/translations/pl.json +++ b/src/translations/pl.json @@ -134,5 +134,14 @@ "extras.images": "Zdjęcia", "extras.notes": "Notatki", "extras.sources": "Źródła", - "extras.files": "Dodatkowe pliki" + "extras.files": "Dodatkowe pliki", + "family.immediate_family": "Najbliższa rodzina", + "family.parents": "Rodzice", + "family.father": "Ojciec", + "family.mother": "Matka", + "family.husband": "Mąż", + "family.wife": "Żona", + "family.unknown_spouse": "Nieznany współmałżonek", + "family.children": "Dzieci", + "family.child": "Dziecko" } diff --git a/src/translations/ru.json b/src/translations/ru.json index a8e3fc8..fb71fd3 100644 --- a/src/translations/ru.json +++ b/src/translations/ru.json @@ -134,5 +134,14 @@ "extras.images": "Картинки", "extras.notes": "Примечание", "extras.sources": "Источники", - "extras.files": "Дополнительные файлы" + "extras.files": "Дополнительные файлы", + "family.immediate_family": "Ближайшие родственники", + "family.parents": "Родители", + "family.father": "Отец", + "family.mother": "Мать", + "family.husband": "Муж", + "family.wife": "Жена", + "family.unknown_spouse": "Неизвестный супруг(а)", + "family.children": "Дети", + "family.child": "Ребёнок" } diff --git a/tests/details_visual.spec.ts b/tests/details_visual.spec.ts index c2e182d..ea1a17a 100644 --- a/tests/details_visual.spec.ts +++ b/tests/details_visual.spec.ts @@ -135,4 +135,70 @@ test.describe('Details panel visual validation @visual', () => { await sidebar.waitFor(); await expect(sidebar).toHaveScreenshot('details-events-sources.png'); }); + + test('Immediate Family Rendering Test', async ({page, context}) => { + const immediateFamilyGedcom = dedent` + 0 HEAD + 1 GEDC + 2 VERS 5.5.1 + 2 FORM Lineage-Linked + 1 CHAR UTF-8 + 0 @I1@ INDI + 1 NAME Focus /Person/ + 1 SEX M + 1 FAMC @F1@ + 1 FAMS @F2@ + 1 FAMS @F3@ + 0 @I2@ INDI + 1 NAME Father /Person/ + 1 SEX M + 1 FAMS @F1@ + 0 @I3@ INDI + 1 NAME Mother /Person/ + 1 SEX F + 1 FAMS @F1@ + 0 @I4@ INDI + 1 NAME Spouse /Person/ + 1 SEX F + 1 FAMS @F2@ + 0 @I5@ INDI + 1 NAME Older /Child/ + 1 SEX M + 1 BIRT + 2 DATE 1 JAN 2000 + 1 FAMC @F2@ + 0 @I6@ INDI + 1 NAME Younger /Child/ + 1 SEX F + 1 BIRT + 2 DATE 1 JAN 2005 + 1 FAMC @F2@ + 0 @I7@ INDI + 1 NAME Half /Child/ + 1 SEX M + 1 BIRT + 2 DATE 1 JAN 2010 + 1 FAMC @F3@ + 0 @F1@ FAM + 1 HUSB @I2@ + 1 WIFE @I3@ + 1 CHIL @I1@ + 0 @F2@ FAM + 1 HUSB @I1@ + 1 WIFE @I4@ + 1 CHIL @I5@ + 1 CHIL @I6@ + 0 @F3@ FAM + 1 HUSB @I1@ + 1 CHIL @I7@ + 0 TRLR + `; + + await mockGedcomResponse(context, immediateFamilyGedcom); + + await page.goto('/#/view?url=https://example.org/family.ged'); + const sidebar = page.locator('#sidebar'); + await sidebar.waitFor(); + await expect(sidebar).toHaveScreenshot('details-immediate-family.png'); + }); }); diff --git a/tests/details_visual.spec.ts-snapshots/details-events-sources-visual-linux.png b/tests/details_visual.spec.ts-snapshots/details-events-sources-visual-linux.png index c41a6e4c10ffccd7f76cea798ec502b6d9b290ca..98649ecc5692fd4934c92737ab3f355c05e3f3a1 100644 GIT binary patch literal 19786 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 literal 19750 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 diff --git a/tests/details_visual.spec.ts-snapshots/details-immediate-family-visual-linux.png b/tests/details_visual.spec.ts-snapshots/details-immediate-family-visual-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..b3d2e0c4b3859a826ee3722e388e1ad82546bbca GIT binary patch literal 16879 zcmeHvWn9$Xx-SO!7eN#iqy?o@Ivu4;K%^U_+X3kT6$O#*6qFFjp+ibQkfFOnq`SNB z!`}DYbME=^P9Dv^*rBN_$et!;p39xVqsz7%SekWV_{v;!@|1w^{t#C6@3fnH-27suX7~%NVmdkrySQ$f54aiTJzZSHt*x_nzvt!WV`919{>0x?7C^(7T3_;uHddKE+ysbp);vx7Zyj5T z2O=tq2Q09#(ccD2-d=FIDSinHJNd%vi(Occ-i|M%sJ3&*=284SMvx%pEOU9 z_PE4LtIYmO_2NQL`tx)Jo4!odP#THK%F4zd3iq>9)XL27wKasnkJqF;mc5y(SyI82 zbM2qP-`flqy*x{wX^Hk)uf4L$#HwAQ!bWiIT0EzTY@un}HgTAZ=T4tG9eTX%<&?hX zLBl!+2Z#M&p5a>MmcmehiOIFi(Q=15A75Yk;v{M3jGdMi`1{^spH+K;0Oy}P+c7~+ znzOy(mc`C5Vw(d3?z_vWxcovwXWKoBKE4h9#L?RN`V%EKBaMxXPOGEk&THd*wxc1I zyk4gs2Pt-)pWj4{6;6kr{BF@x z3LuT^eemhxWi89!7@HJZ_Q6+8)j9fI>m5WPB-@rG>{{UAc>VfyA?H<{VoTMn*)}fI z)|g&T8dTb!;DR(k)OME?{4o5|LQB$h<*Y1q^mwtA`iz#lyL-6pGZmFyUn)-qJDao9 zlWyZqVp)nT?NZxP+c9|a+1c5zX-ThNzb-WEP>AP!dbabu=vq;)3OqyTeJNRo&*FZB zegi>wA0{Jbnqd{w3^77iyFC$x0!xkz(_YTe&6sfdolDtK_K!on3wM>nyep42TlCjA zrhc({G$)FjE`X%Av;m5C< z4c>5pYyt%y{@r8$kJ><qSBll2EcNG<+D)+4zZoAN@BSXT-yhvl_S*3A%h}f0;cNbKA&k$z zLPg8fD}4`XwAu;o+OH=UcF8lm+}jHKrkUP%@7KpvHO!O!(h1LSq1@bDm@f3&TF z)Cs%xs^ens!cV_j*N9j;e~kpr4f9g^L>wWtb9DsDMI2@WF#V}^w52A^5nXy034h+A zlMmseIeSuY=Jt)2(x-@MK^yZr4R5}=>8;_Hap_9r%*S`=>gkHhPvd!cYLcY&Gmaz{ za6SFJqmRpo3NvknQ)_;8( zZ+tA{{tEeoUr@eJlq3v&*Kd#8Toobl8;*D$TU1YS$a`Y zHDsc)mR^C~CIwKI1RZr|E#R^{-&Mb;u3c_FX*5*8E@Ad4vU1n% z2768KVRF&W8oXW^_cvJ_7tqPQi%Lx~g$dZbSe0=x&Dj6675{@yomXK$nd}oyaK;XM z$*F(owK@d_E*9=Tc;&zC>Hp-PH4bEleg#o*dA(VNeg)@5*S&nK>}7pRON)!2x3^eV zvIOj^UZzUM-h>xIJy(ZxT`Q%}AhfATnu;n3+OB*o=gdm!#OdkLTI|IuXg=mr(g0S? zf(ILQP%)P12#cPtCM{8{yu500gm835s@$E$#ec%_{PgKlTWRoXbuA`Iv7N=fV)dl- z^mKoJ|IrN1LeqF&8yo`4%2!Kju4U$3$qJtYO`1ZUT+)+rWKe$m7RJGa!;_IxyQ8Bc zs~=WOceL?mVNho4RUIB5Y!S2Rgb=yMa+-|0Oa(@MCGZ99@gWoV8+empMUI$En~Y2115d!0h7(j|ZU z+Ui6NJ6VQCz7ZUL6Z>a!SEn`!s2*_(Z*OgB!_bN4GGo)P*2&h$myKj9wwtI{`XcI6 z2j88H%Tzv5*flj~xxP7)xvHvahBbf+QSG!c9JQQCn-p`(7c#q}m=g&_<&XU2DRaOIR z^@N!0C*C-i9_?bwv(iiD+%!f=>j`LRA(Kl3{y zIs#!X#-@^^RV?98q@2QQH_mcL2K|gE%nWtB@yo3tJg^t7e>PlfWi^nCfAy-2Mb?wu z=Qa1smCEc5%kQ_n>p-08=!q)W!^kaB%h6Kiie}em3#1rw6)2IrCi;=2-Ms0ZL==mr z+x9$l3oX0xm9R097R19#7;HX1K7kG<{2P7*7D7#RF!TxW^OT_GU=lrz!XxL;Q%rh< zI9?ai(1;O^xSy%Qgo^CFav)RcRq}$rbLZu_b4wT8~`)X3Q?yg*B116%sU^GvJgJp6vf89-T8Vt zb%!H0;UIj=3;C^W?>9@+Ky27 zQq=vND8jSDff`x5kXvjM9$SIqH$%R@sg_fIv9~tC?rePHiQdehetV*bcB=GE)-RJU z3Tg=+?f>8>{`=a!*d+8>Gm&wSY%iSOBN2T6zI)ppA6Xgp6=`goIvPEj>#5xNqw~i4 z&Q2fU>4zQOlHUB~p+YP6bFeDOwzoXw0OtgXTs2omvyp|2&z8kIP74>4DE)qUq!g{9 z;>vKvrV4ZKm+{O1d8&gUv*0sc$q!<#PFS1uj@$(*Qd7+>94DARBAg4JrXO@?< zC%VWwf~gSwRHWB4*+msDdz_u@Ee)WfEuA>u2uFmL2R}M&I=;1o7GBt!QSc+AwYIUr zx2mtNZ$pgLDRC9LAEtlNT=%=67SUfH;^W4q>m05MNVn0Xz_cwB!5uJC^H+uhC&M62 zHJFwZ@UcJMT-$Mmr_=hXDimKxyGC9YEI}-?ki|^Z1Xenm2k0DKsZnJ)Fs&-7~v7@*pXOVMO|LO zmgZg1FAk%t!tAj?KPq@RC5ei;r)lccv8jlcm+ZK&SO5CLrPN(n-7tqY%2dxHoQT&@xV0GvJGhf|-8<`mFeCx_-nBgANDR{IuvQ<9X|nt|emKzx~H zA5%sv=VN}yd8I9FX{YnHgJmV-YtEpSJvfaCHwkzu*`oM>Bb!P0`*x~KI37V7tBCDr znPI(;OtEI@k38A9P7+Sz5QmR?dU`M&qGkC3GNU3{A_}pPB@;>-htqK0BAEC9q)&-h z^k)zGQ`yaMze(+bT{bxyA-t=G(G(*ok$1X=`TGvAE^J9Gxa};;q#MA|?Y_sgvss;H_ zi}{pQR6vC*cxhBP*|?U$3jU;p1!BnpVwZ?c%?Bb!r$>7Y`e(I4?b~$4B)VdEz=dVN zHCs0GU;H8^DlzY>(@m3$W}Drs{UJ{>!~AvILCLe%d3Cgl%4xATLnT9bq{N16yl#7; zC#`jVV~XdVfRonZ5x|gm9;?~;d2TkO8&@WA4>TZl(tTJ zfiR2G=hw7H2Gs$Zcaqi|q??KLJ-WU}__YBB>iZF-IX_TTu86P}~VNdapcoF4wU4~Jw(gnCN@TwwX4B^3LW4~!p zV1Gbh;b>-Fz{u?6`v95)@MC{^eDLMVm%}iC?k!>#tFZLK`Z6t5C%Yrc8>wG`TgzzP zd+=Zy$O-fFudV4xo=gN!4@onqht!Mu=Q!+tKeo8vnkaGv10JaT*-W%PlghXCHLo-6 zODrMZy8uw(l&=h+Cr*y`X3EmpBWgB*wqxq%m@|Y>hudA3;bR9{-KGNhrgwWYo;Mf6 zY``NRu!BtkDt2BQz8mg)s}@oD##DGF;u;zn1?ZUWj@kg&E&@tnjbYNT>%e+G1O=TQ zZ*}afT*AoubKPF6Ijbh$m?k(eylBA$=-|;yWrdA;Hkx*Rep2PO6US$l$Pzl6zwMG#k*YxT%-`#h6Q&Z|LZQVbh+KdWE$FL@U3DxhB@1eX;XW=gTf*{rQFADkFxDqf2s(z`?7Vqj()@Kpx6xhY zCPqGiSEa}qS&RODSP;O!>>AxYJzPW7k3W@`mX4}rsxWRaq4?KfNs!WfED;V@kZPjs z*p?VrGx=tXQ}_}_vly4usLpcxSFif8{L`Ls|0Q6#@WKEoT%?9E#*ln$i|3nbi!TL$ zPM1YPLsMcs6b7sn08;ZaEqw;59iYl?P;gP=VzO!5cXIXxuoxqqy6*k@an936gf>dO z6H`(hYXWQ74LnS{@)qmfU+exAmG1*@Nc+fvu~@}tK2@FlmvMa^lWOKU1BY|-qA{TB z3S%orA%QF-O5z-#kvMaE$cf^R#&KIDU+AD+Nq!=?Utg>yLsG;y>g?pin;Uh=lu@L- z1Tt6mw`cdAo%eofhfr20OxlfoFWwN%P;ZOlIXak2no-e*Q&K!Pb|r1j<@}vLjk|YO z?euGtu2+_kvteO->S6ywvFo1@qkrjV|Mj2WMw+=YX%-l(s6=dpy_{+!$-QhMX>V^2 ztzNsxd;=JeWq*&=_yY4A!$!G7*E=>ll8;O#g{W`N*@@U{oOZPQ;J)i@t`pDM=Reo0 z*BVnCy{GGT&)M3B^LA@wMy7jEyB$$;T$kDiHPnwgog_Hk!Kn3;$FiHZ<*-U{tC6yw$i{aKs3Yf?{Rq;U9Ne#BGcx8eSvS9JgD z=$M_9T979t14*MIS~Q zXev-Y2_o*ipq9Y|zAqW@*VU_`X0KL95BhVo=@k5w#1u=rG&*P=3gB z<4?otScP25RJ>g^fRPWvOQ1UdCUCH~zsqeN5+KzIkf|VZbQ`UUc{VD3CD+;m8sV_J!4;q*x96W}Te|mQ|F~*}k^Jlvw zf@V_ft#uM2LQ736J4i#2{lPxKILPRnqrH!_H4CR11kTxypRcd4$^zgX>9&qY=4h5s zCe|1Dhj;z}K%c1b@+zNNTB>l__!G}(NBPJ@gO~r+qRL4aF5u$s{?3#qTDXliml;z= zlUUPNn-M3~Uj#a{p4>#qoD{I#^4!>|I4d&xV(pi7v_^U$S7s6_^fYVwQ*n>t>T<>H z+awf1>tjZ4&Ywfmm!h7(aYNZ^vg#|B+aJ4q;Fg?L$j!cv-%{b^R`_`)K8#LM+;MqK z>L&6y`t(Co=d|C4Ad;@udOGi@5saaI_#YH;LTD%B?}TUN9X}kT#|)**(G#Khjgidi zvMIkoM+)(!GkZwbgJ!sO>(*N!aiTo6I1doazmxpd|EBl#Oj3v9}%i#A>ah_VZ~__prX9MBq& zLO^~AX=Uf-2=#rL(o*@l>?UKM1o{)0tH>WN9&U_^<_?kjPq$ZoR;OKguUQR>P80pv zgZ9&k#Xqy*nyCvf&t%@IxQURbR^2P*#QJifKb%P4HLO;&{ME~sp*Jrq$li@w8t@wj zdmzHBAn5jem8^-zRF*TEnW} z4A?E9HVo}{+aqv`>vfo53O~|RY5jP=bf#LRU6*(@Y5iJPqW}B&uulgots;!~bOYqC zmu#Xv1&D|Gc4{WN{#+q0n(?(&WeOWRzI!D^+2STXr~JJ+(kPhpK))|yy`W03NT8qcB;LUd1=D;g#g1l{J5_R1ZRYCewmL5DbU+9|bzVoQ~4O+-a=Mw4F) z%nBx6uIioS`+n~bP-Q|tuis?r9*gPBZC%~koAK+W3U$1@bzvgxb>vG!AuQZupNszy zXnz}-^2Hbv26CAQ00+z_pkEBKKDe0mCOJ9Fj4vKZvZgB9HNB!$Fm^vWs)Odm_*whW zR$p{0;zU9EXOP1lJ^@*PkmK^A*vk7rP51KgL9tEry0~$9UC9&PSQ$SLyM8Y(d+@(8^czLk|9U*AFwk?~+N%6c}QY9IoXHAj6zuom5f9v?-=gn^$Ccq75T3+*ufw!M2L~(et&UM4JV&9w$MIOnz7cSkWzi{9V)xkiBSAnwa24Cj z%ZtQ0M9)vS3YdjDT91O;TnP-AXi!59YA;r;17Ld)0~QVSRU^-mCOCmP!bl;0?&>Qy z*Eu|vV%mCj-(rbWA@hO3s#Q~YAP4`@I zLeCf%4b$vV&VaGsqlFi>IN=KMT7UIG9o98 z%VYmuK=jHFNsYzVfdYlidSj3zN+EB=7L=N=ai0u$v z-2?;a^;Y$9T}o)Zs`d4Cs0C7xO$)@MvbBnv^T2)P;pOE8^af4B9oVS%6@qPxuVCer z*iY7h%Db~NqAusxp{|c?HZS!w-+3jLS))ql{G;BURre)Iu#z&H1RtN2J7ffPw7Won z^6<#jDK|1RD|MJtKqdbI!Vhm-0uKy_$`Pi@ZUfkm+e_R4H*5R)is1}4`%#7y-X(kq zh;U92+lJG86K!EqiZi2A6paOsp4A=~-bT!#k!RHK5kPXe=gIeN((NpDd~$yK<_JbG zpIyO`27MDv%gwgE8Fn!-F%kNx&1hNvqxVI^a&N`Hlligh65qTTx-a^wA%@5HU$lTB zu92Z(V~v;7yPuu?Npj0S)9O^%h*lIhI3FF2d1?Km-CE!KNZfMEOM+;ocsx~ZbFwu& z3rDSG0xqE(chsaklG9JbJT+y*|0ZToTk)|`|=7V`(Mkxgy=VdPn z{GMwH74snj5u1pFgfWzw_5Ja|Q}offs7_B$FB1ZCm9%7&c>@r2sX$WNskrX>5JxaL z-g|r312dm+UlR$R<3-0gKU-_=c0+hAy-dP3>vubIy~DDgGtc_Iq!?E^y?$-{dHu{{ z>MJEqyZ+jzACoq{QuQk&F!sg#7Qs!sGoNkBS`)OdO9?nGMaOcvMtPzH5BOX#nyzR`l_}=32?F}rGKF)HjQ3w6}p!4N^ae@}^L+k6?dV71P@qJ+reNNE* z++~0Liz97wG<(uAQABj^bG>i21MiROqxCu!HOAe^si&@WH}?;X_NMwXvGT)!BA7#R3=j5ulDjoS!W^6qS_~^yJkuZH`)h3mZ7=oE9*NH| zGwqQ`+o0#(uS}=@F5@-HB<{$#;KKGd928xT{rPd$KM$Y)zkuEZ&GpqncSBE4q3zgr zu%Gk_O`qD^=T%f3fx;w@8{c|E6Y>?%KN~y&llEAe(@)YvT_Es@4nc4Ln&~VrA0YmElkpHQRLhO5X7Xc&Rg~e{odGIY!6pRi;)jN+tih45vZko= zc6z(^04lz-E#J8yC#{Y{iB^QfuCWf8r{4P_gSPAEoHea)ecXL*q5LyY)uxDr4yv0I zpnZYW8p)(;IaDw+S?|?ur3^9=*n|(phikpB0Q_OC3WJV5UgfT?|IJw*48pM-ZN8y) zu<48^LAy>nQ%;k;V-YVO!$A!eF#9g(ogR=^LH=4thA9^H?ITXUgU_q!S;w9_P}#Glz~60FOOo`uW=?Grc)$IIzyhgbf~V0=7h>d~ zn|;vr^wi7rQ#Rjjr%6iP=@Z3{QJ3BlwF|5kpd37kbN=4-?tb?aM{5KtnYt5A*f8_& z0}U=x4-b#&b4)37r_5y|+1K|MIF%*7b$r=ZhPMXjGrD7eF3=y2^aS)kpa{)jLQcyr$NL)~eD4UDc6<_|zeMCy3>@cS zD{~c0Y5+}&p9G76_h^ZJ1xGp=^ah!#gos|fA6;3s`7ejRnNnVN;w}F~Zt23GBp(ye zz;To^e$;8^)obR;m3Y$i?m)j};W?uD6LjMC;e|bNcWhxkD@kwevEp}@EEE^EXm_rT z8ROApT=ewZ;GtGb6mBk#LotDQZV3T2qrjewo{~n z@m}CZIXF4>6E@O?u^xEbk|7Nj`>ryD|7$I#x4U@!Lhca7%wN`(9PXw^c}?>_$z&Fa zLRWKR<>p$xHwyg-GnZCV{@e3YniUvhXzqLM?(TvPr3Jb;SiB}mkK2tvuT_?#W@l$7 zsY&3o8wVd|+6l~DnMf6d2eB%KGnd1S#GeOSIoDSYdF&`iAFI<-iUjH*fA@dA^(F zUWMhF2k!Xi3Sx!RN}gf8WWZf&g0w0n$R7ZLwq$&O3J0YTvw-88YyD)ifuqb^R3Ow? zIbKzPBZIb;Poyw@ZlFfzpriHHvxhG?!k-hjKT7vCYiHS|(+=r>lb{w;IkdOc*VWx` zuE&FZ)Ruj|;w{l!Q_HJ~NYA3F?I})W1FP^aqF=1N<8SvUvt?9WOe8B5zMy3A8}~ot zsw?wdDaB`Y`Z-&%rE`-0nFn|^bOhG}-Ohy8_@8DeF;whw`uPQF&!MDtcR|q0IXY>fa+f=gc{@45*5D zxvFcBD;Veay_$Fb8pU2n-Zxb#JF=+Op_#RWzAvbix5F*dh8ijz<>{zPVig0-l>ka< zQJE3UF>Ob~VqA)bY%;=p%x9I0sz41;KwhVnSbW>8W0yTv-`OIZ*D4fdY`SfTw0UO3 z#IOU>t4uKF`!Q$GATL9U^0qle)i$b?e;0VSoB!bkSA7}ZNzGfv1( zLaizK6Vb1y^q#{)=nY?Y9+vMry<^(79UxtX<;=8@c>UBnJNmR@wuZTY;GHbB1|^mc zA5Bfd4O%8k1d;3(ldJZ?homTlL+q5e=>3D=Iq^?AOdWH~W4IKOwuDIEGr z*Zh|3MCg5=+P;;OIdiTyhu6^`i_WfYM%PK`a+$Rlqc5C^`_d#95u~!6IL)qt(qf0e zTU)w=&{fqCZ~Znyyk+d5Gg`5^Ut(f=#n&r;Htb;KXJdoRnU_nUm;5}#0jGPk7Zp00 z%y-~!Uu%6=yQxJ@W-F~7%Ta0N6C@kR!6uiV`4e2UIryR- z`O!G~t7qbJ5U1YnPxeomTP}RTC=}EEvd`!P#V`Yu>SHV3gZXMXf*3hMb^$GXnJ}M| zcTOhNM?1qsHUnwb?u`XLr23ikS48G%!%^B->+-`D^gwEg-ru2B{80P%iM8qW+5M#^ zBr;A+@aBZ|?%2Bf_KJF-rlmIw18NaneTq3_lUfkf*57o6i7*$Oo=Ky;4e zp8J!&klm18EwUcs+<2%NGy*~0p!9SwsQB6z1i&Gx)$eoA7GL-aaW1`mFeKy@kETdhEOEM9@Z}VhqQVIKs{3bLHcr>FzXe z8)Z-6)o!sM@-)|f`0xReRp(J=$WDdw4W`KvyXIz#c%4>`q5;1E;G3p3dhvqiH*H8i z#YgOGL=nvDw(x~cPfx{s@Ir@;DtF<-ws&?Qz>WMO`aX>54AQ%~x)pk0f6sS*QCTDe0H9~ zdS;?g0p5#iauMS+5*r8lj> zOf7IHT_==Yx-J2<{ai(HesGZpO!yq{O4qH$EC6x^mVKFL$8!i}Oj|^>80zuk*W|~L zyklyiASVahLp${z0u6_UOK6iE@;7@cBLgs`D1@Avn&!a*OpA$*R#zqi?I5+fd3;=t zX$}m)^r!K3zs_K4fk$Kj*}+3CflRrqC#ydj8f1v1SEa=sm(!m!ldY?eYUj|e_6VnY z8g{g)Rp8rQ9rE>^Fdo1ztT2zR*W0FTYGP3=8(YK>og!iH)t*&Q_^K}79P`kVX*(w7 z?#U!*5~+=|m~b;lbvFl+HMdM^txC(F%2l|^Bbk^~b3q`0xm2?_~SP>Q%EJVLoac)J@Js&N%RHPP?C-4WpVJdsQOD@)M^QHFPYnchGpoa+I0tkjs6b5bPO$h>p+)eEI)!Ana{t!M`a1jy`Qvaq@ zd+d<*5aF@E4$6nDU7d#vq|wSF!w$u&*cSSf-S9!eIM^A`PwQf97Qg%0baqBE2?p;t`adBi&0Nz7sbqP`m2zDPm z1)QX}8x7LD)epHJ%`fob%W967*l3e{3%4A~e<77|wYxQ{(Megc>&h934t?-QUS~%W z-LEIgUZ%uGoA+nOs??lIV-rs@t5gbUBtFiIU3Ei05v1#m4-s-p62-ZJ#9){2bwK^+`?((%Vu{976WF$jDpkROS1YBvxC^YJM_J(3m@! zTVqL*Y?L3IKN?R>@!uWeW~7VPa$qrNQk)}G6y7{_9=}BNY0PuCgSnsYuJin0pD*3a z{p1&Eg9&4&e)1+y+>)HiSO>>nQPf=(_d_#N&l5aL3M)P+_E$6={2E1l&G z?s}jk!^_I}Pn^}z-!z3z?65_2g{JYPD!fuxz&atw-$@ z`|91%2_KGl>VucIDKOI#`V2gYe@|~m_y3jNVyqQ#*x1-W{_NL7y`i4GgKNfz!QPk= zOsW*%@*J&vciP#du%ub@;o#}ei0R#duSGbi%vMeefZkbieD=oOJ2+7BQ5<{EzRJgL zAAzM!!eQ_@O*S%M&V&W7ra+4zv|E904Tn5RPX?w8z5~rXML6&R=cWFqB`JzHNiJ>; zsbAkjyvx+B*o9DY(d}Uu8YMxBb5{DQKjVINEuGa7tFZgATT}D>(lmn2lYT3onSW)W zT-uKos5ZMQdjjdmLn);|Dn%LoT3A&0d9~&Sitmtxf9lqa%nKQfab3TsrtX)Tn%b2A zH$ED9ON{i|e@{hCP(G^OK<8A^dZ@+#5>5p}Q@4hnJ&%WnhnxGiUGD%68N#5&pb-LOF8pGgk%TR9}vqObmOEvzltGy3@ z(8#Yw7*0%4HH&;SCy&_4={}>_^EC`54YAA~`qF78#>-`FV5%p1>t7k@d9;%NIH+07 zPfeJtQgMWbsG04LkoA>aoWZ*#5~QB{*qqa5SmFeHQFEloOw{~Uv+=lN z;8gd%*VWQ}zpXemjF44&Qf!zM8s}G|MM|72|KQNH6Y|^Sq(?Wq_$6guo|GqXt6HKw zQ9-W{!kS%40uK%v)Cud0{OLH&PLKGlWAvUWUI=w*E-}_u_naG_g zJA=W)iA!u_p2)SA$N7T1{mDsL&1EU0Ktk1W4K@X6#PIS>y|Bq{kSEf|r+8D$#fK98 zUC_37aDWt8`1U$j255GV?fFo{>{=v*akc6O#S3WhdzhmbHs+L)C@-r$sPgl?)`4fK z;TlfsRsN{t^GufGVg3=_cw7_5lheuS{qn@v# zcdko!IUsB_l^d_s3{8{WB|J+D02wMP7#mN=LqV>5nD!Huu%Gb!EyQ1Lv>eMnX0DuX zD1vVqoUfUPX$Wr*13v)M3fjK#uQb~nyM-cv`&A5+k za(Oap$9t_xTV5clYrN!}oM}r^JiA%r(3r?2DhZHgbmGWXzEUC<$%M;f9>{KXP3D zeOi)PsveRY0_L6f${pbTLYP+uAVNqo0njBUBeN=y-CIJ}EMALd(KH(Dg{X%K24pWd z5!TApI^{^2swhM6Mr?6;`BuIOkNXwWLR)ahU}t$~3-0&$3;+ZT7q$Wncvx?&-(~C# zIwE*gO8`o@RZYkJaVlw)OZ(3Ac5v4MdN5onIM0{pqjn-OOrKOFP?PX3US}uH;epa3 z(VTGAApGe3I?z$G;MdX5we(3In_C@-7Tc!wV?gepV&M`H45;f?x^#_<2!Uh+bEWk7 z4&rE;Ysdh?Q}7&cwM2C2^YRavHh9<(YuGNTsS>_4Fb~1oT%M?@Q2_(D9d3f?UvB}M zFi!Ox=D`h}a}+!l@+m{9@we04SauAF~X77XJa225#$UrK^2o(>#4*H!wo4A3Cs1Y#&uctSh*-6xKZr|8 zS~40B8bq_{%BxX8g2WcF|J(a#2kzCYLvS>+;j|zj>ZXm05kyXZ80EF14BmsCWIt$L zOiWDB@twd9>;9@yYO4!3DWb?vzCUUf;r7g#``cSpnDe`=e;)0Jrsoxd@H$<*ic7>| z&TwB90zH5RY9b$sW)x}3-sL^NZxXJ04sS+8+;?MGqAe>O7rN)?=e4< z;Y?;Ud-&jJy2$)bSU-yW@$heC8P@H6-Ut7~o2ch4U`a|07H%L{*Q(MO^5QVNH~01i zuqtV?kGC=*N_yqW72rwwUUx}J1tAFnfnKPT*_LR7 zML_!cE%r4*etvT-y_;&bJmB07ix)5Ar4Yai)PitKaBslH*mG~@C!;-3)8q>-#Tu^JPui7Y;F6@{ z*MvIb?DHQL_T2z~f}DK$&!1!joPt6i+i>G4isPjfoavO56u3rv@&AHl{O=ps|KOhQ z|9pe}N4JFk^MC&z