Unverified Commit 2718eb5f authored by Marcos Iglesias's avatar Marcos Iglesias Committed by GitHub

fix: Fixes sectioning and accessibility issues all over the application (#480)

* Adds alt attribute to images

* Uses time tags on times on the application

* Dealing with sectioning and accessibility issues

* Formatting

* Fixing stuff

* Tamika's comments

* Fixing tests

* Fixing watermark label size

* Tamika's comments

* Tweaks

* More tweaks
parent adf52564
...@@ -185,3 +185,17 @@ body { ...@@ -185,3 +185,17 @@ body {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
// Text for Screen Readers only
// Reference: Bootstrap 4 codebase
.sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
...@@ -52,17 +52,19 @@ export class AnnouncementPage extends React.Component<AnnouncementPageProps> { ...@@ -52,17 +52,19 @@ export class AnnouncementPage extends React.Component<AnnouncementPageProps> {
render() { render() {
return ( return (
<DocumentTitle title="Announcements - Amundsen"> <DocumentTitle title="Announcements - Amundsen">
<div className="container announcement-container"> <main className="container announcement-container">
<div className="row"> <div className="row">
<div className="col-xs-12"> <div className="col-xs-12">
<h3 id="announcement-header">Announcements</h3> <h1 id="announcement-header" className="h3">
Announcements
</h1>
<hr /> <hr />
<div id="announcement-content" className="announcement-content"> <div id="announcement-content" className="announcement-content">
{this.createPosts()} {this.createPosts()}
</div> </div>
</div> </div>
</div> </div>
</div> </main>
</DocumentTitle> </DocumentTitle>
); );
} }
......
...@@ -7,15 +7,17 @@ export class BrowsePage extends React.Component { ...@@ -7,15 +7,17 @@ export class BrowsePage extends React.Component {
render() { render() {
return ( return (
<DocumentTitle title="Browse - Amundsen"> <DocumentTitle title="Browse - Amundsen">
<div className="container"> <main className="container">
<div className="row"> <div className="row">
<div className="col-xs-12"> <div className="col-xs-12">
<h3 id="browse-header">Browse Tags</h3> <h1 className="h3" id="browse-header">
Browse Tags
</h1>
<hr className="header-hr" /> <hr className="header-hr" />
<TagsList /> <TagsList />
</div> </div>
</div> </div>
</div> </main>
</DocumentTitle> </DocumentTitle>
); );
} }
......
...@@ -2,6 +2,7 @@ export const ERROR_MESSAGE = ...@@ -2,6 +2,7 @@ export const ERROR_MESSAGE =
'Unable to load the dashboard preview image. \ 'Unable to load the dashboard preview image. \
Please view the dashboard at'; Please view the dashboard at';
export const PREVIEW_BUTTON_TEXT = 'See Dashboard Preview';
export const PREVIEW_BASE = '/api/dashboard_preview/v0/dashboard'; export const PREVIEW_BASE = '/api/dashboard_preview/v0/dashboard';
export const PREVIEW_END = 'preview.jpg'; export const PREVIEW_END = 'preview.jpg';
......
...@@ -43,7 +43,7 @@ const PreviewModal = ({ imageSrc, onClose }: PreviewModalProps) => { ...@@ -43,7 +43,7 @@ const PreviewModal = ({ imageSrc, onClose }: PreviewModalProps) => {
</Modal.Title> </Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<img src={imageSrc} height="auto" width="100%" /> <img src={imageSrc} height="auto" width="100%" alt="" />
</Modal.Body> </Modal.Body>
</Modal> </Modal>
); );
...@@ -89,6 +89,7 @@ export class ImagePreview extends React.Component< ...@@ -89,6 +89,7 @@ export class ImagePreview extends React.Component<
type="button" type="button"
onClick={this.handlePreviewButton} onClick={this.handlePreviewButton}
> >
<span className="sr-only">{Constants.PREVIEW_BUTTON_TEXT}</span>
<img <img
className="preview" className="preview"
style={ style={
...@@ -99,6 +100,7 @@ export class ImagePreview extends React.Component< ...@@ -99,6 +100,7 @@ export class ImagePreview extends React.Component<
onError={this.onError} onError={this.onError}
height="auto" height="auto"
width="100%" width="100%"
alt=""
/> />
</button> </button>
)} )}
......
import * as React from 'react'; import * as React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import { ResourceType } from 'interfaces';
import QueryList, { QueryListProps } from '.'; import QueryList, { QueryListProps } from '.';
import QueryListItem from '../QueryListItem'; import QueryListItem from '../QueryListItem';
import { ResourceType } from 'interfaces';
const setup = (propOverrides?: Partial<QueryListProps>) => { const setup = (propOverrides?: Partial<QueryListProps>) => {
const props = { const props = {
queries: [], queries: [],
......
import * as React from 'react'; import * as React from 'react';
import QueryListItem from '../QueryListItem';
import { QueryResource } from 'interfaces'; import { QueryResource } from 'interfaces';
import QueryListItem from '../QueryListItem';
import './styles.scss'; import './styles.scss';
...@@ -26,7 +25,11 @@ class QueryList extends React.Component<QueryListProps> { ...@@ -26,7 +25,11 @@ class QueryList extends React.Component<QueryListProps> {
/> />
)); ));
return <ul className="query-list list-group">{queryList}</ul>; return (
<ul className="query-list list-group" role="tablist">
{queryList}
</ul>
);
} }
} }
......
...@@ -168,7 +168,7 @@ export class DashboardPage extends React.Component< ...@@ -168,7 +168,7 @@ export class DashboardPage extends React.Component<
/> />
</div> </div>
<div className="header-section header-title"> <div className="header-section header-title">
<h3 className="header-title-text truncated">{dashboard.name}</h3> <h1 className="h3 header-title-text truncated">{dashboard.name}</h1>
<BookmarkIcon <BookmarkIcon
bookmarkKey={dashboard.uri} bookmarkKey={dashboard.uri}
resourceType={ResourceType.dashboard} resourceType={ResourceType.dashboard}
...@@ -203,7 +203,7 @@ export class DashboardPage extends React.Component< ...@@ -203,7 +203,7 @@ export class DashboardPage extends React.Component<
</div> </div>
</header> </header>
<article className="column-layout-1"> <article className="column-layout-1">
<section className="left-panel"> <aside className="left-panel">
<EditableSection <EditableSection
title="Description" title="Description"
readOnly readOnly
...@@ -257,19 +257,19 @@ export class DashboardPage extends React.Component< ...@@ -257,19 +257,19 @@ export class DashboardPage extends React.Component<
</section> </section>
<section className="metadata-section"> <section className="metadata-section">
<div className="section-title title-3">Created</div> <div className="section-title title-3">Created</div>
<div className="body-2 text-primary"> <time className="body-2 text-primary">
{formatDateTimeShort({ {formatDateTimeShort({
epochTimestamp: dashboard.created_timestamp, epochTimestamp: dashboard.created_timestamp,
})} })}
</div> </time>
</section> </section>
<section className="metadata-section"> <section className="metadata-section">
<div className="section-title title-3">Last Updated</div> <div className="section-title title-3">Last Updated</div>
<div className="body-2 text-primary"> <time className="body-2 text-primary">
{formatDateTimeShort({ {formatDateTimeShort({
epochTimestamp: dashboard.updated_timestamp, epochTimestamp: dashboard.updated_timestamp,
})} })}
</div> </time>
</section> </section>
<section className="metadata-section"> <section className="metadata-section">
<div className="section-title title-3">Recent View Count</div> <div className="section-title title-3">Recent View Count</div>
...@@ -289,25 +289,25 @@ export class DashboardPage extends React.Component< ...@@ -289,25 +289,25 @@ export class DashboardPage extends React.Component<
<div className="section-title title-3"> <div className="section-title title-3">
Last Successful Run Last Successful Run
</div> </div>
<div className="last-successful-run-timestamp body-2 text-primary"> <time className="last-successful-run-timestamp body-2 text-primary">
{dashboard.last_successful_run_timestamp {dashboard.last_successful_run_timestamp
? formatDateTimeShort({ ? formatDateTimeShort({
epochTimestamp: epochTimestamp:
dashboard.last_successful_run_timestamp, dashboard.last_successful_run_timestamp,
}) })
: NO_TIMESTAMP_TEXT} : NO_TIMESTAMP_TEXT}
</div> </time>
</section> </section>
<section className="metadata-section"> <section className="metadata-section">
<div className="section-title title-3">Last Run</div> <div className="section-title title-3">Last Run</div>
<div> <div>
<div className="last-run-timestamp body-2 text-primary"> <time className="last-run-timestamp body-2 text-primary">
{dashboard.last_run_timestamp {dashboard.last_run_timestamp
? formatDateTimeShort({ ? formatDateTimeShort({
epochTimestamp: dashboard.last_run_timestamp, epochTimestamp: dashboard.last_run_timestamp,
}) })
: NO_TIMESTAMP_TEXT} : NO_TIMESTAMP_TEXT}
</div> </time>
<div className="last-run-state"> <div className="last-run-state">
<Flag <Flag
caseType="sentenceCase" caseType="sentenceCase"
...@@ -322,8 +322,8 @@ export class DashboardPage extends React.Component< ...@@ -322,8 +322,8 @@ export class DashboardPage extends React.Component<
</section> </section>
</section> </section>
<ImagePreview uri={this.state.uri} redirectUrl={dashboard.url} /> <ImagePreview uri={this.state.uri} redirectUrl={dashboard.url} />
</section> </aside>
<section className="right-panel">{this.renderTabs()}</section> <main className="right-panel">{this.renderTabs()}</main>
</article> </article>
</div> </div>
); );
......
...@@ -17,7 +17,7 @@ import { ...@@ -17,7 +17,7 @@ import {
} from 'components/Feedback/constants'; } from 'components/Feedback/constants';
import globalState from 'fixtures/globalState'; import globalState from 'fixtures/globalState';
import { BugReportFeedbackForm, mapDispatchToProps, mapStateToProps } from '..'; import { BugReportFeedbackForm, mapDispatchToProps, mapStateToProps } from '.';
describe('BugReportFeedbackForm', () => { describe('BugReportFeedbackForm', () => {
const setup = () => { const setup = () => {
......
...@@ -15,7 +15,7 @@ import { ...@@ -15,7 +15,7 @@ import {
} from 'components/Feedback/constants'; } from 'components/Feedback/constants';
import globalState from 'fixtures/globalState'; import globalState from 'fixtures/globalState';
import { RatingFeedbackForm, mapDispatchToProps, mapStateToProps } from '..'; import { RatingFeedbackForm, mapDispatchToProps, mapStateToProps } from '.';
describe('RatingFeedbackForm', () => { describe('RatingFeedbackForm', () => {
const setup = () => { const setup = () => {
......
...@@ -34,8 +34,8 @@ export class RatingFeedbackForm extends AbstractFeedbackForm { ...@@ -34,8 +34,8 @@ export class RatingFeedbackForm extends AbstractFeedbackForm {
return ( return (
<form id={AbstractFeedbackForm.FORM_ID} onSubmit={this.submitForm}> <form id={AbstractFeedbackForm.FORM_ID} onSubmit={this.submitForm}>
<input type="hidden" name="feedback-type" value="NPS Rating" /> <input type="hidden" name="feedback-type" value="NPS Rating" />
<div className="form-group"> <div className="form-group clearfix">
<label>{RATING_LABEL}</label> <label htmlFor="rating">{RATING_LABEL}</label>
<div> <div>
<div className="radio-set">{radioButtonSet}</div> <div className="radio-set">{radioButtonSet}</div>
<div> <div>
...@@ -48,14 +48,19 @@ export class RatingFeedbackForm extends AbstractFeedbackForm { ...@@ -48,14 +48,19 @@ export class RatingFeedbackForm extends AbstractFeedbackForm {
</div> </div>
</div> </div>
</div> </div>
<textarea <div className="form-group">
className="form-control form-group" <label htmlFor="comment">{COMMENTS_PLACEHOLDER}</label>
name="comment" <textarea
form={AbstractFeedbackForm.FORM_ID} className="form-control form-group"
rows={8} name="comment"
maxLength={2000} id="comment"
placeholder={COMMENTS_PLACEHOLDER} form={AbstractFeedbackForm.FORM_ID}
/> rows={8}
maxLength={2000}
placeholder={COMMENTS_PLACEHOLDER}
/>
</div>
<button className="btn btn-primary" type="submit"> <button className="btn btn-primary" type="submit">
{SUBMIT_TEXT} {SUBMIT_TEXT}
</button> </button>
......
...@@ -17,7 +17,7 @@ import { ...@@ -17,7 +17,7 @@ import {
} from 'components/Feedback/constants'; } from 'components/Feedback/constants';
import globalState from 'fixtures/globalState'; import globalState from 'fixtures/globalState';
import { RequestFeedbackForm, mapDispatchToProps, mapStateToProps } from '..'; import { RequestFeedbackForm, mapDispatchToProps, mapStateToProps } from '.';
describe('RequestFeedbackForm', () => { describe('RequestFeedbackForm', () => {
const setup = () => { const setup = () => {
......
...@@ -9,6 +9,7 @@ export const SUBMIT_SUCCESS_MESSAGE = ...@@ -9,6 +9,7 @@ export const SUBMIT_SUCCESS_MESSAGE =
/* Button Set */ /* Button Set */
export const BUG_REPORT_TEXT = 'Bug Report'; export const BUG_REPORT_TEXT = 'Bug Report';
export const FEEDBACK_BUTTON_TEXT = 'Give us Feedback';
export const FEEDBACK_TYPE_TEXT = 'Feedback Type Selector'; export const FEEDBACK_TYPE_TEXT = 'Feedback Type Selector';
export const RATING_TEXT = 'Rating'; export const RATING_TEXT = 'Rating';
export const REQUEST_TEXT = 'Request'; export const REQUEST_TEXT = 'Request';
......
...@@ -7,6 +7,7 @@ import RequestFeedbackForm from './FeedbackForm/RequestFeedbackForm'; ...@@ -7,6 +7,7 @@ import RequestFeedbackForm from './FeedbackForm/RequestFeedbackForm';
import { import {
BUG_REPORT_TEXT, BUG_REPORT_TEXT,
FEEDBACK_BUTTON_TEXT,
BUTTON_CLOSE_TEXT, BUTTON_CLOSE_TEXT,
FEEDBACK_TITLE, FEEDBACK_TITLE,
FEEDBACK_TYPE_TEXT, FEEDBACK_TYPE_TEXT,
...@@ -81,7 +82,8 @@ export default class Feedback extends React.Component< ...@@ -81,7 +82,8 @@ export default class Feedback extends React.Component<
}`} }`}
onClick={this.toggle} onClick={this.toggle}
> >
<img className="icon icon-help" /> <span className="sr-only">{FEEDBACK_BUTTON_TEXT}</span>
<img className="icon icon-help" alt="" />
</button> </button>
{this.state.isOpen && ( {this.state.isOpen && (
<div className="feedback-component"> <div className="feedback-component">
......
...@@ -37,12 +37,12 @@ export class Footer extends React.Component<FooterProps> { ...@@ -37,12 +37,12 @@ export class Footer extends React.Component<FooterProps> {
); );
} }
return ( return (
<div> <footer>
<div className="phantom-div" /> <div className="phantom-div" />
<div id="footer" className="footer"> <div id="footer" className="footer">
{content} {content}
</div> </div>
</div> </footer>
); );
} }
} }
......
export const SEARCH_BREADCRUMB_TEXT = 'Advanced Search'; export const SEARCH_BREADCRUMB_TEXT = 'Advanced Search';
export const HOMEPAGE_TITLE = 'Amundsen Homepage';
...@@ -13,7 +13,7 @@ import { resetSearchState } from 'ducks/search/reducer'; ...@@ -13,7 +13,7 @@ import { resetSearchState } from 'ducks/search/reducer';
import { UpdateSearchStateReset } from 'ducks/search/types'; import { UpdateSearchStateReset } from 'ducks/search/types';
import SearchBar from 'components/common/SearchBar'; import SearchBar from 'components/common/SearchBar';
import TagsList from 'components/common/TagsList'; import TagsList from 'components/common/TagsList';
import { SEARCH_BREADCRUMB_TEXT } from './constants'; import { SEARCH_BREADCRUMB_TEXT, HOMEPAGE_TITLE } from './constants';
export interface DispatchFromProps { export interface DispatchFromProps {
searchReset: () => UpdateSearchStateReset; searchReset: () => UpdateSearchStateReset;
...@@ -28,9 +28,10 @@ export class HomePage extends React.Component<HomePageProps> { ...@@ -28,9 +28,10 @@ export class HomePage extends React.Component<HomePageProps> {
render() { render() {
return ( return (
<div className="container home-page"> <main className="container home-page">
<div className="row"> <div className="row">
<div className="col-xs-12 col-md-offset-1 col-md-10"> <div className="col-xs-12 col-md-offset-1 col-md-10">
<h1 className="sr-only">{HOMEPAGE_TITLE}</h1>
<SearchBar /> <SearchBar />
<div className="filter-breadcrumb pull-right"> <div className="filter-breadcrumb pull-right">
<Breadcrumb <Breadcrumb
...@@ -56,7 +57,7 @@ export class HomePage extends React.Component<HomePageProps> { ...@@ -56,7 +57,7 @@ export class HomePage extends React.Component<HomePageProps> {
</div> </div>
</div> </div>
</div> </div>
</div> </main>
); );
} }
} }
......
...@@ -69,7 +69,7 @@ export class NavBar extends React.Component<NavBarProps> { ...@@ -69,7 +69,7 @@ export class NavBar extends React.Component<NavBarProps> {
render() { render() {
return ( return (
<div className="container-fluid"> <nav className="container-fluid">
<div className="row"> <div className="row">
<div className="nav-bar"> <div className="nav-bar">
<div id="nav-bar-left" className="nav-bar-left"> <div id="nav-bar-left" className="nav-bar-left">
...@@ -79,6 +79,7 @@ export class NavBar extends React.Component<NavBarProps> { ...@@ -79,6 +79,7 @@ export class NavBar extends React.Component<NavBarProps> {
id="logo-icon" id="logo-icon"
className="logo-icon" className="logo-icon"
src={AppConfig.logoPath} src={AppConfig.logoPath}
alt=""
/> />
)} )}
<span className="title-3">AMUNDSEN</span> <span className="title-3">AMUNDSEN</span>
...@@ -130,7 +131,7 @@ export class NavBar extends React.Component<NavBarProps> { ...@@ -130,7 +131,7 @@ export class NavBar extends React.Component<NavBarProps> {
</div> </div>
</div> </div>
</div> </div>
</div> </nav>
); );
} }
} }
......
...@@ -12,7 +12,7 @@ const NotFoundPage: React.SFC<any> = () => { ...@@ -12,7 +12,7 @@ const NotFoundPage: React.SFC<any> = () => {
<div className="container not-found-page"> <div className="container not-found-page">
<Breadcrumb path="/" text="Home" /> <Breadcrumb path="/" text="Home" />
<h1>404 Page Not Found</h1> <h1>404 Page Not Found</h1>
<img className="icon icon-alert" /> <img className="icon icon-alert" alt="" />
</div> </div>
</DocumentTitle> </DocumentTitle>
); );
......
...@@ -192,7 +192,7 @@ export class ProfilePage extends React.Component< ...@@ -192,7 +192,7 @@ export class ProfilePage extends React.Component<
const { user } = this.props; const { user } = this.props;
return ( return (
<DocumentTitle title={`${user.display_name} - Amundsen Profile`}> <DocumentTitle title={`${user.display_name} - Amundsen Profile`}>
<div className="resource-detail-layout profile-page"> <main className="resource-detail-layout profile-page">
<header className="resource-header"> <header className="resource-header">
<div className="header-section"> <div className="header-section">
<Breadcrumb /> <Breadcrumb />
...@@ -204,7 +204,7 @@ export class ProfilePage extends React.Component< ...@@ -204,7 +204,7 @@ export class ProfilePage extends React.Component<
</div> </div>
<div className="header-section header-title"> <div className="header-section header-title">
<h3 className="header-title-text truncated"> <h1 className="h3 header-title-text truncated">
{user.display_name} {user.display_name}
{!user.is_active && ( {!user.is_active && (
<Flag <Flag
...@@ -213,7 +213,7 @@ export class ProfilePage extends React.Component< ...@@ -213,7 +213,7 @@ export class ProfilePage extends React.Component<
text="Alumni" text="Alumni"
/> />
)} )}
</h3> </h1>
<div className="body-3"> <div className="body-3">
<ul className="header-bullets"> <ul className="header-bullets">
{user.role_name && <li id="user-role">{user.role_name}</li>} {user.role_name && <li id="user-role">{user.role_name}</li>}
...@@ -241,7 +241,7 @@ export class ProfilePage extends React.Component< ...@@ -241,7 +241,7 @@ export class ProfilePage extends React.Component<
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
> >
<img className="icon icon-dark icon-mail" /> <img className="icon icon-dark icon-mail" alt="" />
<span className="email-link-label body-2">{user.email}</span> <span className="email-link-label body-2">{user.email}</span>
</a> </a>
)} )}
...@@ -267,19 +267,19 @@ export class ProfilePage extends React.Component< ...@@ -267,19 +267,19 @@ export class ProfilePage extends React.Component<
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
> >
<img className="icon icon-dark icon-github" /> <img className="icon icon-dark icon-github" alt="" />
<span className="github-link-label body-2">Github</span> <span className="github-link-label body-2">Github</span>
</a> </a>
)} )}
</div> </div>
</header> </header>
<main className="profile-body"> <div className="profile-body">
<TabsComponent <TabsComponent
tabs={this.generateTabInfo()} tabs={this.generateTabInfo()}
defaultTab={this.generateTabKey(ResourceType.table)} defaultTab={this.generateTabKey(ResourceType.table)}
/> />
</main> </div>
</div> </main>
</DocumentTitle> </DocumentTitle>
); );
} }
......
...@@ -68,7 +68,7 @@ export class FilterSection extends React.Component<FilterSectionProps> { ...@@ -68,7 +68,7 @@ export class FilterSection extends React.Component<FilterSectionProps> {
{hasValue && ( {hasValue && (
/* eslint-disable jsx-a11y/anchor-is-valid */ /* eslint-disable jsx-a11y/anchor-is-valid */
<a onClick={this.onClearFilter} className="btn btn-flat-icon"> <a onClick={this.onClearFilter} className="btn btn-flat-icon">
<img className="icon icon-left" /> <img className="icon icon-left" alt="" />
<span>{CLEAR_BTN_TEXT}</span> <span>{CLEAR_BTN_TEXT}</span>
</a> </a>
)} )}
......
...@@ -8,7 +8,7 @@ type SearchPanelProps = { ...@@ -8,7 +8,7 @@ type SearchPanelProps = {
const SearchPanel: React.SFC = ({ children }: SearchPanelProps) => { const SearchPanel: React.SFC = ({ children }: SearchPanelProps) => {
return ( return (
<div className="search-control-panel"> <aside className="search-control-panel">
{React.Children.map(children, (child, index) => { {React.Children.map(children, (child, index) => {
return ( return (
<div key={`search-panel-child:${index}`} className="section"> <div key={`search-panel-child:${index}`} className="section">
...@@ -16,7 +16,7 @@ const SearchPanel: React.SFC = ({ children }: SearchPanelProps) => { ...@@ -16,7 +16,7 @@ const SearchPanel: React.SFC = ({ children }: SearchPanelProps) => {
</div> </div>
); );
})} })}
</div> </aside>
); );
}; };
......
...@@ -6,6 +6,7 @@ export const RESULTS_PER_PAGE = 10; ...@@ -6,6 +6,7 @@ export const RESULTS_PER_PAGE = 10;
// TODO: Hard-coded text strings should be translatable/customizable // TODO: Hard-coded text strings should be translatable/customizable
export const DOCUMENT_TITLE_SUFFIX = ' - Amundsen Search'; export const DOCUMENT_TITLE_SUFFIX = ' - Amundsen Search';
export const SEARCHPAGE_TITLE = 'Amundsen Search';
export const PAGE_INDEX_ERROR_MESSAGE = export const PAGE_INDEX_ERROR_MESSAGE =
'Page index out of bounds for available matches'; 'Page index out of bounds for available matches';
......
...@@ -37,6 +37,7 @@ import { ...@@ -37,6 +37,7 @@ import {
DASHBOARD_RESOURCE_TITLE, DASHBOARD_RESOURCE_TITLE,
TABLE_RESOURCE_TITLE, TABLE_RESOURCE_TITLE,
USER_RESOURCE_TITLE, USER_RESOURCE_TITLE,
SEARCHPAGE_TITLE,
} from './constants'; } from './constants';
export interface StateFromProps { export interface StateFromProps {
...@@ -169,7 +170,10 @@ export class SearchPage extends React.Component<SearchPageProps> { ...@@ -169,7 +170,10 @@ export class SearchPage extends React.Component<SearchPageProps> {
<ResourceSelector /> <ResourceSelector />
<SearchFilter /> <SearchFilter />
</SearchPanel> </SearchPanel>
<div className="search-results">{this.renderContent()}</div> <main className="search-results">
<h1 className="sr-only">{SEARCHPAGE_TITLE}</h1>
{this.renderContent()}
</main>
</div> </div>
); );
if (searchTerm.length > 0) { if (searchTerm.length > 0) {
......
...@@ -14,6 +14,8 @@ import { RequestMetadataType, TableColumn } from 'interfaces'; ...@@ -14,6 +14,8 @@ import { RequestMetadataType, TableColumn } from 'interfaces';
import './styles.scss'; import './styles.scss';
import EditableSection from 'components/common/EditableSection'; import EditableSection from 'components/common/EditableSection';
const MORE_BUTTON_TEXT = 'More options';
interface DispatchFromProps { interface DispatchFromProps {
openRequestDescriptionDialog: ( openRequestDescriptionDialog: (
requestMetadataType: RequestMetadataType, requestMetadataType: RequestMetadataType,
...@@ -149,7 +151,8 @@ export class ColumnListItem extends React.Component< ...@@ -149,7 +151,8 @@ export class ColumnListItem extends React.Component<
className="column-dropdown" className="column-dropdown"
> >
<Dropdown.Toggle noCaret> <Dropdown.Toggle noCaret>
<img className="icon icon-more" /> <span className="sr-only">{MORE_BUTTON_TEXT}</span>
<img className="icon icon-more" alt="" />
</Dropdown.Toggle> </Dropdown.Toggle>
<Dropdown.Menu> <Dropdown.Menu>
<MenuItem onClick={this.openRequest}> <MenuItem onClick={this.openRequest}>
......
...@@ -35,8 +35,8 @@ export function renderReader( ...@@ -35,8 +35,8 @@ export function renderReader(
> >
<Link <Link
className="avatar-overlap" className="avatar-overlap"
id="frequent-users"
onClick={logClick} onClick={logClick}
data-type="frequent-users"
to={link} to={link}
target={target} target={target}
> >
......
...@@ -196,7 +196,7 @@ export class OwnerEditor extends React.Component< ...@@ -196,7 +196,7 @@ export class OwnerEditor extends React.Component<
onClick={() => this.recordDeleteItem(key)} onClick={() => this.recordDeleteItem(key)}
/* tslint:enable */ /* tslint:enable */
> >
<img className="icon icon-delete" /> <img className="icon icon-delete" alt="" />
</button> </button>
</li> </li>
); );
...@@ -268,7 +268,7 @@ export class OwnerEditor extends React.Component< ...@@ -268,7 +268,7 @@ export class OwnerEditor extends React.Component<
className="btn btn-flat-icon add-item-button" className="btn btn-flat-icon add-item-button"
onClick={this.handleShow} onClick={this.handleShow}
> >
<img className="icon icon-plus-circle" /> <img className="icon icon-plus-circle" alt="" />
<span>Add Owner</span> <span>Add Owner</span>
</button> </button>
)} )}
......
...@@ -92,9 +92,9 @@ describe('ReportTableIssue', () => { ...@@ -92,9 +92,9 @@ describe('ReportTableIssue', () => {
const { wrapper } = setup(); const { wrapper } = setup();
const previsOpenState = wrapper.state().isOpen; const previsOpenState = wrapper.state().isOpen;
wrapper wrapper.instance().toggle({
.instance() currentTarget: { id: 'id', nodeName: 'button' },
.toggle({ currentTarget: { id: 'id', nodeName: 'button' } }); });
expect(setStateSpy).toHaveBeenCalledWith({ isOpen: !previsOpenState }); expect(setStateSpy).toHaveBeenCalledWith({ isOpen: !previsOpenState });
}); });
......
...@@ -232,7 +232,7 @@ export class RequestMetadataForm extends React.Component< ...@@ -232,7 +232,7 @@ export class RequestMetadataForm extends React.Component<
className="btn btn-primary submit-request-button" className="btn btn-primary submit-request-button"
type="submit" type="submit"
> >
<img className="icon icon-send" /> <img className="icon icon-send" alt="" />
{SEND_BUTTON} {SEND_BUTTON}
</button> </button>
</form> </form>
...@@ -258,9 +258,11 @@ export const mapStateToProps = (state: GlobalState) => { ...@@ -258,9 +258,11 @@ export const mapStateToProps = (state: GlobalState) => {
tableOwners: Object.keys(ownerObj), tableOwners: Object.keys(ownerObj),
}; };
if (columnName) { if (columnName) {
// eslint-disable-next-line @typescript-eslint/dot-notation
mappedProps['columnName'] = columnName; mappedProps['columnName'] = columnName;
} }
if (requestMetadataType) { if (requestMetadataType) {
// eslint-disable-next-line @typescript-eslint/dot-notation
mappedProps['requestMetadataType'] = requestMetadataType; mappedProps['requestMetadataType'] = requestMetadataType;
} }
return mappedProps; return mappedProps;
......
...@@ -83,9 +83,12 @@ describe('WatermarkLabel', () => { ...@@ -83,9 +83,12 @@ describe('WatermarkLabel', () => {
'2018-08-03', '2018-08-03',
'2019-10-15' '2019-10-15'
); );
expect(mount(watermarkInfo).find('.range-dates').text()).toBe( const watermark = mount(watermarkInfo);
'Aug 03, 2018Oct 15, 2019' const startTime = watermark.find('.date-range-value').at(0).text();
); const endTime = watermark.find('.date-range-value').at(1).text();
expect(startTime).toBe('Aug 03, 2018');
expect(endTime).toBe('Oct 15, 2019');
}); });
}); });
......
...@@ -43,18 +43,24 @@ class WatermarkLabel extends React.Component<WatermarkLabelProps> { ...@@ -43,18 +43,24 @@ class WatermarkLabel extends React.Component<WatermarkLabelProps> {
} }
return ( return (
<> <div className="date-ranges">
<div className="range-labels body-2"> {low && (
{LOW_WATERMARK_LABEL} <p className="date-range body-2">
<br /> <span className="date-range-label">{LOW_WATERMARK_LABEL}</span>
{HIGH_WATERMARK_LABEL} <time className="date-range-value">
</div> {this.formatWatermarkDate(low)}
<div className="range-dates body-2"> </time>
{low && this.formatWatermarkDate(low)} </p>
<br /> )}
{high && this.formatWatermarkDate(high)} {high && (
</div> <p className="date-range body-2">
</> <span className="date-range-label">{HIGH_WATERMARK_LABEL}</span>
<time className="date-range-value">
{this.formatWatermarkDate(high)}
</time>
</p>
)}
</div>
); );
}; };
...@@ -64,7 +70,11 @@ class WatermarkLabel extends React.Component<WatermarkLabelProps> { ...@@ -64,7 +70,11 @@ class WatermarkLabel extends React.Component<WatermarkLabelProps> {
return ( return (
<div className="watermark-label"> <div className="watermark-label">
<img className="range-icon" src="/static/images/watermark-range.png" /> <img
className="range-icon"
src="/static/images/watermark-range.png"
alt=""
/>
{this.renderWatermarkInfo(low, high)} {this.renderWatermarkInfo(low, high)}
</div> </div>
); );
......
@import 'variables'; @import 'variables';
$date-range-label-width: 45px;
.watermark-label { .watermark-label {
display: flex; display: flex;
.range-icon { .range-icon {
flex-basis: 12px; flex-basis: 12px;
height: 40px; height: 40px;
margin-right: 8px; margin-right: $spacer-1;
width: 12px; width: 12px;
margin-top: 2px;
} }
.range-labels { .range-labels {
flex-basis: 42px; flex-basis: 42px;
} }
.date-range {
margin-top: 0;
margin-bottom: $spacer-1/2;
}
.date-range-label {
width: $date-range-label-width;
display: inline-block;
}
.date-range-value {
margin-left: $spacer-1/2;
}
} }
...@@ -180,9 +180,9 @@ export class TableDetail extends React.Component< ...@@ -180,9 +180,9 @@ export class TableDetail extends React.Component<
/> />
</div> </div>
<div className="header-section header-title"> <div className="header-section header-title">
<h3 className="header-title-text truncated"> <h1 className="h3 header-title-text truncated">
{this.getDisplayName()} {this.getDisplayName()}
</h3> </h1>
<BookmarkIcon <BookmarkIcon
bookmarkKey={data.key} bookmarkKey={data.key}
resourceType={ResourceType.table} resourceType={ResourceType.table}
...@@ -208,8 +208,8 @@ export class TableDetail extends React.Component< ...@@ -208,8 +208,8 @@ export class TableDetail extends React.Component<
<ExploreButton tableData={data} /> <ExploreButton tableData={data} />
</div> </div>
</header> </header>
<article className="column-layout-1"> <div className="column-layout-1">
<section className="left-panel"> <aside className="left-panel">
<EditableSection title="Description"> <EditableSection title="Description">
<TableDescEditableText <TableDescEditableText
maxLength={AppConfig.editableText.tableDescLength} maxLength={AppConfig.editableText.tableDescLength}
...@@ -239,11 +239,11 @@ export class TableDetail extends React.Component< ...@@ -239,11 +239,11 @@ export class TableDetail extends React.Component<
{!!data.last_updated_timestamp && ( {!!data.last_updated_timestamp && (
<section className="metadata-section"> <section className="metadata-section">
<div className="section-title title-3">Last Updated</div> <div className="section-title title-3">Last Updated</div>
<div className="body-2"> <time className="body-2">
{formatDateTimeShort({ {formatDateTimeShort({
epochTimestamp: data.last_updated_timestamp, epochTimestamp: data.last_updated_timestamp,
})} })}
</div> </time>
</section> </section>
)} )}
<section className="metadata-section"> <section className="metadata-section">
...@@ -283,9 +283,9 @@ export class TableDetail extends React.Component< ...@@ -283,9 +283,9 @@ export class TableDetail extends React.Component<
</EditableSection> </EditableSection>
</section> </section>
))} ))}
</section> </aside>
<section className="right-panel">{this.renderTabs()}</section> <main className="right-panel">{this.renderTabs()}</main>
</article> </div>
</div> </div>
); );
} }
......
...@@ -63,7 +63,6 @@ describe('TagInfo', () => { ...@@ -63,7 +63,6 @@ describe('TagInfo', () => {
it('renders a button with correct props', () => { it('renders a button with correct props', () => {
expect(wrapper.find('button').props()).toMatchObject({ expect(wrapper.find('button').props()).toMatchObject({
id: `tag::${props.data.tag_name}`, id: `tag::${props.data.tag_name}`,
role: 'button',
onClick: wrapper.instance().onClick, onClick: wrapper.instance().onClick,
className: 'btn tag-button', className: 'btn tag-button',
}); });
......
...@@ -40,7 +40,6 @@ export class TagInfo extends React.Component<TagInfoProps> { ...@@ -40,7 +40,6 @@ export class TagInfo extends React.Component<TagInfoProps> {
return ( return (
<button <button
id={`tag::${name}`} id={`tag::${name}`}
role="button"
className={'btn tag-button' + (this.props.compact ? ' compact' : '')} className={'btn tag-button' + (this.props.compact ? ' compact' : '')}
onClick={this.onClick} onClick={this.onClick}
> >
......
...@@ -275,7 +275,7 @@ class TagInput extends React.Component<TagInputProps, TagInputState> { ...@@ -275,7 +275,7 @@ class TagInput extends React.Component<TagInputProps, TagInputState> {
className="btn btn-default muted add-btn" className="btn btn-default muted add-btn"
onClick={this.startEditing} onClick={this.startEditing}
> >
<img className="icon icon-plus" /> <img className="icon icon-plus" alt="" />
New New
</button> </button>
); );
......
...@@ -62,6 +62,7 @@ export class BookmarkIcon extends React.Component<BookmarkIconProps> { ...@@ -62,6 +62,7 @@ export class BookmarkIcon extends React.Component<BookmarkIconProps> {
'icon ' + 'icon ' +
(this.props.isBookmarked ? 'icon-bookmark-filled' : 'icon-bookmark') (this.props.isBookmarked ? 'icon-bookmark-filled' : 'icon-bookmark')
} }
alt=""
/> />
</div> </div>
); );
......
...@@ -29,9 +29,9 @@ export const Breadcrumb: React.SFC<BreadcrumbProps> = ( ...@@ -29,9 +29,9 @@ export const Breadcrumb: React.SFC<BreadcrumbProps> = (
return ( return (
<div className="amundsen-breadcrumb"> <div className="amundsen-breadcrumb">
<Link to={path} className="btn btn-flat-icon title-3"> <Link to={path} className="btn btn-flat-icon title-3">
{direction === 'left' && <img className="icon icon-left" />} {direction === 'left' && <img className="icon icon-left" alt="" />}
<span>{text}</span> <span>{text}</span>
{direction === 'right' && <img className="icon icon-right" />} {direction === 'right' && <img className="icon icon-right" alt="" />}
</Link> </Link>
</div> </div>
); );
...@@ -43,8 +43,8 @@ export const Breadcrumb: React.SFC<BreadcrumbProps> = ( ...@@ -43,8 +43,8 @@ export const Breadcrumb: React.SFC<BreadcrumbProps> = (
onClick={props.loadPreviousSearch} onClick={props.loadPreviousSearch}
className="btn btn-flat-icon title-3" className="btn btn-flat-icon title-3"
> >
{direction === 'left' && <img className="icon icon-left" />} {direction === 'left' && <img className="icon icon-left" alt="" />}
{direction === 'right' && <img className="icon icon-right" />} {direction === 'right' && <img className="icon icon-right" alt="" />}
</a> </a>
</div> </div>
); );
......
...@@ -75,7 +75,8 @@ describe('EditableSection', () => { ...@@ -75,7 +75,8 @@ describe('EditableSection', () => {
it('renders children as-is for non-react elements', () => { it('renders children as-is for non-react elements', () => {
const child = 'non-react-child'; const child = 'non-react-child';
const { wrapper } = setup(null, child); const { wrapper } = setup(null, child);
expect(wrapper.childAt(1).text()).toBe(child);
expect(wrapper.find('.editable-section-content').text()).toBe(child);
}); });
it('renders edit button correctly when readOnly=false', () => { it('renders edit button correctly when readOnly=false', () => {
......
...@@ -62,10 +62,12 @@ export class EditableSection extends React.Component< ...@@ -62,10 +62,12 @@ export class EditableSection extends React.Component<
}`} }`}
onClick={this.toggleEdit} onClick={this.toggleEdit}
> >
<span className="sr-only">{Constants.EDIT_TEXT}</span>
<img <img
className={`icon icon-small icon-edit ${ className={`icon icon-small icon-edit ${
this.state.isEditing ? 'icon-color' : '' this.state.isEditing ? 'icon-color' : ''
}`} }`}
alt=""
/> />
</button> </button>
); );
...@@ -92,7 +94,8 @@ export class EditableSection extends React.Component< ...@@ -92,7 +94,8 @@ export class EditableSection extends React.Component<
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<img className="icon icon-small icon-edit" /> <span className="sr-only">{Constants.EDIT_TEXT}</span>
<img className="icon icon-small icon-edit" alt="" />
</a> </a>
</OverlayTrigger> </OverlayTrigger>
); );
...@@ -105,6 +108,7 @@ export class EditableSection extends React.Component< ...@@ -105,6 +108,7 @@ export class EditableSection extends React.Component<
if (!React.isValidElement(child)) { if (!React.isValidElement(child)) {
return child; return child;
} }
return React.cloneElement(child, { return React.cloneElement(child, {
isEditing: this.state.isEditing, isEditing: this.state.isEditing,
setEditMode: this.setEditMode, setEditMode: this.setEditMode,
...@@ -114,11 +118,15 @@ export class EditableSection extends React.Component< ...@@ -114,11 +118,15 @@ export class EditableSection extends React.Component<
return ( return (
<section className="editable-section"> <section className="editable-section">
<div className="section-title title-3"> <label className="editable-section-label">
{EditableSection.convertText(title)} <div className="editable-section-label-wrapper">
{!readOnly ? this.renderButton() : this.renderReadOnlyButton()} <span className="section-title title-3">
</div> {EditableSection.convertText(title)}
{childrenWithProps} </span>
{!readOnly ? this.renderButton() : this.renderReadOnlyButton()}
</div>
<div className="editable-section-content">{childrenWithProps}</div>
</label>
</section> </section>
); );
} }
......
@import 'variables'; @import 'variables';
.editable-section { .editable-section {
.editable-section-label {
display: block;
font-weight: 400;
margin-bottom: 0;
}
.editable-section-label-wrapper {
margin-bottom: $spacer-1;
}
.section-title { .section-title {
color: $text-tertiary; color: $text-tertiary;
margin-bottom: 4px; margin-bottom: $spacer-1/2;
font-weight: 700;
} }
.edit-button { .edit-button {
margin-left: 4px; margin-left: $spacer-1/2;
opacity: 0; opacity: 0;
img { img {
......
...@@ -156,7 +156,7 @@ class EditableText extends React.Component< ...@@ -156,7 +156,7 @@ class EditableText extends React.Component<
className="btn btn-primary refresh-button" className="btn btn-primary refresh-button"
onClick={this.refreshText} onClick={this.refreshText}
> >
<img className="icon icon-refresh" /> <img className="icon icon-refresh" alt="" />
{REFRESH_BUTTON_TEXT} {REFRESH_BUTTON_TEXT}
</button> </button>
</> </>
......
...@@ -15,7 +15,7 @@ const FlashMessage: React.SFC<FlashMessageProps> = ({ ...@@ -15,7 +15,7 @@ const FlashMessage: React.SFC<FlashMessageProps> = ({
}: FlashMessageProps) => { }: FlashMessageProps) => {
return ( return (
<div className="flash-message"> <div className="flash-message">
{iconClass && <img className={`icon ${iconClass}`} />} {iconClass && <img className={`icon ${iconClass}`} alt="" />}
<div className="message">{message}</div> <div className="message">{message}</div>
<button <button
type="button" type="button"
......
...@@ -7,6 +7,8 @@ import SanitizedHTML from 'react-sanitized-html'; ...@@ -7,6 +7,8 @@ import SanitizedHTML from 'react-sanitized-html';
// TODO: Use css-modules instead of 'import' // TODO: Use css-modules instead of 'import'
import './styles.scss'; import './styles.scss';
const INFO_BUTTON_TEXT = 'More info';
export interface InfoButtonProps { export interface InfoButtonProps {
infoText?: string; infoText?: string;
title?: string; title?: string;
...@@ -32,7 +34,9 @@ const InfoButton: React.SFC<InfoButtonProps> = ({ ...@@ -32,7 +34,9 @@ const InfoButton: React.SFC<InfoButtonProps> = ({
placement={placement} placement={placement}
overlay={popoverHoverFocus} overlay={popoverHoverFocus}
> >
<button className={'btn icon info-button ' + size} /> <button className={'btn icon info-button ' + size} type="button">
<span className="sr-only">{INFO_BUTTON_TEXT}</span>
</button>
</OverlayTrigger> </OverlayTrigger>
); );
}; };
......
...@@ -73,15 +73,15 @@ class DashboardListItem extends React.Component<DashboardListItemProps, {}> { ...@@ -73,15 +73,15 @@ class DashboardListItem extends React.Component<DashboardListItemProps, {}> {
<div className="resource-badges"> <div className="resource-badges">
<div> <div>
<div className="title-3">{Constants.LAST_RUN_TITLE}</div> <div className="title-3">{Constants.LAST_RUN_TITLE}</div>
<div className="body-secondary-3"> <time className="body-secondary-3">
{dashboard.last_successful_run_timestamp {dashboard.last_successful_run_timestamp
? formatDate({ ? formatDate({
epochTimestamp: dashboard.last_successful_run_timestamp, epochTimestamp: dashboard.last_successful_run_timestamp,
}) })
: NO_TIMESTAMP_TEXT} : NO_TIMESTAMP_TEXT}
</div> </time>
</div> </div>
<img className="icon icon-right" /> <img className="icon icon-right" alt="" />
</div> </div>
</Link> </Link>
</li> </li>
......
...@@ -82,7 +82,7 @@ class TableListItem extends React.Component<TableListItemProps, {}> { ...@@ -82,7 +82,7 @@ class TableListItem extends React.Component<TableListItemProps, {}> {
</div> </div>
</div> </div>
)} )}
<img className="icon icon-right" /> <img className="icon icon-right" alt="" />
</div> </div>
</Link> </Link>
</li> </li>
......
...@@ -53,7 +53,7 @@ class UserListItem extends React.Component<UserListItemProps, {}> { ...@@ -53,7 +53,7 @@ class UserListItem extends React.Component<UserListItemProps, {}> {
<div className="resource-type">User</div> <div className="resource-type">User</div>
<div className="resource-badges"> <div className="resource-badges">
{!user.is_active && <Flag text="Alumni" labelStyle="danger" />} {!user.is_active && <Flag text="Alumni" labelStyle="danger" />}
<img className="icon icon-right" /> <img className="icon icon-right" alt="" />
</div> </div>
</Link> </Link>
</li> </li>
......
...@@ -56,7 +56,7 @@ export class SearchItem extends React.Component<SearchItemProps, {}> { ...@@ -56,7 +56,7 @@ export class SearchItem extends React.Component<SearchItemProps, {}> {
onClick={this.onViewAllResults} onClick={this.onViewAllResults}
target="_blank" target="_blank"
> >
<img className="icon icon-search" /> <img className="icon icon-search" alt="" />
<div className="title-2 search-item-info"> <div className="title-2 search-item-info">
<div className="search-term">{`${searchTerm}\u00a0`}</div> <div className="search-term">{`${searchTerm}\u00a0`}</div>
<div className="search-item-text">{listItemText}</div> <div className="search-item-text">{listItemText}</div>
......
// TODO: Hard-coded text strings should be translatable/customizable // TODO: Hard-coded text strings should be translatable/customizable
export const PLACEHOLDER_DEFAULT = 'search for data resources...'; export const PLACEHOLDER_DEFAULT = 'search for data resources...';
export const SEARCH_BUTTON_TEXT = 'Search';
export const BUTTON_CLOSE_TEXT = 'Close'; export const BUTTON_CLOSE_TEXT = 'Close';
export const SIZE_SMALL = 'small'; export const SIZE_SMALL = 'small';
......
...@@ -24,6 +24,7 @@ import './styles.scss'; ...@@ -24,6 +24,7 @@ import './styles.scss';
import { import {
BUTTON_CLOSE_TEXT, BUTTON_CLOSE_TEXT,
SEARCH_BUTTON_TEXT,
INVALID_SYNTAX_MESSAGE, INVALID_SYNTAX_MESSAGE,
PLACEHOLDER_DEFAULT, PLACEHOLDER_DEFAULT,
SIZE_SMALL, SIZE_SMALL,
...@@ -207,7 +208,8 @@ export class SearchBar extends React.Component<SearchBarProps, SearchBarState> { ...@@ -207,7 +208,8 @@ export class SearchBar extends React.Component<SearchBarProps, SearchBarState> {
autoComplete="off" autoComplete="off"
/> />
<button className={searchButtonClass} type="submit"> <button className={searchButtonClass} type="submit">
<img className="icon icon-search" /> <span className="sr-only">{SEARCH_BUTTON_TEXT}</span>
<img className="icon icon-search" alt="" />
</button> </button>
{this.props.size === SIZE_SMALL && ( {this.props.size === SIZE_SMALL && (
<button <button
......
...@@ -117,6 +117,7 @@ export default function reducer( ...@@ -117,6 +117,7 @@ export default function reducer(
}; };
const { columnName } = (<OpenRequestAction>action).payload; const { columnName } = (<OpenRequestAction>action).payload;
if (columnName) { if (columnName) {
// eslint-disable-next-line @typescript-eslint/dot-notation
newState['columnName'] = columnName; newState['columnName'] = columnName;
} }
return newState; return newState;
......
...@@ -40,7 +40,8 @@ export function logClick( ...@@ -40,7 +40,8 @@ export function logClick(
const target = event.currentTarget; const target = event.currentTarget;
const inferredProps: ActionLogParams = { const inferredProps: ActionLogParams = {
command: 'click', command: 'click',
target_id: target.id, target_id:
target.dataset && target.dataset.type ? target.dataset.type : target.id,
label: target.innerText || target.textContent, label: target.innerText || target.textContent,
}; };
......
...@@ -40,7 +40,7 @@ ReactDOM.render( ...@@ -40,7 +40,7 @@ ReactDOM.render(
<DocumentTitle title="Amundsen - Data Discovery Portal"> <DocumentTitle title="Amundsen - Data Discovery Portal">
<Provider store={store}> <Provider store={store}>
<Router history={BrowserHistory}> <Router history={BrowserHistory}>
<main id="main"> <div id="main">
<Preloader /> <Preloader />
<Route component={NavBar} /> <Route component={NavBar} />
<Switch> <Switch>
...@@ -57,7 +57,7 @@ ReactDOM.render( ...@@ -57,7 +57,7 @@ ReactDOM.render(
<Route path="/" component={HomePage} /> <Route path="/" component={HomePage} />
</Switch> </Switch>
<Footer /> <Footer />
</main> </div>
</Router> </Router>
</Provider> </Provider>
</DocumentTitle>, </DocumentTitle>,
......
...@@ -32,6 +32,7 @@ export const generateSearchUrl = (searchParams: SearchParams): string => { ...@@ -32,6 +32,7 @@ export const generateSearchUrl = (searchParams: SearchParams): string => {
index: searchParams.index, index: searchParams.index,
}; };
if (hasFilters) { if (hasFilters) {
// eslint-disable-next-line @typescript-eslint/dot-notation
queryStringValues['filters'] = filtersForResource; queryStringValues['filters'] = filtersForResource;
} }
......
...@@ -68,7 +68,6 @@ ...@@ -68,7 +68,6 @@
"enzyme-adapter-react-16": "^1.15.2", "enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.4", "enzyme-to-json": "^3.4.4",
"eslint": "^7.2.0", "eslint": "^7.2.0",
"eslint-config-airbnb": "^18.1.0",
"eslint-config-airbnb-typescript": "^8.0.2", "eslint-config-airbnb-typescript": "^8.0.2",
"eslint-config-prettier": "^6.11.0", "eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.21.1", "eslint-plugin-import": "^2.21.1",
...@@ -201,8 +200,9 @@ ...@@ -201,8 +200,9 @@
"extends": [ "extends": [
"plugin:react/recommended", "plugin:react/recommended",
"airbnb-typescript", "airbnb-typescript",
"prettier", "prettier/@typescript-eslint",
"prettier/@typescript-eslint" "plugin:prettier/recommended",
"prettier/react"
], ],
"ignorePatterns": [ "ignorePatterns": [
"**/*{.,-}min.js", "**/*{.,-}min.js",
...@@ -283,6 +283,7 @@ ...@@ -283,6 +283,7 @@
} }
} }
], ],
"@typescript-eslint/indent": "off",
"arrow-parens": [ "arrow-parens": [
"off", "off",
"always" "always"
...@@ -389,6 +390,7 @@ ...@@ -389,6 +390,7 @@
"react/no-unescaped-entities": 0, "react/no-unescaped-entities": 0,
"react/no-unused-prop-types": 0, "react/no-unused-prop-types": 0,
"react/no-string-refs": 0, "react/no-string-refs": 0,
"react/jsx-indent": 0,
"indent": 0, "indent": 0,
"no-multi-spaces": 0, "no-multi-spaces": 0,
"padded-blocks": 0, "padded-blocks": 0,
...@@ -428,7 +430,7 @@ ...@@ -428,7 +430,7 @@
"react/jsx-closing-tag-location": "warn", "react/jsx-closing-tag-location": "warn",
"react/no-did-update-set-state": "warn", "react/no-did-update-set-state": "warn",
"react/no-access-state-in-setstate": "warn", "react/no-access-state-in-setstate": "warn",
"react/jsx-one-expression-per-line": "warn", "react/jsx-one-expression-per-line": "off",
"react/sort-comp": "warn", "react/sort-comp": "warn",
"react/jsx-props-no-spreading": "warn", "react/jsx-props-no-spreading": "warn",
"react/prefer-stateless-function": "warn", "react/prefer-stateless-function": "warn",
...@@ -520,10 +522,25 @@ ...@@ -520,10 +522,25 @@
} }
}, },
"lint-staged": { "lint-staged": {
"*.js": "eslint --fix", "*.js": [
"*.ts": "eslint --fix", "prettier --write",
"*.tsx": "eslint --fix", "eslint --fix"
"*.scss": "npm run stylelint-fix", ],
"*.{ts,tsx,css,scss}": "prettier --write" "*.jsx": [
"prettier --write",
"eslint --fix"
],
"*.ts": [
"prettier --write",
"eslint --fix"
],
"*.tsx": [
"prettier --write",
"eslint --fix"
],
"*.scss": [
"prettier --write",
"npm run stylelint-fix"
]
} }
} }
<!doctype html> <!doctype html>
<html lang="en-US"> <html lang="en-US">
<head> <head>
{% if <%= htmlWebpackPlugin.options.config.google.enabled%> %}
{% include 'fragments/google-analytics-loader.html' %}
{% endif %}
<meta charset="utf-8"> <meta charset="utf-8">
<title>Amundsen - Data Discovery Portal</title> <title>Amundsen - Data Discovery Portal</title>
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
{% if env == "development" %} {% if env == "development" %}
{% include 'fragments/icons-dev.html' %} {% include 'fragments/icons-dev.html' %}
{% elif env == "staging" %} {% elif env == "staging" %}
...@@ -18,6 +13,10 @@ ...@@ -18,6 +13,10 @@
{% include 'fragments/icons-prod.html' %} {% include 'fragments/icons-prod.html' %}
{% endif %} {% endif %}
{% if <%= htmlWebpackPlugin.options.config.google.enabled%> %}
{% include 'fragments/google-analytics-loader.html' %}
{% endif %}
<%= htmlWebpackPlugin.tags.headTags %> <%= htmlWebpackPlugin.tags.headTags %>
</head> </head>
<body class="{{ env }}"> <body class="{{ env }}">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment