From 11b0b9460fe3d22e3344a60641cff0f594584eb8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jordan=20Aug=C3=A9?= Date: Wed, 14 Aug 2013 14:27:02 +0200 Subject: [PATCH] plugins: updated resource selected to receive proper updates from the query --- manifold/js/manifold.js | 59 +- manifold/js/plugin.js | 3 + plugins/resources_selected/__init__.py | 2 +- .../static/js/resources_selected.js | 515 +++++++++--------- .../static/resources_selected.html | 7 +- trash/pluginview.py | 2 +- trash/sliceview.py | 21 +- 7 files changed, 321 insertions(+), 288 deletions(-) diff --git a/manifold/js/manifold.js b/manifold/js/manifold.js index abbd6e6d..a59fa101 100644 --- a/manifold/js/manifold.js +++ b/manifold/js/manifold.js @@ -28,6 +28,7 @@ var FIELD_REMOVED = 5; var CLEAR_FIELDS = 6; var NEW_RECORD = 7; var CLEAR_RECORDS = 8; +var FIELD_STATE_CHANGED = 9; var IN_PROGRESS = 101; var DONE = 102; @@ -37,6 +38,15 @@ var SET_ADD = 201; var SET_REMOVED = 202; var RUN_UPDATE = 203; +// request +var FIELD_REQUEST_CHANGE = 301; +var FIELD_REQUEST_ADD = 302; +var FIELD_REQUEST_REMOVE = 303; +// status +var FIELD_REQUEST_PENDING = 301; +var FIELD_REQUEST_SUCCESS = 302; +var FIELD_REQUEST_FAILURE = 303; + /* Query status */ var STATUS_NONE = 500; // Query has not been started yet var STATUS_GET_IN_PROGRESS = 501; // Query has been sent, no result has been received @@ -48,6 +58,7 @@ var STATUS_UPDATE_RECEIVED = 506; var STATUS_UPDATE_ERROR = 507; // outdated ? + // A structure for storing queries @@ -539,13 +550,39 @@ var manifold = { query = query_ext.query; switch(event_type) { + case FIELD_STATE_CHANGED: + // value is an object (request, key, value, status) + // update is only possible is the query is not pending, etc + // SET_ADD is on a subquery, FIELD_STATE_CHANGED on the query itself + // we should map SET_ADD on this... + + // 1. Update internal query store about the change in status + + // 2. Update the update query + update_query = query_ext.main_query_ext.update_query_ext.query; + update_query.params[value.key].push(value.value); + + // 3. Inform others about the change + // a) the main query... + manifold.raise_record_event(query_uuid, event_type, value); + + // b) subqueries eventually (dot in the key) + // XXX make this DOT a global variable... could be '/' + break; + case SET_ADD: + case SET_REMOVED: + // update is only possible is the query is not pending, etc // CHECK status ! // XXX we can only update subqueries of the main query. Check ! // assert query_ext.parent_query == query_ext.main_query - update_query = query_ext.main_query_ext.update_query_ext.query; + // old // update_query = query_ext.main_query_ext.update_query_ext.query; + + // This SET_ADD is called on a subquery, so we have to + // recontruct the path of the key in the main_query + // We then call FIELD_STATE_CHANGED which is the equivalent for the main query var path = ""; var sq = query_ext; @@ -556,8 +593,17 @@ var manifold = { sq = sq.parent_query_ext; } - update_query.params[path].push(value); - console.log('Updated query params', update_query); + main_query = query_ext.main_query_ext.query; + data = { + request: (event_type == SET_ADD) ? FIELD_REQUEST_ADD : FIELD_REQUEST_REMOVE, + key : path, + value : value, + status: FIELD_REQUEST_PENDING, + }; + this.raise_event(main_query.query_uuid, FIELD_STATE_CHANGED, data); + + // old //update_query.params[path].push(value); + // old // console.log('Updated query params', update_query); // NOTE: update might modify the fields in Get // NOTE : we have to modify all child queries // NOTE : parts of a query might not be started (eg slice.measurements, how to handle ?) @@ -566,11 +612,9 @@ var manifold = { // object = the same as get // filter = key : update a single object for now // fields = the same as get + manifold.raise_query_event(query_uuid, event_type, value); break; - case SET_REMOVED: - // Query uuid has been updated with the key of a removed element - break; case RUN_UPDATE: update_query = query_ext.main_query_ext.update_query_ext.query; @@ -579,8 +623,10 @@ var manifold = { break; case FILTER_ADDED: + manifold.raise_query_event(query_uuid, event_type, value); break; case FILTER_REMOVED: + manifold.raise_query_event(query_uuid, event_type, value); break; case FIELD_ADDED: main_query = query_ext.main_query_ext.query; @@ -595,6 +641,7 @@ var manifold = { // XXX When is an update query associated ? // XXX main_update_query.select(value); + manifold.raise_query_event(query_uuid, event_type, value); break; case FIELD_REMOVED: diff --git a/manifold/js/plugin.js b/manifold/js/plugin.js index b72cc30c..85b24785 100644 --- a/manifold/js/plugin.js +++ b/manifold/js/plugin.js @@ -94,6 +94,9 @@ var Plugin = Class.extend({ case DONE: fn = 'query_done'; break; + case FIELD_STATE_CHANGED: + fn = 'field_state_changed'; + break; default: return; } // switch diff --git a/plugins/resources_selected/__init__.py b/plugins/resources_selected/__init__.py index 606a6d8b..a5bbac70 100644 --- a/plugins/resources_selected/__init__.py +++ b/plugins/resources_selected/__init__.py @@ -13,7 +13,7 @@ class ResourcesSelected(Plugin): return reqs def json_settings_list (self): - return ['plugin_uuid', 'domid', 'resource_query_uuid', 'lease_query_uuid'] + return ['plugin_uuid', 'domid', 'query_uuid'] def export_json_settings (self): return True diff --git a/plugins/resources_selected/static/js/resources_selected.js b/plugins/resources_selected/static/js/resources_selected.js index 77d023c9..18b61fdb 100644 --- a/plugins/resources_selected/static/js/resources_selected.js +++ b/plugins/resources_selected/static/js/resources_selected.js @@ -9,169 +9,265 @@ * License: GPLv3 */ -/* - * It's a best practice to pass jQuery to an IIFE (Immediately Invoked Function - * Expression) that maps it to the dollar sign so it can't be overwritten by - * another library in the scope of its execution. - */ (function( $ ){ - var PLUGIN_NAME = 'ResourcesSelected'; - - // Routing calls - jQuery.fn.ResourcesSelected = function( method ) { - if ( methods[method] ) { - return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); - } else if ( typeof method === 'object' || ! method ) { - return methods.init.apply( this, arguments ); - } else { - jQuery.error( 'Method ' + method + ' does not exist on jQuery.' + PLUGIN_NAME ); - } - - }; - - /*************************************************************************** - * Public methods - ***************************************************************************/ - - var methods = { - - /** - * @brief Plugin initialization - * @param options : an associative array of setting values - * @return : a jQuery collection of objects on which the plugin is - * applied, which allows to maintain chainability of calls - */ - init : function( options ) { - - return this.each(function(){ - - var $this = $(this); - - /* An object that will hold private variables and methods */ - var plugin = new ResourcesSelected(options); - $(this).data('Manifold', plugin); - - //$this.set_query_handler(options.query_uuid, hazelnut.query_handler); - //$this.set_record_handler(options.query_uuid, hazelnut.record_handler); - - //var RESULTS_RESOURCES = '/results/' + options.resource_query_uuid + '/changed'; - //var UPDATE_RESOURCES = '/update-set/' + options.resource_query_uuid; - //$.subscribe(RESULTS_RESOURCES, function(e, resources) { s.set_resources(resources); }); - //$.subscribe(UPDATE_RESOURCES, function(e, resources, change) { s.update_resources(resources, change); }); - - }); // this.each - }, // init - - /** - * @brief Plugin destruction - * @return : a jQuery collection of objects on which the plugin is - * applied, which allows to maintain chainability of calls - */ - destroy : function( ) { - - return this.each(function() { - var $this = $(this); - var plugin = $this.data('Manifold'); - - // Remove associated data - plugin.remove(); - $this.removeData('Manifold'); - }); - }, // destroy - - }; // var methods - - /*************************************************************************** - * Plugin object - ***************************************************************************/ - - function ResourcesSelected(options) - { - /* member variables */ - this.options = options; - var object = this; - - /* The resources that are in the slice */ - this.current_resources = null; - - /* The resources that are in the slice before any edit */ - this.initial_resources = null; - - var rs = this; - - /* constructor */ - // ioi: resources table id - var TABLE_NAME = '#table-' + options.plugin_uuid; - this.table = $(TABLE_NAME).dataTable({ - //sPaginationType: 'full_numbers', // Use pagination - sPaginationType: 'bootstrap', - //bJQueryUI: true, - //bRetrieve: true, - sScrollX: '100%', // Horizontal scrolling - bSortClasses: false, // Disable style for the sorted column - aaSorting: [[ 1, "asc" ]], // Default sorting on URN - fnDrawCallback: function() { // Reassociate close click every time the table is redrawn - /* Prevent to loop on click while redrawing table */ - jQuery('.ResourceSelectedClose').unbind('click'); - /* Handle clicks on close span */ - /* Reassociate close click every time the table is redrawn */ - $('.ResourceSelectedClose').bind('click',{instance: rs}, object.close_click); - } - }); + // XXX record selected (multiple selection ?) + // XXX record disabled ? + // XXX out of sync plugin ? + // XXX out of date record ? + // record tags ??? + // + // criticality of the absence of a handler in a plugin + // non-critical only can have switch case + // + // Record state through the query cycle + - /* methods */ + var ResourcesSelected = Plugin.extend({ - this.set_resources = function(resources) + init: function(options, element) { - console.log("set_resources"); - /* Some sanity checks on the API results */ - if(resources.length==0){ - this.table.html(errorDisplay("No Result")); - return; - } + this._super(options, element); + + var self = this; + this.table = this.el('table').dataTable({ + //sPaginationType: 'full_numbers', // Use pagination + sPaginationType: 'bootstrap', + //bJQueryUI : true, + //bRetrieve : true, + sScrollX : '100%', // Horizontal scrolling + bSortClasses : false, // Disable style for the sorted column + aaSorting : [[ 0, 'asc' ]], // Default sorting on URN + fnDrawCallback: function() { // Reassociate close click every time the table is redrawn + /* Prevent to loop on click while redrawing table */ + $('.ResourceSelectedClose').unbind('click'); + /* Handle clicks on close span */ + /* Reassociate close click every time the table is redrawn */ + $('.ResourceSelectedClose').bind('click', self, self._close_click); + } + }); + + this.listen_query(options.query_uuid); + }, - if (typeof(resources[0].error) != 'undefined') { - this.table.html(errorDisplay(resources[0].error)); - return; + /*************************** PLUGIN EVENTS ****************************/ + + /***************************** GUI EVENTS *****************************/ + + // Move through the query cycle + // XXX 'update', 'refresh', 'reset' and 'remove annotation' button + // This is a query scheduler + + /************************** GUI MANIPULATION **************************/ + + clear: function() + { + + }, + + set_state: function(data) + { + var action; + var color; + var msg; + var button = ''; + + switch(data.request) { + case FIELD_REQUEST_CHANGE: + action = 'UPDATE'; + break; + case FIELD_REQUEST_ADD: + action = 'ADD'; + break; + case FIELD_REQUEST_REMOVE: + action = 'REMOVE'; + break; } - /* Update the table with resources in the slice */ - //var slivers = $.grep(resources, function(i) {return typeof(i['sliver']) != 'undefined';}) - var slivers = resources; - var sliver_urns = Array(); - // ioi : refubrished - $.each(resources, function(i, x) { sliver_urns.push({urn:x.urn, timeslot:"0"}); }); // ioi - - this.initial_resources = sliver_urns; // We make a copy of the object // ioi - // ioi - - if (this.current_resources == null) { - this.current_resources = sliver_urns; - - /* We simply add to the ResourceSelected table */ - var newlines=Array(); - $.each(sliver_urns, function(index, elt) { - newlines.push(Array('attached', elt.urn, elt.timeslot, "")); // ioi: added last element - }); - this.table.dataTable().fnAddData(newlines); - } else { - alert('Slice updated. Refresh not yet implemented!'); + switch(data.status) { + case FIELD_REQUEST_PENDING: + msg = 'PENDING'; + color = 'white'; + button = ""; + break; + case FIELD_REQUEST_SUCCESS: + msg = 'SUCCESS'; + color = 'green'; + break; + case FIELD_REQUEST_FAILURE: + msg = 'FAILURE'; + color = 'red'; + break; } - } - this.update_resources = function(resources, change) { + var status = msg + color; + + this.table.fnAddData([ + action, + data.key, + data.value, + msg, + button + ]); + // XXX change cell color according to status + }, + + /*************************** QUERY HANDLER ****************************/ + + // NONE + + /*************************** RECORD HANDLER ***************************/ + + on_new_record: function(record) + { + // if (not and update) { + + // initial['resource'], initial['lease'] ? + this.initial.push(record.urn); + + // We simply add to the table + // } else { + // \ this.initial_resources + // \ + // this. \ + // current_resources \ YES | NO + // --------------------+----------+--------- + // YES | attached | added + // NO | removed | / + // + + // } + }, + + // QUERY STATUS + // +-----------------+--------------+ + // v R | | + // +-------+ ?G +-------+ +-------+ +---+---+ | + // | | -----> | | !G | | | | DA | + // | ND | | PG | -----> | D | -----> | PC | <------+ | + // | | <----- | | ~G | | C | | | | + // +-------+ GE +-------+ +-------+ +-------+ +------+ + // ^ ^ | | | + // | DA UE | | ?U | PCA | + // | | v | | + // +-------+ +-------+ +------+ + // | | !U | | ^ + // | AD | <----- | PU | --------+ + // | | | | ~U + // +-------+ +-------+ + // + // + // LEGEND: + // + // Plugins (i) receive state information, (ii) perform actions + // + // States: Actions: + // ND : No data ?G : Get query + // PG : Pending Get !G : Get reply + // D : Data present ~G : Get partial reply + // PC : Pending changes GE : Get error + // PU : Pending update C : Change request + // PCA: Pending change with annotation R : Reset request + // AD : Annotated data ?U : Update query + // !U : Update reply + // ~U : Update partial reply + // UE : Update error + // DA : Delete annotation request + // NOTE: + // - D -> PU directly if the user chooses 'dynamic update' + // - Be careful for updates if partial Get success + + // ND: No data == initialization state + + // PG : Pending get + // - on_query_in_progress + // NOTE: cannot distinguish get and update here. Is it important ? + + on_query_in_progress: function() + { + this.spin(); + }, + + // D : Data present + // - on_clear_records (Get) + // - on_new_record (shared with AD) XXX + // - on_query_done + // NOTE: cannot distinguish get and update here. Is it important ? + // NOTE: Would record key be sufficient for update ? + + on_clear_records: function() + { + this.clear(); + }, + + on_new_record: function(record) + { + }, + + on_query_done: function() + { + this.unspin(); + }, + + // PC : Pending changes + // NOTE: record_key could be sufficient + on_added_record: function(record) + { + this.set_record_state(record, RECORD_STATE_ADDED); + }, + + on_removed_record: function(record_key) + { + this.set_record_state(RECORD_STATE_REMOVED); + }, + + // PU : Pending update + // - on_query_in_progress (already done) + + // PCA : Pending change with annotation + // NOTE: Manifold will inform the plugin about updates, and thus won't + // call new record, even if the same channel UUID is used... + // - TODO on_updated_record + // - Key and confirmation could be sufficient, or key and record state + // XXX move record state to the manifold plugin API + + on_field_state_changed: function(request, key, value, status) + { + this.set_state(request, key, value, status); + }, + + // XXX we will have the requests for change + // XXX + the requests to move into the query cycle = the buttons aforementioned + + // XXX what happens in case of updates ? not implemented yet + // XXX we want resources and leases + // listen for SET_ADD and SET_REMOVE for slice query + + /************************** PRIVATE METHODS ***************************/ + + _close_click: function(e) + { + var self = e.data; + + //jQuery.publish('selected', 'add/'+key_value); + // this.parentNode is this.parentNode.parentNode is + // this.parentNode.parentNode.firstChild is the first cell of this line + // this.parentNode.parentNode.firstChild.firstChild is the text in that cell + //var firstCellVal=this.parentNode.parentNode.firstChild.firstChild.data; + var remove_urn = this.id; + var current_resources = event.data.instance.current_resources; + var list_resources = $.grep(current_resources, function(x) {return x.urn != remove_urn}); + //jQuery.publish('selected', 'cancel/'+this.id+'/'+get_value(firstCellVal)); + $.publish('/update-set/' + event.data.instance.options.resource_query_uuid, [list_resources, true]); + }, + + /******************************** TODO ********************************/ + + update_resources: function(resources, change) + { console.log("update_resources"); var my_oTable = this.table.dataTable(); var prev_resources = this.current_resources; - /* \ this.initial_resources - * \ - * this. \ - * current_resources \ YES | NO - * --------------------+----------+--------- - * YES | attached | added - * NO | removed | / - */ /* * The first time the query is advertised, don't do anything. The @@ -262,123 +358,10 @@ /* Allow the user to update the slice */ //jQuery('#updateslice-' + data.ResourceSelected.plugin_uuid).prop('disabled', false); - } // update_resources - - this.record_handler = function(e, event_type, record) - { - // elements in set - switch(event_type) { - case NEW_RECORD: - /* NOTE in fact we are doing a join here */ - if (object.received_all) - // update checkbox for record - object.set_checkbox(record); - else - // store for later update of checkboxes - object.in_set_buffer.push(record); - break; - case CLEAR_RECORDS: - // nothing to do here - break; - case IN_PROGRESS: - manifold.spin($(this)); - break; - case DONE: - if (object.received_all) - manifold.spin($(this), false); - object.received_set = true; - break; - } - }; - - this.record_handler_all = function(e, event_type, record) - { - // all elements - switch(event_type) { - case NEW_RECORD: - // Add the record to the table - object.new_record(record); - break; - case CLEAR_RECORDS: - object.table.fnClearTable(); - break; - case IN_PROGRESS: - manifold.spin($(this)); - break; - case DONE: - if (object.received_set) { - /* XXX needed ? XXX We uncheck all checkboxes ... */ - $("[id^='datatables-checkbox-" + object.options.plugin_uuid +"']").attr('checked', false); - - /* ... and check the ones specified in the resource list */ - $.each(object.in_set_buffer, function(i, record) { - object.set_checkbox(record); - }); - - manifold.spin($(this), false); - } - object.received_all = true; - break; - } - }; + }, // update_resources - this.query_handler = function(e, event_type, data) - { - // This replaces the complex set_query function - // The plugin does not need to remember the query anymore - switch(event_type) { - // Filters - case FILTER_ADDED: - case FILTER_REMOVED: - case CLEAR_FILTERS: - // XXX Here we might need to maintain the list of filters ! - /* Process updates in filters / current_query must be updated before this call for filtering ! */ - object.table.fnDraw(); - break; + }); - // Fields - /* Hide/unhide columns to match added/removed fields */ - case FIELD_ADDED: - var field = data; - var oSettings = object.table.fnSettings(); - var cols = oSettings.aoColumns; - var index = object.getColIndex(field,cols); - if(index != -1) - object.table.fnSetColumnVis(index, true); - break; - case FIELD_REMOVED: - var field = data; - var oSettings = object.table.fnSettings(); - var cols = oSettings.aoColumns; - var index = object.getColIndex(field,cols); - if(index != -1) - object.table.fnSetColumnVis(index, false); - break; - case CLEAR_FIELDS: - alert('Hazelnut::clear_fields() not implemented'); - break; - } // switch - } - - } // ResourcesSelected - - - /*************************************************************************** - * Private methods - ***************************************************************************/ - - /* Callbacks */ - function close_click(event){ - //jQuery.publish('selected', 'add/'+key_value); - // this.parentNode is this.parentNode.parentNode is - // this.parentNode.parentNode.firstChild is the first cell of this line - // this.parentNode.parentNode.firstChild.firstChild is the text in that cell - //var firstCellVal=this.parentNode.parentNode.firstChild.firstChild.data; - var remove_urn = this.id; - var current_resources = event.data.instance.current_resources; - var list_resources = $.grep(current_resources, function(x) {return x.urn != remove_urn}); - //jQuery.publish('selected', 'cancel/'+this.id+'/'+get_value(firstCellVal)); - $.publish('/update-set/' + event.data.instance.options.resource_query_uuid, [list_resources, true]); - } + $.plugin('ResourcesSelected', ResourcesSelected); })(jQuery); diff --git a/plugins/resources_selected/static/resources_selected.html b/plugins/resources_selected/static/resources_selected.html index 00ac3ec1..a4450eb5 100644 --- a/plugins/resources_selected/static/resources_selected.html +++ b/plugins/resources_selected/static/resources_selected.html @@ -1,9 +1,10 @@ - +
+ + + - - diff --git a/trash/pluginview.py b/trash/pluginview.py index b165d6a1..be17ee22 100644 --- a/trash/pluginview.py +++ b/trash/pluginview.py @@ -18,7 +18,7 @@ from plugins.querycode.querycode import QueryCode from plugins.raw.raw import Raw from plugins.messages.messages import Messages from plugins.hazelnut import Hazelnut -from plugins.updater.updater import Updater +from plugins.updater import Updater from myslice.viewutils import topmenu_items, the_user from myslice.viewutils import hard_wired_slice_names, hard_wired_list, lorem_p, lorem, quickfilter_criterias diff --git a/trash/sliceview.py b/trash/sliceview.py index 632aec40..4afd6250 100644 --- a/trash/sliceview.py +++ b/trash/sliceview.py @@ -180,17 +180,6 @@ def _slice_view (request, slicename): stack_resources.insert(tab_resource_plugins) - # -------------------------------------------------------------------------- - # ResourcesSelected - # - stack_resources.insert(ResourcesSelected( - page = page, - title = 'Pending operations', - resource_query_uuid = sq_resource, - lease_query_uuid = sq_lease, - togglable = True, - )) - sq_plugin.insert(stack_resources) ############################################################################ @@ -253,6 +242,16 @@ def _slice_view (request, slicename): main_plugin.insert(sq_plugin) + # -------------------------------------------------------------------------- + # ResourcesSelected + # + main_plugin.insert(ResourcesSelected( + page = page, + title = 'Pending operations', + query = main_query, + togglable = True, + )) + main_plugin.insert(Messages( page = page, title = "Runtime messages for slice %s"%slicename, -- 2.43.0
actionkeyvalue statusurnslot +/-