import React, { Component } from 'react';
import { SimpleTable, Container, TruncatedText, SVGIcon, Tooltip, Tags } from 'ca-ui-toolkit';
import PropTypes from 'prop-types';
import menuOverflow16 from '@ba-ui-toolkit/ba-graphics/dist/icons/overflow-menu--horizontal_16.svg';
import './ListView.scss';
const COL_LENGTH = 4;
/*
Use in HomeView.js
import { ListView } from '../ListView/ListView.js';
...
} stringGetter={stringGetter} glassContext={glassContext} entries={this._formatAssets()} entryAssets={assets} allowUploadFiles={allowUploadFiles} homeView={homeView} stateId={stateId}/>
*/
export class ListView extends Component {
static propTypes = {
/** Custom class name(s) */
className: PropTypes.string,
/** The glass context handed down */
glassContext: PropTypes.object,
/** A reference to the ES5 homeView object */
homeView: PropTypes.object,
/** A copy of the i18n object used to translate strings */
stringGetter: PropTypes.object,
/** A list of the list entries formatted properly for use from the ca-ui-toolkit */
entries: PropTypes.array,
/** A list of the list entries unformatted with all information. This is to be used by glassContext */
entryAssets: PropTypes.array,
/** a boolean showing whether or not something can be uploaded if there is no data */
allowUploadFiles: PropTypes.bool,
/** An id used to remove context menus for list entries */
stateId: PropTypes.string,
/** Height Value for SimpleTable Component */
height: PropTypes.string.isRequired
};
static defaultProps = {
entries: []
}
constructor(props) {
super(props);
}
state = {
data: [],
headerData: [
{ label: '' },
{ label: '' },
{ label: '' },
{ label: '' }
],
menuLoading: false
};
componentDidMount(){
// Data preparation for rendering
const { entries, stringGetter } = this.props;
this.setState({ entries: entries });
this.setState({ data: this.dataPrep(entries) });
this.setState({ headerData: [
{ label: stringGetter.get('list_header_name') },
{ label: stringGetter.get('list_header_type') },
{ label: stringGetter.get('list_header_last_modified') },
{ label: '' }
] });
}
componentDidUpdate(prevProps) {
// In case if entries removed, refresh the list
if(prevProps.entries.length !== this.props.entries.length)
this.setState({ data: this.dataPrep(this.props.entries) });
else{
for(let i = 0; i < this.props.entries.length; i++){
if(prevProps.entries[i].label !== this.props.entries[i].label || prevProps.entries[i].date !== this.props.entries[i].date){
this.setState({ data: this.dataPrep(this.props.entries) });
break;
}
}
}
}
// Handler for data preparation and formating
dataPrep = (data) => {
const result = data.map(element => [
{ label: element.label },
{ label: element.type },
{ label: element.date },
{ label: '' }
]);
return result;
}
// Return the value in the designated table cell
_getValue = (row, col) => {
if (this.state.data.length > row && this.state.data[row].length > col) {
return this.state.data[row][col].label;
}
return null;
};
// Function for rendering the table body
_cellRenderer(row, col) {
/*
Three situations of cell content:
- Text (Name, Last updated)
- Asset tag (Type)
- Overflow menu icon
*/
// Must: check the length first -> row length are fixed before state updates (concurrency issue)
if(row >= this.props.entryAssets.length)
return;
if(col === 0) {
return (
{ this._openEntryViaTabbing(e, row); }}
value={this.state.data[row][col].label}
title={this.state.data[row][col].label}
location='end'
className='cell_assetName'
/>
);
} else if (col === 1) {
const typeName = this.state.data[row][col].label;
const asset = this.props.entryAssets[row];
let tagColor;
let supportedtypeName = typeName ? typeName[0].toUpperCase() + typeName.slice(1).toLowerCase() : '';
/**
* dashboard/report/story => purple tags
* exploration/notebooks = blue tags
* data upload, data sets, data module, data = green tags
* others = grey tags
*/
if(asset.type === 'report' || asset.type === 'reportView' || asset.type === 'interactiveReport' || asset.type === 'powerPlay8Report' || (asset.type === 'exploration' && (!asset.tags || asset.tags[0] !== 'explore'))){
tagColor = 'purple';
}else if((asset.type === 'exploration' && asset.tags && asset.tags[0] === 'explore') || asset.type === 'jupyterNotebook'){
tagColor = 'blue';
}else if(asset.type === 'dataSet2' || asset.type === 'module' || asset.type === 'uploadedFile' || asset.type === 'URL'){
tagColor = 'teal';
// If it's data and only one word, make all lowercased according to design doc
supportedtypeName = supportedtypeName && supportedtypeName.split(' ').length === 1? supportedtypeName.toLowerCase() : supportedtypeName;
}else{
tagColor = 'gray';
}
return (
);
} else if (col === 3) {
return (
{ this._openActionMenu(e, row); }}>
);
} else {
return (
);
}
}
// Handler for waking the action menu while clicking the menu icon on each table row
_openActionMenu(e, index=e.target.id.split('_')[1]) {
e.stopPropagation();
// If not a shift click, ctrl click or a right click or the user pressed enter on the context menu
if((e.type == 'click' && !e.shiftKey && !e.ctrlKey && e.nativeEvent.which !== 3) || (e.type=='keyup' && e.keyCode === 13)) {
this.setState({ menuLoading: true });
e.persist();
const { homeView, entryAssets } = this.props;
let asset = entryAssets[index];
if(homeView && homeView.requiresAssetVerification) {
homeView.loadAssetContextMenu(asset, e).then(function() {
this.setState({ menuLoading: false });
}.bind(this));
}
}
}
// Handler to open the project via tabbing action
_openEntryViaTabbing(e, index=e.target.id.split('_')[1]){
e.stopPropagation();
// If not a shift click, ctrl click or a right click or the user pressed enter on the context menu
if((e.type == 'click' && !e.shiftKey && !e.ctrlKey && e.nativeEvent.which !== 3) || (e.type=='keyup' && e.keyCode === 13)) {
e.persist();
this._openEntry(index);
}
}
// Handler for clicking the entry to open the detail page
_openEntry(row){
this.props.homeView.onTileClick(this.props.entryAssets[row]);
}
// Function used to render the table header
_headerRenderer(col) {
return (
);
}
render() {
/*
Dynamic allocation for width division to avoid horizontal scrolling
Original Proportion in design spec is: 544:205:314
If necessary, reduced by 15% to make sure that moreButton won't be jumped outside of the table
*/
return (
(
{this._cellRenderer(row, col)}
)}
headerRenderer={col => (
{this._headerRenderer(col)}
)}
onRowClick={row => this._openEntry(row) }
/>
);
}
}