Skip to content

Commit

Permalink
Fix first time user challenges (equinor#642)
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms authored Jun 13, 2024
1 parent 2276c20 commit 57afd20
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 33 deletions.
9 changes: 6 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ function App() {
WORKBENCH.getGuiMessageBroker().setState(GuiState.DrawerContent, DrawerContent.ModuleSettings);
}
setInitAppState(InitAppState.InitCompleted);
WORKBENCH.getGuiMessageBroker().setState(GuiState.AppInitialized, true);
}

function signIn() {
Expand Down Expand Up @@ -158,9 +159,11 @@ function App() {
"opacity-100": !isInitializingApp,
})}
>
<LeftNavBar workbench={WORKBENCH} />
<SettingsContentPanels workbench={WORKBENCH} />
<RightNavBar workbench={WORKBENCH} />
<>
<LeftNavBar workbench={WORKBENCH} />
<SettingsContentPanels workbench={WORKBENCH} />
<RightNavBar workbench={WORKBENCH} />
</>
</div>
<ToggleDevToolsButton guiMessageBroker={WORKBENCH.getGuiMessageBroker()} />
</>
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/framework/GuiMessageBroker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum GuiState {
EditDataChannelConnections = "editDataChannelConnections",
RightSettingsPanelWidthInPercent = "rightSettingsPanelWidthInPercent",
RightSettingsPanelExpanded = "rightSettingsPanelExpanded",
AppInitialized = "appInitialized",
}

export enum GuiEvent {
Expand Down Expand Up @@ -79,6 +80,7 @@ type GuiStateValueTypes = {
[GuiState.EditDataChannelConnections]: boolean;
[GuiState.RightSettingsPanelWidthInPercent]: number;
[GuiState.RightSettingsPanelExpanded]: boolean;
[GuiState.AppInitialized]: boolean;
};

const defaultStates: Map<GuiState, any> = new Map();
Expand All @@ -89,6 +91,7 @@ defaultStates.set(GuiState.DataChannelConnectionLayerVisible, false);
defaultStates.set(GuiState.DevToolsVisible, isDevMode());
defaultStates.set(GuiState.RightSettingsPanelWidthInPercent, 0);
defaultStates.set(GuiState.RightSettingsPanelExpanded, false);
defaultStates.set(GuiState.AppInitialized, false);

const persistentStates: GuiState[] = [
GuiState.LeftSettingsPanelWidthInPercent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ModuleRegistry } from "@framework/ModuleRegistry";
import { DrawPreviewFunc } from "@framework/Preview";
import { Workbench } from "@framework/Workbench";
import { Drawer } from "@framework/internal/components/Drawer";
import { useModuleInstances } from "@framework/internal/hooks/workbenchHooks";
import { Checkbox } from "@lib/components/Checkbox";
import { useElementBoundingRect } from "@lib/hooks/useElementBoundingRect";
import { createPortal } from "@lib/utils/createPortal";
Expand Down Expand Up @@ -460,6 +461,7 @@ if (isDevMode()) {

export const ModulesList: React.FC<ModulesListProps> = (props) => {
const drawerContent = useGuiValue(props.workbench.getGuiMessageBroker(), GuiState.DrawerContent);
const moduleInstances = useModuleInstances(props.workbench);

const ref = React.useRef<HTMLDivElement>(null);
const boundingClientRect = useElementBoundingRect(ref);
Expand Down Expand Up @@ -500,6 +502,10 @@ export const ModulesList: React.FC<ModulesListProps> = (props) => {
setDetailsPosY(yPos);
}

function handleNotificationClick() {
props.workbench.getGuiMessageBroker().setState(GuiState.DrawerContent, DrawerContent.ModuleSettings);
}

const handleDraggingStart = React.useCallback(function handleDraggingStart() {
setShowDetailsForModule(null);
}, []);
Expand All @@ -524,7 +530,12 @@ export const ModulesList: React.FC<ModulesListProps> = (props) => {
showFilter
filterPlaceholder="Filter modules..."
onFilterChange={handleSearchQueryChange}
headerChildren={<DevStatesFilter onFilterChange={handleDevStatesChange} initialDevStates={devStates} />}
headerChildren={
<>
<Notification onClick={handleNotificationClick} visible={moduleInstances.length > 0} />
<DevStatesFilter onFilterChange={handleDevStatesChange} initialDevStates={devStates} />
</>
}
>
<>
{MODULE_CATEGORIES.map((el) => (
Expand Down Expand Up @@ -563,3 +574,23 @@ export const ModulesList: React.FC<ModulesListProps> = (props) => {
</div>
);
};

type NotificationProps = {
visible: boolean;
onClick: () => void;
};

function Notification(props: NotificationProps): React.ReactNode {
if (!props.visible) {
return null;
}
return (
<div
className="bg-green-600 hover:bg-green-500 p-2 mb-4 text-sm cursor-pointer text-white"
onClick={props.onClick}
>
<p className="font-bold mb-1">Done editing?</p>
Click here or on a module header to start using your dashboard.
</div>
);
}
39 changes: 23 additions & 16 deletions frontend/src/framework/internal/components/NavBar/leftNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";

import WebvizLogo from "@assets/webviz.svg";
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { DrawerContent, GuiState, useGuiState } from "@framework/GuiMessageBroker";
import { DrawerContent, GuiState, useGuiState, useGuiValue } from "@framework/GuiMessageBroker";
import { UserEnsembleSetting, Workbench, WorkbenchEvents } from "@framework/Workbench";
import { useEnsembleSet, useIsEnsembleSetLoading } from "@framework/WorkbenchSession";
import { LoginButton } from "@framework/internal/components/LoginButton";
Expand All @@ -27,10 +27,12 @@ const NavBarDivider: React.FC = () => {
};

export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
const ensembleSet = useEnsembleSet(props.workbench.getWorkbenchSession());
const [ensembleDialogOpen, setEnsembleDialogOpen] = React.useState<boolean>(false);
const [newSelectedEnsembles, setNewSelectedEnsembles] = React.useState<EnsembleItem[]>([]);
const [layoutEmpty, setLayoutEmpty] = React.useState<boolean>(props.workbench.getLayout().length === 0);
const [expanded, setExpanded] = React.useState<boolean>(localStorage.getItem("navBarExpanded") === "true");
const [collapsed, setCollapsed] = React.useState<boolean>(localStorage.getItem("navBarCollapsed") === "true");
const [prevIsAppInitialized, setPrevIsAppInitialized] = React.useState<boolean>(false);
const loadingEnsembleSet = useIsEnsembleSetLoading(props.workbench.getWorkbenchSession());
const [drawerContent, setDrawerContent] = useGuiState(
props.workbench.getGuiMessageBroker(),
Expand All @@ -40,7 +42,12 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
props.workbench.getGuiMessageBroker(),
GuiState.LeftSettingsPanelWidthInPercent
);
const ensembleSet = useEnsembleSet(props.workbench.getWorkbenchSession());
const isAppInitialized = useGuiValue(props.workbench.getGuiMessageBroker(), GuiState.AppInitialized);

if (isAppInitialized !== prevIsAppInitialized) {
setEnsembleDialogOpen(ensembleSet.getEnsembleArr().length === 0);
setPrevIsAppInitialized(isAppInitialized);
}

const queryClient = useQueryClient();
const colorSet = props.workbench.getWorkbenchSettings().useColorSet();
Expand Down Expand Up @@ -106,8 +113,8 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
}

function handleCollapseOrExpand() {
setExpanded(!expanded);
localStorage.setItem("navBarExpanded", (!expanded).toString());
setCollapsed(!collapsed);
localStorage.setItem("navBarCollapsed", (!collapsed).toString());
}

const selectedEnsembles: EnsembleItem[] = ensembleSet.getEnsembleArr().map((ens) => ({
Expand Down Expand Up @@ -137,7 +144,7 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
<div
className={resolveClassNames(
"bg-white p-2 border-r-2 border-slate-200 z-50 shadow-lg flex flex-col",
expanded ? "w-64" : "w-[4.5rem]"
collapsed ? "w-[4.5rem]" : "w-64"
)}
>
<div className="flex flex-col gap-2 flex-grow">
Expand All @@ -154,9 +161,9 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
<Button
onClick={handleCollapseOrExpand}
className="!text-slate-800"
title={expanded ? "Collapse menu" : "Expand menu"}
title={collapsed ? "Expand menu" : "Collapse menu"}
>
{expanded ? <ChevronLeft fontSize="small" /> : <ChevronRight fontSize="small" />}
{collapsed ? <ChevronRight fontSize="small" /> : <ChevronLeft fontSize="small" />}
</Button>
</div>
<NavBarDivider />
Expand Down Expand Up @@ -184,7 +191,7 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
)
}
>
{expanded ? "Ensembles" : ""}
{!collapsed ? "Ensembles" : ""}
</Button>
<NavBarDivider />
<Button
Expand All @@ -198,7 +205,7 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
)}
disabled={layoutEmpty}
>
{expanded ? "Module settings" : ""}
{!collapsed ? "Module settings" : ""}
</Button>
<Button
title="Show sync settings"
Expand All @@ -211,7 +218,7 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
)}
disabled={layoutEmpty}
>
{expanded ? "Sync settings" : ""}
{!collapsed ? "Sync settings" : ""}
</Button>
<NavBarDivider />
<Button
Expand All @@ -224,7 +231,7 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
drawerContent === DrawerContent.ModulesList ? "text-cyan-600" : "!text-slate-800"
)}
>
{expanded ? "Add modules" : ""}
{!collapsed ? "Add modules" : ""}
</Button>
<Button
title="Show templates list"
Expand All @@ -236,7 +243,7 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
drawerContent === DrawerContent.TemplatesList ? "text-cyan-600" : "!text-slate-800"
)}
>
{expanded ? "Use templates" : ""}
{!collapsed ? "Use templates" : ""}
</Button>
<NavBarDivider />
<Button
Expand All @@ -249,14 +256,14 @@ export const LeftNavBar: React.FC<LeftNavBarProps> = (props) => {
drawerContent === DrawerContent.ColorPaletteSettings ? "text-cyan-600" : "!text-slate-800"
)}
>
{expanded ? "Color settings" : ""}
{!collapsed ? "Color settings" : ""}
</Button>
<NavBarDivider />
<LoginButton className="w-full !text-slate-800 h-10" showText={expanded} />
<LoginButton className="w-full !text-slate-800 h-10" showText={!collapsed} />
<div className="flex-grow h-5" />
<div className={isDevMode() ? "mb-16" : ""}>
<NavBarDivider />
<UserSessionState expanded={expanded} />
<UserSessionState expanded={!collapsed} />
</div>
</div>
{ensembleDialogOpen && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ interface CaseFilterSettings {
users: string[];
}

function readInitialStateFromLocalStorage(stateName: string): string {
const storedState = localStorage.getItem(stateName);
if (storedState && typeof storedState === "string") {
return storedState;
}
return "";
}

function storeStateInLocalStorage(stateName: string, value: string) {
localStorage.setItem(stateName, value);
}

export const SelectEnsemblesDialog: React.FC<SelectEnsemblesDialogProps> = (props) => {
const [isLoadingEnsembles, setIsLoadingEnsembles] = React.useState<boolean>(false);
const [confirmCancel, setConfirmCancel] = React.useState<boolean>(false);
Expand All @@ -74,7 +86,7 @@ export const SelectEnsemblesDialog: React.FC<SelectEnsemblesDialogProps> = (prop
});

const [selectedField, setSelectedField] = useValidState<string>({
initialState: "",
initialState: readInitialStateFromLocalStorage("selectedField"),
validStates: fieldsQuery.data?.map((item) => item.field_identifier) ?? [],
keepStateWhenInvalid: true,
});
Expand All @@ -94,7 +106,7 @@ export const SelectEnsemblesDialog: React.FC<SelectEnsemblesDialogProps> = (prop

const [selectedCaseId, setSelectedCaseId] = useValidState<string>({
initialState: "",
validStates: casesQuery.data?.map((item) => item.uuid) ?? [],
validStates: filterCases(casesQuery.data)?.map((item) => item.uuid) ?? [],
keepStateWhenInvalid: true,
});

Expand All @@ -118,6 +130,7 @@ export const SelectEnsemblesDialog: React.FC<SelectEnsemblesDialogProps> = (prop
});

function handleFieldChanged(fieldIdentifier: string) {
storeStateInLocalStorage("selectedField", fieldIdentifier);
setSelectedField(fieldIdentifier);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ const DragBar: React.FC<DragBarProps> = (props) => {
<div
data-handle={props.index}
className={resolveClassNames("z-40 touch-none absolute bg-transparent", {
"cursor-ew-resize w-5 -left-2 top-0 h-full": props.direction === "horizontal",
"cursor-ns-resize h-5 left-0 -top-2 w-full": props.direction === "vertical",
"cursor-ew-resize w-1 -left-0.25 top-0 h-full": props.direction === "horizontal",
"cursor-ns-resize h-2 left-0 -top-0.25 w-full": props.direction === "vertical",
})}
/>
</div>
Expand Down
22 changes: 13 additions & 9 deletions frontend/src/lib/components/TableSelect/tableSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const TableSelect = withDefaults<TableSelectProps>()(defaultProps, (props
const [lastShiftIndex, setLastShiftIndex] = React.useState<number>(-1);
const [currentIndex, setCurrentIndex] = React.useState<number>(0);
const [prevFilteredOptions, setPrevFilteredOptions] = React.useState<TableSelectOption[]>([]);
const [prevValue, setPrevValue] = React.useState<string[] | undefined>(props.value);

if (!isEqual(prevHeaderLabels, props.headerLabels)) {
setPrevHeaderLabels(props.headerLabels);
Expand Down Expand Up @@ -92,6 +93,18 @@ export const TableSelect = withDefaults<TableSelectProps>()(defaultProps, (props
[props.options, filters, props.filter]
);

if (!isEqual(prevValue, props.value)) {
setPrevValue(props.value);
setSelected(props.value ?? []);
if (props.value?.length === 1) {
const newIndex = filteredOptions.findIndex((option) => option.id === props.value[0]);
if (newIndex !== -1) {
setCurrentIndex(newIndex);
setStartIndex(newIndex);
}
}
}

if (!checkForEqualityWithoutAdornment(filteredOptions, prevFilteredOptions)) {
let newCurrentIndex = 0;
let newStartIndex = 0;
Expand Down Expand Up @@ -212,15 +225,6 @@ export const TableSelect = withDefaults<TableSelectProps>()(defaultProps, (props
[currentIndex, selected, filteredOptions, props.size, hasFocus, startIndex, toggleValue]
);

React.useLayoutEffect(
function handleInitialSelection() {
if (props.value) {
setSelected(props.value);
}
},
[props.value]
);

function handleFilterChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, index: number) {
setFilters((prev) => {
const newFilters = [...prev];
Expand Down

0 comments on commit 57afd20

Please sign in to comment.