Commit 2f93217a authored by Marc Duez's avatar Marc Duez
Browse files
parents 5b11d9c8 76418308
......@@ -10,8 +10,8 @@ LIB=../core/vidjil.a ../lib/lib.a
SHOULD=$(wildcard *.should_get)
SHOULD_LOG=$(SHOULD:.should_get=.tap)
SHOULD_VDJ=$(wildcard should-vdj-tests/*.should-vdj.fa)
REPORTS_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../reports
VALGRIND=valgrind -v --tool=memcheck --leak-check=full --show-reachable=yes --undef-value-errors=yes --track-origins=yes --xml=yes --xml-file=\"$$(mktemp "$(REPORTS_PATH)/valgrind.xml.XXXXXX")\"
REPORTS_PATH := $(patsubst %/Makefile,%,$(abspath $(lastword $(MAKEFILE_LIST))))/../../reports
VALGRIND=valgrind -v --tool=memcheck --leak-check=full --show-reachable=yes --undef-value-errors=yes --track-origins=yes --xml=yes --xml-file="$$(mktemp "$(REPORTS_PATH)/valgrind.xml.XXXXXX")"
.PHONY: all force clean forcedep
......
!NO_LAUNCHER:
!LAUNCH: ../../vidjil -z 200 -g ../../germline
$ Warning, -z
......
......@@ -1189,7 +1189,10 @@ text.alert {
border-bottom: solid;
border-color: #333333;
border-width: 1px;
cursor: pointer;
}
.pointer
{
cursor: pointer;
}
.db_table tr:hover {
background: #333333;
......@@ -1420,6 +1423,10 @@ table.log {
table.log textarea {
width: 100%;
}
.loglink {
color: purple;
text-decoration: none;
}
#waiting_screen {
background: rgba(0, 0, 0, 0.5);
position: absolute;
......
......@@ -1189,6 +1189,9 @@ text.alert {
border-bottom: solid;
border-color: #cccccc;
border-width: 1px;
}
.pointer
{
cursor: pointer;
}
.db_table tr:hover {
......@@ -1420,6 +1423,10 @@ table.log {
table.log textarea {
width: 100%;
}
.loglink {
color: purple;
text-decoration: none;
}
#waiting_screen {
background: rgba(0, 0, 0, 0.5);
position: absolute;
......
......@@ -1362,6 +1362,10 @@ text.alert { fill: red; }
border-bottom: solid;
border-color: @border;
border-width: 1px;
}
.pointer
{
cursor: pointer;
}
......@@ -1617,6 +1621,11 @@ table.log textarea
width: 100%;
}
.loglink {
color: purple;
text-decoration: none;
}
#waiting_screen{
background: rgba(0, 0, 0, 0.5);
position: absolute;
......
......@@ -407,6 +407,7 @@ Segment.prototype = {
del.onclick = function () {
self.m.clone(cloneID).unselect();
self.aligned = false;
}
seq_name.appendChild(document.createTextNode(this.m.clone(cloneID).getName()));
seq_name.title = this.m.clone(cloneID).getName();
......
......@@ -4,6 +4,8 @@ import os.path, subprocess
import vidjil_utils
from collections import defaultdict
MAX_LOG_LINES = 200
if request.env.http_origin:
response.headers['Access-Control-Allow-Origin'] = request.env.http_origin
response.headers['Access-Control-Allow-Credentials'] = 'true'
......@@ -53,13 +55,24 @@ def log():
lines = []
file = open(defs.DIR_LOG+request.vars["file"])
log_format = request.vars['format'] if 'format' in request.vars else ''
if "filter" not in request.vars :
request.vars["filter"] = ""
for row in reversed(file.readlines()) :
if vidjil_utils.filter(row, request.vars["filter"]) :
if not vidjil_utils.filter(row, request.vars["filter"]) :
continue
if not log_format: # == 'vidjil'
line = { 'mes': row, 'date': '', 'date2': '', 'user': '', 'type':'', 'file':''}
else:
# Parses lines such as
# [11889] 2015-02-01 12:01:28,367 INFO - default.py:312 1.23.45.67/user/Toto <Toto> xxxxx log message
# [11889] 2015-02-01 12:01:28,367 INFO - default.py:312 1.23.45.67 log message
# [11889] 2015-02-01 12:01:28,367 INFO - default.py:312 log message
line = {}
tmp = re.split('\t+| +', row)
......@@ -70,22 +83,26 @@ def log():
line["file"] = tmp[5]
if tmp[6] != "Creating":
line["user"] = tmp[7]
line["mes"] = ""
for i in range(8,len(tmp)):
line["mes"] += tmp[i] + " "
if '<' in tmp[8]:
line["user"] = tmp[8] + ' ' + tmp[7]
j = 9
else:
line["user"] = tmp[7]
j = 8
line["mes"] = " ".join(tmp[j:])
else:
line["user"] = ""
line["mes"] = ""
for i in range(6,len(tmp)):
line["mes"] += tmp[i] + " "
line["mes"] = " ".join(tmp[6:])
line["mes"] = vidjil_utils.log_links(line["mes"])
lines.append(line)
### Stores log line
lines.append(line)
if len(lines) >= 100 :
return dict(lines = lines)
if len(lines) >= MAX_LOG_LINES :
break
return dict(lines = lines)
return {'lines': lines, 'format': log_format}
## to use after change in the upload folder
def repair_missing_files():
......
......@@ -62,7 +62,7 @@ def add_form():
provider=auth.user_id)
res = {"file_id" : id,
"message": "(%s) upload started: %s" % (request.vars['patient_id'], request.vars['filename']),
"message": "file %s (%s): upload started: %s" % (id, request.vars['patient_id'], request.vars['filename']),
"redirect": "patient/info",
"args" : {"id" : request.vars['patient_id']}
}
......@@ -118,7 +118,7 @@ def edit_form():
res = {"file_id" : request.vars['id'],
"redirect": "patient/info",
"args" : { "id" : patient_id},
"message": "%s: metadata saved" % str(request.vars['filename'])}
"message": "file %s: metadata saved" % request.vars["id"]}
log.info(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
......@@ -129,20 +129,22 @@ def upload():
error += "missing id"
if error=="" :
mes = "file " + str(request.vars['id']) + " : "
res = {"message": mes + ": processing uploaded file",
patient_id = db.sequence_file[request.vars["id"]].patient_id
mes = "file %s (%s): " % (request.vars['id'], patient_id)
res = {"message": mes + "processing uploaded file",
"redirect": "patient/info",
"args" : {"id" : request.vars['id']}
}
log.info(res)
log.debug(res)
if request.vars.file != None :
f = request.vars.file
db.sequence_file[request.vars["id"]] = dict(data_file = db.sequence_file.data_file.store(f.file, f.filename))
mes = "upload finished: %s" % f.filename
mes += "upload finished"
seq_file = defs.DIR_SEQUENCES+db.sequence_file[request.vars["id"]].data_file
size = os.path.getsize(seq_file)
mes += ' (%s)' % vidjil_utils.format_size(size)
db.sequence_file[request.vars["id"]] = dict(size_file = size)
res = {"message": mes}
......@@ -170,7 +172,7 @@ def delete():
res = {"redirect": "patient/info",
"args" : { "id" : patient_id},
"message": "(%s) sequence file deleted" % patient_id}
"message": "file %s (%s): sequence file deleted" % (request.vars["id"], patient_id)}
log.info(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
else:
......
......@@ -345,7 +345,7 @@ def edit_form():
)
res = {"redirect": "back",
"message": "patient %s %s edited" % (request.vars["first_name"], request.vars["last_name"])}
"message": "%s %s (%s): patient edited" % (request.vars["first_name"], request.vars["last_name"], request.vars["id"])}
log.info(res)
return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
......
......@@ -8,10 +8,19 @@ if request.env.http_origin:
def index():
query = db(db.auth_user).select()
for row in query :
row.created = db( db.patient.creator == row.id ).count()
row.access = ''
if auth.has_permission('create', 'patient', 0, row.id): row.access += 'c'
if auth.has_permission('upload', 'sequence_file', 0, row.id): row.access += 'u'
if auth.has_permission('run', 'results_file', 0, row.id): row.access += 'r'
q = [g.group_id for g in db(db.auth_membership.user_id==row.id).select()]
q.sort()
row.groups = ' '.join([str(g) for g in q])
row.size = 0
row.files = 0
query_size = db( db.sequence_file.provider == row.id ).select()
......
......@@ -273,7 +273,7 @@ def _init_log():
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("Creating logger")
logger.debug("Creating logger")
return MsgUserAdapter(logger, {})
log = _init_log()
......
import math
import re
from gluon import current
def format_size(n, unit='B'):
......@@ -78,3 +79,56 @@ def filter(str, filter_str):
if f.lower() not in str.lower():
return False
return True
log_patient = re.compile('\((\d+)\)')
log_config = re.compile(' c(\d+)')
def log_links(s):
'''Add HTML links to a log string
>>> log_links("abcdef")
'abcdef'
>>> log_links("abcdef(234)")
'abcdef(<a class="loglink" onclick="db.call(\\'patient/info\\', {\\'id\\': \\'234\\'})">234</a>)'
>>> log_links("abcdef(234)abcdef c11")
'abcdef(234)abcdef <a class="loglink" href="?patient=234&config=11">c11</a>'
'''
### Parses the input string
m_patient = log_patient.search(s)
patient = m_patient.group(1) if m_patient else None
m_config = log_config.search(s)
config = m_config.group(1) if m_config else None
### Rules
url = '' # href link
call = '' # call to db
if patient and config:
url = "?patient=%s&config=%s" % (patient, config)
(start, end) = m_config.span()
start += 1
elif patient:
call = "patient/info"
args = {'id': patient}
(start, end) = m_patient.span()
start += 1
end -= 1
### Build final string
link = ''
if url:
link = 'href="%s"' % url
if call:
link = '''onclick="db.call('%s', %s)"''' % (call, str(args))
if link:
s = '%s<a class="loglink pointer" %s>%s</a>%s' % (s[:start], link, s[start:end], s[end:])
return s
......@@ -13,8 +13,8 @@
<hr>
</br>Vidjil server:
<a class="button" onclick="db.call('admin/log', {'file' : 'vidjil.log'} );">vidjil.log</a>
<a class="button" onclick="db.call('admin/log', {'file' : 'vidjil-debug.log'} );">debug.log</a>
<a class="button" onclick="db.call('admin/log', {'file' : 'vidjil.log', 'format': 'vidjil'} );">vidjil.log</a>
<a class="button" onclick="db.call('admin/log', {'file' : 'vidjil-debug.log', 'format': 'vidjil'} );">debug.log</a>
<a class="button" href="/admin/default/errors/vidjil">web2py tickets</a>
</br>Ngnix:
......
......@@ -7,7 +7,7 @@
<div class="db_block_left">
search
<input id="db_filter_input" type="text" value="{{=request.vars["filter"]}}"
onchange="db.call('admin/log', {'file' : '{{=request.vars["file"]}}', 'filter' : this.value} )" >
onchange="db.call('admin/log', {'file' : '{{=request.vars["file"]}}', 'filter' : this.value, 'format': '{{=request.vars["format"]}}' } )" >
</div>
</div>
......@@ -17,23 +17,27 @@
<thead>
<tr>
{{ if format: }}
<td class="column_100"> date </td>
<td class="column_100"> </td>
<td class="column_200"> user </td>
<td class="column_100"> type </td>
<td class="column_100"> file </td>
{{ pass }}
<td> </td>
</tr>
</thead>
{{for line in lines :}}
<tr>
{{ if format: }}
<td> {{=line["date"]}} </td>
<td> {{=line["date2"]}} </td>
<td> {{=line["user"]}} </td>
<td> {{=line["type"]}} </td>
<td> {{=line["file"]}} </td>
<td> {{=line["mes"]}} </td>
{{ pass }}
<td> {{=XML(line["mes"])}} </td>
</tr>
{{pass}}
</table>
......
......@@ -16,19 +16,19 @@
<thead>
<tr><td class="column_200" onclick="db.call('patient/index', {'sort' :'last_name', 'filter' : '{{=request.vars["filter"]}}'
<tr><td class="column_200 pointer" onclick="db.call('patient/index', {'sort' :'last_name', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="last_name" :}} , 'reverse' : true {{pass}} })"> name </td>
<td class="column_100" onclick="db.call('patient/index', {'sort' :'birth', 'filter' : '{{=request.vars["filter"]}}'
<td class="column_100 pointer" onclick="db.call('patient/index', {'sort' :'birth', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="birth" :}} , 'reverse' : true {{pass}} })"> birth </td>
<td onclick="db.call('patient/index', {'sort' :'info', 'filter' : '{{=request.vars["filter"]}}'
<td class="pointer" onclick="db.call('patient/index', {'sort' :'info', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="info" :}} , 'reverse' : true {{pass}} })"> info </td>
<td class="column_100" onclick="db.call('patient/index', {'sort' :'configs', 'filter' : '{{=request.vars["filter"]}}'
<td class="pointer" class="column_100" onclick="db.call('patient/index', {'sort' :'configs', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="configs" :}} , 'reverse' : true {{pass}} })"> configs </td>
{{if isAdmin:}} <td class="column_50" onclick="db.call('patient/index', {'sort' :'groups', 'filter' : '{{=request.vars["filter"]}}'
{{if isAdmin:}} <td class="column_50 pointer" onclick="db.call('patient/index', {'sort' :'groups', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="groups" :}} , 'reverse' : true {{pass}} })"> groups </td> {{pass}}
{{if isAdmin:}} <td class="column_100" onclick="db.call('patient/index', {'sort' :'creator', 'filter' : '{{=request.vars["filter"]}}'
{{if isAdmin:}} <td class="column_100 pointer" onclick="db.call('patient/index', {'sort' :'creator', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="creator" :}} , 'reverse' : true {{pass}} })"> creator </td> {{pass}}
<td class="column_100" onclick="db.call('patient/index', {'sort' :'files', 'filter' : '{{=request.vars["filter"]}}'
<td class="column_100 pointer" onclick="db.call('patient/index', {'sort' :'files', 'filter' : '{{=request.vars["filter"]}}'
{{if not reverse and request.vars["sort"]=="files" :}} , 'reverse' : true {{pass}} })"> files </td>
......@@ -40,7 +40,7 @@
{{for row in query :}}
<tr onclick="db.call('patient/info', {'id' :'{{=row.patient.id}}' , 'config_id' : {{=row.most_used_conf}} } )" >
<tr class="pointer" onclick="db.call('patient/info', {'id' :'{{=row.patient.id}}' , 'config_id' : {{=row.most_used_conf}} } )" >
<td> {{=vidjil_utils.anon(row.patient.id, auth.user_id)}} </td>
<td> {{=row.patient.birth }} </td>
<td> {{=row.patient.info }} </td>
......
......@@ -78,8 +78,8 @@
{{pass}}
{{if (auth.has_permission('admin', 'patient', request.vars["id"]) ):}}
<td onclick="db.call('file/edit', {'id' :'{{=row.sequence_file.id}}', 'patient_id' :'{{=request.vars['id']}}'} )" > e </td>
<td onclick="db.call('file/confirm', {'id' :'{{=row.sequence_file.id}}', 'patient_id' :'{{=request.vars['id']}}'} )" > X </td>
<td class="pointer" onclick="db.call('file/edit', {'id' :'{{=row.sequence_file.id}}', 'patient_id' :'{{=request.vars['id']}}'} )" > e </td>
<td class="pointer" onclick="db.call('file/confirm', {'id' :'{{=row.sequence_file.id}}', 'patient_id' :'{{=request.vars['id']}}'} )" > X </td>
<td> <a {{if row.sequence_file.data_file == None :}} {{=XML("class='inactive' title='file is missing' ")}}
{{else:}} href="{{=URL('patient','download', scheme='https', args=row.sequence_file.data_file)}}" {{pass}} >dl</a></td>
{{else:}}<td></td><td></td><td></td>{{pass}}
......@@ -92,7 +92,7 @@
<td class="button" onclick="db.call('results_file/info', { 'results_file_id' : '{{=row.results_file.id}}' } )"> {{=row.results_file.run_date }}</td>
{{else:}}<td></td>{{pass}}
<td class="button" onclick="db.call('results_file/info', { 'results_file_id' : '{{=row.results_file.id}}' } )"> {{=status}} </td>
<td onclick="db.call('results_file/confirm', {'results_file_id' :'{{=row.results_file.id}}'})" > X </td>
<td class="pointer" onclick="db.call('results_file/confirm', {'results_file_id' :'{{=row.results_file.id}}'})" > X </td>
<td>
{{if row.sequence_file.data_file != None and ( row.results_file.id == None or ( status != "RUNNING" and status != "QUEUED" and status != "ASSIGNED") ):}}
{{if auth.has_permission("run", "results_file") :}}
......
......@@ -7,19 +7,23 @@
<div id="db_table_container">
<table class="db_table" id="table">
<thead>
<tr><td class="column_100">id</td>
<tr><td class="column_50">id</td>
<td class="column_200"> name</td>
<td> @</td>
<td class="colum1">patients created </td>
<td class="colum1">files uploaded </td>
<td class="column_200"> @</td>
<td class="column_50">access</td>
<td class="column_100">groups</td>
<td class="column_50">patients created </td>
<td class="column_100">files uploaded </td>
</tr>
</thead>
{{for row in query :}}
<tr onclick="db.call('user/info', {'id' :'{{=row.id}}'} )">
<tr class="pointer" onclick="db.call('user/info', {'id' :'{{=row.id}}'} )">
<td> {{=row.id}}</td>
<td> {{=row.first_name}} {{=row.last_name}}</td>
<td> {{=row.email}} </td>
<td> {{=row.access}} </td>
<td> {{=row.groups}} </td>
<td> {{=row.created}} </td>
<td> {{=row.files}} ({{=vidjil_utils.format_size(row.size)}}) </td>
</tr>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment