Commit af59cd16 authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Redesign the check and validate view using inline javascript.

parent 4c1b4a20
......@@ -20,10 +20,8 @@ def check_validate():
"""Check and validate publication records.
"""
counters = {}
logs = []
nfound = 0
nok = 0
nvalidated = 0
id_ok = db(db.status.code=='OK').select().first().id
# get user requirement
......@@ -36,11 +34,18 @@ def check_validate():
# analyse the publications
for row in rows:
nfound += 1
# alias
project = row.projects.project
# initialize counters
if project not in counters:
counters[project] = Storage(found=0, ok=0, validated=0)
counters[project].found += 1
# skip publication already validated
if row.status.code == 'OK':
nok += 1
counters[project].ok += 1
continue
# initialise the log for this record
......@@ -49,6 +54,7 @@ def check_validate():
msg.category = row.categories.code
msg.id = row.publications.id
msg.project = project
msg.title = row.publications.title
msg.year = row.publications.year
......@@ -57,16 +63,14 @@ def check_validate():
# update publication status
if not msg.txt:
nvalidated += 1
counters[project].validated += 1
del logs[-1]
if selector.mode != DRY_RUN:
row.publications.update_record(id_status=id_ok)
return dict(logs=logs,
nfound=nfound,
nok=nok,
nvalidated=nvalidated,
return dict(counters=counters,
logs=logs,
selector=selector)
......
......@@ -85,6 +85,7 @@
'check': 'vérifier',
'Check and validate': 'Vérifier et valider',
'check and validate': 'vérifier et valider',
'Check and validate took %s seconds': 'Vérifier et valider a duré %s secondes',
'Check latex syntax in the title': 'Vérifier la syntaxe latex dans le titre',
'Check to delete': 'Check to delete',
'Click on the link %(link)s to verify your email': 'Click on the link %(link)s to verify your email',
......@@ -152,6 +153,7 @@
'done!': 'done!',
'Dry Run': 'Essai à blanc',
'dry run': 'essai à blanc',
'Duplicate': 'Doublon',
'E-mail': 'E-mail',
'Edit current record': 'Edit current record',
'Email sent': 'Email sent',
......@@ -305,6 +307,7 @@
'Number of records validated: %s': "Nombre d'enregistrements validé : %s",
'Number(s)': 'Numéro(s)',
'Object or table name': 'Object or table name',
'Ok': 'Ok',
'Old password': 'Old password',
'or import from csv file': 'or import from csv file',
'organisation': 'organisation',
......@@ -328,7 +331,7 @@
'Please, define sections for the list "%s"': 'définissez des sections pour la liste "%s"',
'plugin not install': 'plugin not install',
'Position': 'Position',
'Possible duplicate entries [%s]': 'Doublon probable [%s]',
'Possible duplicate entries': 'Doublon probable',
'Postprocessing': 'Postprocessing',
'Preprint': 'Preprint',
'Preprint identifier separated by comma: arXiv:0906.1516': 'Numéro(s) du preprint séparé par des virgules: arXiv:0906.1516',
......@@ -501,6 +504,7 @@
'users': 'utilisateurs',
'Usual': 'Usual',
'Validate': 'Valider',
'Validated': 'Validé',
'Value': 'Valeur',
'value already in database or empty': 'La valeur existe déjà dans la base de données ou est nulle',
'value not allowed': 'value not allowed',
......
......@@ -33,7 +33,7 @@ def check_publication(row):
- the second one contains the list of duplicate ids.
"""
T, li, ids = current.T, [], []
T, li, idset = current.T, [], set()
# status code
if row.status.code == '???':
......@@ -91,7 +91,8 @@ def check_publication(row):
# duplicate by origin
ids = duplicate_origin(row.publications)
if len(ids) > 1:
text = T("Entries with duplicate origin [%s]") % ', '.join(ids)
idset = idset.union(ids)
text = T("Entries with duplicate origin")
li.append(text)
# specific fields for article
......@@ -115,7 +116,8 @@ def check_publication(row):
ids = duplicate_article(row.publications)
if ids:
text = T("Possible duplicate entries [%s]") % ', '.join(ids)
idset = idset.union(ids)
text = T("Possible duplicate entries")
li.append(text)
# specific fields for proceeding and talk
......@@ -143,7 +145,8 @@ def check_publication(row):
ids = duplicate_conference(row.publications)
if ids:
text = T("Possible duplicate entries [%s]") % ', '.join(ids)
idset = idset.union(ids)
text = T("Possible duplicate entries")
li.append(text)
# specific fields for report
......@@ -155,10 +158,11 @@ def check_publication(row):
ids = duplicate_report(row.publications)
if ids:
text = T("Possible duplicate entries [%s]") % ', '.join(ids)
idset = idset.union(ids)
text = T("Possible duplicate entries")
li.append(text)
return (li, ids)
return (li, list(idset))
def extend_ids(db, query, ids):
......@@ -338,5 +342,4 @@ def duplicate_report(publication):
extend_ids(db, qmain, ids)
return ids
\ No newline at end of file
return ids
\ No newline at end of file
......@@ -34,8 +34,8 @@
<!--
The two DIV blocks to hook the Ext JS grid
-->
<div id="grid-{{=divstat}}" style="padding: 0 40 20 30;"></div>
<div id="grid-{{=divlogs}}" style="padding: 10 40 20 30;"></div>
<div id="grid-{{=divstat}}"></div>
<div id="grid-{{=divlogs}}"></div>
<!--
Inline javascript to instantiate and render the Ext JS Grid
-->
......@@ -138,6 +138,7 @@
],
features: [{ftype:'summary'}],
forceFit: true,
padding: "0 40 20 30",
renderTo: 'grid-{{=divstat}}'
});
......@@ -158,6 +159,7 @@
{ftype:'grouping', groupHeaderTpl: '{name}', startCollapsed: true}
],
forceFit: true,
padding: "10 40 20 30",
renderTo: 'grid-{{=divlogs}}'
});
......
<!--
The python controller return:
- logs (List of Storage)
- selector (Selector)
- counters (dict of Storage) the key are the project
The storage keys are: found, ok, validated
Prepare the data
- Configuration for the Ext.data.Array
- Unique DIV identifiers
- Title
-->
{{
from view_tools import compare_html
my_style = """
.my-li,
.my-ol,
.my-p,
.my-p-smallcap {
font-family: Liberation Sherif, Sherif;
font-size: 11px;
}
.my-li,
.my-ol {
margin-left: 35px;
margin-bottom: 0px;
}
.my-ol {
list-style-type: decimal;
}
.my-p,
.my-p-smallcap {
margin-left: 20px;
}
.my-p-smallcap {
font-variant: small-caps;
margin-bottom: 1ex;
}
"""
response.write(BR())
response.write(STYLE(XML(my_style)))
def myli(txt):
txt = "&ndash; %s" % txt
return LI(XML(txt), _class="my-li")
def myol(*args):
return OL(*args, _class="my-ol")
def myp(txt):
return P(txt, _class="my-p")
def myp_smallcap(txt):
return P(txt, _class="my-p-smallcap")
import json
#
# Header
# transform the counters into a configuration of the Ext.data.Array
#
response.write(myp_smallcap(T("Check and validate")))
cfg = dict(sorters=['project'])
cfg['fields'] = [{'name': 'found', 'type': 'int'},
{'name': 'ok', 'type': 'int'},
{'name': 'project', 'type': 'string'},
{'name': 'validated', 'type': 'int'},
{'name': 'error', 'type': 'int'}]
cfg['data'] = []
for project in counters:
counter = counters[project]
error = counter.found - counter.ok - counter.validated
cfg['data'].append([counter.found, counter.ok, project, counter.validated, error])
pass
cfg_statStore = json.dumps(cfg)
#
# Scanning condition and results
# transform the logs into a configuration for the Ext.data.Array
#
ul = UL()
cfg = dict(groupField='txt',
sorters=['txt', 'title'])
cfg['fields'] = [{'name': 'category', 'type': 'string'},
{'name': 'id', 'type': 'int'},
{'name': 'ids', 'type': 'string'},
{'name': 'project', 'type': 'string'},
{'name': 'title', 'type': 'string'},
{'name': 'txt', 'type': 'string'},
{'name': 'year', 'type': 'int'}]
cfg['data'] = []
for row in logs:
cfg['data'].append([row.category,
row.id,
','.join(row.ids),
row.project,
row.title,
', '.join(row.txt),
row.year])
pass
txt = T("Number of records found: %s") % nfound
ul.append(myli(txt))
cfg_logsStore = json.dumps(cfg)
if session.role == ADMIN:
txt = T("Number of records already validated: %s") % nok
ul.append(myli(txt))
#
# identifier for each DIV block associated to a grid
#
divlogs = abs(hash(cfg_logsStore))
divstat = abs(hash(cfg_statStore))
txt = T("Number of records validated: %s") % nvalidated
ul.append(myli(txt))
#
# Write the Title on the HTML page
#
period = ""
if selector.year:
period = selector.year
pass
txt = T("Number of invalid records: %s") % (nfound - nok - nvalidated)
ul.append(myli(txt))
team = ""
if selector.id_teams:
team = db.teams[selector.id_teams].team
pass
response.write(ul)
project = ""
if selector.id_projects:
project = db.projects[selector.id_projects].project
pass
#
# Log
#
response.write(BR())
response.write(myp_smallcap(T("Invalid records")))
ids, ol = [], myol()
for msg in logs:
if msg.ids:
id1, id2 = int(msg.id), int(msg.ids[0])
if (id2, id1) in ids:
continue
else:
ids.append((id1, id2))
pass
pass
title = "%s, " % msg.title
txt = SPAN(', '.join(msg.txt), _style="color: red;")
id = SPAN(', id %s ' % msg.id, _style="color: green;")
diff = ''
if msg.ids:
diff = compare_html(msg.id, msg.ids[0])
pass
ol.append(LI(title, txt, id, diff))
if team and not project:
project = team
elif team and project:
project = "%s / %s" % (team, project)
pass
response.write(ol)
title = "%s %s %s" % (T("Check and validate"), project, period)
style = ["font-size: 12px;",
"font-variant: small-caps;",
"margin-left: 10px;",
"margin-bottom: 3ex;",
"margin-top: 2ex;"]
response.write(P(title, _style="".join(style)))
}}
<!--
The two DIV blocks to hook the Ext JS grid
-->
<div id="grid-{{=divstat}}"></div>
<div id="grid-{{=divlogs}}"></div>
<!--
Inline javascript to instantiate and render the Ext JS Grid
-->
<script type="text/javascript">
/**
* Display the results of the Check and validate controller.
* The report is built around two Ext.grid.Panels.
* The first one summarizes the static while the second one
* shows what happen for each publication found in the store.
*/
var cfgLogsStore,
cfgStatStore,
gridLogs,
gridStat,
trCategory,
trCollection,
trDuplicate,
trError,
trFound,
trId,
trOk,
trProject,
trStatistics,
trTitle,
trValidated,
trYear;
/**
* Renderer function returning the string Total
*/
function rTotal() {
return 'Total';
}
// bind the python and javascript variables
// use the internationalization of web2py to translate grid header
// MANDATORY: escape false to convert properly the quotes
{{
response.write("cfgLogsStore = %s;" % cfg_logsStore, escape=False)
response.write("cfgStatStore = %s;" % cfg_statStore, escape=False)
response.write("trCategory = '%s';" % T('Category'), escape=False),
response.write("trCollection = '%s';" % T('Collection'), escape=False)
response.write("trDuplicate = '%s';" % T('Duplicate'), escape=False),
response.write("trError = '%s';" % T('Error'), escape=False),
response.write("trFound = '%s';" % T('Found'), escape=False),
response.write("trId = '%s';" % T('Id'), escape=False),
response.write("trOk = '%s';" % T('Ok'), escape=False),
response.write("trProject = '%s';" % T('Project'), escape=False),
response.write("trStatistics = '%s';" % T('Statistics'), escape=False)
response.write("trTitle = '%s';" % T('Title'), escape=False)
response.write("trValidated = '%s';" % T('Validated'), escape=False),
response.write("trYear = '%s';" % T('Year'), escape=False)
}}
// instantiate the grids for the Stat
var gridStat = Ext.create('Ext.grid.Panel', {
title: trStatistics,
store: Ext.create('Ext.data.ArrayStore', cfgStatStore),
columns: [
{xtype: 'rownumberer'},
{text: trProject, dataIndex: 'project', flex: 2, summaryRenderer: rTotal},
{text: trFound, dataIndex: 'found', flex: 1, summaryType: 'sum'},
{text: trOk, dataIndex: 'ok', flex: 1, summaryType: 'sum'},
{text: trValidated, dataIndex: 'validated', flex: 1, summaryType: 'sum'},
{text: trError, dataIndex: 'error', flex: 1, summaryType: 'sum'}
],
forceFit: true,
features: [{ftype:'summary'}],
padding: "0 40 20 30",
renderTo: 'grid-{{=divstat}}'
});
// instantiate the grids for the LOGs
// The row are group per error and sorted by title.
var gridLog = Ext.create('Ext.grid.Panel', {
store: Ext.create('Ext.data.ArrayStore', cfgLogsStore),
columns: [
{xtype: 'rownumberer'},
{text: trTitle, dataIndex: 'title', flex: 3},
{text: trError, dataIndex: 'txt', flex: 1, hidden: true},
{text: trId, dataIndex: 'id', flex: 0.2},
{text: trDuplicate, dataIndex: 'ids', flex: 0.2, hidden: true},
{text: trCategory, dataIndex: 'category', flex: 0.2, hidden: true},
{text: trProject, dataIndex: 'project', flex: 0.5, hidden: true},
{text: trYear, dataIndex: 'year', flex: 0.2, hidden: true}
],
features: [
{ftype:'grouping', groupHeaderTpl: '{name}', startCollapsed: true}
],
forceFit: true,
padding: "10 40 20 30",
renderTo: 'grid-{{=divlogs}}'
});
</script>
{{
# processing time of the request
from datetime import datetime
delta = (datetime.now()-request.now).total_seconds()
delta = T('Check and validate took %s seconds') % round(delta, 2)
style = ["font-size: 10px;",
"margin-left: 10px;",
"margin-bottom: 3ex;",
"margin-top: 2ex;"]
response.write(P(delta, _style="".join(style)))
}}
\ No newline at end of file
Markdown is supported
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