Skip to content

Commit

Permalink
Distinguish TreeNode more
Browse files Browse the repository at this point in the history
  • Loading branch information
imnasnainaec committed Oct 4, 2022
1 parent a29711a commit 5e75191
Show file tree
Hide file tree
Showing 17 changed files with 149 additions and 153 deletions.
2 changes: 1 addition & 1 deletion Backend/Contexts/SemanticDomainContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ public SemanticDomainContext(IOptions<Startup.Settings> options)
public IMongoCollection<SemanticDomainTreeNode> SemanticDomains => _db.GetCollection<SemanticDomainTreeNode>("SemanticDomainTree");
public IMongoCollection<SemanticDomainFull> FullSemanticDomains => _db.GetCollection<SemanticDomainFull>("SemanticDomains");
}
}
}
1 change: 1 addition & 0 deletions Backend/Models/SemanticDomain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public class SemanticDomainTreeNode
public SemanticDomain? Next { get; set; }
[BsonElement("parent")]
public SemanticDomain? Parent { get; set; }
[Required]
[BsonElement("children")]
public List<SemanticDomain> Children { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/api/models/semantic-domain-tree-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,5 @@ export interface SemanticDomainTreeNode {
* @type {Array<SemanticDomain>}
* @memberof SemanticDomainTreeNode
*/
children?: Array<SemanticDomain> | null;
children: Array<SemanticDomain>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import DataEntryTable, {
} from "components/DataEntry/DataEntryTable/DataEntryTable";
import NewEntry from "components/DataEntry/DataEntryTable/NewEntry/NewEntry";
import { newProject } from "types/project";
import { newSemanticDomain } from "types/semanticDomain";
import {
newSemanticDomain,
newSemanticDomainTreeNode,
semDomFromTreeNode,
} from "types/semanticDomain";
import { multiSenseWord, newSense, simpleWord } from "types/word";
import { firstGlossText } from "types/wordUtilities";
import { Bcp47Code } from "types/writingSystem";
Expand All @@ -35,7 +39,8 @@ let testHandle: ReactTestInstance;

const mockWord = () => simpleWord("mockVern", "mockGloss");
const mockMultiWord = multiSenseWord("vern", ["gloss1", "gloss2"]);
const mockSemanticDomain = newSemanticDomain();
const mockTreeNode = newSemanticDomainTreeNode();
const mockSemanticDomain = semDomFromTreeNode(mockTreeNode);
const mockOpenTree = jest.fn();
const getWordsFromBackendMock = jest.fn();

Expand All @@ -58,7 +63,7 @@ beforeEach(() => {
renderer.act(() => {
testRenderer = renderer.create(
<DataEntryTable
semanticDomain={mockSemanticDomain}
semanticDomain={mockTreeNode}
openTree={mockOpenTree}
hideQuestions={mockHideQuestions}
getWordsFromBackend={getWordsFromBackendMock}
Expand All @@ -72,7 +77,7 @@ async function exitToTree() {
await renderer.act(async () => {
testRenderer.update(
<DataEntryTable
semanticDomain={mockSemanticDomain}
semanticDomain={mockTreeNode}
treeIsOpen
openTree={mockOpenTree}
hideQuestions={mockHideQuestions}
Expand Down
2 changes: 1 addition & 1 deletion src/components/TreeView/DomainTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function domainText(
{domain.id !== RootId ? domain.id : ""}
</Typography>
<Typography variant={"body1"}>
{domain.id !== "Sem" ? domain.name : t("addWords.domain")}
{domain.id !== RootId ? domain.name : t("addWords.domain")}
</Typography>
</div>
);
Expand Down
20 changes: 7 additions & 13 deletions src/components/TreeView/TreeDepiction.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Grid, ImageList, ImageListItem } from "@material-ui/core";
import React, { ReactElement } from "react";

import { SemanticDomainTreeNode } from "api";
import { SemanticDomain, SemanticDomainTreeNode } from "api";
import DomainTile, { Direction } from "components/TreeView/DomainTile";
import { TreeViewHeader } from "components/TreeView/TreeViewHeader";
import {
Expand All @@ -23,7 +23,7 @@ const HALF_TILE = (RATIO_TILE_TO_GAP - 1) / 2; // Half of cols-per-tile, rounded

interface TreeDepictionProps {
currentDomain: SemanticDomainTreeNode;
animate: (domain: SemanticDomainTreeNode) => Promise<void>;
animate: (domain: SemanticDomain) => Promise<void>;
}

interface TreeDepictionState {
Expand Down Expand Up @@ -57,7 +57,7 @@ export default class TreeDepiction extends React.Component<

// Computes a new width for each tile
updateColWidth() {
const length = this.props.currentDomain.children?.length;
const length = this.props.currentDomain.children.length;
const clientWidth = document.documentElement.clientWidth;
let colWidth = length
? Math.floor(clientWidth / (length * (RATIO_TILE_TO_GAP + 1) - 1))
Expand All @@ -77,7 +77,7 @@ export default class TreeDepiction extends React.Component<
// Renders the subdomains + their connectors to the current domain
subDomains(): ReactElement {
const children = this.props.currentDomain.children;
const cols = (children ? children.length : 0) * (RATIO_TILE_TO_GAP + 1) - 1;
const cols = children.length * (RATIO_TILE_TO_GAP + 1) - 1;
return (
<ImageList
cols={cols}
Expand All @@ -94,10 +94,7 @@ export default class TreeDepiction extends React.Component<
// Creates the joist connecting current domain with subdomains
joistRow(): ReactElement[] {
const row: ReactElement[] = [];
const teeCount =
(this.props.currentDomain.children
? this.props.currentDomain.children.length
: 0) - 2;
const teeCount = this.props.currentDomain.children.length - 2;
const middleTeeCount = teeCount % 2;
const halfTeeCount = (teeCount - middleTeeCount) / 2;

Expand Down Expand Up @@ -145,9 +142,8 @@ export default class TreeDepiction extends React.Component<

// Places the subdomain tiles
domainRow(): ReactElement[] {
const children = this.props.currentDomain.children;
const subdomains: ReactElement[] = [];
children?.forEach((child, i) => {
this.props.currentDomain.children.forEach((child, i) => {
if (i > 0) {
subdomains.push(<ImageListItem key={"GapTile" + i} />);
}
Expand Down Expand Up @@ -228,9 +224,7 @@ export default class TreeDepiction extends React.Component<

{/* Label subdomains, if available */}
<Grid item>
{currentDomain.children &&
currentDomain.children.length > 0 &&
this.subDomains()}
{currentDomain.children.length > 0 && this.subDomains()}
</Grid>
</React.Fragment>
);
Expand Down
3 changes: 2 additions & 1 deletion src/components/TreeView/TreeViewActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SemanticDomain, SemanticDomainTreeNode } from "api/models";
import { getSemanticDomainTreeNode } from "backend";
import { StoreState } from "types";
import { StoreStateDispatch } from "types/Redux/actions";
import { Bcp47Code } from "types/writingSystem";

export function closeTreeAction(): TreeViewAction {
return { type: TreeActionType.CLOSE_TREE };
Expand Down Expand Up @@ -48,7 +49,7 @@ export function initTreeDomain(language: string) {
const currentDomain = getState().treeViewState.currentDomain;
if (currentDomain === defaultState.currentDomain) {
if (!currentDomain.lang) {
currentDomain.lang = language ?? "en";
currentDomain.lang = language ?? Bcp47Code.Default;
}
dispatch(traverseTreeAction(currentDomain));
}
Expand Down
3 changes: 1 addition & 2 deletions src/components/TreeView/TreeViewComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ export function TreeView(props: TreeViewProps): ReactElement {
i18n.resolvedLanguage;
if (newLang && newLang !== semDomLanguage) {
dispatch(updateTreeLanguage(newLang));
// Don't update when props updates, except props.i18n.resolvedLanguage
} // eslint-disable-next-line react-hooks/exhaustive-deps
}
dispatch(initTreeDomain(newLang));
}, [semDomLanguage, semDomWritingSystem, dispatch, i18n.resolvedLanguage]);

Expand Down
31 changes: 14 additions & 17 deletions src/components/TreeView/TreeViewHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import DomainTile, {

export interface TreeHeaderProps {
currentDomain: SemanticDomainTreeNode;
animate: (domain: SemanticDomainTreeNode) => Promise<void>;
animate: (domain: SemanticDomain) => Promise<void>;
}

export function TreeViewHeader(props: TreeHeaderProps) {
const { getLeftBrother, getRightBrother } = useTreeNavigation(props);
const { getPrevSibling, getNextSibling } = useTreeNavigation(props);

return (
<ImageList cols={7} gap={20} rowHeight={"auto"}>
<ImageListItem cols={2}>
{getLeftBrother(props) ? (
{getPrevSibling(props) ? (
<DomainTile
domain={getLeftBrother(props)!}
domain={getPrevSibling(props)!}
onClick={props.animate}
direction={Direction.Left}
/>
Expand All @@ -42,9 +42,9 @@ export function TreeViewHeader(props: TreeHeaderProps) {
</Button>
</ImageListItem>
<ImageListItem cols={2}>
{getRightBrother(props) ? (
{getNextSibling(props) ? (
<DomainTile
domain={getRightBrother(props)!}
domain={getNextSibling(props)!}
onClick={props.animate}
direction={Direction.Right}
/>
Expand All @@ -56,35 +56,32 @@ export function TreeViewHeader(props: TreeHeaderProps) {

// exported for unit testing only
export function useTreeNavigation(props: TreeHeaderProps) {
function getRightBrother(props: TreeHeaderProps): SemanticDomain | undefined {
function getNextSibling(props: TreeHeaderProps): SemanticDomain | undefined {
return props.currentDomain.next;
}

function getLeftBrother(props: TreeHeaderProps): SemanticDomain | undefined {
function getPrevSibling(props: TreeHeaderProps): SemanticDomain | undefined {
return props.currentDomain.previous;
}

// Navigate tree via arrow keys
const navigateDomainArrowKeys = useCallback(
(event: KeyboardEvent) => {
let domain: SemanticDomainTreeNode | undefined;
let domain: SemanticDomain | undefined;
switch (event.key) {
case Key.ArrowLeft:
domain = getLeftBrother(props);
domain = getPrevSibling(props);
break;
case Key.ArrowRight:
domain = getRightBrother(props);
domain = getNextSibling(props);
break;
case Key.ArrowUp:
if (props.currentDomain.parent !== undefined) {
domain = props.currentDomain.parent;
}
break;
case Key.ArrowDown:
if (
props.currentDomain.children &&
props.currentDomain.children.length === 1
) {
if (props.currentDomain.children.length === 1) {
domain = props.currentDomain.children[0];
}
break;
Expand All @@ -106,7 +103,7 @@ export function useTreeNavigation(props: TreeHeaderProps) {
}, [navigateDomainArrowKeys]);

return {
getRightBrother,
getLeftBrother,
getNextSibling,
getPrevSibling,
};
}
16 changes: 3 additions & 13 deletions src/components/TreeView/TreeViewReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from "components/TreeView/TreeViewReduxTypes";
import i18n from "i18n";
import { StoreAction, StoreActionTypes } from "rootActions";
import { newSemanticDomainTreeNode } from "types/semanticDomain";

export interface TreeViewState {
currentDomain: SemanticDomainTreeNode;
Expand All @@ -15,16 +16,7 @@ export interface TreeViewState {
export const defaultState: TreeViewState = {
language: "",
open: false,
currentDomain: {
guid: "",
lang: i18n.language,
id: "Sem",
name: "",
previous: undefined,
next: undefined,
parent: undefined,
children: undefined,
},
currentDomain: newSemanticDomainTreeNode("Sem", "", i18n.language),
};

export const treeViewReducer = (
Expand All @@ -38,9 +30,7 @@ export const treeViewReducer = (
return { ...state, open: true };
case TreeActionType.SET_DOMAIN_LANGUAGE:
if (!action.language) {
throw new Error(
"Cannot set domain map without a domain map and language."
);
throw new Error("Cannot set domain language to undefined.");
}
return {
...state,
Expand Down
4 changes: 2 additions & 2 deletions src/components/TreeView/TreeViewReduxTypes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SemanticDomain } from "api/models";
import { SemanticDomain, SemanticDomainTreeNode } from "api/models";

export enum TreeActionType {
CLOSE_TREE = "CLOSE_TREE",
Expand All @@ -9,6 +9,6 @@ export enum TreeActionType {

export interface TreeViewAction {
type: TreeActionType;
domain?: SemanticDomain;
domain?: SemanticDomainTreeNode;
language?: string;
}
Loading

0 comments on commit 5e75191

Please sign in to comment.