Skip to content

Commit

Permalink
refactor(core/help): Migrate HelpContext to react hooks style (#7487)
Browse files Browse the repository at this point in the history
Export the entire context object instead of Provider and Consumer objects.
Also migrate HelpField to hooks style.
  • Loading branch information
christopherthielen committed Oct 3, 2019
1 parent 3c08b38 commit 5c3fcc7
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 68 deletions.
3 changes: 0 additions & 3 deletions app/scripts/modules/core/src/help/HelpContext.tsx

This file was deleted.

95 changes: 36 additions & 59 deletions app/scripts/modules/core/src/help/HelpField.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import * as ReactGA from 'react-ga';
import * as DOMPurify from 'dompurify';
import { isUndefined } from 'lodash';

import { HelpContentsRegistry } from 'core/help';
import { HelpContentsRegistry, HelpTextExpandedContext } from 'core/help';
import { HoverablePopover, Placement } from 'core/presentation';
import { HelpContextConsumer } from './HelpContext';

export interface IHelpFieldProps {
id?: string;
Expand All @@ -15,73 +15,50 @@ export interface IHelpFieldProps {
label?: string;
}

export class HelpField extends React.PureComponent<IHelpFieldProps> {
public static defaultProps: IHelpFieldProps = {
placement: 'top',
};

private popoverShownStart: number;

private renderContents(id: string, fallback: string, content: string): JSX.Element {
let contentString = content;
if (id && !contentString) {
contentString = HelpContentsRegistry.getHelpField(id) || fallback;
}
function HelpFieldContents(props: Pick<IHelpFieldProps, 'id' | 'fallback' | 'content'>): JSX.Element {
const { id, fallback, content } = props;

const config = { ADD_ATTR: ['target'] }; // allow: target="_blank"
return <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(contentString, config) }} />;
let contentString = content;
if (id && !contentString) {
contentString = HelpContentsRegistry.getHelpField(id) || fallback;
}

private onShow = (): void => {
this.popoverShownStart = Date.now();
};
const config = { ADD_ATTR: ['target'] }; // allow: target="_blank"
return <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(contentString, config) }} />;
}

private onHide = (): void => {
if (Date.now() - this.popoverShownStart > 500) {
ReactGA.event({ action: 'Help contents viewed', category: 'Help', label: this.props.id || this.props.content });
export function HelpField(props: IHelpFieldProps) {
const { content, expand, fallback, id, label, placement } = props;

const [popoverShownStart, setPopoverShownStart] = React.useState();
const onShow = (): void => setPopoverShownStart(Date.now());
const onHide = (): void => {
if (Date.now() - popoverShownStart > 500) {
ReactGA.event({ action: 'Help contents viewed', category: 'Help', label: props.id || props.content });
}
};

private shouldExpandHelpText(expandFromContext: any, expandFromProps: any) {
if (expandFromProps !== undefined) {
return expandFromProps;
}
return expandFromContext;
}
const icon = <i className="small glyphicon glyphicon-question-sign" />;
const shouldExpandFromContext = React.useContext(HelpTextExpandedContext);
const expandHelpText = isUndefined(expand) ? shouldExpandFromContext : expand;

public render() {
const { placement, label, expand, id, fallback, content } = this.props;
const contents = this.renderContents(id, fallback, content);
const contents = <HelpFieldContents content={content} fallback={fallback} id={id} />;
const popover = (
<HoverablePopover placement={placement || 'top'} template={contents} onShow={onShow} onHide={onHide}>
<a className="clickable help-field"> {label || icon} </a>
</HoverablePopover>
);

const icon = <i className="small glyphicon glyphicon-question-sign" />;
if (label) {
return <div className="text-only">{!expandHelpText && contents && popover}</div>;
} else {
const expanded = <div className="help-contents small"> {contents} </div>;

const popover = (
<HoverablePopover placement={placement} template={contents} onShow={this.onShow} onHide={this.onHide}>
<a className="clickable help-field"> {label || icon} </a>
</HoverablePopover>
return (
<div style={{ display: 'inline-block' }}>
{!expandHelpText && contents && popover}
{expandHelpText && contents && expanded}
</div>
);

if (label) {
return (
<HelpContextConsumer>
{context => (
<div className="text-only">{!this.shouldExpandHelpText(context, expand) && contents && popover}</div>
)}
</HelpContextConsumer>
);
} else {
const expanded = <div className="help-contents small"> {contents} </div>;

return (
<HelpContextConsumer>
{context => (
<div style={{ display: 'inline-block' }}>
{!this.shouldExpandHelpText(context, expand) && contents && popover}
{this.shouldExpandHelpText(context, expand) && contents && expanded}
</div>
)}
</HelpContextConsumer>
);
}
}
}
3 changes: 3 additions & 0 deletions app/scripts/modules/core/src/help/HelpTextExpandedContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as React from 'react';

export const HelpTextExpandedContext = React.createContext(false);
6 changes: 3 additions & 3 deletions app/scripts/modules/core/src/help/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './helpContents.registry';
export * from './help.contents';
export * from './HelpField';
export * from './HelpMenu';
export * from './HelpContext';
export * from './HelpTextExpandedContext';
export * from './help.contents';
export * from './helpContents.registry';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { HelpContextProvider } from 'core/help';
import { HelpTextExpandedContext } from 'core/help';
import { ValidationMessage } from 'core/validation';

import { IFieldLayoutProps } from '../interface';
Expand All @@ -15,7 +15,7 @@ export class ResponsiveFieldLayout extends React.Component<IFieldLayoutProps> {
const helpUnder = false;

return (
<HelpContextProvider value={helpUnder}>
<HelpTextExpandedContext.Provider value={helpUnder}>
<div className="sp-formItem">
<div className="sp-formItem__left">
{showLabel && (
Expand All @@ -34,7 +34,7 @@ export class ResponsiveFieldLayout extends React.Component<IFieldLayoutProps> {
{validationMessage && <ValidationMessage type={validationStatus} message={validationMessage} />}
</div>
</div>
</HelpContextProvider>
</HelpTextExpandedContext.Provider>
);
}
}

0 comments on commit 5c3fcc7

Please sign in to comment.