123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- import React, { Component } from 'react';
- import PropTypes from 'prop-types';
- import { QuickLaunch } from '../QuickLaunch/QuickLaunch.js';
- import ReactHtmlParser from 'react-html-parser';
- import { SVGIcon, ToggleSwitch, Tooltip } from 'ca-ui-toolkit';
- import './HomeView.scss';
- import { TilesView } from '../TilesView/TilesView.js';
- import iconMap from '../utils/IconMap';
- import grid16 from '@ba-ui-toolkit/ba-graphics/dist/icons/grid_16.svg';
- import list32 from '@ba-ui-toolkit/ba-graphics/dist/icons/list_32.svg';
- import dragdrop_icon from '../../../../../images/DragAndDrop.svg';
- import ca_logoicon from '../../../../../images/ca_logoicon.png';
- import noUpload from '../../../../../images/noUploadCapability.svg';
- import { WelcomeView } from '../WelcomeView/WelcomeView';
- import { ListView } from '../ListView/ListView.js';
- export class HomeView extends Component {
- static propTypes = {
- /** Custom class name(s) */
- className: PropTypes.string,
- /** An array of all of the tiles, if there are no assets it defaults to empty */
- assets: PropTypes.array,
- /** A boolean which determines if a user can drag and drop uploads to quick launch */
- allowUploadFiles: PropTypes.bool,
- /** A function which communicates with glass to upload the data from quick launch */
- uploadFiles: PropTypes.func,
- /** A copy of the glass context */
- glassContext: PropTypes.object,
- /** The strings used for the welcome label */
- labels: PropTypes.object,
- /** A copy of the i18n translation object */
- stringGetter: PropTypes.object,
- /** A reference to the ES5 homeView object */
- homeView: PropTypes.object,
- /** a string used in the tiles to remove the context menu later */
- stateId: PropTypes.string,
- /** The ID used to reference the file uploaded through Quick Launch */
- quickLaunchCollectionId: PropTypes.string,
- /** The folder name in which to upload the file if a user runs QuickLaunch */
- folderName: PropTypes.string,
- /** Specifies if a jupyter server is configured */
- jupyterEnabled: PropTypes.string,
- /** The theme values from glass */
- themeValues: PropTypes.object
- };
- static defaultProps = {
- assets: [],
- allowUploadFiles: false
- }
- _quickRefCollectionId = 'com.ibm.bi.bahome_common.quickReferences';
- state = {
- dragEnterTargets: [],
- tilesLoaded: false,
- showQuickLaunch: false,
- quickRefContent: '',
- assets: [],
- showWelcome: false,
- enableWelcome: false,
- showTile: true,
- listHeight: 550
- }
- getTileAssets() {
- this._getMRUList()
- .then(function(mruList) {
- this.setState({ assets: mruList, tilesLoaded: true });
- }.bind(this));
- }
- constructor(props) {
- super(props);
- // Grab the quickLaunchTargets
- this.props.glassContext.appController.findCollection(this.props.quickLaunchCollectionId)
- .then(function (itemCollection) {
- this.quickLaunchItems = itemCollection || [];
- }.bind(this));
- // Set up quick reference items
- this.quickRefItemData = {
- label: props.stringGetter.get('quickReference'),
- panels: [{
- label: props.stringGetter.get('getStarted'),
- expanded: true,
- references:[]
- }, {
- label: props.stringGetter.get('sampleData'),
- expanded: false,
- references:[]
- }, {
- label: props.stringGetter.get('support'),
- expanded: false,
- references:[]
- }]
- };
- this.props.glassContext.appController.findCollection(this._quickRefCollectionId)
- .then(function (refItems) {
- this.quickRefContentData = refItems;
- }.bind(this));
- /**
- * Fetch assets to show on the Home page.
- */
- this.getTileAssets();
- }
- // Update local storage for the display of welcome section
- _toShowWelcomeAtLogin = (displayNextTime) => {
- const prefixID = this.localStorageIdentifier()+'_';
- if(typeof(Storage)!=='undefined')
- window.localStorage.setItem(prefixID+'showWelcome', displayNextTime ? 'true' : 'false');
- }
- // Update local storage for the display of tile or view
- _toShowTileViewAtLogin = (displayNextTime) => {
- const prefixID = this.localStorageIdentifier()+'_';
- if(typeof(Storage)!=='undefined')
- window.localStorage.setItem(prefixID+'showTile', displayNextTime ? 'true' : 'false');
- }
- componentDidMount(){
- const prefixID = this.localStorageIdentifier()+'_';
- if(typeof(Storage)!=='undefined'){
- // Check local storage to determine whether welcome section should be displayed
- if(window.localStorage.getItem(prefixID+'showWelcome')){
- // Not First time user
- this.setState({ showWelcome: window.localStorage.getItem(prefixID+'showWelcome')==='true' ? true : false });
- }else{
- // First time user
- window.localStorage.setItem(prefixID+'showWelcome', 'true');
- this.setState({ showWelcome: true });
- }
- // Check local storage to determine whether tile view or list view should be displayed
- if(window.localStorage.getItem(prefixID+'showTile')){
- // Not First time user
- this.setState({ showTile: window.localStorage.getItem(prefixID+'showTile')==='true' ? true : false });
- }else{
- // First time user
- window.localStorage.setItem(prefixID+'showTile', 'true');
- this.setState({ showTile: true });
- }
- }else{
- // local storage is not supported
- this.setState({ showWelcome: false, showTile: true });
- }
- // Retrieve the admin's config context to determine whether welcome section should be shown
- this.props.glassContext.getCoreSvc('.Config').getConfigValue('Glass.welcomeScreenDisabled').then(state => {
- this.setState({ enableWelcome: (state.toString() !== 'true') ? true : false }, () => {
- if(!this.state.enableWelcome)
- this.setState({ showWelcome: false });
- });
- });
- this._calculateListHeight();
- window.addEventListener('resize', () => this._calculateListHeight());
- }
- /**
- * Add an onClick listener for the 'browse' anchor tags. Uses a function from the AMD homeView object to upload.
- * Does this both for the 'Add some data' link and the 'Browse' link.
- */
- componentDidUpdate() {
- const browseLinks = document.getElementsByClassName('homeBrowseFile');
- for(let i = 0; i < browseLinks.length; i++) {
- let link = browseLinks[i];
- link.onclick = function() {
- this.onBrowseFile(this.quickLaunchItems).bind(this);
- }.bind(this.props.homeView);
- }
- }
- componentWillUnmount(){
- window.removeEventListener('resize', () => this._calculateListHeight());
- }
- localStorageIdentifier = () => {
- return this.props.glassContext.profile.account.email;
- }
- _getContentService = () => {
- return this.props.glassContext.getSvc('.Content');
- }
- _getMRUList = () => {
- return this.props.homeView._getMRUList();
- }
- refreshMRUList = () => {
- return this._getContentService()
- .then(function(contentSvc) {
- // check if the refreshMRU method is available...
- if (contentSvc.refreshMRU) {
- return contentSvc.refreshMRU();
- }
- return Promise.resolve();
- }.bind(this))
- .then(function(mruList) { // eslint-disable-line no-unused-vars
- this.getTileAssets(); // Note: May not need to call getTileAssets here, see if only need to do this.tiles = mruList;
- }.bind(this));
- }
- /**
- * Formats the tile assets into the correct format to pass to the toolkit
- */
- _formatAssets = () => {
- return this.props.homeView.formatAssetsInToolkitFormat(this.state.assets, iconMap);
- }
- _hasFiles(data) {
- if (data.types && data.types.length > 0) {
- if ((data.types.contains && data.types.contains('Files')) || (data.types.indexOf && data.types.indexOf('Files') >= 0)) {
- // IE11 or Chrome, Safari, Firefox
- return true;
- }
- }
- return false;
- }
- _getDataFromEvent(event) {
- if (event.originalEvent) {
- return event.originalEvent.dataTransfer;
- } else {
- return event.dataTransfer;
- }
- }
- _getName(glassContext) {
- const { account } = glassContext.profile;
- if (account && account.isAnonymous === true) {
- return null;
- }
- if (account && account.givenName) {
- return account.givenName;
- } else if (account && account.defaultName) {
- return account.defaultName;
- }
- return null;
- }
- _registerDragEnterEvent (target) {
- let state = this.state;
- state.dragEnterTargets.push(target);
- state.showQuickLaunch = true;
- this.setState(state);
- }
- _registerDragLeaveEvent (target) {
- let state = this.state;
- let targetsStillEntered = [];
- // See what targets you have left from dragging over and remove them from state
- let i;
- let oldTarget;
- for (i = 0; i < state.dragEnterTargets.length; i++) {
- oldTarget = state.dragEnterTargets[i];
- if (oldTarget !== target) {
- targetsStillEntered.push(oldTarget);
- }
- }
- state.dragEnterTargets = targetsStillEntered;
- // If you are no longer hovering over items, hide the quick launch
- if (targetsStillEntered.length === 0) {
- state.showQuickLaunch = false;
- }
- this.setState(state);
- }
- hideQuickLaunch() {
- let state = this.state;
- state.dragEnterTargets = [];
- state.showQuickLaunch = false;
- this.setState(state);
- }
- _onDragOver (e) {
- e.preventDefault();
- e.stopPropagation();
- }
- _onDragEnter(e) {
- e.preventDefault();
- e.stopPropagation();
- // Retrieve the data file
- const data = this._getDataFromEvent(e);
- // Check if you can download
- if (this.props.allowUploadFiles && this._hasFiles(data)) {
- this._registerDragEnterEvent(e.target);
- }
- }
- _onDragLeave (e) {
- e.preventDefault();
- e.stopPropagation();
- if (this.props.allowUploadFiles) {
- this._registerDragLeaveEvent(e.target);
- }
- }
- _onDrop(e) {
- e.preventDefault();
- e.stopPropagation();
- let data = this._getDataFromEvent(e);
- if (this.props.allowUploadFiles && this._hasFiles(data)) {
- // Hide Quick Launch
- this.setState({ showQuickLaunch: false });
- if (this.props.uploadFiles) {
- this.props.uploadFiles('drop', data.files, this.quickLaunchItems);
- }
- }
- }
- // Event handler to open the sample folder in the content nav (side-navbar)
- _openSamplesFolder = () => {
- const { homeView } = this.props;
- homeView._openSamples();
- }
- _checkSamplesFolder = () => {
- const { homeView } = this.props;
- return homeView._checkSamplesFolder().then(function(status) {
- return status;
- });
- }
- // Reformat the primary title to a DOM node by enforcing a new-line for brand name
- titleFormatter(brandText){
- const { stringGetter } = this.props;
- let primaryTitleArray = stringGetter.get('welcome_primary_title', {
- 'brandName': brandText
- }).split(' ');
- return ReactHtmlParser(primaryTitleArray.join(' '));
- }
- // Handler to switch the view mode via tabbing
- _switchModeViaTabbing = (e, mode) => {
- e.stopPropagation();
- if((e.type == 'click' && !e.shiftKey && !e.ctrlKey && e.nativeEvent.which !== 3) || (e.type=='keyup' && e.keyCode === 13)) {
- e.persist();
- if(mode==='tile'){
- this._showTileView();
- }else if(mode==='list'){
- this._showListView();
- }
- }
- }
- // Handler to enable the tile view
- _showTileView = () => {
- this._toShowTileViewAtLogin(true);
- this.setState({ showTile : true });
- }
- // Handler to enable the list view
- _showListView = () => {
- this._toShowTileViewAtLogin(false);
- this.setState({ showTile : false });
- }
- // Helper function to calculate the height of list view
- _calculateListHeight = () => {
- /*
- A little hacky trick used to determine the height of listView:
- 56: Margin-top of Welcome Header
- 64: Header Height
- 36: Margin-top of Recent Header while welcome is not shown
- 48: Height of Recent Header
- 20: Gap between Recent Header and Body
- 54: Recent View Footer
- 132: Calculated offset
- */
- this.setState({ listHeight: window.innerHeight - 56 - 64 - 36 - 48 - 20 - 54 - 132 });
- }
- render() {
- const { showQuickLaunch, assets, tilesLoaded } = this.state;
- const { glassContext, stringGetter, allowUploadFiles, folderName, homeView, stateId, quickLaunchCollectionId, jupyterEnabled, themeValues } = this.props;
- const wrapperClassName = showQuickLaunch ? 'homeViewWrapper dragging' : 'homeViewWrapper';
- // Only render the main container once the tiles load, this makes it not look like it renders twice
- const tileContainer = tilesLoaded ?
- (<div className='homeContentContainer recentTileContainer'>
- <TilesView glassContext={glassContext} tiles={this._formatAssets()} tileAssets={assets} stringGetter={stringGetter} allowUploadFiles={allowUploadFiles} homeView={homeView} stateId={stateId}/>
- </div>) :
- (<div className='homeContentContainer recentTileContainer'></div>);
- // Only rendered when no recent task exists
- const noRecentContainer = tilesLoaded ?
- (<div className='homeContentContainer recentNoneContainer'>
- <div style={{ 'width': '128px', 'height': '128px', 'margin': '0 auto' }}>
- <svg style={{ 'width': '128px', 'height': '128px' }}>
- <use xlinkHref={`#${dragdrop_icon.id}`} />
- </svg>
- </div>
- <h4 style={{ 'margin': '32px auto 0px auto' }}>
- {stringGetter.get('noRecents')}
- </h4>
- </div>) :
- (<div className='homeContentContainer recentNoneContainer'></div>);
- const noRecentContainerNoUpload = tilesLoaded ?
- (<div className='homeContentContainer recentNoneContainer'>
- <div style={{ 'width': '200px', 'height': '200px', 'margin': '0 auto' }}>
- <svg style={{ 'width': '200px', 'height': '200px' }}>
- <use xlinkHref={`#${noUpload.id}`} />
- </svg>
- </div>
- <h4 style={{ 'margin': '32px auto 0px auto' }}>
- {stringGetter.get('noRecents')}
- </h4>
- </div>) :
- (<div className='homeContentContainer recentNoneContainer'></div>);
- const viewModeSwitch = assets.length > 0 ?
- (<div className='recentModeSwitchWrapper'>
- <Tooltip title={stringGetter.get('tooltip_tileView')} orient="top">
- <div tabIndex='0' role="application" title={stringGetter.get('tooltip_tileView')} onKeyUp={(e) => this._switchModeViaTabbing(e, 'tile')} className={`recentViewButton recentViewButtonLeft ${this.state.showTile? 'recentViewButtonIsActive' : ''}`} id="viewRecentTile" onClick={() => this._showTileView()}>
- <SVGIcon style={{ 'margin': '8px' }} iconId={grid16.id} />
- </div>
- </Tooltip>
- <Tooltip title={stringGetter.get('tooltip_listView')} orient="top">
- <div tabIndex='0' role="application" title={stringGetter.get('tooltip_listView')} onKeyUp={(e) => this._switchModeViaTabbing(e, 'list')} className={`recentViewButton recentViewButtonRight ${!this.state.showTile ? 'recentViewButtonIsActive' : ''}`} id="viewRecentList" onClick={() => this._showListView()}>
- <SVGIcon style={{ 'margin': '8px' }} iconId={list32.id} />
- </div>
- </Tooltip>
- </div>):null;
- const welcomeSwitch = this.state.enableWelcome ?
- (<div className='welcomeToggleWrapper'>
- <label className='welcomeToggleLabel'>{stringGetter.get('welcome_show')}</label>
- <ToggleSwitch title={stringGetter.get('welcome_show')} style={{ 'z-index': '999' }} onChange={() => {this._toShowWelcomeAtLogin(!this.state.showWelcome); this.setState({ showWelcome: !this.state.showWelcome });}} checked={!!this.state.showWelcome} small/>
- </div>) : null;
- const welcomeContainer = this.state.showWelcome && this.state.enableWelcome ?
- <WelcomeView themeValues={themeValues} sampleChecker={()=>this._checkSamplesFolder()} sampleOpener={()=>this._openSamplesFolder()} glassContext={glassContext} stringGetter={stringGetter} labels={{ brand: themeValues.brandText }}/> : null;
- // Prepare the list component for display
- const listContainer = tilesLoaded ? (<div className='homeContentContainer recentListContainer'>
- <ListView height={this.state.listHeight} stringGetter={stringGetter} glassContext={glassContext} entries={this._formatAssets()} entryAssets={assets} allowUploadFiles={allowUploadFiles} homeView={homeView} stateId={stateId}/></div>)
- :(<div className='homeContentContainer recentListContainer'></div>);
- const recentBrandLogo = themeValues.images.brandIcon==='common-CA_Avatar_Colour_64' ?
- <img className="recentBrandTitleIcon" src={ca_logoicon} /> :
- <img className="recentBrandTitleIcon" src={themeValues.images.brandIcon} />;
- const recentBrandContainer = this.state.showWelcome ? null : (<div className="recentBrandTitle">
- {recentBrandLogo}
- <div className="recentBrandTitleText">{this.titleFormatter(themeValues.brandText)}</div></div>);
- return (
- <div className='homeViewReactRoot' onDragOver={ this._onDragOver.bind(this) } onDragEnter={ this._onDragEnter.bind(this) } onDragStop={ this._onDragLeave.bind(this) } onDragLeave={ this._onDragLeave.bind(this) } onDragEnd={ this._onDragLeave.bind(this) } onDrop={ this._onDrop.bind(this) }>
- <div className={ wrapperClassName }>
- <QuickLaunch showQuickLaunch={showQuickLaunch} stringGetter={stringGetter} folderName={folderName} glassContext={glassContext} quickLaunchCollectionId={quickLaunchCollectionId} homeView={homeView} hideQuickLaunch={this.hideQuickLaunch.bind(this)} jupyterEnabled={jupyterEnabled}></QuickLaunch>
- </div>
- <div>
- {welcomeSwitch}
- {recentBrandContainer}
- </div>
- <div className='homeViewContent' >
- <div className='homeViewBody'>
- {welcomeContainer}
- <div className='recentView'>
- <div className='recentViewHeader' style={{ 'margin-top': this.state.showWelcome ? '48px' : '36px' }}>
- <div className='recentTitleWrapper'>{stringGetter.get('recent')}</div>
- {viewModeSwitch}
- </div>
- <div className='recentViewBody'>
- {assets.length === 0 ? ( homeView.canUploadFiles() ? noRecentContainer : noRecentContainerNoUpload) : (this.state.showTile ? tileContainer : listContainer)}
- </div>
- {homeView.canUploadFiles() && homeView.allowUploadFiles &&
- <div className='recentViewFooter' style={assets.length === 0 ? { 'padding-top': '32px', 'margin-bottom': '64px' } : (this.state.showTile ? { 'padding-top': '48px', 'height': '54px', 'margin-bottom': '64px' } : { 'padding-top': '18px', 'height': '54px' })}>
- { ReactHtmlParser(stringGetter.get('dndPrompt')) }
- </div>
- }
- </div>
- </div>
- </div>
- </div>
- );
- }
- }
|