diff --git a/jsapp/js/assetUtils.es6 b/jsapp/js/assetUtils.es6 index 548e382657..01c1aae44c 100644 --- a/jsapp/js/assetUtils.es6 +++ b/jsapp/js/assetUtils.es6 @@ -148,20 +148,20 @@ export function getAssetDisplayName(asset) { } /** - * @param {Object} question - Part of BE asset data + * @param {Object} questionOrChoice - Part of BE asset data * @param {number} [translationIndex] - defaults to first (default) language - * @returns {string} usable name of the question when possible, "Unlabelled" otherwise. + * @returns {string} usable name of the question or choice when possible, "Unlabelled" otherwise. */ -export function getQuestionDisplayName(question, translationIndex = 0) { - if (question.label && Array.isArray(question.label)) { - return question.label[translationIndex]; - } else if (question.label && !Array.isArray(question.label)) { +export function getQuestionOrChoiceDisplayName(questionOrChoice, translationIndex = 0) { + if (questionOrChoice.label && Array.isArray(questionOrChoice.label)) { + return questionOrChoice.label[translationIndex]; + } else if (questionOrChoice.label && !Array.isArray(questionOrChoice.label)) { // in rare cases the label could be a string - return question.label; - } else if (question.name) { - return question.name; - } else if (question.$autoname) { - return question.$autoname; + return questionOrChoice.label; + } else if (questionOrChoice.name) { + return questionOrChoice.name; + } else if (questionOrChoice.$autoname) { + return questionOrChoice.$autoname; } else { t('Unlabelled'); } @@ -432,7 +432,7 @@ export function getFlatQuestionsList(survey, translationIndex = 0, includeMeta = let openedRepeatGroupsCount = 0; survey.forEach((row) => { if (row.type === 'begin_group' || row.type === 'begin_repeat') { - openedGroups.push(getQuestionDisplayName(row, translationIndex)); + openedGroups.push(getQuestionOrChoiceDisplayName(row, translationIndex)); } if (row.type === 'end_group' || row.type === 'end_repeat') { openedGroups.pop(); @@ -453,7 +453,7 @@ export function getFlatQuestionsList(survey, translationIndex = 0, includeMeta = type: row.type, name: rowName, isRequired: Boolean(row.required), - label: getQuestionDisplayName(row, translationIndex), + label: getQuestionOrChoiceDisplayName(row, translationIndex), path: flatPaths[rowName], parents: openedGroups.slice(0), hasRepatParent: openedRepeatGroupsCount >= 1, @@ -553,7 +553,7 @@ export default { getLanguageIndex, getLanguagesDisplayString, getOrganizationDisplayString, - getQuestionDisplayName, + getQuestionOrChoiceDisplayName, getRowName, getSectorDisplayString, getSurveyFlatPaths, diff --git a/jsapp/js/components/formSubScreens.es6 b/jsapp/js/components/formSubScreens.es6 index 7a31b91ffb..402e82fe47 100644 --- a/jsapp/js/components/formSubScreens.es6 +++ b/jsapp/js/components/formSubScreens.es6 @@ -11,7 +11,7 @@ import assetUtils from 'js/assetUtils'; import DocumentTitle from 'react-document-title'; import SharingForm from './permissions/sharingForm'; import ProjectSettings from './modalForms/projectSettings'; -import DataTable from './table'; +import DataTable from 'js/components/submissions/table'; import ProjectExportsCreator from 'js/components/projectDownloads/projectExportsCreator'; import ProjectExportsList from 'js/components/projectDownloads/projectExportsList'; import {PROJECT_SETTINGS_CONTEXTS} from '../constants'; diff --git a/jsapp/js/components/modal.es6 b/jsapp/js/components/modal.es6 index d86351c75a..0db8160897 100644 --- a/jsapp/js/components/modal.es6 +++ b/jsapp/js/components/modal.es6 @@ -40,8 +40,8 @@ import BulkEditSubmissionsForm from './modalForms/bulkEditSubmissionsForm.es6'; import ProjectSettings from './modalForms/projectSettings'; import RESTServicesForm from './RESTServices/RESTServicesForm'; import SharingForm from './permissions/sharingForm'; -import Submission from './modalForms/submission'; -import TableColumnFilter from './modalForms/tableColumnFilter'; +import SubmissionModal from 'js/components/submissions/submissionModal'; +import TableColumnFilter from 'js/components/submissions/tableColumnFilter'; import TranslationSettings from './modalForms/translationSettings'; import TranslationTable from './modalForms/translationTable'; @@ -316,12 +316,14 @@ class Modal extends React.Component { } { this.props.params.type === MODAL_TYPES.SUBMISSION && this.state.sid && - + } { this.props.params.type === MODAL_TYPES.SUBMISSION && !this.state.sid &&
diff --git a/jsapp/js/components/submissionDataTable.es6 b/jsapp/js/components/submissions/submissionDataTable.es6 similarity index 99% rename from jsapp/js/components/submissionDataTable.es6 rename to jsapp/js/components/submissions/submissionDataTable.es6 index 16faeb83da..49e0cc6b60 100644 --- a/jsapp/js/components/submissionDataTable.es6 +++ b/jsapp/js/components/submissions/submissionDataTable.es6 @@ -9,7 +9,7 @@ import {renderQuestionTypeIcon} from 'js/assetUtils'; import { DISPLAY_GROUP_TYPES, getSubmissionDisplayData, -} from 'js/submissionUtils'; +} from 'js/components/submissions/submissionUtils'; import { META_QUESTION_TYPES, QUESTION_TYPES, diff --git a/jsapp/js/components/modalForms/submission.es6 b/jsapp/js/components/submissions/submissionModal.es6 similarity index 93% rename from jsapp/js/components/modalForms/submission.es6 rename to jsapp/js/components/submissions/submissionModal.es6 index e731c8ced7..e9d09c3169 100644 --- a/jsapp/js/components/modalForms/submission.es6 +++ b/jsapp/js/components/submissions/submissionModal.es6 @@ -10,30 +10,28 @@ import {actions} from 'js/actions'; import mixins from 'js/mixins'; import {bem} from 'js/bem'; import {LoadingSpinner} from 'js/ui'; -import {notify, launchPrinting} from 'utils'; +import {launchPrinting} from 'utils'; import {stores} from 'js/stores'; import { VALIDATION_STATUSES_LIST, MODAL_TYPES, - GROUP_TYPES_BEGIN, - GROUP_TYPES_END } from 'js/constants'; -import SubmissionDataTable from 'js/components/submissionDataTable'; +import SubmissionDataTable from './submissionDataTable'; import Checkbox from 'js/components/common/checkbox'; const DETAIL_NOT_FOUND = '{\"detail\":\"Not found.\"}'; -class Submission extends React.Component { +class SubmissionModal extends React.Component { constructor(props) { super(props); - let translations = this.props.asset.content.translations, - translationOptions = []; + let translations = this.props.asset.content.translations; + let translationOptions = []; if (translations.length > 1) { translationOptions = translations.map((trns) => { return { value: trns, - label: trns || t('Unnamed language') + label: trns || t('Unnamed language'), }; }); } @@ -56,7 +54,7 @@ class Submission extends React.Component { promptRefresh: false, translationIndex: 0, translationOptions: translationOptions, - showXMLNames: false + showXMLNames: false, }; autoBind(this); @@ -88,7 +86,7 @@ class Submission extends React.Component { let next = -1; if (this.props.ids && sid) { - const c = this.props.ids.findIndex((k) => {return k === parseInt(sid);}); + const c = this.props.ids.findIndex((k) => k === parseInt(sid)); let tableInfo = this.props.tableInfo || false; if (this.props.ids[c - 1]) { prev = this.props.ids[c - 1]; @@ -114,7 +112,7 @@ class Submission extends React.Component { submission: data, loading: false, next: next, - previous: prev + previous: prev, }); }).fail((error) => { if (error.responseText) { @@ -134,7 +132,7 @@ class Submission extends React.Component { componentWillReceiveProps(nextProps) { this.setState({ sid: nextProps.sid, - promptRefresh: false + promptRefresh: false, }); this.getSubmission(nextProps.asset.uid, nextProps.sid); @@ -151,7 +149,7 @@ class Submission extends React.Component { }, oncancel: () => { dialog.destroy(); - } + }, }; dialog.set(opts).show(); } @@ -183,7 +181,7 @@ class Submission extends React.Component { triggerRefresh() { this.getSubmission(this.props.asset.uid, this.props.sid); this.setState({ - promptRefresh: false + promptRefresh: false, }); // Prompt table to refresh submission list actions.resources.refreshTableSubmissions(); @@ -196,7 +194,7 @@ class Submission extends React.Component { sid: sid, asset: this.props.asset, ids: this.props.ids, - tableInfo: this.props.tableInfo || false + tableInfo: this.props.tableInfo || false, }); } @@ -206,7 +204,7 @@ class Submission extends React.Component { stores.pageState.showModal({ type: MODAL_TYPES.SUBMISSION, sid: false, - page: 'prev' + page: 'prev', }); } @@ -216,7 +214,7 @@ class Submission extends React.Component { stores.pageState.showModal({ type: MODAL_TYPES.SUBMISSION, sid: false, - page: 'next' + page: 'next', }); } @@ -233,9 +231,9 @@ class Submission extends React.Component { } languageChange(e) { - let index = this.state.translationOptions.findIndex((x) => {return x === e;}); + let index = this.state.translationOptions.findIndex((x) => x === e); this.setState({ - translationIndex: index || 0 + translationIndex: index || 0, }); } @@ -460,9 +458,12 @@ class Submission extends React.Component { } - + @@ -490,7 +491,7 @@ class Submission extends React.Component { } } -reactMixin(Submission.prototype, Reflux.ListenerMixin); -reactMixin(Submission.prototype, mixins.permissions); +reactMixin(SubmissionModal.prototype, Reflux.ListenerMixin); +reactMixin(SubmissionModal.prototype, mixins.permissions); -export default Submission; +export default SubmissionModal; diff --git a/jsapp/js/submissionUtils.es6 b/jsapp/js/components/submissions/submissionUtils.es6 similarity index 98% rename from jsapp/js/submissionUtils.es6 rename to jsapp/js/components/submissions/submissionUtils.es6 index b79d37f7b9..9c6d63a1ee 100644 --- a/jsapp/js/submissionUtils.es6 +++ b/jsapp/js/components/submissions/submissionUtils.es6 @@ -203,9 +203,9 @@ export function getSubmissionDisplayData(survey, choices, translationIndex, subm // score and rank don't have list name on them and they need to use // the one of their parent if (row.type === SCORE_ROW_TYPE || row.type === RANK_LEVEL_TYPE) { - const parentGroupRow = survey.find((row) => { - return getRowName(row) === parentGroup.name; - }); + const parentGroupRow = survey.find((row) => + getRowName(row) === parentGroup.name + ); rowListName = getRowListName(parentGroupRow); } @@ -265,9 +265,9 @@ function populateMatrixData( */ Object.keys(flatPaths).forEach((questionName) => { if (flatPaths[questionName].startsWith(`${matrixGroupPath}/`)) { - const questionSurveyObj = survey.find((row) => { - return getRowName(row) === questionName; - }); + const questionSurveyObj = survey.find((row) => + getRowName(row) === questionName + ); /* * NOTE: Submission data for a Matrix question is kept in an unusal diff --git a/jsapp/js/submissionUtils.mocks.es6 b/jsapp/js/components/submissions/submissionUtils.mocks.es6 similarity index 100% rename from jsapp/js/submissionUtils.mocks.es6 rename to jsapp/js/components/submissions/submissionUtils.mocks.es6 diff --git a/jsapp/js/submissionUtils.tests.es6 b/jsapp/js/components/submissions/submissionUtils.tests.es6 similarity index 97% rename from jsapp/js/submissionUtils.tests.es6 rename to jsapp/js/components/submissions/submissionUtils.tests.es6 index 59f425e0cf..32c1777748 100644 --- a/jsapp/js/submissionUtils.tests.es6 +++ b/jsapp/js/components/submissions/submissionUtils.tests.es6 @@ -27,8 +27,8 @@ import { matrixRepeatSurveyChoices, matrixRepeatSurveySubmission, matrixRepeatSurveyDisplayData, -} from 'js/submissionUtils.mocks'; -import {getSubmissionDisplayData} from 'js/submissionUtils'; +} from './submissionUtils.mocks'; +import {getSubmissionDisplayData} from './submissionUtils'; describe('getSubmissionDisplayData', () => { it('should return a valid data for a survey with a group', () => { diff --git a/jsapp/js/components/table.es6 b/jsapp/js/components/submissions/table.es6 similarity index 76% rename from jsapp/js/components/table.es6 rename to jsapp/js/components/submissions/table.es6 index 1c5bedd091..c417fc8ba0 100644 --- a/jsapp/js/components/table.es6 +++ b/jsapp/js/components/submissions/table.es6 @@ -4,14 +4,13 @@ import Reflux from 'reflux'; import reactMixin from 'react-mixin'; import _ from 'underscore'; import enketoHandler from 'js/enketoHandler'; -import {dataInterface} from '../dataInterface'; +import {dataInterface} from 'js/dataInterface'; import Checkbox from 'js/components/common/checkbox'; -import {actions} from '../actions'; -import {bem} from '../bem'; -import ui from '../ui'; -import {stores} from '../stores'; -import mixins from '../mixins'; -import alertify from 'alertifyjs'; +import {actions} from 'js/actions'; +import {bem} from 'js/bem'; +import ui from 'js/ui'; +import {stores} from 'js/stores'; +import mixins from 'js/mixins'; import ReactTable from 'react-table'; import Select from 'react-select'; import {DebounceInput} from 'react-debounce-input'; @@ -21,14 +20,16 @@ import { MODAL_TYPES, QUESTION_TYPES, GROUP_TYPES_BEGIN, - GROUP_TYPES_END -} from '../constants'; + GROUP_TYPES_END, + META_QUESTION_TYPES, + ADDITIONAL_SUBMISSION_PROPS, +} from 'js/constants'; +import {formatTimeDate} from 'utils'; import { - formatTimeDate, - renderCheckbox -} from 'utils'; -import {getSurveyFlatPaths} from 'js/assetUtils'; -import {getRepeatGroupAnswers} from 'js/submissionUtils'; + getSurveyFlatPaths, + getQuestionOrChoiceDisplayName, +} from 'js/assetUtils'; +import {getRepeatGroupAnswers} from 'js/components/submissions/submissionUtils'; import TableBulkOptions from './tableBulkOptions'; import TableBulkCheckbox from './tableBulkCheckbox'; @@ -48,7 +49,7 @@ const EXCLUDED_COLUMNS = [ '_geolocation', 'meta/instanceID', 'meta/deprecatedID', - '_validation_status' + '_validation_status', ]; export const SUBMISSION_LINKS_ID = '__SubmissionLinks'; @@ -78,31 +79,36 @@ export class DataTable extends React.Component { selectAll: false, fetchState: false, submissionPager: false, - overrideLabelsAndGroups: null + overrideLabelsAndGroups: null, }; this.tableScrollTop = 0; autoBind(this); } requestData(instance) { - let pageSize = instance.state.pageSize, - page = instance.state.page * instance.state.pageSize, - sort = instance.state.sorted, - filter = instance.state.filtered, - filterQuery = ''; + let pageSize = instance.state.pageSize; + let page = instance.state.page * instance.state.pageSize; + let sort = instance.state.sorted; + let filter = instance.state.filtered; + let filterQuery = ''; if (filter.length) { filterQuery = '&query={'; - filter.forEach(function(f, i) { + filter.forEach(function (f, i) { if (f.id === '_id') { filterQuery += `"${f.id}":{"$in":[${f.value}]}`; } else if (f.id === '_validation_status.uid') { - (f.value === NOT_ASSIGNED) ? filterQuery += `"${f.id}":null` : filterQuery += `"${f.id}":"${f.value}"`; + if (f.value === NOT_ASSIGNED) { + filterQuery += `"${f.id}":null`; + } else { + filterQuery += `"${f.id}":"${f.value}"`; + } } else { filterQuery += `"${f.id}":{"$regex":"${f.value}","$options":"i"}`; } - if (i < filter.length - 1) + if (i < filter.length - 1) { filterQuery += ','; + } }); filterQuery += '}'; } @@ -111,10 +117,10 @@ export class DataTable extends React.Component { let results = data.results; if (results && results.length > 0) { - if (this.state.submissionPager == 'next') { + if (this.state.submissionPager === 'next') { this.submissionModalProcessing(results[0]._id, results); } - if (this.state.submissionPager == 'prev') { + if (this.state.submissionPager === 'prev') { this.submissionModalProcessing(results[results.length - 1]._id, results); } this.setState({ @@ -123,30 +129,30 @@ export class DataTable extends React.Component { selectAll: false, tableData: results, submissionPager: false, - resultsTotal: data.count + resultsTotal: data.count, }); this._prepColumns(results); + } else if (filterQuery.length) { + this.setState({ + loading: false, + selectedRows: {}, + tableData: results, + resultsTotal: 0, + }); } else { - if (filterQuery.length) { - this.setState({ - loading: false, - selectedRows: {}, - tableData: results, - resultsTotal: 0 - }); - } else { - this.setState({error: t('This project has no submitted data. ' + - 'Please collect some and try again.'), - loading: false}); - } + this.setState({ + error: t('This project has no submitted data. Please collect some and try again.'), + loading: false, + }); } - }).fail((error)=>{ - if (error.responseText) + }).fail((error) => { + if (error.responseText) { this.setState({error: error.responseText, loading: false}); - else if (error.statusText) + } else if (error.statusText) { this.setState({error: error.statusText, loading: false}); - else + } else { this.setState({error: t('Error: could not load data.'), loading: false}); + } }); } getValidationStatusOption(originalRow) { @@ -160,7 +166,7 @@ export class DataTable extends React.Component { const _this = this; if (evt.value === null) { - dataInterface.removeSubmissionValidationStatus(_this.props.asset.uid, sid).done((result) => { + dataInterface.removeSubmissionValidationStatus(_this.props.asset.uid, sid).done(() => { _this.state.tableData[index]._validation_status = {}; _this.setState({tableData: _this.state.tableData}); }).fail(console.error); @@ -184,34 +190,33 @@ export class DataTable extends React.Component { let output = Object.values(flatPaths); // Gather unique columns from all visible submissions and add them to output - const dataKeys = Object.keys(data.reduce(function(result, obj) { + const dataKeys = Object.keys(data.reduce(function (result, obj) { return Object.assign(result, obj); }, {})); output = [...new Set([...dataKeys, ...output])]; // exclude some technical non-data columns - output = output.filter((key) => { - return EXCLUDED_COLUMNS.includes(key) === false; - }); + output = output.filter((key) => EXCLUDED_COLUMNS.includes(key) === false); // exclude notes output = output.filter((key) => { - const foundPathKey = Object.keys(flatPaths).find((pathKey) => { - return flatPaths[pathKey] === key; - }); + const foundPathKey = Object.keys(flatPaths).find( + (pathKey) => flatPaths[pathKey] === key + ); + // no path means this definitely is not a note type if (!foundPathKey) { return true; } - const foundNoteRow = this.props.asset.content.survey.find((row) => { - return ( + const foundNoteRow = this.props.asset.content.survey.find( + (row) => typeof foundPathKey !== 'undefined' && (foundPathKey === row.name || foundPathKey === row.$autoname) && row.type === QUESTION_TYPES.note.id - ); - }); + ); + if (typeof foundNoteRow !== 'undefined') { // filter out this row as this is a note type return false; @@ -234,9 +239,7 @@ export class DataTable extends React.Component { excludedMatrixKeys.push(rowPath); } }); - output = output.filter((key) => { - return excludedMatrixKeys.includes(key) === false; - }); + output = output.filter((key) => excludedMatrixKeys.includes(key) === false); return output; } @@ -244,24 +247,24 @@ export class DataTable extends React.Component { _prepColumns(data) { const displayedColumns = this.getDisplayedColumns(data); - let showLabels = this.state.showLabels, - showGroupName = this.state.showGroupName, - showHXLTags = this.state.showHXLTags, - settings = this.props.asset.settings, - translationIndex = this.state.translationIndex, - maxPageRes = Math.min(this.state.pageSize, this.state.tableData.length), - _this = this; + let showLabels = this.state.showLabels; + let showGroupName = this.state.showGroupName; + let showHXLTags = this.state.showHXLTags; + let settings = this.props.asset.settings; + let translationIndex = this.state.translationIndex; + let maxPageRes = Math.min(this.state.pageSize, this.state.tableData.length); + let _this = this; - if (settings['data-table'] && settings['data-table']['translation-index'] != null) { + if (settings['data-table'] && settings['data-table']['translation-index'] !== null) { translationIndex = settings['data-table']['translation-index']; showLabels = translationIndex > -1 ? true : false; } - if (settings['data-table'] && settings['data-table']['show-group-name'] != null) { + if (settings['data-table'] && settings['data-table']['show-group-name'] !== null) { showGroupName = settings['data-table']['show-group-name']; } - if (settings['data-table'] && settings['data-table']['show-hxl-tags'] != null) { + if (settings['data-table'] && settings['data-table']['show-hxl-tags'] !== null) { showHXLTags = settings['data-table']['show-hxl-tags']; } @@ -280,18 +283,16 @@ export class DataTable extends React.Component { this.userCan('change_submissions', this.props.asset) ) { columns.push({ - Header: () => { - return ( - - ); - }, + Header: () => ( + + ), accessor: 'sub-checkbox', index: '__0', id: SUBMISSION_CHECKBOX_ID, @@ -301,14 +302,14 @@ export class DataTable extends React.Component { resizable: false, headerClassName: 'table-bulk-checkbox-header', className: 'rt-checkbox', - Cell: row => ( + Cell: (row) => (
- ) + ), }); } @@ -324,7 +325,7 @@ export class DataTable extends React.Component { sortable: false, resizable: false, className: 'rt-link', - Cell: row => ( + Cell: (row) => (
@@ -342,17 +343,15 @@ export class DataTable extends React.Component { }
- ) + ), }); columns.push({ - Header: () => { - return ( - - {t('Validation status')} - - ); - }, + Header: () => ( + + {t('Validation status')} + + ), accessor: '_validation_status.uid', index: '__2', id: '_validation_status.uid', @@ -360,17 +359,15 @@ export class DataTable extends React.Component { className: 'rt-status', Filter: ({ filter, onChange }) => , - Cell: row => ( + Cell: (row) => ( onChange(event.target.value)} - style={{ width: '100%' }} - value={filter ? filter.value : ''}> - - {choices.filter(c => c.list_name === col.question.select_from_list_name).map((item, n) => { - let displayLabel = t('Unlabelled'); - if (item.label) { - displayLabel = item.label[translationIndex]; - } else if (item.name) { - displayLabel = item.name; - } else if (item.$autoname) { - displayLabel = item.$autoname; - } - return ( - - ); + ; } @@ -586,8 +591,9 @@ export class DataTable extends React.Component { onChange(event.target.value)} - style={{ width: '100%' }}/>; + onChange={(event) => onChange(event.target.value)} + style={{ width: '100%' }} + />; } if (frozenColumn === col.id) { @@ -601,8 +607,9 @@ export class DataTable extends React.Component { const selCos = settings['data-table']['selected-columns']; // always include frozenColumn, if set - if (frozenColumn && !selCos.includes(frozenColumn)) + if (frozenColumn && !selCos.includes(frozenColumn)) { selCos.unshift(frozenColumn); + } selectedColumns = columns.filter((el) => { // always include checkbox column @@ -620,14 +627,14 @@ export class DataTable extends React.Component { translationIndex: translationIndex, showLabels: showLabels, showGroupName: showGroupName, - showHXLTags: showHXLTags + showHXLTags: showHXLTags, }); } getColumnHXLTags(key) { if (this.state.showHXLTags) { - const colQuestion = _.find(this.props.asset.content.survey, (question) => { - return question.$autoname === key; - }); + const colQuestion = _.find(this.props.asset.content.survey, (question) => + question.$autoname === key + ); if (!colQuestion || !colQuestion.tags) { return null; } @@ -663,10 +670,10 @@ export class DataTable extends React.Component { } var label = key; - let showLabels = this.state.showLabels, - showGroupName = this.state.showGroupName, - translationIndex = this.state.translationIndex, - survey = this.props.asset.content.survey; + let showLabels = this.state.showLabels; + let showGroupName = this.state.showGroupName; + let translationIndex = this.state.translationIndex; + let survey = this.props.asset.content.survey; if (stateOverrides) { showGroupName = stateOverrides.showGroupName; @@ -677,17 +684,19 @@ export class DataTable extends React.Component { var splitK = key.split('/'); label = splitK[splitK.length - 1]; } - if (q && q.label && showLabels && q.label[translationIndex]) + if (q && q.label && showLabels && q.label[translationIndex]) { label = q.label[translationIndex]; + } // show Groups in labels, when selected if (showGroupName && qParentG && key.includes('/')) { var gLabels = qParentG.join(' / '); if (showLabels) { - var gT = qParentG.map(function(g) { - var x = survey.find(o => o.name === g || o.$autoname == g); - if (x && x.label && x.label[translationIndex]) + var gT = qParentG.map(function (g) { + var x = survey.find((o) => o.name === g || o.$autoname === g); + if (x && x.label && x.label[translationIndex]) { return x.label[translationIndex]; + } return g; }); @@ -701,12 +710,12 @@ export class DataTable extends React.Component { overrideLabelsAndGroups(overrides) { stores.pageState.hideModal(); this.setState({ - overrideLabelsAndGroups: overrides + overrideLabelsAndGroups: overrides, }, () => { this._prepColumns(this.state.tableData); }); } - toggleFullscreen () { + toggleFullscreen() { this.setState({isFullscreen: !this.state.isFullscreen}); } @@ -726,7 +735,7 @@ export class DataTable extends React.Component { refreshSubmissionValidationStatus(result, sid) { if (sid) { - var subIndex = this.state.tableData.findIndex(x => x._id === parseInt(sid)); + var subIndex = this.state.tableData.findIndex((x) => x._id === parseInt(sid)); if (typeof subIndex !== 'undefined' && this.state.tableData[subIndex]) { var newData = this.state.tableData; newData[subIndex]._validation_status = result || {}; @@ -752,20 +761,25 @@ export class DataTable extends React.Component { pageSize: instance.state.pageSize, currentPage: instance.state.page, fetchState: state, - fetchInstance: instance + fetchInstance: instance, }); this.requestData(instance); } - launchSubmissionModal (evt) { + launchSubmissionModal(evt) { let el = $(evt.target).closest('[data-sid]').get(0); const sid = el.getAttribute('data-sid'); this.submissionModalProcessing(sid, this.state.tableData); } - submissionModalProcessing(sid, tableData, isDuplicated=false, duplicatedSubmission=null) { + submissionModalProcessing( + sid, + tableData, + isDuplicated = false, + duplicatedSubmission = null + ) { let ids = []; - tableData.forEach(function(r) { + tableData.forEach(function (r) { ids.push(r._id); }); @@ -779,45 +793,48 @@ export class DataTable extends React.Component { tableInfo: { currentPage: this.state.currentPage, pageSize: this.state.pageSize, - resultsTotal: this.state.resultsTotal - } + resultsTotal: this.state.resultsTotal, + }, }); } - showTableColumsOptionsModal () { + showTableColumnsOptionsModal() { stores.pageState.showModal({ type: MODAL_TYPES.TABLE_COLUMNS, asset: this.props.asset, columns: this.state.columns, getColumnLabel: this.getColumnLabel, - overrideLabelsAndGroups: this.overrideLabelsAndGroups + overrideLabelsAndGroups: this.overrideLabelsAndGroups, }); } - launchEditSubmission (evt) { + launchEditSubmission(evt) { enketoHandler.editSubmission(this.props.asset.uid, evt.currentTarget.dataset.sid); } onPageStateUpdated(pageState) { - if (!pageState.modal) + if (!pageState.modal) { return false; + } if (pageState.modal.type === MODAL_TYPES.BULK_EDIT_SUBMISSIONS) { return false; } - let params = pageState.modal, - page = 0; + let params = pageState.modal; + let page = 0; if (params.type !== MODAL_TYPES.TABLE_COLUMNS && !params.sid) { let fetchInstance = this.state.fetchInstance; - if (params.page === 'next') + if (params.page === 'next') { page = this.state.currentPage + 1; - if (params.page === 'prev') + } + if (params.page === 'prev') { page = this.state.currentPage - 1; + } fetchInstance.setState({ page: page }); this.setState({ fetchInstance: fetchInstance, - submissionPager: params.page - }, function() { + submissionPager: params.page, + }, function () { this.fetchData(this.state.fetchState, this.state.fetchInstance); }); } @@ -834,12 +851,12 @@ export class DataTable extends React.Component { this.setState({ selectedRows: selectedRows, - selectAll: false + selectAll: false, }); } bulkSelectAllRows(isChecked) { let s = this.state.selectedRows; - this.state.tableData.forEach(function(r) { + this.state.tableData.forEach(function (r) { if (isChecked) { s[r._id] = true; } else { @@ -855,12 +872,12 @@ export class DataTable extends React.Component { if (scount === this.state.resultsTotal) { this.setState({ selectedRows: s, - selectAll: true + selectAll: true, }); } else { this.setState({ selectedRows: s, - selectAll: false + selectAll: false, }); } } @@ -872,13 +889,13 @@ export class DataTable extends React.Component { bulkSelectAll() { // make sure all rows on current page are selected let s = this.state.selectedRows; - this.state.tableData.forEach(function(r) { + this.state.tableData.forEach(function (r) { s[r._id] = true; }); this.setState({ selectedRows: s, - selectAll: true + selectAll: true, }); } bulkClearSelection() { @@ -914,13 +931,12 @@ export class DataTable extends React.Component { ); } getMediaDownloadLink(fileName) { - this.state.tableData.forEach(function(a) { - a._attachments.forEach(function(b) { + this.state.tableData.forEach(function (a) { + a._attachments.forEach(function (b) { if (b.filename.includes(fileName)) { fileName = b.filename; } }); - }); var kc_server = document.createElement('a'); @@ -929,7 +945,7 @@ export class DataTable extends React.Component { var kc_base = `${kc_server.origin}${kc_prefix}`; return `${kc_base}/attachment/original?media_file=${encodeURI(fileName)}`; } - render () { + render() { if (this.state.error) { return ( @@ -942,10 +958,9 @@ export class DataTable extends React.Component { ); } - const { tableData, columns, selectedColumns, defaultPageSize, loading, pageSize, currentPage, resultsTotal } = this.state; + const { tableData, columns, selectedColumns, defaultPageSize, loading, pageSize, resultsTotal } = this.state; const pages = Math.floor(((resultsTotal - 1) / pageSize) + 1); - let asset = this.props.asset, - tableClasses = this.state.frozenColumn ? '-striped -highlight has-frozen-column' : '-striped -highlight'; + let tableClasses = this.state.frozenColumn ? '-striped -highlight has-frozen-column' : '-striped -highlight'; const formViewModifiers = ['table']; if (this.state.isFullscreen) { @@ -966,7 +981,7 @@ export class DataTable extends React.Component { @@ -1003,7 +1018,7 @@ export class DataTable extends React.Component { this.tableScrollTop = e.target.scrollTop; } } - } + }, }; }} filterable diff --git a/jsapp/js/components/tableBulkCheckbox.es6 b/jsapp/js/components/submissions/tableBulkCheckbox.es6 similarity index 100% rename from jsapp/js/components/tableBulkCheckbox.es6 rename to jsapp/js/components/submissions/tableBulkCheckbox.es6 diff --git a/jsapp/js/components/tableBulkOptions.es6 b/jsapp/js/components/submissions/tableBulkOptions.es6 similarity index 96% rename from jsapp/js/components/tableBulkOptions.es6 rename to jsapp/js/components/submissions/tableBulkOptions.es6 index 8cc394b3df..812b374eb4 100644 --- a/jsapp/js/components/tableBulkOptions.es6 +++ b/jsapp/js/components/submissions/tableBulkOptions.es6 @@ -110,7 +110,8 @@ class TableBulkOptions extends React.Component { data.submission_ids = Object.keys(this.props.selectedRows); selectedCount = data.submission_ids.length; } - let msg, onshow; + let msg; + let onshow; msg = t('You are about to permanently delete ##count## data entries.').replace('##count##', selectedCount); msg += `${renderCheckbox('dt1', t('All selected data associated with this form will be deleted.'))}`; msg += `${renderCheckbox('dt2', t('I understand that if I delete the selected entries I will not be able to recover them.'))}`; @@ -123,10 +124,10 @@ class TableBulkOptions extends React.Component { ok_button.disabled = true; - $els.each(function() {$(this).prop('checked', false);}); - $els.change(function() { + $els.each(function () {$(this).prop('checked', false);}); + $els.change(function () { ok_button.disabled = false; - $els.each(function() { + $els.each(function () { if (!$(this).prop('checked')) { ok_button.disabled = true; } @@ -186,16 +187,15 @@ class TableBulkOptions extends React.Component { {Object.keys(this.props.selectedRows).length > 0 && {this.userCan('validate_submissions', this.props.asset) && - VALIDATION_STATUSES_LIST.map((item, n) => { - return ( + VALIDATION_STATUSES_LIST.map((item, n) => ( {t('Set status: ##status##').replace('##status##', item.label)} - ); - }) + ) + ) } } diff --git a/jsapp/js/components/modalForms/tableColumnFilter.es6 b/jsapp/js/components/submissions/tableColumnFilter.es6 similarity index 86% rename from jsapp/js/components/modalForms/tableColumnFilter.es6 rename to jsapp/js/components/submissions/tableColumnFilter.es6 index 76cccda79e..04b22bf4af 100644 --- a/jsapp/js/components/modalForms/tableColumnFilter.es6 +++ b/jsapp/js/components/submissions/tableColumnFilter.es6 @@ -1,6 +1,5 @@ import _ from 'underscore'; import React from 'react'; -import PropTypes from 'prop-types'; import Reflux from 'reflux'; import reactMixin from 'react-mixin'; import Select from 'react-select'; @@ -8,15 +7,13 @@ import autoBind from 'react-autobind'; import Checkbox from 'js/components/common/checkbox'; import Radio from 'js/components/common/radio'; import {bem} from 'js/bem'; -import ui from 'js/ui'; import {actions} from 'js/actions'; -import {stores} from 'js/stores'; import mixins from 'js/mixins'; import {notify} from 'utils'; import { SUBMISSION_LINKS_ID, SUBMISSION_CHECKBOX_ID, -} from 'js/components/table'; +} from 'js/components/submissions/table'; export class TableColumnFilter extends React.Component { constructor(props){ @@ -26,23 +23,27 @@ export class TableColumnFilter extends React.Component { frozenColumn: false, showGroupName: true, showHXLTags: false, - translationIndex: 0 + translationIndex: 0, }; let _sett = props.asset.settings; if (_sett['data-table']) { - if (_sett['data-table']['selected-columns'] !== null) + if (_sett['data-table']['selected-columns'] !== null) { this.state.selectedColumns = _sett['data-table']['selected-columns']; + } if (typeof _sett['data-table']['frozen-column'] !== 'undefined') { const cols = this.listColumns(); - this.state.frozenColumn = _.find(cols, (col) => {return col.value === _sett['data-table']['frozen-column']}); + this.state.frozenColumn = _.find(cols, (col) => col.value === _sett['data-table']['frozen-column']); } - if (typeof _sett['data-table']['show-group-name'] !== 'undefined') + if (typeof _sett['data-table']['show-group-name'] !== 'undefined') { this.state.showGroupName = _sett['data-table']['show-group-name']; - if (typeof _sett['data-table']['translation-index'] !== 'undefined') + } + if (typeof _sett['data-table']['translation-index'] !== 'undefined') { this.state.translationIndex = _sett['data-table']['translation-index']; - if (typeof _sett['data-table']['show-hxl-tags'] !== 'undefined') + } + if (typeof _sett['data-table']['show-hxl-tags'] !== 'undefined') { this.state.showHXLTags = _sett['data-table']['show-hxl-tags']; + } } autoBind(this); @@ -66,11 +67,11 @@ export class TableColumnFilter extends React.Component { actions.table.updateSettings(this.props.asset.uid, settings); } else { - console.log('just update the state, since user cannot save settings'); + // just update the state, since user cannot save settings let overrides = { showGroupName: s.showGroupName, - translationIndex: s.translationIndex - } + translationIndex: s.translationIndex, + }; this.props.overrideLabelsAndGroups(overrides); } @@ -85,45 +86,36 @@ export class TableColumnFilter extends React.Component { selectedColumns.push(columnId); } - this.setState({ - selectedColumns: selectedColumns - }) + this.setState({selectedColumns: selectedColumns}); } setFrozenColumn(col) { - this.setState({ - frozenColumn: col ? col : false - }) + this.setState({frozenColumn: col ? col : false}); } updateGroupHeaderDisplay(isChecked) { - this.setState({ - showGroupName: isChecked - }) + this.setState({showGroupName: isChecked}); } onHXLTagsChange(isChecked) { - this.setState({ - showHXLTags: isChecked - }) + this.setState({showHXLTags: isChecked}); } onLabelChange(name, value) { - this.setState({ - translationIndex: parseInt(value) - }) + this.setState({translationIndex: parseInt(value)}); } settingsUpdateFailed() { notify(t('There was an error, table settings could not be saved.')); } resetTableSettings() { let settings = this.props.asset.settings; - if (settings['data-table']) + if (settings['data-table']) { delete settings['data-table']; + } actions.table.updateSettings(this.props.asset.uid, settings); } listColumns() { let stateOverrides = { showGroupName: this.state.showGroupName, - translationIndex: this.state.translationIndex - } + translationIndex: this.state.translationIndex, + }; let colsArray = this.props.columns.reduce((acc, col) => { if (col.id && col.id !== SUBMISSION_LINKS_ID && col.id !== SUBMISSION_CHECKBOX_ID) { let qParentGroup = []; @@ -133,7 +125,7 @@ export class TableColumnFilter extends React.Component { acc.push({ value: col.id, - label: this.props.getColumnLabel(col.id, col.question, qParentGroup, stateOverrides) + label: this.props.getColumnLabel(col.id, col.question, qParentGroup, stateOverrides), }); } return acc; @@ -141,16 +133,16 @@ export class TableColumnFilter extends React.Component { colsArray.unshift({ value: SUBMISSION_LINKS_ID, - label: t('Submission links') + label: t('Submission links'), }); return colsArray; } - getDisplayedLabelOptions () { + getDisplayedLabelOptions() { const options = []; options.push({ value: -1, - label: t('XML Values') + label: t('XML Values'), }); this.props.asset.content.translations.map((trns, n) => { let label = t('Labels'); @@ -159,12 +151,12 @@ export class TableColumnFilter extends React.Component { } options.push({ value: n, - label: label + label: label, }); }); return options; } - render () { + render() { let _this = this; return ( @@ -218,7 +210,7 @@ export class TableColumnFilter extends React.Component { {t('All columns are visible by default')}
    - {this.listColumns().map(function(col) { + {this.listColumns().map(function (col) { return (
- ) + ); } } diff --git a/test/index.js b/test/index.js index d962eef587..1ae8298eb6 100644 --- a/test/index.js +++ b/test/index.js @@ -19,4 +19,4 @@ require('./xlform/utils.tests'); require('../jsapp/js/utils.tests'); require('../jsapp/js/components/permissions/permParser.tests'); require('../jsapp/js/assetUtils.tests'); -require('../jsapp/js/submissionUtils.tests'); +require('../jsapp/js/components/submissions/submissionUtils.tests');