* feat: 🎸 Load spinner when selecting gcloud store. Add key on td * feat: 🎸 Code review. Translate loading study status * feat: 🎸 Code review. Minor code refactoring * fix: add missing study and index declerations * Newer version of react-dates (calendar input component) * Add useMedia hook * Add useDebounce hook * Export hooks for consumption * Pull search filter into own component * StudyListWithData to StudyListRoute * Rename pagination component * Rename Toolbar * CustomeDateRangePicker to plain ol' css * Remove unused styles * Misc * Magic to make our "OR" filters work * Play w/ Mobile styles * Fix pagination pushing out max width for viewport * Tidy up small and medium templates * Remove unecessary nesting * Better mobile header and logo styles * Fix studyList font size * Remove unused code * hookup on click * Fix table search selectors * Cypress uses medium width * Remove irrelevant test * Fix primary sort * Fix sort for our smaller displays * fix study list sometimes longer than specified rowsPerPage * Simplify date picker styles * restore study date filters * Fix about table styling * fix take value for search * Fix header sizing for viewer and list route * Remove dead code * Restore isLoading * Update platform/ui/src/components/studyList/StudyList.styl Co-Authored-By: Rodrigo Antinarelli <rodrigoantinarelli@gmail.com> * Attempt first usage of translations w/ hooks * Pull from react-i18n library * Fit presets on to a single line * add no results message * Show error message in studyList table * Update input selectors for e2e tests * Make sure messages span all columns * fix test selector for table results * Skip hover for result rows * fix imports * Date filtering w/ config * Default export * Pushed to PageComponent * Remove DropZone This previously only worked for null/undefined studies. I'm unable to trigger the state by testing the data. This "might" have happened when using a fresh/empty PACS; but even an empty array of studies would not show
144 lines
3.9 KiB
JavaScript
144 lines
3.9 KiB
JavaScript
import './Header.css';
|
|
|
|
import { Link, withRouter } from 'react-router-dom';
|
|
import React, { Component } from 'react';
|
|
|
|
import { Dropdown } from '@ohif/ui';
|
|
import OHIFLogo from '../OHIFLogo/OHIFLogo.js';
|
|
import PropTypes from 'prop-types';
|
|
import { AboutModal } from '@ohif/ui';
|
|
import { hotkeysManager } from './../../App.js';
|
|
import { withTranslation } from 'react-i18next';
|
|
|
|
// Context
|
|
import AppContext from './../../context/AppContext';
|
|
|
|
class Header extends Component {
|
|
static contextType = AppContext;
|
|
static propTypes = {
|
|
home: PropTypes.bool.isRequired,
|
|
location: PropTypes.object.isRequired,
|
|
children: PropTypes.node,
|
|
t: PropTypes.func.isRequired,
|
|
userManager: PropTypes.object,
|
|
};
|
|
|
|
static defaultProps = {
|
|
home: true,
|
|
children: OHIFLogo(),
|
|
};
|
|
|
|
// onSave: data => {
|
|
// const contextName = store.getState().commandContext.context;
|
|
// const preferences = cloneDeep(store.getState().preferences);
|
|
// preferences[contextName] = data;
|
|
// dispatch(setUserPreferences(preferences));
|
|
// dispatch(setUserPreferencesModalOpen(false));
|
|
// OHIF.hotkeysUtil.setHotkeys(data.hotKeysData);
|
|
// },
|
|
// onResetToDefaults: () => {
|
|
// dispatch(setUserPreferences());
|
|
// dispatch(setUserPreferencesModalOpen(false));
|
|
// OHIF.hotkeysUtil.setHotkeys();
|
|
// },
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = { isUserPreferencesOpen: false, isOpen: false };
|
|
|
|
this.loadOptions();
|
|
}
|
|
|
|
loadOptions() {
|
|
const { t } = this.props;
|
|
this.options = [
|
|
{
|
|
title: t('About'),
|
|
icon: { name: 'info' },
|
|
onClick: () => {
|
|
this.setState({
|
|
isOpen: true,
|
|
});
|
|
},
|
|
},
|
|
];
|
|
|
|
if (this.props.user && this.props.userManager) {
|
|
this.options.push({
|
|
title: t('Logout'),
|
|
icon: { name: 'power-off' },
|
|
onClick: () => {
|
|
this.props.userManager.signoutRedirect();
|
|
},
|
|
});
|
|
}
|
|
|
|
this.hotKeysData = hotkeysManager.hotkeyDefinitions;
|
|
}
|
|
|
|
onUserPreferencesSave({ windowLevelData, hotKeysData }) {
|
|
// console.log(windowLevelData);
|
|
// console.log(hotKeysData);
|
|
// TODO: Update hotkeysManager
|
|
// TODO: reset `this.hotKeysData`
|
|
}
|
|
|
|
// ANTD -- Hamburger, Drawer, Menu
|
|
render() {
|
|
const { t } = this.props;
|
|
const { appConfig = {} } = this.context;
|
|
const showStudyList =
|
|
appConfig.showStudyList !== undefined ? appConfig.showStudyList : true;
|
|
return (
|
|
<>
|
|
<div className="notification-bar">{t('INVESTIGATIONAL USE ONLY')}</div>
|
|
<div className={`entry-header ${this.props.home ? 'header-big' : ''}`}>
|
|
<div className="header-left-box">
|
|
{this.props.location && this.props.location.studyLink && (
|
|
<Link
|
|
to={this.props.location.studyLink}
|
|
className="header-btn header-viewerLink"
|
|
>
|
|
{t('Back to Viewer')}
|
|
</Link>
|
|
)}
|
|
|
|
{this.props.children}
|
|
|
|
{showStudyList && !this.props.home && (
|
|
<Link
|
|
className="header-btn header-studyListLinkSection"
|
|
to={{
|
|
pathname: '/',
|
|
state: { studyLink: this.props.location.pathname },
|
|
}}
|
|
>
|
|
{t('Study list')}
|
|
</Link>
|
|
)}
|
|
</div>
|
|
|
|
<div className="header-menu">
|
|
<span className="research-use">
|
|
{t('INVESTIGATIONAL USE ONLY')}
|
|
</span>
|
|
<Dropdown title={t('Options')} list={this.options} align="right" />
|
|
|
|
{/* TODO: We need a Modal service */}
|
|
<AboutModal
|
|
{...this.state}
|
|
onCancel={() =>
|
|
this.setState({
|
|
isOpen: false,
|
|
})
|
|
}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default withTranslation('Header')(withRouter(Header));
|