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

Update tab-order #1569

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
173 changes: 96 additions & 77 deletions apps/client/src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,10 @@ class App extends React.PureComponent {
}
}

this.setToggleDrawerPermanentRef = (element) => {
this.buttonToggleDrawerPermanentRef = element;
};

this.globalObserver = new Observer();

// Initiate the Analytics model
Expand Down Expand Up @@ -754,6 +758,14 @@ class App extends React.PureComponent {
this.setState((prevState) => ({
drawerButtons: [...prevState.drawerButtons, button],
}));

this.globalObserver.subscribe("core.drawerToggled", () => {
if (this.state.drawerPermanent) {
if (this.buttonToggleDrawerPermanentRef) {
this.buttonToggleDrawerPermanentRef.focus();
}
}
});
});

/**
Expand Down Expand Up @@ -898,6 +910,9 @@ class App extends React.PureComponent {
// just "un-permanent" the Drawer, but it would still be visible).
this.state.drawerPermanent === false &&
this.globalObserver.publish("core.hideDrawer");

// Publish the event to notify plugins to re-render
this.globalObserver.publish("core.pluginsRerender");
});
};

Expand Down Expand Up @@ -1003,6 +1018,7 @@ class App extends React.PureComponent {
}
>
<IconButton
ref={this.setToggleDrawerPermanentRef}
sx={{ margin: "-12px" }} // Ugh... However, it tightens everything up
onClick={this.togglePermanent}
onMouseEnter={this.handleMouseEnter}
Expand Down Expand Up @@ -1082,6 +1098,70 @@ class App extends React.PureComponent {
return this.state.drawerStatic && isOnlyOneButtonVisible ? false : true;
}

renderDrawer() {
const { config } = this.props;
const clean = config.mapConfig.map.clean;

return (
<>
{clean !== true && ( // NB: Special case here, important with !== true, because there is an edge-case where clean===undefined, and we don't want to match on that!
<Drawer
open={this.state.drawerVisible}
ModalProps={{
hideBackdrop: this.state.drawerPermanent, //Don't show backdrop if drawer is permanent
disableEnforceFocus: true, //Dont enforce focus to be able to handle elements underneath modal
onClose: () => {
this.globalObserver.publish("core.hideDrawer");
},
style: {
//Needs to be set to be able to handle elements underneath modal
position: this.state.drawerPermanent ? "initial" : "fixed",
},
keepMounted: true, //Ensure we dont have to render plugins more than once - UnMounting every time is slow
}}
variant={this.state.drawerPermanent ? "permanent" : "temporary"}
sx={{
"& .MuiPaper-root": {
width: DRAWER_WIDTH,
backgroundColor: (theme) => theme.palette.background.default,
backgroundImage: "unset", // To match the new (darker) black theme.
},
}}
>
{this.renderDrawerHeader()}
<Divider />
{this.renderAllDrawerContent()}
{
// See #1336
config.mapConfig.map.linkInDrawer &&
typeof config.mapConfig.map.linkInDrawer?.text === "string" &&
typeof config.mapConfig.map.linkInDrawer?.href === "string" && (
<>
<Divider />
<Link
align="center"
variant="button"
href={config.mapConfig.map.linkInDrawer.href}
target={
config.mapConfig.map.linkInDrawer.newWindow === true
? "_blank"
: "_self"
}
sx={{
p: 1,
}}
>
{config.mapConfig.map.linkInDrawer.text}
</Link>
</>
)
}
</Drawer>
)}
</>
);
}

render() {
const { config } = this.props;

Expand Down Expand Up @@ -1132,6 +1212,7 @@ class App extends React.PureComponent {
title="Meddelande"
/>
<SrShortcuts globalObserver={this.globalObserver}></SrShortcuts>
{this.renderDrawer()}
<AppBox
id="appBox"
sx={{
Expand Down Expand Up @@ -1164,6 +1245,20 @@ class App extends React.PureComponent {
{/* Render Search even if clean === false: Search contains logic to handle clean inside the component. */}
{this.renderSearchComponent()}
</StyledHeader>
<WindowsContainer id="windows-container">
{useNewInfoclick === false && this.renderInfoclickWindow()}
{useNewInfoclick && (
<MapClickViewer
appModel={this.appModel}
globalObserver={this.globalObserver}
infoclickOptions={this.infoclickOptions}
/>
)}
<PluginWindows
plugins={this.appModel.getBothDrawerAndWidgetPlugins()}
/>
<SimpleDialog globalObserver={this.globalObserver} />
</WindowsContainer>
<StyledMain>
<Box
id="left-column"
Expand Down Expand Up @@ -1239,6 +1334,7 @@ class App extends React.PureComponent {
</Box>
</StyledMain>
<StyledFooter
id="footer"
sx={{
"& > *": {
pointerEvents: "auto",
Expand All @@ -1260,83 +1356,6 @@ class App extends React.PureComponent {
left: this.drawerIsLocked() ? DRAWER_WIDTH : 0,
}}
></MapContainer>
<WindowsContainer
id="windows-container"
sx={{
left: this.drawerIsLocked() ? DRAWER_WIDTH : 0,
"& > *": {
pointerEvents: "auto",
},
}}
>
{useNewInfoclick === false && this.renderInfoclickWindow()}
{useNewInfoclick && (
<MapClickViewer
appModel={this.appModel}
globalObserver={this.globalObserver}
infoclickOptions={this.infoclickOptions}
/>
)}
<PluginWindows
plugins={this.appModel.getBothDrawerAndWidgetPlugins()}
/>
<SimpleDialog globalObserver={this.globalObserver} />
</WindowsContainer>
{clean !== true && ( // NB: Special case here, important with !== true, because there is an edge-case where clean===undefined, and we don't want to match on that!
<Drawer
open={this.state.drawerVisible}
ModalProps={{
hideBackdrop: this.state.drawerPermanent, //Don't show backdrop if drawer is permanent
disableEnforceFocus: true, //Dont enforce focus to be able to handle elements underneath modal
onClose: () => {
this.globalObserver.publish("core.hideDrawer");
},
style: {
//Needs to be set to be able to handle elements underneath modal
position: this.state.drawerPermanent ? "initial" : "fixed",
},
keepMounted: true, //Ensure we dont have to render plugins more than once - UnMounting every time is slow
}}
variant="temporary"
sx={{
"& .MuiPaper-root": {
width: DRAWER_WIDTH,
backgroundColor: (theme) => theme.palette.background.default,
backgroundImage: "unset", // To match the new (darker) black theme.
},
}}
>
{this.renderDrawerHeader()}
<Divider />
{this.renderAllDrawerContent()}
{
// See #1336
config.mapConfig.map.linkInDrawer &&
typeof config.mapConfig.map.linkInDrawer?.text === "string" &&
typeof config.mapConfig.map.linkInDrawer?.href ===
"string" && (
<>
<Divider />
<Link
align="center"
variant="button"
href={config.mapConfig.map.linkInDrawer.href}
target={
config.mapConfig.map.linkInDrawer.newWindow === true
? "_blank"
: "_self"
}
sx={{
p: 1,
}}
>
{config.mapConfig.map.linkInDrawer.text}
</Link>
</>
)
}
</Drawer>
)}
{clean === false && (
<Introduction
introductionEnabled={
Expand Down
23 changes: 15 additions & 8 deletions apps/client/src/components/Window.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class Window extends React.PureComponent {
position: propTypes.string.isRequired,
title: propTypes.string.isRequired,
width: propTypes.number.isRequired,
componentId: propTypes.string,
};

static defaultProps = {
Expand Down Expand Up @@ -168,18 +169,23 @@ class Window extends React.PureComponent {
this.updatePosition();
}
});
this.#bindSubscriptions();
}

componentDidUpdate = (prevProps, prevState) => {
if (prevProps.open === false && this.props.open === true) {
//This is ugly but there is a timing problem further down somewhere (i suppose?).
//componentDidUpdate is run before the render is actually fully completed and the DOM is ready
setTimeout(() => {
this.windowRef.current.focus();
}, 200);
#bindSubscriptions = () => {
const { globalObserver } = this.props;
if (globalObserver) {
globalObserver.subscribe("core.focusWindow", (elementId) =>
this.focusWindow(elementId)
);
}
};

focusWindow = (elementId) => {
let element = document.getElementById(elementId);
if (element) element.focus();
};

componentDidMount() {
const { globalObserver } = this.props;
if (globalObserver) {
Expand Down Expand Up @@ -538,7 +544,6 @@ class Window extends React.PureComponent {
}}
>
<PanelContent
tabIndex="0"
ref={this.windowRef}
sx={{
display: this.props.height === "dynamic" ? "contents" : "flex",
Expand All @@ -557,6 +562,8 @@ class Window extends React.PureComponent {
title={title}
/>
<StyledSection
id={this.props.componentId}
tabIndex={-1}
sx={{
overflowY: this.props.scrollable ? "auto" : "hidden",
padding:
Expand Down
20 changes: 19 additions & 1 deletion apps/client/src/plugins/BaseWindowPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class BaseWindowPlugin extends React.PureComponent {
this.props.app.globalObserver.publish("analytics.trackEvent", {
eventName: "pluginShown",
pluginName: this.type,
pluginLocaleName: this.title,
activeMap: this.props.app.config.activeMap,
});
}
Expand Down Expand Up @@ -80,6 +81,10 @@ class BaseWindowPlugin extends React.PureComponent {
props.app.globalObserver.subscribe(closeEventName, () => {
this.closeWindow();
});

props.app.globalObserver.subscribe("core.pluginsRerender", () => {
this.forceUpdate();
});
}

// Does not run on initial render, but runs on subsequential re-renders.
Expand All @@ -103,6 +108,7 @@ class BaseWindowPlugin extends React.PureComponent {
runCallback: true,
});
this.props.app.globalObserver.publish("core.onlyHideDrawerIfNeeded");
this.props.app.globalObserver.publish("core.focusWindow", this.type);
};

showWindow = (opts = {}) => {
Expand All @@ -115,6 +121,7 @@ class BaseWindowPlugin extends React.PureComponent {
this.props.app.globalObserver.publish("analytics.trackEvent", {
eventName: "pluginShown",
pluginName: this.type,
pluginLocaleName: this.title,
activeMap: this.props.app.config.activeMap,
});

Expand Down Expand Up @@ -149,6 +156,16 @@ class BaseWindowPlugin extends React.PureComponent {
);
};

closeWindowClick = () => {
this.props.app.globalObserver.publish("analytics.trackEvent", {
eventName: "pluginHides",
pluginName: this.type,
pluginLocaleName: this.title,
activeMap: this.props.app.config.activeMap,
});
this.closeWindow();
};

closeWindow = () => {
// If closeWindow was initiated by the tool that is currently
// active, we should unset the activeTool property
Expand Down Expand Up @@ -188,10 +205,11 @@ class BaseWindowPlugin extends React.PureComponent {
// button (that will trigger opening of the plugin Window).
<>
<Window
componentId={this.type}
globalObserver={this.props.app.globalObserver}
title={this.state.title}
color={this.state.color}
onClose={this.closeWindow}
onClose={this.closeWindowClick}
open={this.state.windowVisible}
onResize={this.props.custom.onResize}
onMaximize={this.props.custom.onMaximize}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class DocumentViewer extends React.PureComponent {
)}

<ContentContainer
id="documentViewerContentContainer"
tabIndex="0" //Focus grid to be able to use onKeyDown
onKeyDown={(e) => {
//If ctrl-a or command-a is pressed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ class PanelMenuView extends React.PureComponent {
this.#setDocument(document, null);
this.#setItemStateProperties(id).then(() => {
app.globalObserver.publish("core.onlyHideDrawerIfNeeded");
app.globalObserver.publish(
"core.focusWindow",
"documentViewerContentContainer"
);
});
}
};
Expand Down