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/inline help a11y #43960

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
2731bf2
inline-help: add admin sections file
retrofox Jun 30, 2020
eda83fc
inline-help: use simple quotes instead of `
retrofox Jun 30, 2020
c134f27
inline-help: add new admin items. tidy code.
retrofox Jun 30, 2020
3ea4ace
inline-help: add a selector for admin sections
retrofox Jun 30, 2020
2e833f5
inline-help: add unit test for real search term
retrofox Jun 30, 2020
22d2937
inline-help: tidy code
retrofox Jun 30, 2020
2916619
inline-help: tidy code
retrofox Jun 30, 2020
de9861f
inline-help: move admin helper function to cmp
retrofox Jul 2, 2020
e123ca0
inline-help: add unit tests for admin sections
retrofox Jul 2, 2020
66c264e
inline-help: formcat code. tidy.
retrofox Jul 2, 2020
aa2fec5
inline-help: remove duplicated test
retrofox Jul 2, 2020
d7586d2
inline-help: fixing link errors
retrofox Jul 2, 2020
26e410f
inline-help: add site icon help
retrofox Jul 6, 2020
7e8c9ab
Update client/blocks/inline-help/admin-sections.js
retrofox Jul 6, 2020
18fb454
Update client/blocks/inline-help/admin-sections.js
retrofox Jul 6, 2020
fb57c78
Update client/blocks/inline-help/admin-sections.js
retrofox Jul 6, 2020
65530f8
inline-help: format code
retrofox Jul 7, 2020
bb0e5d9
inline-help: early return if term is empty
retrofox Jul 7, 2020
88f3109
Generalise limit description
frontdevde Jul 7, 2020
a76d893
Simplify check for searchTermWords value
frontdevde Jul 7, 2020
9131eca
Add default arg to siteSlug
frontdevde Jul 7, 2020
e214f34
Rename test file to match admin-sections.js
frontdevde Jul 7, 2020
edfe790
Change test descriptions to use natural language
frontdevde Jul 7, 2020
b964f15
inine-help: add synonyms to admin sections
retrofox Jul 7, 2020
4520d47
inline-help: store all support links in the store
retrofox Jul 2, 2020
e520373
inline-help: add support_type to contextual links
retrofox Jul 2, 2020
05d92a7
inline-help: add support_type to admin links
retrofox Jul 2, 2020
fca1886
inline-help: add icon to item if it's defined
retrofox Jul 2, 2020
61d1ce7
inline-help: add admin results selector
retrofox Jul 2, 2020
c57a409
inline-help: add tests for admin results selector
retrofox Jul 2, 2020
93813b9
inline-help: add contextual results selector`
retrofox Jul 2, 2020
af950a0
inline-help: add test for contextual selector
retrofox Jul 2, 2020
c040249
inline-help: add API results selector
retrofox Jul 2, 2020
bc83c2e
inline-help: add test for API results selector
retrofox Jul 2, 2020
2b9f26f
inline-help: render contextual and api results
retrofox Jul 2, 2020
c517b02
inline-help: chane no results error
retrofox Jul 2, 2020
69b3681
inline-help: wrap each results
retrofox Jul 2, 2020
f44a1b5
inline-help: add results section title
retrofox Jul 2, 2020
9419c09
inline-help: add selector to show results
retrofox Jul 2, 2020
d261e7d
inline-help: simplify using results ui seector
retrofox Jul 2, 2020
6a9c24d
inline-help: update selected result value
retrofox Jul 2, 2020
4f9eb92
inline-help: map support_type in admin sections
retrofox Jul 6, 2020
e7ae0ba
inline-help: handle internal links
retrofox Jul 6, 2020
8516cb8
inline-help: assing properly component key
retrofox Jul 6, 2020
7973095
inline-help: rename prop to onSelect
retrofox Jul 6, 2020
8f21143
help-search: pick up selected item from state
retrofox Jul 6, 2020
3dc08b5
inline-help: set current by mousedown
retrofox Jul 6, 2020
c885c99
inline-help: remove unused second argument
retrofox Jul 6, 2020
da88482
inline-help: handle admin section form search card
retrofox Jul 6, 2020
75e7b16
inline-help: populate state with result items
retrofox Jul 6, 2020
0373632
inline-help: use search results selector
retrofox Jul 6, 2020
a34d72d
inline-help: remove uneeded selectors
retrofox Jul 6, 2020
823e74b
inline-help: simplify current item action
retrofox Jul 6, 2020
372de3d
inline-help: add const to define support types
retrofox Jul 6, 2020
1171319
inline-help: adjust results header style
retrofox Jul 6, 2020
dd3da75
inline-help: tweak admin section icon
retrofox Jul 6, 2020
cf778f4
inline-help: adjust empty results style
retrofox Jul 6, 2020
a5ae302
inline-help: add chevron to admin section links
retrofox Jul 6, 2020
d9c143e
inline-help: consolidate icon styles between cmps
retrofox Jul 6, 2020
e965f64
inline-help: retain query search
retrofox Jul 6, 2020
2afc152
inline-help: cast selectedResult prop
retrofox Jul 6, 2020
63f53a4
inline-help: handle internal links properly
retrofox Jul 6, 2020
84e9bb7
inline-help: dealing with external links
retrofox Jul 6, 2020
9ea3d0f
inline-help: pipck 3 admin links as max
retrofox Jul 6, 2020
40730b9
inline: set support type in the action
retrofox Jul 6, 2020
865b5bf
inline-help: format code
retrofox Jul 7, 2020
f99adea
inline-help: revert chnages in nav results items
retrofox Jul 7, 2020
1f5d61b
inline-help: remove unused selectors
retrofox Jul 7, 2020
b3ab872
inline-help: remove unused dependencies
retrofox Jul 7, 2020
8050e1c
inline-help: tidy reducer. add helper function.
retrofox Jul 7, 2020
4f859a4
inline-help: format code
retrofox Jul 7, 2020
7f38c4c
inline-help: remove colon form translated strings
retrofox Jul 7, 2020
7d06707
inline-help: remove comment block
retrofox Jul 7, 2020
2f33228
inline-help: format code
retrofox Jul 7, 2020
d092524
inline-help: set colon by CSS
retrofox Jul 7, 2020
c96a177
inline-help: set admin results to 3
retrofox Jul 7, 2020
5dbc09d
inline-help: set customizer URL properly
retrofox Jul 7, 2020
970e926
inline-help: update unit tests
retrofox Jul 7, 2020
634ed0b
Reformat inline search help HTML
jeryj Jul 7, 2020
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
436 changes: 436 additions & 0 deletions client/blocks/inline-help/admin-sections.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions client/blocks/inline-help/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export const VIEW_CONTACT = 'contact';
export const VIEW_RICH_RESULT = 'richresult';
export const VIEW_FORUM = 'forums';
export const SUPPORT_BLOG_ID = 9619154;

export const SUPPORT_TYPE_CONTEXTUAL_HELP = 'contextual_help';
export const SUPPORT_TYPE_API_HELP = 'api_help';
export const SUPPORT_TYPE_ADMIN_SECTION = 'admin_section';
38 changes: 31 additions & 7 deletions client/blocks/inline-help/inline-help-search-card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { localize } from 'i18n-calypso';
import { identity, includes } from 'lodash';
import page from 'page';
import debugFactory from 'debug';

/**
Expand All @@ -22,6 +23,7 @@ import {
selectNextResult,
selectPreviousResult,
} from 'state/inline-help/actions';
import { SUPPORT_TYPE_ADMIN_SECTION } from './constants';

/**
* Module variables
Expand All @@ -30,17 +32,19 @@ const debug = debugFactory( 'calypso:inline-help' );

class InlineHelpSearchCard extends Component {
static propTypes = {
openResult: PropTypes.func.isRequired,
onSelect: PropTypes.func.isRequired,
translate: PropTypes.func,
query: PropTypes.string,
placeholder: PropTypes.string,
location: PropTypes.string,
selectedResult: PropTypes.object,
};

static defaultProps = {
translate: identity,
query: '',
location: 'inline-help-popover',
selectedResult: {},
};

constructor() {
Expand Down Expand Up @@ -69,8 +73,32 @@ class InlineHelpSearchCard extends Component {
this.props.selectNextResult();
break;
case 'Enter': {
const hasSelection = this.props.selectedResultIndex >= 0;
hasSelection && this.props.openResult( event, this.props.selectedResult );
const {
selectedResultIndex,
selectedResult,
query,
onSelect,
recordTracksEvent,
} = this.props;

// check and catch admin section links.
const { support_type: supportType, link } = selectedResult;
if ( supportType === SUPPORT_TYPE_ADMIN_SECTION && link ) {
recordTracksEvent( 'calypso_inlinehelp_admin_section_search', {
link: link,
search_term: query,
} );
// push state only if it's internal link.
if ( ! /^http/.test( link ) ) {
event.preventDefault();
return page( link );
} else {
// redirect external links.
return ( window.location.href = link );
}
}

selectedResultIndex >= 0 && onSelect( event );
break;
}
}
Expand All @@ -91,10 +119,6 @@ class InlineHelpSearchCard extends Component {
this.props.setInlineHelpSearchQuery( searchQuery );
};

componentDidMount() {
this.props.setInlineHelpSearchQuery( '' );
}

render() {
return (
<SearchCard
Expand Down
152 changes: 130 additions & 22 deletions client/blocks/inline-help/inline-help-search-results.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/**
* External dependencies
*/
import React from 'react';
import React, { useRef, Fragment } from 'react';
import PropTypes from 'prop-types';
import { identity, isEmpty } from 'lodash';
import { connect } from 'react-redux';
import { localize } from 'i18n-calypso';
import classNames from 'classnames';
import Gridicon from 'gridicons';
import page from 'page';

/**
* Internal Dependencies
Expand All @@ -15,61 +17,165 @@ import { recordTracksEvent } from 'state/analytics/actions';
import QueryInlineHelpSearch from 'components/data/query-inline-help-search';
import PlaceholderLines from './placeholder-lines';
import { decodeEntities, preventWidows } from 'lib/formatting';
import getInlineHelpSearchResultsForQuery from 'state/inline-help/selectors/get-inline-help-search-results-for-query';
import getSearchResultsByQuery from 'state/inline-help/selectors/get-inline-help-search-results-for-query';
import getSelectedResultIndex from 'state/inline-help/selectors/get-selected-result-index';
import getInlineHelpCurrentlySelectedResult from 'state/inline-help/selectors/get-inline-help-currently-selected-result';
import isRequestingInlineHelpSearchResultsForQuery from 'state/inline-help/selectors/is-requesting-inline-help-search-results-for-query';
import hasInlineHelpAPIResults from 'state/selectors/has-inline-help-api-results';
import { selectResult } from 'state/inline-help/actions';
import { localizeUrl } from 'lib/i18n-utils';
import { SUPPORT_TYPE_ADMIN_SECTION, SUPPORT_TYPE_API_HELP } from './constants';

function HelpSearchResults( {
hasAPIResults = false,
isSearching = false,
openResult,
onSelect,
searchQuery = '',
searchResults,
searchResults = [],
selectedResult = {},
selectedResultIndex = -1,
selectSearchResult,
translate = identity,
placeholderLines,
recordTracksEvent,
} ) {
const selectResultHandler = ( selectionIndex ) => ( event ) => {
const selectedResult = searchResults?.[ selectionIndex ] ?? null;
selectSearchResult( selectionIndex );
openResult( event, selectedResult );
const supportType = useRef( searchResults?.[ 0 ]?.support_type );

function getTitleBySectionType( type ) {
let title = '';
switch ( type ) {
case SUPPORT_TYPE_API_HELP:
title = translate( 'Support articles' );
break;
case SUPPORT_TYPE_ADMIN_SECTION:
title = translate( 'Show me where to' );
break;
default:
return null;
}

return title;
}

const onLinkClickHandler = ( event ) => {
const { support_type: supportType, link } = selectedResult;

// check and catch admin section links.
if ( supportType === SUPPORT_TYPE_ADMIN_SECTION && link ) {
// record track-event.
recordTracksEvent( 'calypso_inlinehelp_admin_section_search', {
link: link,
search_term: searchQuery,
} );

// push state only if it's internal link.
if ( ! /^http/.test( link ) ) {
event.preventDefault();
return page( link );
} else {
// default behavior for external links.
return;
}
}

// Set the current selected result item.
onSelect( event );
};

const renderHelpLink = ( { link, key, description, title }, index ) => {
const selectCurrentResultIndex = ( index ) => () => selectSearchResult( index );

const renderHelpLink = (
{ link, key, description, title, support_type = SUPPORT_TYPE_API_HELP },
index
) => {
const addResultsSection = supportType?.current !== support_type || ! index;
if ( addResultsSection ) {
supportType.current = support_type;
}

const classes = classNames( 'inline-help__results-item', {
'is-selected': selectedResultIndex === index,
} );

return (
<li key={ link ?? key } className={ classes }>
<a
href={ localizeUrl( link ) }
onClick={ selectResultHandler( index ) }
title={ decodeEntities( description ) }
tabIndex={ -1 }
<Fragment key={ link ?? key }>
<li role="row" className={ classes }>
<span role="gridcell">
<a
href={ localizeUrl( link ) }
onMouseDown={ selectCurrentResultIndex( index ) }
onClick={ onLinkClickHandler }
tabIndex={ -1 }
>
{ support_type === SUPPORT_TYPE_ADMIN_SECTION && (
<Gridicon icon="domains" size={ 18 } />
) }
<span>{ preventWidows( decodeEntities( title ) ) }</span>
{ support_type === SUPPORT_TYPE_ADMIN_SECTION && (
<Gridicon icon="chevron-right" size={ 18 } />
) }
</a>
</span>
</li>
</Fragment>
);
};

const renderSearchResultsSection = ( id, title, results ) => {
/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */
return (
<Fragment key={ id }>
{ title ? <h3 id={ id }> { title }</h3> : null }
<ul
role="grid"
className="inline-help__results-list"
aria-labelledby={ title ? id : undefined }
>
{ preventWidows( decodeEntities( title ) ) }
</a>
</li>
{ results.map( renderHelpLink ) }
</ul>
</Fragment>
);
/* eslint-enable jsx-a11y/no-noninteractive-element-to-interactive-role */
};

const renderSearchSections = ( results ) => {
// Get the unique result types
// TODO: Clean this up. There has to be a simpler way to find the unique search result types
const searchResultTypes = results
.map( ( searchResult ) => searchResult.support_type )
.filter( ( type, index, arr ) => arr.indexOf( type ) === index );

return searchResultTypes.map( ( resultType ) => {
return renderSearchResultsSection(
`inline-search--${ resultType }`,
getTitleBySectionType( resultType ),
results.filter( ( r ) => r.support_type === resultType )
);
} );
};

const renderSearchResults = () => {
if ( isSearching ) {
// reset current section reference.
supportType.current = null;

// search, but no results so far
return <PlaceholderLines lines={ placeholderLines } />;
}

return (
<>
{ ! isEmpty( searchQuery ) && ! hasAPIResults && (
<p className="inline-help__empty-results">{ translate( 'No results.' ) }</p>
<p className="inline-help__empty-results">
{ translate(
'Sorry, there were no matches. Here are some of the most searched for help pages for this section:'
) }
</p>
) }
<ul className="inline-help__results-list">{ searchResults.map( renderHelpLink ) }</ul>

<div aria-label={ translate( 'Search Results' ) }>
{ renderSearchSections( searchResults ) }
</div>
</>
);
};
Expand All @@ -85,19 +191,21 @@ function HelpSearchResults( {
HelpSearchResults.propTypes = {
translate: PropTypes.func,
searchQuery: PropTypes.string,
openResult: PropTypes.func.isRequired,
onSelect: PropTypes.func.isRequired,
hasAPIResults: PropTypes.bool,
searchResults: PropTypes.array,
selectedResultIndex: PropTypes.number,
isSearching: PropTypes.bool,
selectedResult: PropTypes.object,
};

export default connect(
( state, ownProps ) => ( {
searchResults: getInlineHelpSearchResultsForQuery( state ),
searchResults: getSearchResultsByQuery( state ),
isSearching: isRequestingInlineHelpSearchResultsForQuery( state, ownProps.searchQuery ),
selectedResultIndex: getSelectedResultIndex( state ),
hasAPIResults: hasInlineHelpAPIResults( state ),
selectedResult: getInlineHelpCurrentlySelectedResult( state ),
} ),
{
recordTracksEvent,
Expand Down
7 changes: 2 additions & 5 deletions client/blocks/inline-help/popover.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,9 @@ class InlineHelpPopover extends Component {
<Fragment>
<QuerySupportTypes />
<div className="inline-help__search">
<InlineHelpSearchCard
openResult={ this.openResultView }
query={ this.props.searchQuery }
/>
<InlineHelpSearchCard onSelect={ this.openResultView } query={ this.props.searchQuery } />
<InlineHelpSearchResults
openResult={ this.openResultView }
onSelect={ this.openResultView }
searchQuery={ this.props.searchQuery }
/>
</div>
Expand Down
Loading