Une MAJ de sécurité est nécessaire sur notre version actuelle. Elle sera effectuée lundi 02/08 entre 12h30 et 13h. L'interruption de service devrait durer quelques minutes (probablement moins de 5 minutes).

Commit cfd9d6ed authored by Ryan Herbert's avatar Ryan Herbert
Browse files

generic set add/edit form

moves the new patient/form and patient/submit routes to the sample_set
controller and removes any add/edit routes from all set controllers.
The same goes for the templates.

Also allows the inclusion of different types of sets in a single form.

For this, the sample_set/form.html template includes patials for each
set type.

See #2878

One form to rule them all, one form the find them, one form to bring
them all, and in the template bind them.
parent c530adf3
......@@ -12,109 +12,6 @@ if request.env.http_origin:
ACCESS_DENIED = "access denied"
## return form to create new patient
def form():
# edit patient
if("id" in request.vars and auth.can_modify_patient(request.vars["id"])):
groups = [get_set_group(defs.SET_TYPE_PATIENT, request.vars["id"])]
message = 'edit patient'
max_group = None
#new patient
elif (auth.can_create_patient()):
creation_group_tuple = get_default_creation_group(auth)
groups = creation_group_tuple[0]
max_group = creation_group_tuple[1]
message = 'add patient'
else :
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
return dict(message=T(message),
groups=groups,
master_group=max_group,
patients=[db.patient[request.vars["id"]]])
## create a patient if the html form is complete
## need ["first_name", "last_name", "birth_date", "info"]
## redirect to patient list if success
## return a flash error message if fail
def submit():
data = json.loads(request.vars['data'], encoding='utf-8')
mf = ModelFactory()
helper = mf.get_instance('patient')
messages = []
error = False
for p in data['patient']:
p['error'] = helper.validate(p)
if len(p['error']) > 0:
error = True
continue
register = False
reset = False
patient_name = "%s %s" % (p['first_name'], p['last_name'])
# edit patient
if (p['id'] != "" and auth.can_modify_patient(p['id'])):
id = p["id"]
patient = db.patient[id]
db.patient[id] = p
if (patient.info != p['info']):
group_id = get_set_group(defs.SET_TYPE_PATIENT, id)
register = True
reset = True
messages.append("%s (%s): patient edited" % (patient_name, id))
# add patient
elif (auth.can_create_patient()):
id_sample_set = db.sample_set.insert(sample_type=defs.SET_TYPE_PATIENT)
p['creator'] = auth.user_id
p['sample_set_id'] = id_sample_set
id = db.patient.insert(**p)
group_id = int(data["group"])
register = True
#patient creator automaticaly has all rights
auth.add_permission(group_id, PermissionEnum.access.value, db.patient, id)
messages.append("(%s) patient %s added" % (id_sample_set, patient_name))
if (id % 100) == 0:
mail.send(to=defs.ADMIN_EMAILS,
subject="[Vidjil] %d" % id,
message="The %dth patient has just been created." % id)
else :
p['error'].append("permission denied")
error = True
if register:
register_tags(db, defs.SET_TYPE_PATIENT, p["id"], p["info"], group_id, reset=reset)
if not error:
# TODO proper logging of all events
#log.info(res, extra={'user_id': auth.user.id, 'record_id': id, 'table_name': 'patient'})
res = {"redirect": "sample_set/all",
"message": "successfully added/edited patient(s)"}
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else:
response.view = 'patient/form.html'
return dict(message=T("an error occured"),
groups=[{'name': 'foobar', 'id': int(data['group'])}],
master_group=data['group'],
patients=data['patient'])
def download():
return response.download(request, db)
......
......@@ -39,144 +39,6 @@ def add():
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
## create a run if the html form is complete
## need ["name", "run_date"]
## redirect to run list if success
## return a flash error message if fail
def add_form():
if (auth.can_create_patient()):
error = ""
if request.vars["name"] == "" :
error += "name needed, "
if request.vars["run_date"] != "" :
try:
datetime.datetime.strptime(""+request.vars['run_date'], '%Y-%m-%d')
except ValueError:
error += "date (wrong format)"
if error=="" :
id_sample_set = db.sample_set.insert(sample_type=defs.SET_TYPE_RUN)
id = db.run.insert(name=request.vars["name"],
sample_set_id=id_sample_set,
run_date=request.vars["run_date"],
info=request.vars["info"],
id_label=request.vars["id_label"],
sequencer=request.vars["sequencer"],
pcr=request.vars["pcr"],
creator=auth.user_id)
user_group = int(request.vars["run_group"])
admin_group = db(db.auth_group.role=='admin').select().first().id
register_tags(db, defs.SET_TYPE_RUN, id, request.vars["info"], user_group)
#patient creator automaticaly has all rights
auth.add_permission(user_group, PermissionEnum.access.value, db.run, id)
res = {"redirect": "sample_set/all",
"args" : { "type" : 'run' },
"message": request.vars["name"] + ": run added"}
log.info(res, extra={'user_id': auth.user.id, 'record_id': id, 'table_name': 'run'})
if (id % 100) == 0:
mail.send(to=defs.ADMIN_EMAILS,
subject="[Vidjil] %d" % id,
message="The %dth run has just been created." % id)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else :
res = {"success" : "false",
"message" : error}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else :
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
## return edit form
def edit():
if (auth.can_modify_run(request.vars["id"]) ):
sequencer_list = db(
db.run.id>0
).select(
db.run.sequencer,
distinct=True
)
pcr_list = db(
db.run.id>0
).select(
db.run.pcr,
distinct=True
)
group_id = get_set_group(defs.SET_TYPE_RUN, request.vars["id"])
return dict(message=T('edit run'),
sequencer_list = sequencer_list,
pcr_list = pcr_list,
group_id = group_id)
else :
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
## check edit form
## need ["name", "run_date", "info"]
## redirect to run list if success
## return a flash error message if fail
def edit_form():
if (auth.can_modify_run(request.vars["id"]) ):
error = ""
if request.vars["name"] == "" :
error += "name needed, "
if request.vars["run_date"] != "" :
try:
datetime.datetime.strptime(""+request.vars['run_date'], '%Y-%m-%d')
except ValueError:
error += "date (wrong format)"
if request.vars["id"] == "" :
error += "patient id needed, "
if error=="" :
run = db.run[request.vars["id"]]
db.run[request.vars["id"]] = dict(name=request.vars["name"],
run_date=request.vars["run_date"],
info=request.vars["info"],
sequencer=request.vars["sequencer"],
pcr=request.vars["pcr"],
id_label=request.vars["id_label"]
)
group_id = get_set_group(defs.SET_TYPE_RUN, request.vars["id"])
if (run.info != request.vars["info"]):
register_tags(db, defs.SET_TYPE_RUN, request.vars["id"], request.vars["info"], group_id, reset=True)
res = {"redirect": "back",
"message": "%s (%s): run edited" % (request.vars["name"], request.vars["id"])}
log.info(res, extra={'user_id': auth.user.id, 'record_id': request.vars["id"], 'table_name': 'run'})
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else :
res = {"success" : "false", "message" : error}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else :
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
def confirm():
if (auth.can_modify_run(request.vars["id"]) ):
log.debug('request patient deletion')
......
......@@ -379,120 +379,135 @@ def mystats():
log.debug("stats (%.3fs) %s" % (time.time()-start, request.vars["filter"]))
return gluon.contrib.simplejson.dumps(d, separators=(',',':'))
## return form to create new generic sample_set
def add():
if (auth.can_create_patient()):
creation_group_tuple = get_default_creation_group(auth)
## return form to create new set
def form():
denied = False
# edit set
if("id" in request.vars):
sample_set = db.sample_set[request.vars["id"]]
if(auth.can_modify(sample_set.sample_type, request.vars["id"])):
set_type = sample_set.sample_type
sset = db(db[set_type].sample_set_id == sample_set.id).select().first()
groups = [get_set_group(set_type, sset.id)]
message = 'edit %s' % set_type
max_group = None
else:
denied = True
# new set
elif (auth.can_create_patient()):
sset = None
set_type = request.vars["type"]
creation_group_tuple = get_default_creation_group(auth)
groups = creation_group_tuple[0]
max_group = creation_group_tuple[1]
return dict(message=T('add sample_set'), groups=groups, master_group=max_group)
message = 'add %s' % set_type
else :
denied = True
if denied:
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
sets = {
'patient': [],
'run': [],
'generic': []
}
# We add a None object to the desired set type to initialise an empty form in the template.
sets[set_type].append(sset)
return dict(message=T(message),
groups=groups,
master_group=max_group,
sets=sets)
## create a generic sample_set if the html form is complete
## needs ["name", "info"]
## redirect to generic sample_set list if success
## create a patient if the html form is complete
## need ["first_name", "last_name", "birth_date", "info"]
## redirect to patient list if success
## return a flash error message if fail
def add_form():
if (auth.can_create_patient()):
def submit():
data = json.loads(request.vars['data'], encoding='utf-8')
mf = ModelFactory()
messages = []
error = ""
if request.vars["name"] == "" :
error += "name needed, "
error = False
set_types = vidjil_utils.get_found_types(data)
for set_type in set_types:
helper = mf.get_instance(set_type)
for p in data[set_type]:
p['error'] = helper.validate(p)
if len(p['error']) > 0:
error = True
continue
if error=="" :
id_sample_set = db.sample_set.insert(sample_type=defs.SET_TYPE_GENERIC)
register = False
reset = False
id = db.generic.insert(name=request.vars["name"],
info=request.vars["info"],
creator=auth.user_id,
sample_set_id=id_sample_set)
name = helper.get_name(p)
user_group = int(request.vars["sample_set_group"])
admin_group = db(db.auth_group.role=='admin').select().first().id
# edit
if (p['id'] != "" and auth.can_modify(set_type, p['id'])):
id = p["id"]
sset = db[set_type][id]
db[set_type][id] = p
register_tags(db, defs.SET_TYPE_GENERIC, id, request.vars["info"], user_group)
if (sset.info != p['info']):
group_id = get_set_group(set_type, id)
register = True
reset = True
#sample_set creator automaticaly has all rights
auth.add_permission(user_group, PermissionEnum.access.value, db.generic, id)
messages.append("%s (%s): %s edited" % (name, id, set_type))
res = {"redirect": "sample_set/index",
"args" : { "id" : id_sample_set },
"message": "(%s) sample_set %s added" % (id, request.vars["name"]) }
log.info(res, extra={'user_id': auth.user.id, 'record_id': id, 'table_name': 'sample_set'})
# add
elif (auth.can_create_patient()):
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
id_sample_set = db.sample_set.insert(sample_type=set_type)
else :
res = {"success" : "false",
"message" : error}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
p['creator'] = auth.user_id
p['sample_set_id'] = id_sample_set
p['id'] = db[set_type].insert(**p)
else :
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
group_id = int(data["group"])
def edit():
sample_set = db.sample_set[request.vars["id"]]
if sample_set is not None:
register = True
sample_type = sample_set.sample_type
if sample_type == defs.SET_TYPE_PATIENT:
patient = db((db.patient.sample_set_id == request.vars["id"])).select()[0]
redirect(URL('patient', 'form', vars=dict(id=patient.id)), headers=response.headers)
elif sample_type == defs.SET_TYPE_RUN:
run = db((db.run.sample_set_id == request.vars["id"])).select()[0]
redirect(URL('run', 'edit', vars=dict(id=run.id)), headers=response.headers)
#patient creator automaticaly has all rights
auth.add_permission(group_id, PermissionEnum.access.value, db[set_type], p['id'])
else :
generic = db((db.generic.sample_set_id == request.vars["id"])).select()[0]
if (auth.can_modify('generic', generic.id)):
request.vars["id"] = generic.id
group_id = get_set_group(defs.SET_TYPE_GENERIC, request.vars["id"])
return dict(message=T('edit sample_set'), group_id=group_id)
res = {"message": ACCESS_DENIED}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
def edit_form():
if (auth.can_modify('generic', request.vars["id"]) ):
error = ""
if request.vars["name"] == "" :
error += "name needed, "
if request.vars["id"] == "" :
error += "sample set id needed, "
if error=="" :
generic = db.generic[request.vars["id"]]
db.generic[request.vars["id"]] = dict(name=request.vars["name"],
info=request.vars["info"],
)
group_id = get_set_group(defs.SET_TYPE_GENERIC, request.vars["id"])
if (generic.info != request.vars["info"]):
register_tags(db, defs.SET_TYPE_GENERIC, request.vars["id"], request.vars["info"], group_id, reset=True)
res = {"redirect": "back",
"message": "%s (%s): sample_set edited" % (request.vars["name"], request.vars["sample_set_id"])}
log.info(res, extra={'user_id': auth.user.id, 'record_id': request.vars['id'], 'table_name': 'generic'})
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
messages.append("(%s) patient %s added" % (id_sample_set, name))
else :
res = {"success" : "false", "message" : error}
log.error(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else :
res = {"message": ACCESS_DENIED}
log.error(res)
if (p['id'] % 100) == 0:
mail.send(to=defs.ADMIN_EMAILS,
subject="[Vidjil] %d" % p['id'],
message="The %dth %s has just been created." % (p['id'], set_type))
else :
p['error'].append("permission denied")
error = True
if register:
register_tags(db, set_type, p["id"], p["info"], group_id, reset=reset)
if not error:
# TODO proper logging of all events
#log.info(res, extra={'user_id': auth.user.id, 'record_id': id, 'table_name': 'patient'})
res = {"redirect": "sample_set/all",
"message": "successfully added/edited set(s)"}
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else:
sets = {
'patient': data['patient'] if 'patient' in data else [],
'run': data['run'] if 'run' in data else [],
'generic': data['generic'] if 'generic' in data else []
}
response.view = 'patient/form.html'
return dict(message=T("an error occured"),
groups=[{'name': 'foobar', 'id': int(data['group'])}],
master_group=data['group'],
sets=sets)
def custom():
start = time.time()
......
......@@ -135,6 +135,10 @@ class SampleSet(object):
except:
raise ValueError('invalid input %s' % string)
@abstractmethod
def validate(self, data):
pass
def get_sample_name(sample_set_id):
'''
Return the name associated with a sample set (eg. a run or a
......
......@@ -27,3 +27,9 @@ class Generic(SampleSet):
def get_id_string(self, data):
name = data['name'] if data['name'] is not None else "Unnamed Sample Set"
return ":s %s (%d)" % (name, data['id'])
def validate(self, data):
error = []
if data["name"] == "":
error.append("name needed")
return error
......@@ -43,3 +43,15 @@ class Run(SampleSet):
name = data['name']
ident = "(%d)" % data['id']
return ":r %s %s" % (name, ident)
def validate(self, data):
error = []
if data["name"] == "":
error.append("name needed")
if data["run_date"] != "":
try:
datetime.datetime.strptime(""+data['run_date'], '%Y-%m-%d')
except ValueError:
error.append("date (wrong format)")
return error
......@@ -550,3 +550,8 @@ def check_enough_space(directory):
size = int(size)
result = available >= (size * (defs.FS_LOCK_THRESHHOLD/100))
return result
def get_found_types(data):
known_types = set([defs.SET_TYPE_PATIENT, defs.SET_TYPE_RUN, defs.SET_TYPE_GENERIC])
present_types = set(data.keys())
return known_types.intersection(present_types)
<fieldset name="generic{{=i}}">
<legend>Set {{=i+1}}</legend>
<input type="hidden" id="generic_id_{{=i}}" name="generic[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
{{ if set is not None and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{pass}}
<div>
<label for="sample_set_name_{{=i}}" id="sample_set_name__label_{{=i}}">Name: </label>
<input class="string" id="sample_set_name_{{=i}}" name="generic[{{=i}}][name]" type="text"
value="{{if set is not None:}}{{=set['name']}}{{pass}}"><span>*</span>
</div>
<div>
<label for="sample_set_info_{{=i}}" id="sample_set_info__label_{{=i}}">Info: </label>
<textarea
onfocus="$(this).data('group-ids', [$('#group_select option:selected').val()]);
new VidjilAutoComplete().setupAtWho(this);"
data-needs-atwho="true"
class="text"
cols="40"
id="sample_set_info_{{=i}}"
name="generic[{{=i}}][info]"
rows="10">{{if set is not None and set['info'] is not None:}}{{=set['info']}}{{pass}}</textarea>
</div>
</fieldset>
<fieldset name="patient{{=i}}">
<legend>Patient {{=i+1}}</legend>
<input type="hidden" id="patient_id_{{=i}}" name="patient[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
{{ if set is not None and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{ pass }}
<div>