Compare commits
2 Commits
4d5bdaad57
...
4eaaa11cc6
| Author | SHA1 | Date | |
|---|---|---|---|
| 4eaaa11cc6 | |||
| 8cfe51fb0d |
146
geneit_app/package-lock.json
generated
146
geneit_app/package-lock.json
generated
@@ -15,7 +15,8 @@
|
|||||||
"@mdi/js": "^7.2.96",
|
"@mdi/js": "^7.2.96",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mui/icons-material": "^5.11.16",
|
"@mui/icons-material": "^5.11.16",
|
||||||
"@mui/material": "^5.13.4",
|
"@mui/lab": "^5.0.0-alpha.140",
|
||||||
|
"@mui/material": "^5.14.5",
|
||||||
"@mui/x-data-grid": "^6.9.2",
|
"@mui/x-data-grid": "^6.9.2",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
@@ -3030,16 +3031,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/base": {
|
"node_modules/@mui/base": {
|
||||||
"version": "5.0.0-beta.6",
|
"version": "5.0.0-beta.11",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.6.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.11.tgz",
|
||||||
"integrity": "sha512-jcHy6HwOX7KzRhRtL8nvIvUlxvLx2Fl6NMRCyUSQSvMTyfou9kndekz0H4HJaXvG1Y4WEifk23RYedOlrD1kEQ==",
|
"integrity": "sha512-FdKZGPd8qmC3ZNke7CNhzcEgToc02M6WYZc9hcBsNQ17bgAd3s9F//1bDDYgMVBYxDM71V0sv/hBHlOY4I1ZVA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.5",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@emotion/is-prop-valid": "^1.2.1",
|
"@emotion/is-prop-valid": "^1.2.1",
|
||||||
"@mui/types": "^7.2.4",
|
"@mui/types": "^7.2.4",
|
||||||
"@mui/utils": "^5.13.7",
|
"@mui/utils": "^5.14.5",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^2.0.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-is": "^18.2.0"
|
"react-is": "^18.2.0"
|
||||||
},
|
},
|
||||||
@@ -3061,10 +3062,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mui/base/node_modules/clsx": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mui/core-downloads-tracker": {
|
"node_modules/@mui/core-downloads-tracker": {
|
||||||
"version": "5.13.7",
|
"version": "5.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.5.tgz",
|
||||||
"integrity": "sha512-/suIo4WoeL/OyO3KUsFVpdOmKiSAr6NpWXmQ4WLSxwKrTiha1FJxM6vwAki5W/5kR9WnVLw5E8JC4oHHsutT8w==",
|
"integrity": "sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/mui"
|
"url": "https://opencollective.com/mui"
|
||||||
@@ -3095,19 +3104,68 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/material": {
|
"node_modules/@mui/lab": {
|
||||||
"version": "5.13.7",
|
"version": "5.0.0-alpha.140",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.140.tgz",
|
||||||
"integrity": "sha512-+n453jDDm88zZM3b5YK29nZ7gXY+s+rryH9ovDbhmfSkOlFtp+KSqbXy5cTaC/UlDqDM7sYYJGq8BmJov3v9Tg==",
|
"integrity": "sha512-k75jos6jklCD8tA20PAK2H4RSCKycTcR4Pbfz7JbdxIkWXJ+y2MRalwMcen1vpB99v0yZHNUo6BtGz6rvs2jlQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.5",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@mui/base": "5.0.0-beta.6",
|
"@mui/base": "5.0.0-beta.11",
|
||||||
"@mui/core-downloads-tracker": "^5.13.7",
|
"@mui/system": "^5.14.5",
|
||||||
"@mui/system": "^5.13.7",
|
|
||||||
"@mui/types": "^7.2.4",
|
"@mui/types": "^7.2.4",
|
||||||
"@mui/utils": "^5.13.7",
|
"@mui/utils": "^5.14.5",
|
||||||
|
"clsx": "^2.0.0",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
|
"react-is": "^18.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/mui"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/react": "^11.5.0",
|
||||||
|
"@emotion/styled": "^11.3.0",
|
||||||
|
"@mui/material": "^5.0.0",
|
||||||
|
"@types/react": "^17.0.0 || ^18.0.0",
|
||||||
|
"react": "^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^17.0.0 || ^18.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@emotion/styled": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@mui/lab/node_modules/clsx": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@mui/material": {
|
||||||
|
"version": "5.14.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.5.tgz",
|
||||||
|
"integrity": "sha512-4qa4GMfuZH0Ai3mttk5ccXP8a3sf7aPlAJwyMrUSz6h9hPri6BPou94zeu3rENhhmKLby9S/W1y+pmficy8JKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.22.6",
|
||||||
|
"@mui/base": "5.0.0-beta.11",
|
||||||
|
"@mui/core-downloads-tracker": "^5.14.5",
|
||||||
|
"@mui/system": "^5.14.5",
|
||||||
|
"@mui/types": "^7.2.4",
|
||||||
|
"@mui/utils": "^5.14.5",
|
||||||
"@types/react-transition-group": "^4.4.6",
|
"@types/react-transition-group": "^4.4.6",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^2.0.0",
|
||||||
"csstype": "^3.1.2",
|
"csstype": "^3.1.2",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
@@ -3139,13 +3197,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mui/material/node_modules/clsx": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mui/private-theming": {
|
"node_modules/@mui/private-theming": {
|
||||||
"version": "5.13.7",
|
"version": "5.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.5.tgz",
|
||||||
"integrity": "sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA==",
|
"integrity": "sha512-cC4C5RrpXpDaaZyH9QwmPhRLgz+f2SYbOty3cPkk4qPSOSfif2ZEcDD9HTENKDDd9deB+xkPKzzZhi8cxIx8Ig==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.5",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@mui/utils": "^5.13.7",
|
"@mui/utils": "^5.14.5",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -3197,16 +3263,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/system": {
|
"node_modules/@mui/system": {
|
||||||
"version": "5.13.7",
|
"version": "5.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.5.tgz",
|
||||||
"integrity": "sha512-7R2KdI6vr8KtnauEfg9e9xQmPk6Gg/1vGNiALYyhSI+cYztxN6WmlSqGX4bjWn/Sygp1TUE1jhFEgs7MWruhkQ==",
|
"integrity": "sha512-mextXZHDeGcR7E1kx43TRARrVXy+gI4wzpUgNv7MqZs1dvTVXQGVeAT6ydj9d6FUqHBPMNLGV/21vJOrpqsL+w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.5",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@mui/private-theming": "^5.13.7",
|
"@mui/private-theming": "^5.14.5",
|
||||||
"@mui/styled-engine": "^5.13.2",
|
"@mui/styled-engine": "^5.13.2",
|
||||||
"@mui/types": "^7.2.4",
|
"@mui/types": "^7.2.4",
|
||||||
"@mui/utils": "^5.13.7",
|
"@mui/utils": "^5.14.5",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^2.0.0",
|
||||||
"csstype": "^3.1.2",
|
"csstype": "^3.1.2",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
@@ -3235,6 +3301,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mui/system/node_modules/clsx": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mui/types": {
|
"node_modules/@mui/types": {
|
||||||
"version": "7.2.4",
|
"version": "7.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
|
||||||
@@ -3249,11 +3323,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/utils": {
|
"node_modules/@mui/utils": {
|
||||||
"version": "5.13.7",
|
"version": "5.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.5.tgz",
|
||||||
"integrity": "sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA==",
|
"integrity": "sha512-6Hzw63VR9C5xYv+CbjndoRLU6Gntal8rJ5W+GUzkyHrGWIyYPWZPa6AevnyGioySNETATe1H9oXS8f/7qgIHJA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.5",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"@types/react-is": "^18.2.1",
|
"@types/react-is": "^18.2.1",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
"@mdi/js": "^7.2.96",
|
"@mdi/js": "^7.2.96",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mui/icons-material": "^5.11.16",
|
"@mui/icons-material": "^5.11.16",
|
||||||
"@mui/material": "^5.13.4",
|
"@mui/lab": "^5.0.0-alpha.140",
|
||||||
|
"@mui/material": "^5.14.5",
|
||||||
"@mui/x-data-grid": "^6.9.2",
|
"@mui/x-data-grid": "^6.9.2",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { APIClient } from "./ApiClient";
|
import { APIClient } from "./ApiClient";
|
||||||
import { DateValue, Member } from "./MemberApi";
|
import { DateValue, Member } from "./MemberApi";
|
||||||
import { ServerApi } from "./ServerApi";
|
|
||||||
|
|
||||||
interface CoupleApiInterface {
|
interface CoupleApiInterface {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
@@ -64,6 +64,15 @@ export class Family implements FamilyAPI {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get family tree URL for member
|
||||||
|
*/
|
||||||
|
familyTreeURL(member: Member | number): string {
|
||||||
|
return `/family/${this.family_id}/tree/${
|
||||||
|
typeof member === "number" ? member : member.id
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get application URL for couple page
|
* Get application URL for couple page
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ import { PropSelect } from "../../widgets/forms/PropSelect";
|
|||||||
import { SexSelection } from "../../widgets/forms/SexSelection";
|
import { SexSelection } from "../../widgets/forms/SexSelection";
|
||||||
import { UploadPhotoButton } from "../../widgets/forms/UploadPhotoButton";
|
import { UploadPhotoButton } from "../../widgets/forms/UploadPhotoButton";
|
||||||
import { useQuery } from "../../hooks/useQuery";
|
import { useQuery } from "../../hooks/useQuery";
|
||||||
|
import { mdiFamilyTree } from "@mdi/js";
|
||||||
|
import Icon from "@mdi/react";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new member route
|
* Create a new member route
|
||||||
@@ -150,6 +152,7 @@ export function FamilyMemberRoute(): React.ReactElement {
|
|||||||
couples={family.couples.getAllOf(member!)}
|
couples={family.couples.getAllOf(member!)}
|
||||||
creating={false}
|
creating={false}
|
||||||
editing={false}
|
editing={false}
|
||||||
|
onrequestOpenTree={() => n(family.family.familyTreeURL(member!))}
|
||||||
onRequestDelete={deleteMember}
|
onRequestDelete={deleteMember}
|
||||||
onRequestEdit={() =>
|
onRequestEdit={() =>
|
||||||
n(family.family.URL(`member/${member!.id}/edit`))
|
n(family.family.URL(`member/${member!.id}/edit`))
|
||||||
@@ -234,6 +237,7 @@ export function MemberPage(p: {
|
|||||||
onRequestEdit?: () => void;
|
onRequestEdit?: () => void;
|
||||||
onRequestDelete?: () => void;
|
onRequestDelete?: () => void;
|
||||||
onForceReload?: () => void;
|
onForceReload?: () => void;
|
||||||
|
onrequestOpenTree?: () => void;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
const confirm = useConfirm();
|
const confirm = useConfirm();
|
||||||
const snackbar = useSnackbar();
|
const snackbar = useSnackbar();
|
||||||
@@ -308,6 +312,17 @@ export function MemberPage(p: {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Stack direction="row" spacing={1}>
|
<Stack direction="row" spacing={1}>
|
||||||
|
{/* Family tree button */}
|
||||||
|
{p.onrequestOpenTree && (
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<Icon path={mdiFamilyTree} size={1} />}
|
||||||
|
onClick={p.onrequestOpenTree}
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
Arbre
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{/* Edit button */}
|
{/* Edit button */}
|
||||||
{p.onRequestEdit && (
|
{p.onRequestEdit && (
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
||||||
import { MemberItem } from "../../widgets/MemberItem";
|
import { MemberItem } from "../../widgets/MemberItem";
|
||||||
import { RouterLink } from "../../widgets/RouterLink";
|
import { RouterLink } from "../../widgets/RouterLink";
|
||||||
|
import { BasicFamilyTree } from "../../widgets/BasicFamilyTree";
|
||||||
|
|
||||||
enum CurrTab {
|
enum CurrTab {
|
||||||
BasicTree,
|
BasicTree,
|
||||||
@@ -116,7 +117,13 @@ export function FamilyMemberTreeRoute(): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* the tree itself */}
|
{/* the tree itself */}
|
||||||
<Paper style={{ flex: "1" }}>todo</Paper>
|
<Paper style={{ flex: "1" }}>
|
||||||
|
{currTab === CurrTab.BasicTree ? (
|
||||||
|
<BasicFamilyTree tree={tree!} />
|
||||||
|
) : (
|
||||||
|
<>todo</>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function FamilyTreeRoute(): React.ReactElement {
|
|||||||
const family = useFamily();
|
const family = useFamily();
|
||||||
|
|
||||||
const onMemberSelected = (id: number | undefined) => {
|
const onMemberSelected = (id: number | undefined) => {
|
||||||
if (id) n(family.family.URL(`tree/${id}`));
|
if (id) n(family.family.familyTreeURL(id));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
81
geneit_app/src/widgets/BasicFamilyTree.tsx
Normal file
81
geneit_app/src/widgets/BasicFamilyTree.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { TreeItem, TreeView } from "@mui/lab";
|
||||||
|
import { FamilyTreeNode } from "../utils/family_tree";
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
|
import React from "react";
|
||||||
|
import { MemberPhoto } from "./MemberPhoto";
|
||||||
|
import { Member, fmtDate } from "../api/MemberApi";
|
||||||
|
import Icon from "@mdi/react";
|
||||||
|
import { mdiCross } from "@mdi/js";
|
||||||
|
|
||||||
|
export function BasicFamilyTree(p: {
|
||||||
|
tree: FamilyTreeNode;
|
||||||
|
}): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<TreeView
|
||||||
|
defaultCollapseIcon={<ExpandMoreIcon />}
|
||||||
|
defaultExpandIcon={<ChevronRightIcon />}
|
||||||
|
sx={{ flexGrow: 1 }}
|
||||||
|
>
|
||||||
|
<FamilyTreeItem n={p.tree} />
|
||||||
|
</TreeView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FamilyTreeItem(p: { n: FamilyTreeNode }): React.ReactElement {
|
||||||
|
let children = p.n.down ?? [];
|
||||||
|
|
||||||
|
if (p.n.couples) {
|
||||||
|
for (const c of p.n.couples) {
|
||||||
|
children = children.concat(c.down);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TreeItem
|
||||||
|
nodeId={p.n.member.id.toString()}
|
||||||
|
style={{ margin: "10px" }}
|
||||||
|
label={
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<BasicFamilyMemberItem member={p.n.member} primary={true} />
|
||||||
|
|
||||||
|
{p.n.couples?.map((c, n) => (
|
||||||
|
<span
|
||||||
|
key={n}
|
||||||
|
style={{
|
||||||
|
marginLeft: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<BasicFamilyMemberItem member={c.member} />
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children.map((c) => (
|
||||||
|
<FamilyTreeItem key={c.member.id} n={c} />
|
||||||
|
))}
|
||||||
|
</TreeItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function BasicFamilyMemberItem(p: {
|
||||||
|
member: Member;
|
||||||
|
primary?: boolean;
|
||||||
|
}): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<MemberPhoto member={p.member} />
|
||||||
|
<span style={{ width: "10px" }}></span>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<span style={{ fontWeight: p.primary ? "bold" : "unset" }}>
|
||||||
|
{p.member.fullName}{" "}
|
||||||
|
{p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
|
||||||
|
</span>
|
||||||
|
{(p.member.dateOfBirth || p.member.dateOfDeath) &&
|
||||||
|
fmtDate(p.member.dateOfBirth) +
|
||||||
|
(p.member.dateOfDeath ? " - " + fmtDate(p.member.dateOfDeath) : "")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user