From fcbfe2e5da63e8592a1365859fd65c3c4144aa10 Mon Sep 17 00:00:00 2001
From: Ashwin Srinivasan
Date: Fri, 26 Apr 2019 17:01:21 -0400
Subject: [PATCH 01/10] Added option to hide delete button, mask student IDs
---
server/public/javascripts/datarow.js | 3 +-
server/public/javascripts/datatable.js | 37 ++++++++++---
server/public/javascripts/dataview.js | 11 ++--
server/public/javascripts/dataviewbar.js | 3 +-
server/public/javascripts/react/datarow.jsx | 4 +-
server/public/javascripts/react/datatable.jsx | 17 +++++-
server/public/javascripts/react/dataview.jsx | 7 +--
.../public/javascripts/react/dataviewbar.jsx | 54 ++++++++++---------
server/routes/admin.js | 27 +++++-----
server/views/partials/config.hbs | 6 +++
10 files changed, 109 insertions(+), 60 deletions(-)
diff --git a/server/public/javascripts/datarow.js b/server/public/javascripts/datarow.js
index 7e36606..0b537fa 100644
--- a/server/public/javascripts/datarow.js
+++ b/server/public/javascripts/datarow.js
@@ -53,6 +53,7 @@ var DataRow = function (_React$Component) {
key: 'render',
value: function render() {
var _props = this.props,
+ showStudent = _props.showStudent,
_id = _props._id,
section = _props.section,
student_id = _props.student_id,
@@ -76,7 +77,7 @@ var DataRow = function (_React$Component) {
React.createElement(
'td',
null,
- student_id
+ showStudent ? student_id : '••••••'
),
React.createElement(
'td',
diff --git a/server/public/javascripts/datatable.js b/server/public/javascripts/datatable.js
index 3d8f2e0..00e26af 100644
--- a/server/public/javascripts/datatable.js
+++ b/server/public/javascripts/datatable.js
@@ -17,10 +17,12 @@ var DataTable = function (_React$Component) {
var _this = _possibleConstructorReturn(this, (DataTable.__proto__ || Object.getPrototypeOf(DataTable)).call(this, props));
_this.state = {
+ studentVisibility: false,
lab: '',
labActive: false,
preserve: false
};
+ _this.toggleStudentVisibility = _this.toggleStudentVisibility.bind(_this);
_this.toggleLab = _this.toggleLab.bind(_this);
_this.onChangeLab = _this.onChangeLab.bind(_this);
_this.onChangePreserve = _this.onChangePreserve.bind(_this);
@@ -29,10 +31,18 @@ var DataTable = function (_React$Component) {
}
_createClass(DataTable, [{
+ key: 'toggleStudentVisibility',
+ value: function toggleStudentVisibility() {
+ this.setState(function (_ref) {
+ var studentVisibility = _ref.studentVisibility;
+ return { studentVisibility: !studentVisibility };
+ });
+ }
+ }, {
key: 'toggleLab',
value: function toggleLab() {
- this.setState(function (_ref) {
- var labActive = _ref.labActive;
+ this.setState(function (_ref2) {
+ var labActive = _ref2.labActive;
return { labActive: !labActive };
});
}
@@ -67,7 +77,9 @@ var DataTable = function (_React$Component) {
sort = _props.sort,
entries = _props.entries,
updateSort = _props.updateSort;
- var labActive = this.state.labActive;
+ var _state2 = this.state,
+ studentVisibility = _state2.studentVisibility,
+ labActive = _state2.labActive;
var columns = [['Section', 'section'], ['Student ID', 'student_id'], ['Score', 'score'], ['Lab', 'lab'], ['Date', 'date'], ['TA', 'ta'], ['Flags', 'flags']];
return React.createElement(
@@ -79,10 +91,10 @@ var DataTable = function (_React$Component) {
React.createElement(
'tr',
null,
- columns.map(function (_ref2) {
- var _ref3 = _slicedToArray(_ref2, 2),
- title = _ref3[0],
- name = _ref3[1];
+ columns.map(function (_ref3) {
+ var _ref4 = _slicedToArray(_ref3, 2),
+ title = _ref4[0],
+ name = _ref4[1];
return React.createElement(
'th',
@@ -172,6 +184,15 @@ var DataTable = function (_React$Component) {
{ className: 'icon' },
React.createElement('i', { className: 'fas fa-caret-' + (sort[name] > 0 ? 'down' : 'up') })
)
+ ),
+ name === 'student_id' && React.createElement(
+ 'a',
+ { className: 'tooltip', 'data-tooltip': 'Toggle visibility', onClick: _this2.toggleStudentVisibility },
+ React.createElement(
+ 'span',
+ { className: 'icon has-text-info' },
+ React.createElement('i', { className: 'fas fa-' + (studentVisibility ? 'eye-slash' : 'eye') })
+ )
)
);
})
@@ -181,7 +202,7 @@ var DataTable = function (_React$Component) {
'tbody',
null,
entries.map(function (entry) {
- return React.createElement(DataRow, Object.assign({ key: entry._id }, entry));
+ return React.createElement(DataRow, Object.assign({ showStudent: studentVisibility, key: entry._id }, entry));
})
)
);
diff --git a/server/public/javascripts/dataview.js b/server/public/javascripts/dataview.js
index cb8b029..0975f7a 100644
--- a/server/public/javascripts/dataview.js
+++ b/server/public/javascripts/dataview.js
@@ -17,6 +17,7 @@ var DataView = function (_React$Component) {
_this.state = {
error: null,
isLoaded: false,
+ showData: true,
entries: [],
filters: {
good: true
@@ -49,10 +50,9 @@ var DataView = function (_React$Component) {
filters: this.state.filters,
sort: this.state.sort
}).then(function (res) {
- return _this2.setState({
- isLoaded: true,
- entries: res.data
- });
+ return _this2.setState(Object.assign({
+ isLoaded: true
+ }, res.data));
}, function (err) {
return _this2.setState({
isLoaded: true,
@@ -194,6 +194,7 @@ var DataView = function (_React$Component) {
var _state = this.state,
error = _state.error,
isLoaded = _state.isLoaded,
+ showDelete = _state.showDelete,
entries = _state.entries,
filters = _state.filters,
sort = _state.sort,
@@ -221,7 +222,7 @@ var DataView = function (_React$Component) {
'div',
null,
React.createElement(FilterPane, { filters: filters, filtersActive: filtersActive, toggleFilters: this.toggleFilters, updateFilters: this.updateFilters, getData: this.getData }),
- React.createElement(DataViewBar, { entriesCount: entries.length, filters: filters, toggleFilters: this.toggleFilters, updateFilters: this.updateFilters, getData: this.getData, downloadData: this.downloadData, deleteData: this.deleteData }),
+ React.createElement(DataViewBar, { showDelete: showDelete, entriesCount: entries.length, filters: filters, toggleFilters: this.toggleFilters, updateFilters: this.updateFilters, getData: this.getData, downloadData: this.downloadData, deleteData: this.deleteData }),
React.createElement(DataDownload, { isActive: modalActive, toggleModal: this.toggleModal, data: downloadData, type: downloadType }),
React.createElement(DataTable, { sort: sort, entries: entries, updateSort: this.updateSort, assignLab: this.assignLab })
);
diff --git a/server/public/javascripts/dataviewbar.js b/server/public/javascripts/dataviewbar.js
index 09a2d12..1bb37e2 100644
--- a/server/public/javascripts/dataviewbar.js
+++ b/server/public/javascripts/dataviewbar.js
@@ -50,6 +50,7 @@ var DataViewBar = function (_React$Component) {
key: 'render',
value: function render() {
var _props = this.props,
+ showDelete = _props.showDelete,
filters = _props.filters,
toggleFilters = _props.toggleFilters,
updateFilters = _props.updateFilters,
@@ -212,7 +213,7 @@ var DataViewBar = function (_React$Component) {
)
)
),
- React.createElement(
+ showDelete && React.createElement(
'p',
{ className: 'level-item' },
React.createElement(
diff --git a/server/public/javascripts/react/datarow.jsx b/server/public/javascripts/react/datarow.jsx
index 51d99f5..110db22 100644
--- a/server/public/javascripts/react/datarow.jsx
+++ b/server/public/javascripts/react/datarow.jsx
@@ -28,14 +28,14 @@ class DataRow extends React.Component {
}
render() {
- const { _id, section, student_id, score, lab, date, ta, flags } = this.props;
+ const { showStudent, _id, section, student_id, score, lab, date, ta, flags } = this.props;
const { good, isActive } = this.state;
return
{section}
|
- {student_id}
+ {showStudent ? student_id : '••••••'}
|
{score}
diff --git a/server/public/javascripts/react/datatable.jsx b/server/public/javascripts/react/datatable.jsx
index 0232b12..20e2b7a 100644
--- a/server/public/javascripts/react/datatable.jsx
+++ b/server/public/javascripts/react/datatable.jsx
@@ -2,16 +2,22 @@ class DataTable extends React.Component {
constructor(props) {
super(props);
this.state = {
+ studentVisibility: false,
lab: '',
labActive: false,
preserve: false,
};
+ this.toggleStudentVisibility = this.toggleStudentVisibility.bind(this);
this.toggleLab = this.toggleLab.bind(this);
this.onChangeLab = this.onChangeLab.bind(this);
this.onChangePreserve = this.onChangePreserve.bind(this);
this.sendLab = this.sendLab.bind(this);
}
+ toggleStudentVisibility() {
+ this.setState(({ studentVisibility }) => ({ studentVisibility: !studentVisibility }));
+ }
+
toggleLab() {
this.setState(({ labActive }) => ({ labActive: !labActive }));
}
@@ -34,7 +40,7 @@ class DataTable extends React.Component {
render() {
const { sort, entries, updateSort } = this.props;
- const { labActive } = this.state;
+ const { studentVisibility, labActive } = this.state;
const columns = [
['Section', 'section'],
['Student ID', 'student_id'],
@@ -98,13 +104,20 @@ class DataTable extends React.Component {
}
+ {name === 'student_id' &&
+
+
+
+
+
+ }
))}
|
{entries.map(entry => (
-
+
))}
;
diff --git a/server/public/javascripts/react/dataview.jsx b/server/public/javascripts/react/dataview.jsx
index 5c24ec8..d6eac63 100644
--- a/server/public/javascripts/react/dataview.jsx
+++ b/server/public/javascripts/react/dataview.jsx
@@ -4,6 +4,7 @@ class DataView extends React.Component {
this.state = {
error: null,
isLoaded: false,
+ showData: true,
entries: [],
filters: {
good: true,
@@ -32,7 +33,7 @@ class DataView extends React.Component {
sort: this.state.sort,
}).then(res => this.setState({
isLoaded: true,
- entries: res.data,
+ ...res.data,
}), err => this.setState({
isLoaded: true,
error: err,
@@ -135,7 +136,7 @@ class DataView extends React.Component {
render() {
const {
- error, isLoaded, entries, filters, sort, filtersActive, modalActive, downloadData, downloadType,
+ error, isLoaded, showDelete, entries, filters, sort, filtersActive, modalActive, downloadData, downloadType,
} = this.state;
if (error) {
return Error: {error.message}
;
@@ -145,7 +146,7 @@ class DataView extends React.Component {
}
return
-
+
;
diff --git a/server/public/javascripts/react/dataviewbar.jsx b/server/public/javascripts/react/dataviewbar.jsx
index 88bad5a..5bcfbd9 100644
--- a/server/public/javascripts/react/dataviewbar.jsx
+++ b/server/public/javascripts/react/dataviewbar.jsx
@@ -28,7 +28,7 @@ class DataViewBar extends React.Component {
render() {
const {
- filters, toggleFilters, updateFilters, getData, downloadData,
+ showDelete, filters, toggleFilters, updateFilters, getData, downloadData,
} = this.props;
const { deleteConfirmation, deleteActive } = this.state;
return
-
-
-
-
-
-
- Delete
-
-
-
-
-
-
+ {showDelete &&
+
+
-
-
+
+ }
;
}
diff --git a/server/routes/admin.js b/server/routes/admin.js
index 7702dc4..1860244 100644
--- a/server/routes/admin.js
+++ b/server/routes/admin.js
@@ -35,7 +35,7 @@ function parseDataQuery(query) {
const options = {};
const { filters } = query;
const {
- startDate, endDate, flags, good,
+ startDate, endDate, flags,
} = filters;
// special case: start and end date must be used together
if (startDate && endDate) {
@@ -141,17 +141,20 @@ router.post('/rawdata', (req, res, next) => {
Entry.find(options).sort(sort).exec((err, entries) => {
if (err) return next(createError(500, err));
// send data after some modifications
- res.send(entries.map((entry) => {
- // convert each entry to json to get rid of helper functions
- const newEntry = entry.toJSON();
- // prettify date
- newEntry.date = helpers.prettyDate(entry.date);
- // if entry has attempt flag, prettify the time interval
- if (newEntry.flags && newEntry.flags.attemptDiff) {
- newEntry.flags.attemptDiff = helpers.prettyDiff(newEntry.flags.attemptDiff);
- }
- return newEntry;
- }));
+ res.send({
+ showDelete: config.get('showDelete'),
+ entries: entries.map((entry) => {
+ // convert each entry to json to get rid of helper functions
+ const newEntry = entry.toJSON();
+ // prettify date
+ newEntry.date = helpers.prettyDate(entry.date);
+ // if entry has attempt flag, prettify the time interval
+ if (newEntry.flags && newEntry.flags.attemptDiff) {
+ newEntry.flags.attemptDiff = helpers.prettyDiff(newEntry.flags.attemptDiff);
+ }
+ return newEntry;
+ }),
+ });
});
});
diff --git a/server/views/partials/config.hbs b/server/views/partials/config.hbs
index 38906b8..3ea636a 100644
--- a/server/views/partials/config.hbs
+++ b/server/views/partials/config.hbs
@@ -48,6 +48,12 @@
+
+