diff --git a/client/components/Cohorts/DataTable.css b/client/components/Cohorts/DataTable.css index 2b2e8147e..22ef62f90 100644 --- a/client/components/Cohorts/DataTable.css +++ b/client/components/Cohorts/DataTable.css @@ -34,6 +34,15 @@ ); } +.dt__cell-truncated { + overflow: hidden !important; + white-space: nowrap !important; + text-overflow: ellipsis !important; + width: 250px; + max-width: 250px; + min-width: 250px; +} + .gridcolumn__first-child--sticky { min-width: 40% !important; } diff --git a/client/components/Researcher/index.jsx b/client/components/Researcher/index.jsx index 20a1d67b6..31b230558 100644 --- a/client/components/Researcher/index.jsx +++ b/client/components/Researcher/index.jsx @@ -5,13 +5,14 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { Button, Icon, Pagination, Popup, Table } from '@components/UI'; import hash from 'object-hash'; -import { getCohorts } from '@actions/cohort'; +import { getAllCohorts, getCohorts } from '@actions/cohort'; import { getScenarios, getScenarioRunHistory } from '@actions/scenario'; import { getUser } from '@actions/user'; import Loading from '@components/Loading'; import CSV from '@utils/csv'; import { makeHeader } from '@utils/data-table'; import '../Cohorts/Cohort.css'; +import '../Cohorts/DataTable.css'; import './Researcher.css'; const ROWS_PER_PAGE = 10; @@ -43,7 +44,13 @@ class Researcher extends Component { this.props.history.push('/logout'); } else { await this.props.getScenarios(); - await this.props.getCohorts(); + + if (this.props.user.is_super) { + await this.props.getAllCohorts(); + } else { + await this.props.getCohorts(); + } + this.setState({ isReady: true }); } } @@ -68,7 +75,10 @@ class Researcher extends Component { const files = []; for (let id of scenarioIds) { - const { prompts, responses } = await getScenarioRunHistory(id, cohort.id); + const { prompts, responses } = await getScenarioRunHistory( + id, + cohort && cohort.id + ); const records = responses.flat(); @@ -84,7 +94,9 @@ class Researcher extends Component { record.content += ` (${location.origin}/api/media/${value})`; } - record.cohort_id = cohort.id; + if (cohort) { + record.cohort_id = cohort.id; + } }); const fields = [ @@ -96,14 +108,18 @@ class Researcher extends Component { 'created_at', 'ended_at', 'type', - 'referrer_params', - 'cohort_id' + 'referrer_params' ]; - const file = `${hash({ cohort, id })}.csv`; + + if (cohort) { + fields.push('cohort_id'); + } + + const file = hash({ cohort, id }); const parser = new Parser({ fields }); const csv = parser.parse(records); - files.push([file, csv]); + files.push([`${file}.csv`, csv]); } if (Object.entries(files).length === 1) { @@ -117,26 +133,30 @@ class Researcher extends Component { render() { const { onPageChange, downloadData } = this; const { activePage, isReady } = this.state; - const { cohorts, scenariosById, user } = this.props; + const { cohorts, scenarios, scenariosById, user } = this.props; if (!isReady) { return ; } const hasAccessToCohort = cohort => { + if (user.is_super) { + return true; + } + return cohort.users.find(({ id, roles }) => { return id === user.id && roles.includes('researcher'); }); }; - const downloadByCohortIcon = ( + const downloadZipIcon = ( ); - const downloadByScenarioIcon = ( + const downloadRunIcon = ( @@ -152,20 +172,21 @@ class Researcher extends Component { accum.push( ...cohort.scenarios.map((id, index) => { const scenario = scenariosById[id]; - const { title } = scenario; - - const onDownloadByScenarioClick = () => { + const onDownloadByScenarioRunClick = () => { downloadData({ cohort, scenarioId: id }); }; return ( - + {index === 0 ? ( ) : null} @@ -173,11 +194,13 @@ class Researcher extends Component { {cohort.name} - {title} + + {scenario.title} + ); }) @@ -186,6 +209,42 @@ class Researcher extends Component { return accum; }, []); + if (user.is_super) { + const scenarioRunDownloads = scenarios.reduce((accum, scenario) => { + const onDownloadByScenarioRunClick = () => { + downloadData({ scenarioId: scenario.id }); + }; + accum.push( + + + + + + {scenario.title} + + + ); + return accum; + }, []); + + downloads.push(...scenarioRunDownloads); + } + + downloads.sort((a, b) => { + return a.props.created_at > b.props.created_at; + }); + const downloadsPages = Math.ceil(downloads.length / ROWS_PER_PAGE); const downloadsIndex = (activePage - 1) * ROWS_PER_PAGE; const downloadsSlice = downloads.slice( @@ -278,6 +337,7 @@ Researcher.propTypes = { runs: PropTypes.array, scenarios: PropTypes.array, scenariosById: PropTypes.object, + getAllCohorts: PropTypes.func, getCohorts: PropTypes.func, getScenarios: PropTypes.func, getScenarioRunHistory: PropTypes.func, @@ -292,6 +352,7 @@ const mapStateToProps = state => { }; const mapDispatchToProps = dispatch => ({ + getAllCohorts: () => dispatch(getAllCohorts()), getCohorts: () => dispatch(getCohorts()), getScenarios: () => dispatch(getScenarios()), getScenarioRunHistory: (...params) =>