From 61cd0d7e33e0c08a9e87cfb7fb337bd1e3c38a37 Mon Sep 17 00:00:00 2001 From: Patrick White Date: Wed, 25 May 2016 09:56:56 -0400 Subject: [PATCH 1/6] Filter function for dashboard subject search Created an event handler and input element to which it is bound to enable to user to filter subjects by matching against their string properties. --- app/redidropper/static/js/dashboard.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/redidropper/static/js/dashboard.js b/app/redidropper/static/js/dashboard.js index c49a5ad..a88a22f 100644 --- a/app/redidropper/static/js/dashboard.js +++ b/app/redidropper/static/js/dashboard.js @@ -96,6 +96,24 @@ var SubjectsTable = React.createClass({ componentWillReceiveProps: function(nextProps) { this.changeData(1, nextProps.max_events); }, + + onInputChange: function(event) { + var hasMatchingProperty = function (isMatching, property) { + if (typeof property === "String") { + isMatching = isMatching || property.includes(text); + } + return isMatching; + }, + matchEventText = function(subject) { + var text = event.target.value, + properties = Object.keys(subject).map((key) => subject[key]); + return properties.reduce(hasMatchingProperty, false); + }; + this.setState({ + subjects: (this.subjects || []).filter(matchEventText) + }); + }, + render: function() { var table_rows = []; var subjects_data = this.state.subjects; @@ -146,6 +164,7 @@ var SubjectsTable = React.createClass({ return (
+ {subjects_table} {pagination}
From 2559c4a07dbdf36f12ee942f62c2a7b0da2fea78 Mon Sep 17 00:00:00 2001 From: Patrick White Date: Wed, 25 May 2016 11:00:09 -0400 Subject: [PATCH 2/6] Polling for new subject data Users wanted to see new subjects as they were working without a page refresh. We call change data with the arguments it was called with previously every five seconds. --- app/redidropper/static/js/dashboard.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/app/redidropper/static/js/dashboard.js b/app/redidropper/static/js/dashboard.js index a88a22f..e705e82 100644 --- a/app/redidropper/static/js/dashboard.js +++ b/app/redidropper/static/js/dashboard.js @@ -66,7 +66,8 @@ var SubjectsTable = React.createClass({ return { subjects: [], max_events: this.props.max_events, - no_of_pages: 0 + no_of_pages: 0, + previous_changeData_args: [] }; }, changePage: function(i) { @@ -76,11 +77,15 @@ var SubjectsTable = React.createClass({ // if needed we will allow the user to select how many rows to display per page var per_page = 25; var request_data = {'per_page': per_page, 'page_num': page_num}; - var _this = this; var request = Utils.api_post_json("/api/list_local_subjects", request_data); + var self = this; + + this.setState({ + previous_changeData_args: arguments, + }); request.success( function(json) { - _this.setState({ + self.setState({ subjects: json.data.list_of_subjects, max_events: max_events, no_of_pages: json.data.total_pages @@ -92,10 +97,17 @@ var SubjectsTable = React.createClass({ }, componentWillMount: function() { this.changeData(1, this.props.max_events); + + this.setState({ + intervalUpdateHandler: window.setInterval(this.updateData, 5000) + }); }, componentWillReceiveProps: function(nextProps) { this.changeData(1, nextProps.max_events); }, + componentWillUnmount: function() { + window.clearInterval(this.state.updateIntervalHandler); + }, onInputChange: function(event) { var hasMatchingProperty = function (isMatching, property) { @@ -114,6 +126,10 @@ var SubjectsTable = React.createClass({ }); }, + updateData: function() { + this.changeData.apply(this, this.state.previous_changeData_args.slice(1)); + }, + render: function() { var table_rows = []; var subjects_data = this.state.subjects; From 44843c901bc80dc64cfa31379388ed18748ead12 Mon Sep 17 00:00:00 2001 From: Patrick White Date: Wed, 25 May 2016 11:14:28 -0400 Subject: [PATCH 3/6] Fixing error. this reference is not included in arguments object --- app/redidropper/static/js/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/redidropper/static/js/dashboard.js b/app/redidropper/static/js/dashboard.js index e705e82..56532b4 100644 --- a/app/redidropper/static/js/dashboard.js +++ b/app/redidropper/static/js/dashboard.js @@ -127,7 +127,7 @@ var SubjectsTable = React.createClass({ }, updateData: function() { - this.changeData.apply(this, this.state.previous_changeData_args.slice(1)); + this.changeData.apply(this, this.state.previous_changeData_args); }, render: function() { From 2cae5ba5c517c7fa54d18ab21584e3ad0883b058 Mon Sep 17 00:00:00 2001 From: Patrick White Date: Thu, 16 Jun 2016 15:22:07 -0400 Subject: [PATCH 4/6] Fixed dashboard presentation. Added ajax search filtering functionality to limit subjects. Removed polling, instead new subjects are pulled with the search box changes Got rid of some of the use of tables for formatting since this is not good practice. --- app/redidropper/static/css/layout.css | 9 +++ app/redidropper/static/js/dashboard.js | 106 +++++++++---------------- 2 files changed, 48 insertions(+), 67 deletions(-) diff --git a/app/redidropper/static/css/layout.css b/app/redidropper/static/css/layout.css index 192fc5e..92d7709 100644 --- a/app/redidropper/static/css/layout.css +++ b/app/redidropper/static/css/layout.css @@ -69,3 +69,12 @@ table.borderless td, table.borderless th { padding-top: 5px; color: #888; } + +.subject-button{ + margin: .5rem; + float: left; +} + +.search-subjects{ + margin-bottom: 1rem; +} diff --git a/app/redidropper/static/js/dashboard.js b/app/redidropper/static/js/dashboard.js index 56532b4..cc29f1d 100644 --- a/app/redidropper/static/js/dashboard.js +++ b/app/redidropper/static/js/dashboard.js @@ -33,28 +33,16 @@ var SubjectsRow = React.createClass({ */ render: function() { var column_count = this.state.max_events; - var table_columns = []; var row_data = this.state.row_data; var events_count = 0; var i; - /* - for (i = events_count + 2; i <= column_count; i++) { - table_columns.push(); - } - */ - var selectSubject = this.props.subjectSelected.bind(null, row_data); return ( - - - - - {table_columns} - + ); } }); @@ -74,65 +62,56 @@ var SubjectsTable = React.createClass({ this.changeData(i, this.state.max_events); }, changeData: function(page_num, max_events) { - // if needed we will allow the user to select how many rows to display per page - var per_page = 25; - var request_data = {'per_page': per_page, 'page_num': page_num}; - var request = Utils.api_post_json("/api/list_local_subjects", request_data); - var self = this; - - this.setState({ - previous_changeData_args: arguments, - }); - - request.success( function(json) { - self.setState({ - subjects: json.data.list_of_subjects, - max_events: max_events, - no_of_pages: json.data.total_pages - }); - }); - request.fail(function (jqXHR, textStatus, error) { - console.log('Failed: ' + textStatus + error); - }); + var subjects, + success = (json) => { + this.setState({ + subjects: json.data.list_of_subjects + }); + }, + failure = function (jqXHR, textStatus, error) { + console.log('Failed: ' + textStatus + error); + }; + this.getSubjectList(page_num, max_events, success, failure); }, componentWillMount: function() { this.changeData(1, this.props.max_events); - - this.setState({ - intervalUpdateHandler: window.setInterval(this.updateData, 5000) - }); }, componentWillReceiveProps: function(nextProps) { this.changeData(1, nextProps.max_events); }, - componentWillUnmount: function() { - window.clearInterval(this.state.updateIntervalHandler); + + getSubjectList: function (page_num, max_events, successCallback, failureCallback) { + // if needed we will allow the user to select how many rows to display per page + var per_page = 25; + var request_data = {'per_page': per_page, 'page_num': page_num}; + var request = Utils.api_post_json("/api/list_local_subjects", request_data); + var self = this; + + request.success(successCallback); + request.fail(failureCallback); }, onInputChange: function(event) { - var hasMatchingProperty = function (isMatching, property) { - if (typeof property === "String") { - isMatching = isMatching || property.includes(text); - } - return isMatching; + var text = event.target.value, + matchesRedcapId = function(subject) { + return subject.redcap_id.includes(text); + }, + success = (json) => { + this.setState({ + subjects: (json.data.list_of_subjects || []).filter(matchesRedcapId) + }); }, - matchEventText = function(subject) { - var text = event.target.value, - properties = Object.keys(subject).map((key) => subject[key]); - return properties.reduce(hasMatchingProperty, false); + failure = function (jqXHR, textStatus, error) { + console.log('Failed: ' + textStatus + error); }; - this.setState({ - subjects: (this.subjects || []).filter(matchEventText) - }); - }, - - updateData: function() { - this.changeData.apply(this, this.state.previous_changeData_args); + this.getSubjectList(undefined, undefined, success, failure); }, render: function() { var table_rows = []; - var subjects_data = this.state.subjects; + var subjects_data = this.state.subjects.sort((a, b) => { + return Number(a.redcap_id) < Number(b.redcap_id) ? -1 : 1; + }); var row_count = subjects_data.length; var column_count = this.state.max_events; @@ -166,21 +145,14 @@ var SubjectsTable = React.createClass({ else { subjects_table = (
- - - {table_columns} - - {table_rows} - -
); } return (
- + {subjects_table} {pagination}
From a54ee92b300ff3ac0b91666e4c0cffc4b99f666a Mon Sep 17 00:00:00 2001 From: Patrick White Date: Mon, 18 Jul 2016 09:01:24 -0400 Subject: [PATCH 5/6] Adding back in some state changes that got removed. I don't think they are being used, but I don't remember why I took them out so they stay in. --- app/redidropper/static/js/dashboard.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/redidropper/static/js/dashboard.js b/app/redidropper/static/js/dashboard.js index cc29f1d..c711d48 100644 --- a/app/redidropper/static/js/dashboard.js +++ b/app/redidropper/static/js/dashboard.js @@ -55,7 +55,6 @@ var SubjectsTable = React.createClass({ subjects: [], max_events: this.props.max_events, no_of_pages: 0, - previous_changeData_args: [] }; }, changePage: function(i) { @@ -65,7 +64,9 @@ var SubjectsTable = React.createClass({ var subjects, success = (json) => { this.setState({ - subjects: json.data.list_of_subjects + subjects: json.data.list_of_subjects, + max_events: this.props.max_events, + no_of_pages: json.data.total_pages, }); }, failure = function (jqXHR, textStatus, error) { From 2b14c3f22533015af4c7a677d25f8d2d8296a7c4 Mon Sep 17 00:00:00 2001 From: Patrick White Date: Mon, 18 Jul 2016 11:00:19 -0400 Subject: [PATCH 6/6] Fixes for pagination. Results per page increased to 50 Search searches all pages pagination displays below subjects --- app/redidropper/static/js/dashboard.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/redidropper/static/js/dashboard.js b/app/redidropper/static/js/dashboard.js index c711d48..e18de11 100644 --- a/app/redidropper/static/js/dashboard.js +++ b/app/redidropper/static/js/dashboard.js @@ -81,9 +81,9 @@ var SubjectsTable = React.createClass({ this.changeData(1, nextProps.max_events); }, - getSubjectList: function (page_num, max_events, successCallback, failureCallback) { + getSubjectList: function (page_num, max_events, successCallback, failureCallback, resultsPerPage) { // if needed we will allow the user to select how many rows to display per page - var per_page = 25; + var per_page = resultsPerPage || 50; var request_data = {'per_page': per_page, 'page_num': page_num}; var request = Utils.api_post_json("/api/list_local_subjects", request_data); var self = this; @@ -105,7 +105,7 @@ var SubjectsTable = React.createClass({ failure = function (jqXHR, textStatus, error) { console.log('Failed: ' + textStatus + error); }; - this.getSubjectList(undefined, undefined, success, failure); + this.getSubjectList(undefined, undefined, success, failure, 9999); }, render: function() { @@ -152,11 +152,13 @@ var SubjectsTable = React.createClass({ } return ( -
- - {subjects_table} - {pagination} -
+
+
+ + {subjects_table} +
+ {pagination} +
); } });