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

Add the plugin userModelConsistency.

parent bdcd0f28
""" mytool controllers
A collection of tools specific to the applications
"""
import json
import plugin_dbui
USER_DATA_TYPES = ('boolean', 'date', 'number', 'string')
def userModelConsistency():
""" A user data block is associated to each event.
It is configurable by the user and defined in the events table.
The definition of the user data block (model) and the content
of the history.data field have to be kept in synchronization.
This job is done by this controller.
"""
# decode the request
changes = json.loads(request.vars.changes)
event = request.vars.fieldEvent
model = json.loads(request.vars.fieldData)
# keep in model default values but remove type definition
for key in model:
if not isinstance(model[key], (str, unicode)):
continue
if model[key].lower().strip() in USER_DATA_TYPES:
model[key] = None
# build a map of the modified keys.
# each operation is a list containing (action, old key, new key).
# the action is equal to: add, destroy, update
#
# NOTE: add and delete action are handle via dictionary copy.
#
#
update_keys = {}
for action, oldkey, newkey in changes:
if action != 'update':
continue
# simplify the case where key1 > key2 > key3 to key1 > key3
# remove the case where key1 > key2 > ... > key1
if update_keys:
ok = False
for k, v in update_keys.iteritems():
if oldkey == v:
update_keys[k] = newkey
ok = True
if k == newkey:
del update_keys[k]
break
if ok:
continue
# basic case
update_keys[oldkey] = newkey
# get the event id
id_event = plugin_dbui.get_id(db.events, event=event)
if id_event == None:
return
# scan and modify the history table
# NOTE: the delete of old key is implicit
query = db.history.id_events == id_event
rows = db(query).select()
for row in rows:
data = {}
for key in model:
# copy existing key
if key in row.data:
data[key] = row.data[key]
# add new key
else:
data[key] = model[key]
# modify key name
for oldkey, newkey in update_keys.iteritems():
if oldkey in row.data:
data[newkey] = row.data[oldkey]
db(query).update(data=data)
return T('%s entries modified in the history table.') % len(rows)
\ No newline at end of file
# -*- coding: utf-8 -*-
{
'%s between %s and %s': '%s du %s au %s',
'%s entries modified in the history table.': "%s entrés ont été modifié dans l'historique.",
'%s in %s': '%s en %s',
'%Y-%m-%d': '%Y-%m-%d',
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
......
......@@ -19,6 +19,7 @@ plugins = PluginManager()
plugins.dbui.app_css = 'static/my.css'
plugins.dbui.app_debug = 'static/src'
plugins.dbui.app_libmin = plugins.dbui.app_debug
plugins.dbui.app_lg = 'static/local/myapp-lang-fr.js'
plugins.dbui.app_script = 'static/app.js'
# plugins.dbui.app_script_dir = None
......
......@@ -18,6 +18,8 @@ fieldsModifier.configure_field('data',
# FORM CONFIGURATiON
#
#-------------------------------------------------------------------------------
formModifier = dbui.FormModifier('events')
formModifier.configure(plugins=['pUserModelConsistency'])
#-------------------------------------------------------------------------------
#
......
......@@ -9,11 +9,11 @@
#-------------------------------------------------------------------------------
fieldsModifier = dbui.FieldsModifier('history')
fieldsModifier.configure_field('id_events', itemId='keycombo')
fieldsModifier.configure_field('id_events', itemId='keyid_events')
fieldsModifier.configure_field('data',
modifyKeys=True,
modifyKeys=False,
height=150,
comboBoxItemId='keycombo',
comboBoxItemId='keyid_events',
dictField='EventsData',
store='eventsStore',
xtype='xdictmultidefault')
......
......@@ -2,13 +2,12 @@
HEAD
- Migrate to plugin_dbui version 0.6.2.1 and to mariadb.
- Add the user data block in the history / events tables and
remove obsolete tables and codes.
- Add the user data block in the history / events tables
- Add the plugin MyApp.form.plugin.UserModelConsistency.
- Remove obsolete tables and codes.
- Redesing the viewport using a more generic organisation
(configure, metadata, events, lists, metrics and graphs)
- Use the pGridExport plugin in views/report/grid.html
- Links events and the associate data blocks.
70753e8 (Jul 14)
- Migrate to plugin_dbui 0.6.1.6 and Web2py 2.9.5.
......
/**
* French translation
*
*/
Ext.define('MyApp.form.plugin.UserModelConsistency', {
override : 'MyApp.form.plugin.UserModelConsistency',
textError : "Erreur en mettant à jour l'historique...",
textInfo : 'Information...',
textUpdate: "Mise à jour de l'historique..."
});
/**
* Specific plugin to be used with the events form.
*
* The events table contains the definitions of the user data blocks.
* The user data block is used for each event in the history table.
*
* The definition of the user data block (model) and the content of
* the history.data field have to kept in synchronisation.
*
* This is the job of this plugin.
*
*/
Ext.define('MyApp.form.plugin.UserModelConsistency', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.pUserModelConsistency',
/**
* @property {Array} changes
* list of changes apply to the model
*
*/
changes: [],
/**
* @cfg {String} controller
* The URL of the controller running on the server
* encoded as 'controller/action'.
* The controller synchronises the content of the history table with
* the definition of the user data bloc.
*
* The controller receives:
*
* @param{String} fieldEvent
*
* @param{String} fieldData
* The dictionary defining the user data block encode as JSON string.
*
* @param{String} changes
* The list of changes encode as a JSON string.
*
*/
controller: 'mytools/userModelConsistency',
// short cuts
fieldData: null,
fieldEvent: null,
form: null,
historyStore: null,
viewport: null,
// Private properties for internationalization
textError: 'Error modifying the history table...',
textInfo: 'Information...',
textUpdate: 'Update the history table...',
/**
* Initialize the plugin.
*
* @param {Ext.form.Panel} panel
*
*/
init: function (panel) {
"use strict";
var me = this;
me.setCmp(panel);
// short cuts
me.form = panel.getForm();
me.fieldEvent = me.form.findField('EventsEvent');
me.fieldData = me.form.findField('EventsData');
// capture the dictionary keychange signal
me.fieldData.on('keychange', me.onAddChange, me);
// capture form reset signal
// FIXME capture destroy, hidden, ... signale → reset
panel.buttonReset.on('click', me.onResetChanges, me);
// capture form submit signal
panel.buttonAction.on('click', me.onDoChanges, me);
},
/**
* Destroy the plugin
*
*/
destroy: function () {
"use strict";
var me = this,
panel = me.getCmp();
me.fieldData.un('keychange', me.addChange, me);
panel.buttonReset.un('click', me.resetChanges, me);
panel.buttonAction.un('click', me.doChanges, me);
},
//
// The Ajax transaction failed
// Inform the user and clean the mask on the viewport
//
// @param {Object} response
// @param {Object} options
//
onAjaxFailure: function (response, options) {
"use strict";
var me = this;
me.setMaskViewport(false);
Ext.Msg.alert(me.textError, response.responseText);
},
//
// The Ajax transaction is a success
// Clean the mask on the viewport
//
// @param {Object} response
// @param {Object} options
//
onAjaxSuccess: function (response, options) {
"use strict";
var me = this,
current;
me.setMaskViewport(false);
// inform the user of what happened
if (response.responseText) {
Ext.Msg.alert(me.textInfo, response.responseText);
}
// refresh the content of the history store
if (!me.historyStore) {
me.historyStore = App.getStore('historyStore');
}
current = me.historyStore.currentPage;
me.historyStore.loadPage(current);
},
//
// Add change to the list of modifications applied to the dictionary.
//
// @param {App.form.field.Dict} field
// @param {String} action
// @param {String} oldKey
// @param {String} newKey
//
onAddChange: function (field, action, oldKey, newKey) {
"use strict";
var me = this;
me.changes.push([action, oldKey, newKey]);
},
//
// Propagate the change to server.
// It will modify the content of the history table accordingly.
// Through this method, the model and the content of the history
// table are kept in synchronisation.
//
onDoChanges: function () {
"use strict";
var me = this;
// do nothing
if (!me.changes.length) {
return;
}
// mask the viewport
me.setMaskViewport(true);
//send a request to the server
Ext.Ajax.request({
url: '/' + App.name + '/' + me.controller,
params: {
fieldEvent: me.fieldEvent.getValue(),
fieldData: Ext.JSON.encode(me.fieldData.getValue()),
changes: Ext.JSON.encode(me.changes)
},
success: me.onAjaxSuccess,
failure: me.onAjaxFailure,
scope: me
});
// reset the changes
me.changes = [];
},
//
// Reset the list of changes.
//
onResetChanges: function () {
"use strict";
var me = this;
me.changes = [];
},
//
// Mask / unMask the viewport
//
// @param {Boolean} mask
//
setMaskViewport: function (mask) {
"use strict";
var me = this;
if (!me.viewport) {
me.viewport = Ext.ComponentQuery.query('xviewport')[0];
}
me.viewport.setDisabled(mask);
if (mask) {
me.viewport.getEl().mask(me.textUpdate);
} else {
me.viewport.getEl().unmask();
}
}
});
\ 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