Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/restore default #615

Merged
merged 18 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
667a0a5
add compoundSelectors to redux
interim17 Oct 31, 2024
a0e99bf
retrieve stored color data from browser and apply it
interim17 Oct 31, 2024
25f4478
add ColorSettings enum and use container specific selector in ModelPanel
interim17 Oct 31, 2024
7ac652e
add currentColorSettings to selection branch state
interim17 Oct 31, 2024
621c6d0
make applyColorChangeToUiDisplayData a util with tests
interim17 Nov 1, 2024
5a1b26c
fix ids in broken test
interim17 Nov 1, 2024
6071d62
Merge branch 'feature/selector-org' into feature/retrieve-colors
interim17 Nov 1, 2024
9dae22e
rename ColorSetting from plural
interim17 Nov 8, 2024
1818d54
fix typo in selection branch spread in getCurrentUIData test
interim17 Nov 8, 2024
853fb53
Merge branch 'feature/selector-org' of https://github.com/simularium/…
interim17 Nov 11, 2024
881e59c
rename ColorSettings to ColorSetting across the board
interim17 Nov 11, 2024
b7a3bb8
streamline color setting logics and always retrieve settings after pa…
interim17 Nov 20, 2024
7ed1d8c
remove parsing check from current ui data selector
interim17 Nov 20, 2024
a939a1e
update colorPicker to track user interactions instead of initial renders
interim17 Nov 23, 2024
402c980
add button for previewing and resetting selected display data
interim17 Nov 23, 2024
6198f25
Merge branch 'main' of https://github.com/simularium/simularium-websi…
interim17 Nov 23, 2024
d3f0b27
restore deleted comment
interim17 Nov 23, 2024
d535a81
rename default settings applied selector and side bar content wrapper…
interim17 Dec 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions src/components/ColorPicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const ColorPicker = ({
}: ColorPickerProps): JSX.Element => {
const [currentColor, setCurrentColor] = useState(initialColor);
const [debouncedColor] = useDebounce(currentColor, 250);
const isInitialRender = useRef(true);
const isUserInteraction = useRef(false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that other elements are interacting with color changing, this needed to be a little more robust so prevent re-renders from triggering this and making preview events into permanent selection changes.

const [isColorPickerVisible, setColorPickerVisible] = useState(false);
const [lastSelectedColor, setLastSelectedColor] = useState(initialColor);

Expand All @@ -51,21 +51,25 @@ const ColorPicker = ({
color: newColor.toLowerCase(),
};
applyUserColor(colorChange);
updateRecentColors(newColor.toLowerCase());
};

useEffect(() => {
if (isInitialRender.current) {
isInitialRender.current = false;
} else {
if (isUserInteraction.current) {
handleColorChange(debouncedColor);
updateRecentColors(debouncedColor);
isUserInteraction.current = false;
}
}, [debouncedColor]);

useEffect(() => {
setCurrentColor(initialColor);
}, [initialColor]);

const onColorUpdate = (newColor: string) => {
isUserInteraction.current = true;
setCurrentColor(newColor);
};

const updateRecentColors = (color: string) => {
if (recentColors.includes(color)) {
return;
Expand All @@ -79,15 +83,15 @@ const ColorPicker = ({

const renderColorPickerComponent = () => (
<div className={styles.colorPicker}>
<HexColorPicker color={currentColor} onChange={setCurrentColor} />
<HexColorPicker color={currentColor} onChange={onColorUpdate} />
<div className={styles.selectionDisplay}>
<div className={styles.colorSelections}>
<div className={styles.selection}>
<div
className={styles.largeSwatch}
style={{ backgroundColor: lastSelectedColor }}
onClick={() => {
setCurrentColor(lastSelectedColor);
onColorUpdate(lastSelectedColor);
}}
></div>
<label>
Expand All @@ -108,9 +112,7 @@ const ColorPicker = ({
<HexColorInput
className={styles.hexInput}
color={currentColor}
onChange={(color) =>
setCurrentColor(color.toLowerCase())
}
onChange={(color) => onColorUpdate(color.toLowerCase())}
/>
<label>Hex</label>
</div>
Expand All @@ -132,7 +134,7 @@ const ColorPicker = ({
key={color}
className={styles.swatch}
style={{ background: color }}
onClick={() => setCurrentColor(color)}
onClick={() => onColorUpdate(color)}
/>
</Tooltip>
))}
Expand All @@ -144,7 +146,7 @@ const ColorPicker = ({
key={color}
className={styles.swatch}
style={{ background: color }}
onClick={() => setCurrentColor(color)}
onClick={() => onColorUpdate(color)}
/>
))}
</div>
Expand Down
44 changes: 42 additions & 2 deletions src/containers/ModelPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ActionCreator } from "redux";
import { connect } from "react-redux";

import { State } from "../../state/types";
import { areDefaultUISettingsApplied } from "../../state/compoundSelectors";
import { ViewerStatus } from "../../state/viewer/types";
import { getStatus } from "../../state/viewer/selectors";
import { RequestNetworkFileAction } from "../../state/trajectory/types";
Expand All @@ -17,13 +18,18 @@ import {
SetVisibleAction,
SetRecentColorsAction,
HandleColorChangeAction,
ColorSetting,
SetCurrentColorSettingAction,
ResetAction,
} from "../../state/selection/types";
import {
turnAgentsOnByDisplayKey,
highlightAgentsByDisplayKey,
setAgentsVisible,
setRecentColors,
handleColorChange,
setCurrentColorSetting,
clearUserSelectedColors,
} from "../../state/selection/actions";
import {
getAgentVisibilityMap,
Expand All @@ -36,7 +42,8 @@ import NoTrajectoriesText from "../../components/NoTrajectoriesText";
import NetworkFileFailedText from "../../components/NoTrajectoriesText/NetworkFileFailedText";
import NoTypeMappingText from "../../components/NoTrajectoriesText/NoTypeMappingText";
import SideBarContents from "../../components/SideBarContents";
import { AgentMetadata } from "../../constants/interfaces";
import NavButton from "../../components/NavButton";
import { AgentMetadata, ButtonClass } from "../../constants/interfaces";
import {
getSelectAllVisibilityMap,
getSelectNoneVisibilityMap,
Expand All @@ -63,6 +70,9 @@ interface ModelPanelProps {
setRecentColors: ActionCreator<SetRecentColorsAction>;
selectedAgentMetadata: AgentMetadata;
handleColorChange: ActionCreator<HandleColorChangeAction>;
defaultUiSettingsApplied: boolean;
setCurrentColorSetting: ActionCreator<SetCurrentColorSettingAction>;
clearUserSelectedColors: ActionCreator<ResetAction>;
}

const ModelPanel: React.FC<ModelPanelProps> = ({
Expand All @@ -82,6 +92,9 @@ const ModelPanel: React.FC<ModelPanelProps> = ({
setRecentColors,
selectedAgentMetadata,
handleColorChange,
defaultUiSettingsApplied,
setCurrentColorSetting,
clearUserSelectedColors,
}): JSX.Element => {
const checkboxTree = (
<CheckBoxTree
Expand Down Expand Up @@ -112,11 +125,35 @@ const ModelPanel: React.FC<ModelPanelProps> = ({
),
};

const handlePreviewDefaultColors = (colorSetting: ColorSetting) => {
if (!defaultUiSettingsApplied) {
setCurrentColorSetting({ currentColorSetting: colorSetting });
}
};

return (
<div className={styles.container}>
<SideBarContents
mainTitle="Agents"
content={[contentMap[viewerStatus]]}
content={[
<div key="content">
{contentMap[viewerStatus]}
<NavButton
titleText={"Restore color defaults"}
buttonType={ButtonClass.Action}
isDisabled={defaultUiSettingsApplied}
clickHandler={clearUserSelectedColors}
onMouseEnter={() =>
handlePreviewDefaultColors(ColorSetting.Default)
}
onMouseLeave={() =>
handlePreviewDefaultColors(
ColorSetting.UserSelected
)
}
/>
</div>,
]}
selectedAgentMetadata={selectedAgentMetadata}
uiDisplayData={uiDisplayDataTree}
/>
Expand All @@ -136,6 +173,7 @@ function mapStateToProps(state: State) {
isNetworkedFile: getIsNetworkedFile(state),
recentColors: getRecentColors(state),
selectedAgentMetadata: getSelectedAgentMetadata(state),
defaultUiSettingsApplied: areDefaultUISettingsApplied(state),
};
}

Expand All @@ -147,6 +185,8 @@ const dispatchToPropsMap = {
setAgentsVisible,
setRecentColors,
handleColorChange,
setCurrentColorSetting,
clearUserSelectedColors,
};

export default connect(mapStateToProps, dispatchToPropsMap)(ModelPanel);
75 changes: 74 additions & 1 deletion src/state/compoundSelectors/compoundSelectors.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCurrentUIData } from ".";
import { getCurrentUIData, areDefaultUISettingsApplied } from ".";
import { initialState } from "..";
import { ColorSetting } from "../selection/types";

Expand Down Expand Up @@ -77,3 +77,76 @@ describe("getCurrentUIData", () => {
]);
});
});

describe("areDefaultUISettingsApplied", () => {
it("returns false if selectedUIDisplayData contains selections and selectedUIDisplayData and defaultUIData are not equal", () => {
expect(
areDefaultUISettingsApplied({
...initialState,
trajectory: {
defaultUIData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
],
},
selection: {
...initialState.selection,
selectedUIDisplayData: [
{
name: "agent1",
displayStates: [],
color: "#000",
},
],
},
})
).toBe(false);
});
it("returns true if selectedUIDisplayData contains no selections", () => {
expect(
areDefaultUISettingsApplied({
...initialState,
trajectory: {
defaultUIData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
],
},
selection: {
selectedUIDisplayData: [],
},
})
).toBe(true);
});
it("returns true if selectedUIDisplayData and defaultUIData are equal", () => {
expect(
areDefaultUISettingsApplied({
...initialState,
trajectory: {
defaultUIData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
],
},
selection: {
selectedUIDisplayData: [
{
name: "agent1",
displayStates: [],
color: "#bbbbbb",
},
],
},
})
).toBe(true);
});
});
15 changes: 15 additions & 0 deletions src/state/compoundSelectors/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createSelector } from "reselect";
import { UIDisplayData } from "@aics/simularium-viewer";
import { isEqual } from "lodash";

import { getDefaultUIDisplayData } from "../trajectory/selectors";
import {
Expand Down Expand Up @@ -27,3 +28,17 @@ export const getCurrentUIData = createSelector(
: defaultData;
}
);

export const areDefaultUISettingsApplied = createSelector(
[getSelectedUIDisplayData, getDefaultUIDisplayData],
(selectedUIDisplayData, defaultUIData) => {
/**
* we can't just check if currentColorSettings === ColorSettings.Default
* because that state can be used to preview settings
*/
return (
selectedUIDisplayData.length === 0 ||
isEqual(selectedUIDisplayData, defaultUIData)
);
}
);
7 changes: 7 additions & 0 deletions src/state/selection/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
GET_DISPLAY_DATA_FROM_BROWSER,
SET_CURRENT_COLOR_SETTINGS,
HANDLE_COLOR_CHANGE,
CLEAR_UI_DATA_FROM_STATE,
} from "./constants";
import {
ChangeAgentsRenderingStateAction,
Expand Down Expand Up @@ -136,3 +137,9 @@ export function setCurrentColorSetting(payload: {
type: SET_CURRENT_COLOR_SETTINGS,
};
}

export function clearUserSelectedColors(): ResetAction {
return {
type: CLEAR_UI_DATA_FROM_STATE,
};
}
3 changes: 3 additions & 0 deletions src/state/selection/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ export const GET_DISPLAY_DATA_FROM_BROWSER = makeSelectConstant(
export const SET_CURRENT_COLOR_SETTINGS = makeSelectConstant(
"set-current-color-settings"
);
export const CLEAR_UI_DATA_FROM_STATE = makeSelectConstant(
"clear-ui-data-from-state"
);
26 changes: 22 additions & 4 deletions src/state/selection/logics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getCurrentUIData } from "../compoundSelectors";
import {
GET_DISPLAY_DATA_FROM_BROWSER,
HANDLE_COLOR_CHANGE,
CLEAR_UI_DATA_FROM_STATE,
} from "./constants";
import { setCurrentColorSetting, setSelectedUIDisplayData } from "./actions";
import { applyColorChangeToUiDisplayData, isSameAgentTree } from "../../util";
Expand Down Expand Up @@ -57,9 +58,6 @@ const getDisplayDataFromBrowserLogic = createLogic({
);
reject(action);
}
setCurrentColorSetting({
currentColorSetting: ColorSetting.UserSelected,
});
allow(setSelectedUIDisplayData(storedUIData));
},
process() {
Expand All @@ -70,4 +68,24 @@ const getDisplayDataFromBrowserLogic = createLogic({
type: GET_DISPLAY_DATA_FROM_BROWSER,
});

export default [handleColorChangeLogic, getDisplayDataFromBrowserLogic];
export const resetSelectedUIDisplayDataLogic = createLogic({
process(deps: ReduxLogicDeps, dispatch, done) {
const { getState } = deps;
const fileKey = getSimulariumFile(getState()).name;
localStorage.removeItem(fileKey);
dispatch(
setCurrentColorSetting({
currentColorSetting: ColorSetting.Default,
})
);
dispatch(setSelectedUIDisplayData([]));
done();
},
type: CLEAR_UI_DATA_FROM_STATE,
});

export default [
handleColorChangeLogic,
getDisplayDataFromBrowserLogic,
resetSelectedUIDisplayDataLogic,
];
Loading