Start to build basic family tree
This commit is contained in:
		
							
								
								
									
										146
									
								
								geneit_app/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										146
									
								
								geneit_app/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -15,7 +15,8 @@
 | 
			
		||||
        "@mdi/js": "^7.2.96",
 | 
			
		||||
        "@mdi/react": "^1.6.1",
 | 
			
		||||
        "@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",
 | 
			
		||||
        "@testing-library/jest-dom": "^5.16.5",
 | 
			
		||||
        "@testing-library/react": "^13.4.0",
 | 
			
		||||
@@ -3030,16 +3031,16 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mui/base": {
 | 
			
		||||
      "version": "5.0.0-beta.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.6.tgz",
 | 
			
		||||
      "integrity": "sha512-jcHy6HwOX7KzRhRtL8nvIvUlxvLx2Fl6NMRCyUSQSvMTyfou9kndekz0H4HJaXvG1Y4WEifk23RYedOlrD1kEQ==",
 | 
			
		||||
      "version": "5.0.0-beta.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.11.tgz",
 | 
			
		||||
      "integrity": "sha512-FdKZGPd8qmC3ZNke7CNhzcEgToc02M6WYZc9hcBsNQ17bgAd3s9F//1bDDYgMVBYxDM71V0sv/hBHlOY4I1ZVA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.22.5",
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@emotion/is-prop-valid": "^1.2.1",
 | 
			
		||||
        "@mui/types": "^7.2.4",
 | 
			
		||||
        "@mui/utils": "^5.13.7",
 | 
			
		||||
        "@mui/utils": "^5.14.5",
 | 
			
		||||
        "@popperjs/core": "^2.11.8",
 | 
			
		||||
        "clsx": "^1.2.1",
 | 
			
		||||
        "clsx": "^2.0.0",
 | 
			
		||||
        "prop-types": "^15.8.1",
 | 
			
		||||
        "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": {
 | 
			
		||||
      "version": "5.13.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.7.tgz",
 | 
			
		||||
      "integrity": "sha512-/suIo4WoeL/OyO3KUsFVpdOmKiSAr6NpWXmQ4WLSxwKrTiha1FJxM6vwAki5W/5kR9WnVLw5E8JC4oHHsutT8w==",
 | 
			
		||||
      "version": "5.14.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.5.tgz",
 | 
			
		||||
      "integrity": "sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA==",
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/mui"
 | 
			
		||||
@@ -3095,19 +3104,68 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mui/material": {
 | 
			
		||||
      "version": "5.13.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.7.tgz",
 | 
			
		||||
      "integrity": "sha512-+n453jDDm88zZM3b5YK29nZ7gXY+s+rryH9ovDbhmfSkOlFtp+KSqbXy5cTaC/UlDqDM7sYYJGq8BmJov3v9Tg==",
 | 
			
		||||
    "node_modules/@mui/lab": {
 | 
			
		||||
      "version": "5.0.0-alpha.140",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.140.tgz",
 | 
			
		||||
      "integrity": "sha512-k75jos6jklCD8tA20PAK2H4RSCKycTcR4Pbfz7JbdxIkWXJ+y2MRalwMcen1vpB99v0yZHNUo6BtGz6rvs2jlQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.22.5",
 | 
			
		||||
        "@mui/base": "5.0.0-beta.6",
 | 
			
		||||
        "@mui/core-downloads-tracker": "^5.13.7",
 | 
			
		||||
        "@mui/system": "^5.13.7",
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@mui/base": "5.0.0-beta.11",
 | 
			
		||||
        "@mui/system": "^5.14.5",
 | 
			
		||||
        "@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",
 | 
			
		||||
        "clsx": "^1.2.1",
 | 
			
		||||
        "clsx": "^2.0.0",
 | 
			
		||||
        "csstype": "^3.1.2",
 | 
			
		||||
        "prop-types": "^15.8.1",
 | 
			
		||||
        "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": {
 | 
			
		||||
      "version": "5.13.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.7.tgz",
 | 
			
		||||
      "integrity": "sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA==",
 | 
			
		||||
      "version": "5.14.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.5.tgz",
 | 
			
		||||
      "integrity": "sha512-cC4C5RrpXpDaaZyH9QwmPhRLgz+f2SYbOty3cPkk4qPSOSfif2ZEcDD9HTENKDDd9deB+xkPKzzZhi8cxIx8Ig==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.22.5",
 | 
			
		||||
        "@mui/utils": "^5.13.7",
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@mui/utils": "^5.14.5",
 | 
			
		||||
        "prop-types": "^15.8.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
@@ -3197,16 +3263,16 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mui/system": {
 | 
			
		||||
      "version": "5.13.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.7.tgz",
 | 
			
		||||
      "integrity": "sha512-7R2KdI6vr8KtnauEfg9e9xQmPk6Gg/1vGNiALYyhSI+cYztxN6WmlSqGX4bjWn/Sygp1TUE1jhFEgs7MWruhkQ==",
 | 
			
		||||
      "version": "5.14.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.5.tgz",
 | 
			
		||||
      "integrity": "sha512-mextXZHDeGcR7E1kx43TRARrVXy+gI4wzpUgNv7MqZs1dvTVXQGVeAT6ydj9d6FUqHBPMNLGV/21vJOrpqsL+w==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.22.5",
 | 
			
		||||
        "@mui/private-theming": "^5.13.7",
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@mui/private-theming": "^5.14.5",
 | 
			
		||||
        "@mui/styled-engine": "^5.13.2",
 | 
			
		||||
        "@mui/types": "^7.2.4",
 | 
			
		||||
        "@mui/utils": "^5.13.7",
 | 
			
		||||
        "clsx": "^1.2.1",
 | 
			
		||||
        "@mui/utils": "^5.14.5",
 | 
			
		||||
        "clsx": "^2.0.0",
 | 
			
		||||
        "csstype": "^3.1.2",
 | 
			
		||||
        "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": {
 | 
			
		||||
      "version": "7.2.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
 | 
			
		||||
@@ -3249,11 +3323,11 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@mui/utils": {
 | 
			
		||||
      "version": "5.13.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.7.tgz",
 | 
			
		||||
      "integrity": "sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA==",
 | 
			
		||||
      "version": "5.14.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.5.tgz",
 | 
			
		||||
      "integrity": "sha512-6Hzw63VR9C5xYv+CbjndoRLU6Gntal8rJ5W+GUzkyHrGWIyYPWZPa6AevnyGioySNETATe1H9oXS8f/7qgIHJA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.22.5",
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@types/prop-types": "^15.7.5",
 | 
			
		||||
        "@types/react-is": "^18.2.1",
 | 
			
		||||
        "prop-types": "^15.8.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,8 @@
 | 
			
		||||
    "@mdi/js": "^7.2.96",
 | 
			
		||||
    "@mdi/react": "^1.6.1",
 | 
			
		||||
    "@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",
 | 
			
		||||
    "@testing-library/jest-dom": "^5.16.5",
 | 
			
		||||
    "@testing-library/react": "^13.4.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import { APIClient } from "./ApiClient";
 | 
			
		||||
import { DateValue, Member } from "./MemberApi";
 | 
			
		||||
import { ServerApi } from "./ServerApi";
 | 
			
		||||
 | 
			
		||||
interface CoupleApiInterface {
 | 
			
		||||
  id: number;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import {
 | 
			
		||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
 | 
			
		||||
import { MemberItem } from "../../widgets/MemberItem";
 | 
			
		||||
import { RouterLink } from "../../widgets/RouterLink";
 | 
			
		||||
import { BasicFamilyTree } from "../../widgets/BasicFamilyTree";
 | 
			
		||||
 | 
			
		||||
enum CurrTab {
 | 
			
		||||
  BasicTree,
 | 
			
		||||
@@ -116,7 +117,13 @@ export function FamilyMemberTreeRoute(): React.ReactElement {
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      {/* the tree itself */}
 | 
			
		||||
      <Paper style={{ flex: "1" }}>todo</Paper>
 | 
			
		||||
      <Paper style={{ flex: "1" }}>
 | 
			
		||||
        {currTab === CurrTab.BasicTree ? (
 | 
			
		||||
          <BasicFamilyTree tree={tree!} />
 | 
			
		||||
        ) : (
 | 
			
		||||
          <>todo</>
 | 
			
		||||
        )}
 | 
			
		||||
      </Paper>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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