Skip to content

Commit dd8676d

Browse files
committed
Moved Owner field from DataType to Data, Sample, Subject. All tests pass #38
1 parent 0759949 commit dd8676d

34 files changed

+329
-100
lines changed

api/controllers/DataController.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @help :: See http://links.sailsjs.org/docs/controllers
66
*/
77
/* jshint node: true */
8-
/* globals _, sails, Data, DataType, DataService, DataTypeService, SubjectService, SampleService, QueryService, TokenService, DataTypePrivileges */
8+
/* globals _, sails, Data, DataType, DataService, DataTypeService, SubjectService, OperatorService, SampleService, QueryService, TokenService, DataTypePrivileges */
99
"use strict";
1010

1111
const BluebirdPromise = require('bluebird');
@@ -175,6 +175,8 @@ const coroutines = {
175175
if (_.isEmpty(payload.dataTypes)){ throw new PrivilegesError(`Authenticated user has not edit privileges on any data type`); }
176176

177177
if (payload.data){
178+
let operators = yield OperatorService.getOwners(payload.data);
179+
payload.operators = operators;
178180
// if operator has not access to Sensitive Data and dataType has sensitive data, then return forbidden
179181
const sensitiveRes = yield DataService.hasDataSensitive(payload.data.id, DATA);
180182
if (sensitiveRes && ((sensitiveRes.hasDataSensitive && !operator.canAccessSensitiveData))) {

api/controllers/SampleController.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @help :: See http://links.sailsjs.org/docs/controllers
66
*/
77
/* jshint node: true */
8-
/* globals _, sails, Sample, DataType, SubjectService, BiobankService, SampleService, DataTypePrivileges, TokenService, QueryService, DataService, DataTypeService */
8+
/* globals _, sails, Sample, DataType, SubjectService, BiobankService, OperatorService, SampleService, DataTypePrivileges, TokenService, QueryService, DataService, DataTypeService */
99
"use strict";
1010

1111
const BluebirdPromise = require('bluebird');
@@ -176,6 +176,9 @@ const coroutines = {
176176

177177

178178
if (payload.sample){
179+
180+
let operators = yield OperatorService.getOwners(payload.sample);
181+
payload.operators = operators;
179182
// if operator has not access to Sensitive Data and dataType has sensitive data, then return forbidden
180183
const sensitiveRes = yield DataService.hasDataSensitive(payload.sample.id, SAMPLE);
181184
if (sensitiveRes && ((sensitiveRes.hasDataSensitive && !operator.canAccessSensitiveData))) {

api/controllers/SubjectController.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @help :: See http://links.sailsjs.org/docs/controllers
66
*/
77
/* jshint node: true */
8-
/* globals _, sails, DataTypePrivileges, Subject, DataType, SubjectService, TokenService, QueryService, DataService, DataTypeService */
8+
/* globals _, sails, DataTypePrivileges, Subject, DataType, SubjectService, OperatorService, TokenService, QueryService, DataService, DataTypeService */
99
"use strict";
1010

1111
const ControllerOut = require("xtens-utils").ControllerOut;
@@ -178,6 +178,8 @@ const coroutines = {
178178
if (_.isEmpty(payload.dataTypes)){ throw new PrivilegesError(`Authenticated user has not edit privileges on any subject type`); }
179179

180180
if (payload.subject){
181+
let operators = yield OperatorService.getOwners(payload.subject);
182+
payload.operators = operators;
181183
// if operator has not access to Sensitive Data and dataType has sensitive data, then return forbidden
182184
const sensitiveRes = yield DataService.hasDataSensitive(payload.subject.id, SUBJECT);
183185
if (sensitiveRes && ((sensitiveRes.hasDataSensitive && !operator.canAccessSensitiveData))) {

api/models/Data.js

+4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ var Data = {
5454
model: 'data',
5555
columnName: 'parent_data'
5656
},
57+
owner: {
58+
model: 'operator',
59+
columnName: 'owner'
60+
},
5761
createdAt: {
5862
type: 'datetime',
5963
columnName: 'created_at'

api/models/Sample.js

+5
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ module.exports = {
5353
via: 'samples',
5454
dominant: true
5555
},
56+
57+
owner: {
58+
model: 'operator',
59+
columnName: 'owner'
60+
},
5661

5762
createdAt: {
5863
type: 'datetime',

api/models/Subject.js

+5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ var Subject= {
5959
required: false
6060
},
6161

62+
owner: {
63+
model: 'operator',
64+
columnName: 'owner'
65+
},
66+
6267
createdAt: {
6368
type: 'datetime',
6469
columnName: 'created_at'

api/services/DataService.js

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ let DataService = BluebirdPromise.promisifyAll({
5151
let validationSchema = {
5252
id: Joi.number().integer().positive(),
5353
type: Joi.number().integer().positive().required(),
54+
owner: Joi.number().integer().positive().required(),
5455
date: Joi.string().isoDate().allow(null),
5556
tags: Joi.array().allow(null),
5657
notes: Joi.string().allow(null),

api/services/GroupService.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const coroutines = {
2727
}),
2828

2929
getGroupsByProject: BluebirdPromise.coroutine(function *(idProject) {
30-
let groups = yield Group.find().populate('projects');
30+
let groups = yield Group.find().populate(['projects','members']);
3131

3232
for (var i = groups.length - 1; i >= 0; i--) {
3333
if(groups[i].privilegeLevel !== "wheel" && _.indexOf(_.map(groups[i].projects,'id'), _.parseInt(idProject))<0){

api/services/OperatorService.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* @module
3+
* @name OperatorService
4+
* @author Nicolò Zanardi
5+
*/
6+
7+
/* jshint esnext: true */
8+
/* jshint node: true */
9+
/* globals _, sails , GroupService */
10+
11+
const BluebirdPromise = require('bluebird');
12+
13+
const coroutines = {
14+
15+
getOwners: BluebirdPromise.coroutine(function *(datum) {
16+
17+
if (!datum || !datum.type) {
18+
return [];
19+
}
20+
let idProject = _.isObject(datum.type.project) ? datum.type.project.id : datum.type.project;
21+
// _.isObject(datum.type.project);
22+
let groups = yield GroupService.getGroupsByProject(idProject);
23+
24+
let operators = _.uniq(_.flatten(_.map(groups,'members')));
25+
return operators;
26+
27+
})
28+
};
29+
30+
31+
32+
var OperatorService = BluebirdPromise.promisifyAll({
33+
34+
/**
35+
* @method
36+
* @name getOwners
37+
* @param{object} data object
38+
* @description find a list of Operators
39+
* @return {Array} - list of elegible Operators to owner a specific datum
40+
*/
41+
getOwners: function(datum) {
42+
return coroutines.getOwners(datum)
43+
.catch((err) => {
44+
sails.log(err);
45+
return err;
46+
});
47+
}
48+
});
49+
50+
module.exports = OperatorService;

api/services/SampleService.js

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ let SampleService = BluebirdPromise.promisifyAll({
4545
let validationSchema = {
4646
id: Joi.number().integer().positive(),
4747
type: Joi.number().integer().positive().required(),
48+
owner: Joi.number().integer().positive().required(),
4849
biobank: Joi.number().integer().positive().required(),
4950
biobankCode: Joi.string().allow("").allow(null), // TODO change this one
5051
donor: Joi.number().integer().positive(),

api/services/SubjectService.js

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ let SubjectService = BluebirdPromise.promisifyAll({
7676
let validationSchema = {
7777
id: Joi.number().integer().positive(),
7878
type: Joi.number().integer().positive().required(),
79+
owner: Joi.number().integer().positive().required(),
7980
code: Joi.string().uppercase(),
8081
sex: Joi.string().required().valid(_.values(sails.config.xtens.constants.SexOptions)),
8182
personalInfo: Joi.object().keys(personalInfoValidationSchema).allow(null),

assets/js/modules/Data.js

+65-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
var DataTypeModel = xtens.module("datatype").Model;
1818
var DataTypeCollection = xtens.module("datatype").List;
1919
var FileManager = xtens.module("filemanager");
20+
var Group = xtens.module("group");
2021
var replaceUnderscoreAndCapitalize = xtens.module("utils").replaceUnderscoreAndCapitalize;
2122
var dateUtil = xtens.module("utils").date;
2223
var ModalDialog = xtens.module("xtensbootstrap").Views.ModalDialog;
@@ -694,6 +695,7 @@
694695
this.template = JST["views/templates/data-edit.ejs"];
695696
this.schemaView = null;
696697
this.dataTypes = options.dataTypes || [];
698+
this.operators = options.operators ? options.operators : [];
697699
// _.extend(this, options);
698700
if (options.data) {
699701
this.model = new Data.Model(options.data);
@@ -734,7 +736,7 @@
734736
* @description Backbone.stickit bindings
735737
*/
736738
bindings: {
737-
'#dataType': {
739+
'#data-type': {
738740
observe: 'type',
739741
selectOptions: {
740742
collection: 'this.dataTypes',
@@ -762,6 +764,29 @@
762764
}
763765
},
764766

767+
'#owner': {
768+
observe: 'owner',
769+
initialize: function($el) {
770+
$el.select2({placeholder: i18n("please-select") });
771+
},
772+
selectOptions: {
773+
collection: function() {
774+
var coll = [];
775+
_.each(this.operators, function(op){
776+
coll.push({label:op.lastName + ' ' + op.firstName ,value:op.id});
777+
});
778+
return coll;
779+
},
780+
defaultOption: {
781+
label: '',
782+
value: null
783+
}
784+
},
785+
onGet: function(val) {
786+
return val && val.id;
787+
}
788+
},
789+
765790
'#date': {
766791
observe: 'date',
767792

@@ -824,6 +849,7 @@
824849
var that = this;
825850
var metadata = this.schemaView.serialize(useFormattedNames);
826851
this.model.set("metadata", metadata);
852+
this.model.get("owner").id ? this.model.set("owner", this.model.get("owner").id) : null;
827853
// this.model.set("type", this.model.get("type").id); // trying to send only the id to permorf POST or PUT
828854
this.retrieveAndSetFiles();
829855
console.log(this.model);
@@ -856,6 +882,41 @@
856882
return false;
857883
},
858884

885+
setOwnerList: function () {
886+
var that = this, project, projectId;
887+
if ($('#data-type').val()) {
888+
var dataTypeSelected = _.parseInt($('#data-type').val());
889+
projectId = _.find(this.dataTypes,{id:dataTypeSelected}).project;
890+
project = _.find(xtens.session.get('projects'), function (p) {
891+
return p.id === projectId;
892+
});
893+
}else {
894+
project = _.find(xtens.session.get('projects'), function (p) {
895+
return p.name === xtens.session.get('activeProject');
896+
});
897+
}
898+
var groups = new Group.List();
899+
900+
var groupIds = _.compact(_.map(project.groups,function (g) {
901+
if ((g.privilegeLevel ==="wheel" || g.privilegeLevel ==="admin") ) {
902+
return g.id;
903+
}
904+
}));
905+
906+
var groupsDeferred = groups.fetch({
907+
data: $.param({where: {id: groupIds}, sort:'id ASC', limit:100, populate:['members']})
908+
});
909+
$.when(groupsDeferred).then(function(groupRes) {
910+
that.operators = _.isArray(groupRes) ?_.flatten(_.map(groupRes,'members')) :groupRes.members;
911+
var newColl = [];
912+
that.operators.forEach(function (op) {
913+
newColl.push({label:op.lastName + ' ' + op.firstName ,value:op.id});
914+
});
915+
var options = {selectOptions:{collection:newColl}};
916+
Backbone.Stickit.getConfiguration($('#owner')).update($('#owner'),{},{},options);
917+
$('#owner').val({}).trigger("change");
918+
});
919+
},
859920
/**
860921
* @method
861922
* @name deleteDate
@@ -918,6 +979,8 @@
918979
},
919980

920981
dataTypeOnChange: function() {
982+
$('#owner').prop('disabled', false);
983+
this.setOwnerList();
921984
this.renderDataTypeSchema();
922985
},
923986

@@ -1292,7 +1355,7 @@
12921355

12931356
render: function() {
12941357
this.$el.html(this.template({__: i18n}));
1295-
$("#dataType").selectpicker();
1358+
$("#data-type").selectpicker();
12961359
this.$('form').parsley(parsleyOpts);
12971360
this.dropzone = new Dropzone(this.$(".dropzone")[0], this.dropzoneOpts);
12981361

assets/js/modules/DataType.js

+7
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,20 @@
198198
},
199199
'#model': {
200200
observe: 'model',
201+
initialize: function($el) {
202+
$el.select2({placeholder: i18n("please-select") });
203+
},
201204
selectOptions: {
202205
collection: function() {
203206
var coll = [];
204207
_.each(DataTypeClasses, function(value){
205208
coll.push({label: value.toUpperCase(), value: value});
206209
});
207210
return coll;
211+
},
212+
defaultOption: {
213+
label: '',
214+
value: null
208215
}
209216
}
210217
},

assets/js/modules/Sample.js

+27-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
observe: 'biobankCode'
4040
},
4141

42-
'#type': {
42+
'#data-type': {
4343
observe: 'type',
4444
selectOptions: {
4545
collection: 'this.dataTypes',
@@ -73,6 +73,29 @@
7373
}
7474
},
7575

76+
'#owner': {
77+
observe: 'owner',
78+
initialize: function($el) {
79+
$el.select2({placeholder: i18n("please-select") });
80+
},
81+
selectOptions: {
82+
collection: function() {
83+
var coll = [];
84+
_.each(this.operators, function(op){
85+
coll.push({label:op.lastName + ' ' + op.firstName ,value:op.id});
86+
});
87+
return coll;
88+
},
89+
defaultOption: {
90+
label: '',
91+
value: null
92+
}
93+
},
94+
onGet: function(val) {
95+
return val && val.id;
96+
}
97+
},
98+
7699
'#biobank': {
77100
observe: 'biobank',
78101
selectOptions: {
@@ -220,6 +243,7 @@
220243
this.model.set("metadata", metadata);
221244
// this.model.set("type", this.model.get("type").id); // trying to send only the id to permorf POST or PUT
222245
this.retrieveAndSetFiles();
246+
this.model.get("owner").id ? this.model.set("owner", this.model.get("owner").id) : null;
223247
// console.log(this.model);
224248
this.model.save(null, {
225249
success: function(data) {
@@ -311,7 +335,7 @@
311335

312336
dataTypeOnChange: function() {
313337
Data.Views.Edit.prototype.dataTypeOnChange.call(this);
314-
var typeName = this.$('#type :selected').text(),
338+
var typeName = this.$('#data-type :selected').text(),
315339
parentSample = this.model.get("parentSample");
316340

317341
if (parentSample && parentSample.biobankCode) {
@@ -348,7 +372,7 @@
348372

349373
fetchDonorsOnSuccess: function(donors, targetElem) {
350374
this.subjects = donors.models ? donors.toJSON() : donors;
351-
var dataTypeSample = _.find(this.dataTypes, {id: _.parseInt($('#type').val())});
375+
var dataTypeSample = _.find(this.dataTypes, {id: _.parseInt($('#data-type').val())});
352376
if(dataTypeSample){
353377
this.filteredSubjects = _.filter(this.subjects, function (subj) {
354378
return subj.project === dataTypeSample.project;

0 commit comments

Comments
 (0)