UNPKG

d2-ui

Version:
245 lines (206 loc) 7.79 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import log from 'loglevel'; import { Observable, Subject } from 'rxjs'; import styles, { whenWidthLargerThan1150 } from './header-bar-styles'; import getBaseUrlFromD2ApiUrl from './utils/getBaseUrlFromD2ApiUrl'; const defaultStyle = 'light_blue'; const defaultStylesheetUrl = 'light_blue/light_blue.css'; const stylesLocation = 'dhis-web-commons/css'; function islocalStorageSupported() { try { localStorage.setItem('dhis2.menu.localstorage.test', 'dhis2.menu.localstorage.test'); localStorage.removeItem('dhis2.menu.localstorage.test'); return true; } catch (e) { return false; } } function saveToLocalStorage(headerData = {}) { if (islocalStorageSupported()) { headerData.userStyleUrl && localStorage.setItem('dhis2.menu.ui.headerBar.userStyle', headerData.userStyleUrl); headerData.title && localStorage.setItem('dhis2.menu.ui.headerBar.title', headerData.title); } return headerData; } class InnerHeader extends Component { state = { headerBar: {}, }; componentWillMount() { this.getSystemSettings(this.context.d2) .then(this.getHeaderBarData) .catch(this.loadDataFromLocalStorageIfAvailable) .then(saveToLocalStorage) .then((headerData) => { this.setHeaderData(headerData.userStyleUrl, headerData.title); }) .catch((error) => { log.error(error); }); } componentDidMount() { Observable .fromEvent(window, 'resize') .debounceTime(200) .subscribe( () => this.forceUpdate(), e => log.error('Could not update the HeaderBar after resize', e), ); } componentWillReceiveProps(props) { if (this.props.lastUpdate && (this.props.lastUpdate.getTime() - props.lastUpdate.getTime()) !== 0) { dhis2.menu.ui.bootstrapMenu(); } } getSystemSettings(d2) { if (!d2.system) { return Promise.reject(new Error('Offline')); } return d2.system.settings.all(); } getHeaderBarData(systemSettings) { return this.requestUserStyle() .catch(() => { log.info('Unable to load usersettings, falling back to systemSettings'); localStorage.setItem('dhis2.menu.ui.headerBar.userStyle', systemSettings.keyCurrentStyle); return systemSettings.keyCurrentStyle; }) .then(userStyleUrl => ({ userStyleUrl: userStyleUrl || systemSettings.keyCurrentStyle, title: systemSettings.applicationTitle, })) .catch(error => log.error(error)); } getApiBaseUrl() { if (!this.context.d2.Api) { return '/'; } return this.context.d2.Api.getApi().baseUrl; } getBaseUrl() { return getBaseUrlFromD2ApiUrl(this.context.d2); } getLogoUrl() { return [this.getApiBaseUrl(), 'staticContent', 'logo_banner'].join('/'); } getStylesheetUrl(stylesheet) { return [this.getBaseUrl(), stylesLocation, 'themes', stylesheet || defaultStylesheetUrl].join('/'); } getStyleName(userStyle) { if (typeof userStyle === 'string' && userStyle.split('/')[0] && userStyle.split('/').length > 0) { return userStyle.split('/')[0]; } return defaultStyle; } render() { const headerBannerWrapperStyle = { width: 155, height: 44, verticalAlign: 'middle', textAlign: 'center', flexDirection: 'row', display: 'flex', justifyContent: 'center', alignItems: 'center', }; const headerBannerStyle = { maxWidth: 175, maxHeight: 44, }; const linkWrapStyle = { flex: 1, overflow: 'hidden', whiteSpace: 'nowrap', color: '#FFF', alignItems: 'center', justifyItems: 'center', display: 'flex', minWidth: whenWidthLargerThan1150(450, 'auto'), paddingRight: '1rem', boxSizing: 'border-box', }; const linkStyle = { fontSize: '1rem', fontWeight: 'bold', color: '#FFF', textDecoration: 'none', textOverflow: 'ellipsis', minWidth: 1, overflow: 'hidden', whiteSpace: 'nowrap', }; const logoHref = { minWidth: 175, }; const linkHref = [this.getBaseUrl(), 'dhis-web-commons-about/redirect.action'].join('/'); const largeScreensInnerHeader = Object.assign({ display: 'flex', minWidth: 450 + 175, overflow: 'hidden', textOverflow: 'ellipsis' }, styles.headerTitle); const smallerScreensInnerHeader = Object.assign({ display: 'flex', overflow: 'hidden', textOverflow: 'ellipsis' }, styles.headerTitle); return ( <div style={whenWidthLargerThan1150(largeScreensInnerHeader, smallerScreensInnerHeader)}> <a href={linkHref} title={this.state.headerBar.title} style={logoHref} className="title-link"> <div style={headerBannerWrapperStyle}> <div> <img className="header-logo" src={this.getLogoUrl()} id="headerBanner" style={headerBannerStyle} /> </div> </div> </a> <div style={linkWrapStyle}> <a href={linkHref} title={this.state.headerBar.title} style={linkStyle} className="title-link"> {this.state.headerBar.title} </a> </div> </div> ); } loadDataFromLocalStorageIfAvailable() { let title; let userStyle; // Load values from localStorage if they are available if (islocalStorageSupported()) { title = localStorage.getItem('dhis2.menu.ui.headerBar.title'); userStyle = localStorage.getItem('dhis2.menu.ui.headerBar.userStyle'); } return { userStyleUrl: userStyle, title, }; } setHeaderData(userStyleUrl, title) { this.addUserStyleStylesheet(this.getStylesheetUrl(userStyleUrl)); this.setHeaderTitle(title); } setHeaderBarProp(name, value) { this.setState({ headerBar: Object.assign({}, this.state.headerBar, { [name]: value, }), }); } setHeaderTitle(applicationTitle) { this.setHeaderBarProp('title', applicationTitle || 'District Health Information Software 2'); } requestUserStyle() { const api = this.context.d2.Api.getApi(); return api.get('userSettings/keyStyle') .then(response => response.trim()); } isValidUserStyle(userStyle) { return typeof userStyle === 'string' && /^[A-z0-9_\-]+$/.test(userStyle); } addUserStyleStylesheet(stylesheetUrl) { const linkElement = document.createElement('link'); linkElement.setAttribute('href', stylesheetUrl); linkElement.setAttribute('type', 'text/css'); linkElement.setAttribute('rel', 'stylesheet'); linkElement.setAttribute('media', 'screen,print'); document.querySelector('head').appendChild(linkElement); } } InnerHeader.propTypes = { lastUpdate: PropTypes.instanceOf(Date), }; InnerHeader.contextTypes = { d2: PropTypes.object.isRequired, }; export default InnerHeader;