Skip to content

Commit

Permalink
Feature/selector org (#606)
Browse files Browse the repository at this point in the history
* add compoundSelectors to redux

* add ColorSettings enum and use container specific selector in ModelPanel

* add currentColorSettings to selection branch state

* rename ColorSetting from plural

* fix typo in selection branch spread in getCurrentUIData test

* add explanatory comment to compoundSelectors
  • Loading branch information
interim17 authored Nov 18, 2024
1 parent 9fe9f69 commit 5c070a9
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 102 deletions.
6 changes: 2 additions & 4 deletions src/containers/ModelPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import {
requestTrajectory,
changeToNetworkedFile,
} from "../../state/trajectory/actions";
import {
getUiDisplayDataTree,
getIsNetworkedFile,
} from "../../state/trajectory/selectors";
import { getIsNetworkedFile } from "../../state/trajectory/selectors";
import {
AgentRenderingCheckboxMap,
ChangeAgentsRenderingStateAction,
Expand Down Expand Up @@ -44,6 +41,7 @@ import {
getSelectAllVisibilityMap,
getSelectNoneVisibilityMap,
getIsSharedCheckboxIndeterminate,
getUiDisplayDataTree,
} from "./selectors";

import styles from "./style.css";
Expand Down
75 changes: 69 additions & 6 deletions src/containers/ModelPanel/selectors.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { initialState, State } from "../../state";
import {
getSelectAllVisibilityMap,
getSelectNoneVisibilityMap,
getIsSharedCheckboxIndeterminate,
getUiDisplayDataTree,
} from "./selectors";

const mockUiDisplayData = [
Expand Down Expand Up @@ -50,9 +52,8 @@ const mockUiDisplayData = [
describe("ModelPanel selectors", () => {
describe("getSelectAllVisibilityMap", () => {
it("Returns an agent visibility map with all possible states", () => {
const result = getSelectAllVisibilityMap.resultFunc(
mockUiDisplayData
);
const result =
getSelectAllVisibilityMap.resultFunc(mockUiDisplayData);
const expected = {
agentWithChildren1: ["", "state1"],
agentWithChildren2: ["", "state1"],
Expand All @@ -64,9 +65,8 @@ describe("ModelPanel selectors", () => {

describe("getSelectNoneVisibilityMap", () => {
it("Returns an agent visibility map with none of the possible states", () => {
const result = getSelectNoneVisibilityMap.resultFunc(
mockUiDisplayData
);
const result =
getSelectNoneVisibilityMap.resultFunc(mockUiDisplayData);
const expected = {
agentWithChildren1: [],
agentWithChildren2: [],
Expand Down Expand Up @@ -164,4 +164,67 @@ describe("ModelPanel selectors", () => {
expect(result).toBe(true);
});
});
describe("getUiDisplayDataTree", () => {
it("returns an empty array if ui display data is empty", () => {
expect(getUiDisplayDataTree(initialState)).toStrictEqual([]);
});
it("correctly maps agent display info to an array of display data", () => {
const state: State = {
...initialState,
trajectory: {
...initialState.trajectory,
defaultUIData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
{
name: "agent2",
color: "#aaaaaa",
displayStates: [
{
name: "state1",
id: "state1_id",
color: "#000000",
},
{
name: "state2",
id: "state2_id",
color: "#000000",
},
],
},
],
},
};

const expected = [
{
title: "agent1",
key: "agent1",
children: [],
color: "#bbbbbb",
},
{
title: "agent2",
key: "agent2",
color: "#aaaaaa",
children: [
{
color: "#000000",
label: "state1",
value: "state1_id",
},
{
color: "#000000",
label: "state2",
value: "state2_id",
},
],
},
];
expect(getUiDisplayDataTree(state)).toStrictEqual(expected);
});
});
});
26 changes: 25 additions & 1 deletion src/containers/ModelPanel/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,33 @@ import { createSelector } from "reselect";
import { isEmpty } from "lodash";

import { AgentDisplayNode } from "../../components/AgentTree";
import { getUiDisplayDataTree } from "../../state/trajectory/selectors";
import { getAgentVisibilityMap } from "../../state/selection/selectors";
import { AgentRenderingCheckboxMap } from "../../state/selection/types";
import { getCurrentUIData } from "../../state/compoundSelectors";
import { UIDisplayData } from "@aics/simularium-viewer";

export const getUiDisplayDataTree = createSelector(
[getCurrentUIData],
(uiDisplayData: UIDisplayData) => {
if (!uiDisplayData.length) {
return [];
}
return uiDisplayData.map((agent) => ({
title: agent.name,
key: agent.name,
color: agent.color,
children: agent.displayStates.length
? [
...agent.displayStates.map((state) => ({
label: state.name,
value: state.id,
color: state.color,
})),
]
: [],
}));
}
);

// Returns an agent visibility map that indicates all states should be visible
export const getSelectAllVisibilityMap = createSelector(
Expand Down
79 changes: 79 additions & 0 deletions src/state/compoundSelectors/compoundSelectors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { getCurrentUIData } from ".";
import { initialState } from "..";
import { ColorSetting } from "../selection/types";

describe("getCurrentUIData", () => {
it("returns empty array if default UI data has not been entered yet", () => {
expect(getCurrentUIData(initialState)).toEqual([]);
1;
});
it("returns selectedUIDisplayData if colorSetting is equal to ColorSetting.UserSelected", () => {
expect(
getCurrentUIData({
...initialState,
trajectory: {
...initialState.trajectory,
defaultUIData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
],
},
selection: {
...initialState.selection,
currentColorSetting: ColorSetting.UserSelected,
selectedUIDisplayData: [
{
name: "agent1",
displayStates: [],
color: "#000",
},
],
},
})
).toEqual([
{
name: "agent1",
displayStates: [],
color: "#000",
},
]);
});

it("returns defaultUIData if colorSetting is euqal to ColorSetting.Default", () => {
expect(
getCurrentUIData({
...initialState,
trajectory: {
...initialState.trajectory,
defaultUIData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
],
},
selection: {
...initialState.selection,
currentColorSetting: ColorSetting.Default,
selectedUIDisplayData: [
{
name: "agent1",
displayStates: [],
color: "#000",
},
],
},
})
).toEqual([
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
]);
});
});
34 changes: 34 additions & 0 deletions src/state/compoundSelectors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createSelector } from "reselect";
import { UIDisplayData } from "@aics/simularium-viewer";

import { getDefaultUIDisplayData } from "../trajectory/selectors";
import {
getCurrentColorSetting,
getSelectedUIDisplayData,
} from "../selection/selectors";
import { ColorSetting } from "../selection/types";

/**
* compoundSelectors are selectors that consume state from multiple branches
* of state, so don't belong in a particular branch's selectors file,
* and are consumed by multiple containers, and so don't belong in a particular
* container's selectors file.
*/

export const getCurrentUIData = createSelector(
[getCurrentColorSetting, getSelectedUIDisplayData, getDefaultUIDisplayData],
(
colorSetting: ColorSetting,
sessionData: UIDisplayData,
defaultData: UIDisplayData
) => {
const fileHasBeenParsed = defaultData.length > 0;
if (!fileHasBeenParsed) {
return [];
}
if (colorSetting === ColorSetting.UserSelected) {
return sessionData;
}
return defaultData;
}
);
2 changes: 2 additions & 0 deletions src/state/selection/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
SetRecentColorsAction,
SetSelectedAgentMetadataAction,
SetSelectedUIDisplayDataAction,
ColorSetting,
} from "./types";

export const initialState = {
Expand All @@ -36,6 +37,7 @@ export const initialState = {
recentColors: [],
selectedAgentMetadata: {},
selectedUIDisplayData: [],
currentColorSetting: ColorSetting.Default,
};

const actionToConfigMap: TypeToDescriptionMap = {
Expand Down
2 changes: 2 additions & 0 deletions src/state/selection/selectors/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const getSelectedAgentMetadata = (state: State) =>
state.selection.selectedAgentMetadata;
export const getSelectedUIDisplayData = (state: State) =>
state.selection.selectedUIDisplayData;
export const getCurrentColorSetting = (state: State) =>
state.selection.currentColorSetting;
5 changes: 5 additions & 0 deletions src/state/selection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ export interface SetSelectedUIDisplayDataAction {
payload: UIDisplayData;
type: string;
}

export enum ColorSetting {
UserSelected = "userSelected",
Default = "default",
}
26 changes: 1 addition & 25 deletions src/state/trajectory/selectors/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { createSelector } from "reselect";
import { UIDisplayData } from "@aics/simularium-viewer";

import {
isNetworkSimFileInterface,
LocalSimFile,
NetworkedSimFile,
} from "../types";
import { getSimulariumFile, getDefaultUIDisplayData } from "./basic";
import { getSimulariumFile } from "./basic";

export const getIsNetworkedFile = createSelector(
[getSimulariumFile],
Expand All @@ -18,27 +17,4 @@ export const getIsNetworkedFile = createSelector(
}
);

export const getUiDisplayDataTree = createSelector(
[getDefaultUIDisplayData],
(uiDisplayData: UIDisplayData) => {
if (!uiDisplayData.length) {
return [];
}
return uiDisplayData.map((agent) => ({
title: agent.name,
key: agent.name,
color: agent.color,
children: agent.displayStates.length
? [
...agent.displayStates.map((state) => ({
label: state.name,
value: state.id,
color: state.color,
})),
]
: [],
}));
}
);

export * from "./basic";
Loading

0 comments on commit 5c070a9

Please sign in to comment.