From 4d9ce959481f9821b4406948a6eabf1426537e93 Mon Sep 17 00:00:00 2001 From: Loic Baron Date: Fri, 3 Oct 2014 13:49:13 +0200 Subject: [PATCH] Plugin VTAM by Frederic Francois (Univ Bristol) integrated into slice view --- plugins/univbrisvtam/__init__.py | 80 +++ .../univbrisvtam/static/css/univbrisvtam.css | 84 +++ plugins/univbrisvtam/static/img/README | 2 + .../static/img/tablesort-bullet1.png | Bin 0 -> 192 bytes .../static/img/tablesort-bullet2.png | Bin 0 -> 464 bytes .../static/img/tablesort-col-alt.png | Bin 0 -> 512 bytes .../static/img/tablesort-gradient.png | Bin 0 -> 265 bytes .../static/img/tablesort-header-down.png | Bin 0 -> 3845 bytes .../static/img/tablesort-header-sortable.png | Bin 0 -> 3758 bytes .../static/img/tablesort-header-up.png | Bin 0 -> 3877 bytes .../static/img/tablesort-header.png | Bin 0 -> 2887 bytes .../static/img/tablesort-td-alt.png | Bin 0 -> 479 bytes .../univbrisvtam/static/img/toggle-hidden.png | Bin 0 -> 4356 bytes .../static/img/toggle-visible.png | Bin 0 -> 4328 bytes .../univbrisvtam/static/js/univbrisvtam.js | 663 ++++++++++++++++++ .../templates/univbrisvtamplugin.html | 29 + plugins/univbrisvtamform/__init__.py | 43 ++ .../static/css/univbrisvtamform.css | 65 ++ plugins/univbrisvtamform/static/img/README | 2 + .../static/img/tablesort-bullet1.png | Bin 0 -> 192 bytes .../static/img/tablesort-bullet2.png | Bin 0 -> 464 bytes .../static/img/tablesort-col-alt.png | Bin 0 -> 512 bytes .../static/img/tablesort-gradient.png | Bin 0 -> 265 bytes .../static/img/tablesort-header-down.png | Bin 0 -> 3845 bytes .../static/img/tablesort-header-sortable.png | Bin 0 -> 3758 bytes .../static/img/tablesort-header-up.png | Bin 0 -> 3877 bytes .../static/img/tablesort-header.png | Bin 0 -> 2887 bytes .../static/img/tablesort-td-alt.png | Bin 0 -> 479 bytes .../static/img/toggle-hidden.png | Bin 0 -> 4356 bytes .../static/img/toggle-visible.png | Bin 0 -> 4328 bytes .../static/js/univbrisvtamform.js | 321 +++++++++ .../templates/univbrisvtamform.html | 62 ++ portal/sliceresourceview.py | 41 +- portal/templates/slice-resource-view.html | 11 +- portal/templates/univbrisvtam.html | 15 + portal/univbrisvtam.py | 94 +++ portal/urls.py | 11 +- 37 files changed, 1510 insertions(+), 13 deletions(-) create mode 100644 plugins/univbrisvtam/__init__.py create mode 100644 plugins/univbrisvtam/static/css/univbrisvtam.css create mode 100644 plugins/univbrisvtam/static/img/README create mode 100644 plugins/univbrisvtam/static/img/tablesort-bullet1.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-bullet2.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-col-alt.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-gradient.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-header-down.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-header-sortable.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-header-up.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-header.png create mode 100644 plugins/univbrisvtam/static/img/tablesort-td-alt.png create mode 100755 plugins/univbrisvtam/static/img/toggle-hidden.png create mode 100755 plugins/univbrisvtam/static/img/toggle-visible.png create mode 100644 plugins/univbrisvtam/static/js/univbrisvtam.js create mode 100644 plugins/univbrisvtam/templates/univbrisvtamplugin.html create mode 100644 plugins/univbrisvtamform/__init__.py create mode 100644 plugins/univbrisvtamform/static/css/univbrisvtamform.css create mode 100644 plugins/univbrisvtamform/static/img/README create mode 100644 plugins/univbrisvtamform/static/img/tablesort-bullet1.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-bullet2.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-col-alt.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-gradient.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-header-down.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-header-sortable.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-header-up.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-header.png create mode 100644 plugins/univbrisvtamform/static/img/tablesort-td-alt.png create mode 100755 plugins/univbrisvtamform/static/img/toggle-hidden.png create mode 100755 plugins/univbrisvtamform/static/img/toggle-visible.png create mode 100644 plugins/univbrisvtamform/static/js/univbrisvtamform.js create mode 100644 plugins/univbrisvtamform/templates/univbrisvtamform.html create mode 100644 portal/templates/univbrisvtam.html create mode 100644 portal/univbrisvtam.py diff --git a/plugins/univbrisvtam/__init__.py b/plugins/univbrisvtam/__init__.py new file mode 100644 index 00000000..bc2bf9e6 --- /dev/null +++ b/plugins/univbrisvtam/__init__.py @@ -0,0 +1,80 @@ +from unfold.plugin import Plugin + +class UnivbrisVtam (Plugin): + def __init__ (self, query=None, query_all=None, sync_query=None, + checkboxes=False, columns=None, + init_key=None, + datatables_options={}, **settings): + Plugin.__init__ (self, **settings) + self.query = query + self.query_uuid = query.query_uuid if query else None + # Until we have a proper way to access queries in Python + self.query_all = query_all + self.query_all_uuid = query_all.query_uuid if query_all else None + self.sync_query_uuid = sync_query.query_uuid if sync_query else None + self.checkboxes = checkboxes + # XXX We need to have some hidden columns until we properly handle dynamic queries + if columns is not None: + self.columns=columns + self.hidden_columns = [] + elif self.query: + self.columns = list (['Testbed', 'Virtualization Server', 'VM name', 'Delete']) + #replace production + #self.columns = self.query.fields + if query_all: + #replace production + self.hidden_columns = [] + # We need a list because sets are not JSON-serializable + #self.hidden_columns = #list(self.query_all.fields - self.query.fields) + else: + self.hidden_columns = [] + else: + self.columns = [] + self.hidden_columns = [] + + self.columns = list (['Testbed', 'Virtualization Server', 'VM name', 'Delete']) + self.init_key=init_key + self.datatables_options=datatables_options + # if checkboxes were required, we tell datatables about this column's type + # so that sorting can take place on a selected-first basis (or -last of course) + # this relies on the template exposing the checkboxes 'th' with class 'checkbox' + if self.checkboxes: + # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns + if 'aoColumns' in self.datatables_options: + print 'WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded' + del self.datatables_options['aoColumns'] + # set aoColumnDefs in datatables_options - might already have stuff in there + aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[]) + # here 'checkbox' is the class that we give to the dom elem + # dom-checkbox is a sorting type that we define in querytable.js + aoColumnDefs.append ( {'aTargets': ['checkbox'], 'sSortDataType': 'dom-checkbox' } ) + + def template_file (self): + return "univbrisvtamplugin.html" + + def template_env (self, request): + env={} + env.update(self.__dict__) + env['columns']=self.columns + return env + + def requirements (self): + reqs = { + 'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", + "js/dataTables.js", "js/dataTables.bootstrap.js", "js/with-datatables.js", "js/jquery.jeditable.js", + "js/manifold.js", "js/manifold-query.js", + "js/unfold-helper.js", + "js/univbrisvtam.js", + ] , + 'css_files': [ "css/dataTables.bootstrap.css", + "css/dataTables.full_numbers.css", + "css/univbrisvtam.css", + ], + } + return reqs + + def json_settings_list (self): + return ['plugin_uuid', 'domid', + 'query_uuid', 'query_all_uuid', 'sync_query_uuid', + 'checkboxes', 'datatables_options', + 'hidden_columns', 'init_key',] diff --git a/plugins/univbrisvtam/static/css/univbrisvtam.css b/plugins/univbrisvtam/static/css/univbrisvtam.css new file mode 100644 index 00000000..04424afd --- /dev/null +++ b/plugins/univbrisvtam/static/css/univbrisvtam.css @@ -0,0 +1,84 @@ + +/* the bottom of the datatable needs more space */ +div.UnivbrisVtam-spacer { padding: 8px 4px 15px 4px; } + +div.UnivbrisVtam table.dataTable th { + font: bold 12px/22px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + color: #4f6b72; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; + border-top: 1px solid #C1DAD7; + letter-spacing: 1px; + text-transform: uppercase; + text-align: left; + padding: 8px 12px 4px 20px; + vertical-align:middle; +/* background: #CAE8EA url(../img/tablesort-header.jpg) no-repeat; */ +} + +div.UnivbrisVtam table.dataTable th.checkbox { + padding-left: 14px; +} + +div.UnivbrisVtam table.dataTable td, div.UnivbrisVtam table.dataTable textarea, div.UnivbrisVtam table.dataTable input [type="text"] { + font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + color: #660099; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; +} +div.UnivbrisVtam table.dataTable td { + padding: 4px 8px 4px 8px; + /* this applies on even rows only, odd ones have a setting in bootstrap of rbg 249.249.249 */ + background-color: #f4f4f4; + color: #660099; +} +div.UnivbrisVtam table.dataTable td a { + font-weight:normal; +} +/* these come from bootstrap */ +div.UnivbrisVtam div.dataTables_info { + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +/* one could think or using repeat-x here but that's not working because of the arrows + * we might need to make these wider some day + * and/or to add background-color: #caebea + * which would look less conspicuous in case of overflow +*/ + +div.UnivbrisVtam table.dataTable thead .sorting { background: url('../img/tablesort-header-sortable.png') no-repeat; } +div.UnivbrisVtam table.dataTable thead .sorting_asc { background: url('../img/tablesort-header-up.png') no-repeat; } +div.UnivbrisVtam table.dataTable thead .sorting_desc { background: url('../img/tablesort-header-down.png') no-repeat; } +/* this icons set does not have that exact equivalent - using an approximation for now */ +div.UnivbrisVtam table.dataTable thead .sorting_asc_disabled { background: url('../img/tablesort-header.png') repeat-x; } +div.UnivbrisVtam table.dataTable thead .sorting_desc_disabled { background: url('../img/tablesort-header.png') repeat-x; } + +/* the footers are not active */ +div.UnivbrisVtam table.dataTable tfoot { + background: url('../img/tablesort-header.png') repeat-x; + background-color: #caebea; +} +/* and when sorting is turned off it's useful to set this on header too */ +div.UnivbrisVtam table.dataTable thead { + background: url('../img/tablesort-header.png') repeat-x; + background-color: #caebea; +} + +div.UnivbrisVtam table.tbbuttons{ + background-color:#A9E2F3; +} + + +div.UnivbrisVtam table.tbbuttons td{ + padding-top: 7px; + /*padding-left: 7px*/ + /*padding-left: 7px*/ + padding-bottom: 7px; + background-color:#A9E2F3; +} + +div.UnivbrisVtam table.tbbuttons tr{ + background-color:#A9E2F3; +} + + diff --git a/plugins/univbrisvtam/static/img/README b/plugins/univbrisvtam/static/img/README new file mode 100644 index 00000000..5df2d69b --- /dev/null +++ b/plugins/univbrisvtam/static/img/README @@ -0,0 +1,2 @@ +these styling elements come from plekit with a simple transition to png +they're currently not all used in myslice diff --git a/plugins/univbrisvtam/static/img/tablesort-bullet1.png b/plugins/univbrisvtam/static/img/tablesort-bullet1.png new file mode 100644 index 0000000000000000000000000000000000000000..4304f360ff514f28b19261938ad13761c3c40c34 GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRQ!3HGLSWEVS1PVMNiy0WWg+Z8+Vb&Z8pkR@w zi(`m{WOBj+v4j@MFAx5_`>(@efAG$K9v`0n5;G+0j5istkgzb=bU>t0WW(S8TvJ%I z7`Xm7YcZTOJ}A=o;(yN>p8t{&2h>hTR~*c3oXxW7k^TuTwKBF8R)w<#t_tQ2YaGHE mf>_wg^<;kVKfln!$neEe`ZGh$s>49r89ZJ6T-G@yGywoMg+6Hj literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtam/static/img/tablesort-bullet2.png b/plugins/univbrisvtam/static/img/tablesort-bullet2.png new file mode 100644 index 0000000000000000000000000000000000000000..4f181e19fcee46275781f8619c3a0445b68e5d63 GIT binary patch literal 464 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 Hu0mjfbe)_L literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtam/static/img/tablesort-header-sortable.png b/plugins/univbrisvtam/static/img/tablesort-header-sortable.png new file mode 100644 index 0000000000000000000000000000000000000000..0c169040d877c305d38f32654bf7e9bf7129d98f GIT binary patch literal 3758 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 YKbWq-ms_8Wga7~l07*qoM6N<$f@fiU0RR91 literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtam/static/img/tablesort-header-up.png b/plugins/univbrisvtam/static/img/tablesort-header-up.png new file mode 100644 index 0000000000000000000000000000000000000000..d12fe2a5cbec852a02dc1d7aadd46c31c7022287 GIT binary patch literal 3877 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 literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtam/static/img/tablesort-header.png b/plugins/univbrisvtam/static/img/tablesort-header.png new file mode 100644 index 0000000000000000000000000000000000000000..cff526f9c7beb9cb552a669b3c8171583a80c55c GIT binary patch literal 2887 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 literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtam/static/img/tablesort-td-alt.png b/plugins/univbrisvtam/static/img/tablesort-td-alt.png new file mode 100644 index 0000000000000000000000000000000000000000..ef5ab358abd77cc238276d77592083cf7c0b5439 GIT binary patch literal 479 zcmeAS@N?(olHy`uVBq!ia0y~yVAKY(H8_}nq^7F(Pawrv;1OBOz`!jG!i)^F=12fl zP4ske45?szd-LGBCIb!Y^6uimj_=)QsD!0+a&U}Blav{=sO&i{jF_TI1lUjFyd{tN2U-m~n}GkEpT zS=ZvVsd>x)?(!{@C65B z2L;Uqjh?kPSxheQ2zYR1Bm~8qG4h%)vrJ-=nsH^iFHkwdKq>#j*vsJHa&KQm4=~0U NJYD@<);T3K0RZy{!7u;- literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtam/static/img/toggle-hidden.png b/plugins/univbrisvtam/static/img/toggle-hidden.png new file mode 100755 index 0000000000000000000000000000000000000000..023f22a8d8ffb61841939f0e5b60dc13a70ead9a GIT binary patch literal 4356 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 Wx704#E!RQ-0000 + * Copyright (c) 2012-2013 UPMC Sorbonne Universite - INRIA + * License: GPLv3 + */ + +(function($){ + + var debug=false; + debug=true + + pk_flowspace_index=0; + opt_flowspace_index=0; + pk_mode=0; + fvf_add=1; + fvf_nrow=0; + + + var UnivbrisVtam = Plugin.extend({ + + + init: function(options, element) { + this.classname="univbrisvtam"; + this._super(options, element); + + this.elmt().on('show', this, this.on_show); + this.elmt().on('shown.bs.tab', this, this.on_show); + this.elmt().on('resize', this, this.on_resize); + + // We need to remember the active filter for datatables filtering + this.filters = Array(); + + // an internal buffer for records that are 'in' and thus need to be checked + this.buffered_records_to_check = []; + // an internal buffer for keeping lines and display them in one call to fnAddData + this.buffered_lines = []; + + var keys = manifold.metadata.get_key(this.object); + this.canonical_key = (keys && keys.length == 1) ? keys[0] : undefined; + this.init_key = this.options.init_key; + // have init_key default to canonical_key + this.init_key = this.init_key || this.canonical_key; + // sanity check + if ( ! this.init_key ) messages.warning ("UnivbrisVtam : cannot find init_key"); + if ( ! this.canonical_key ) messages.warning ("UnivbrisVtam : cannot find canonical_key"); + if (debug) messages.debug("UnivbrisVtam: canonical_key="+this.canonical_key+" init_key="+this.init_key); + + /* GUI setup and event binding */ + this.initialize_table(); + + }, + + /* PLUGIN EVENTS */ + + on_show: function(e) { + if (debug) messages.debug("UnivbrisVtam.on_show"); + var self = e.data; + self.table.fnAdjustColumnSizing(); + }, + + on_resize: function(e) { + if (debug) messages.debug("UnivbrisVtam.on_resize"); + var self = e.data; + self.table.fnAdjustColumnSizing(); + }, + + /* GUI EVENTS */ + + /* GUI MANIPULATION */ + + initialize_table: function() + { + + + /* Transforms the table into DataTable, and keep a pointer to it */ + var self = this; + //alert(self.options); + var actual_options = { + // Customize the position of Datatables elements (length,filter,button,...) + // we use a fluid row on top and another on the bottom, making sure we take 12 grid elt's each time + //sDom: "<'row'<'col-xs-5'l><'col-xs-1'r><'col-xs-6'f>>t<'row'<'col-xs-5'i><'col-xs-7'p>>", + sDom: "<'row'<'col-xs-5'l><'col-xs-5'r><'col-xs-1'r><'col-xs-6'f>>t<'row'<'col-xs-5'i><'col-xs-7'p>><'buttons'>", + //sDom: "<'row'<'col-xs-9'r>t<'buttons'>", + // XXX as of sept. 2013, I cannot locate a bootstrap3-friendly mode for now + // hopefully this would come with dataTables v1.10 ? + // in any case, search for 'sPaginationType' all over the code for more comments + sPaginationType: 'bootstrap', + // Handle the null values & the error : Datatables warning Requested unknown parameter + // http://datatables.net/forums/discussion/5331/datatables-warning-...-requested-unknown-parameter/p2 + aoColumnDefs: [{sDefaultContent: '',aTargets: [ '_all' ]}], + // WARNING: this one causes tables in a 'tabs' that are not exposed at the time this is run to show up empty + // sScrollX: '100%', /* Horizontal scrolling */ + bProcessing: true, /* Loading */ + fnDrawCallback: function() { self._querytable_draw_callback.call(self);} + //fnFooterCallback: function() {self._UnivbrisVtam_footer_callback.call(self,nFoot, aData, iStart, iEnd, aiDisplay)};} + // XXX use $.proxy here ! + }; + // the intention here is that options.datatables_options as coming from the python object take precedence + // xxx DISABLED by jordan: was causing errors in datatables.js + // xxx turned back on by Thierry - this is the code that takes python-provided options into account + // check your datatables_options tag instead + // however, we have to accumulate in aoColumnDefs from here (above) + // and from the python wrapper (checkboxes management, plus any user-provided aoColumnDefs) + if ( 'aoColumnDefs' in this.options.datatables_options) { + actual_options['aoColumnDefs']=this.options.datatables_options['aoColumnDefs'].concat(actual_options['aoColumnDefs']); + delete this.options.datatables_options['aoColumnDefs']; + } + $.extend(actual_options, this.options.datatables_options ); + + + this.table = $("#univbris_vtam__table").dataTable(actual_options); + + + + //alert(this.table.$("name")); + + /* Setup the SelectAll button in the dataTable header */ + /* xxx not sure this is still working */ + var oSelectAll = $('#datatableSelectAll-'+ this.options.plugin_uuid); + oSelectAll.html("Select All"); + oSelectAll.button(); + oSelectAll.css('font-size','11px'); + oSelectAll.css('float','right'); + oSelectAll.css('margin-right','15px'); + oSelectAll.css('margin-bottom','5px'); + oSelectAll.unbind('click'); + oSelectAll.click(this._selectAll); + + /* Add a filtering function to the current table + * Note: we use closure to get access to the 'options' + */ + $.fn.dataTableExt.afnFiltering.push(function( oSettings, aData, iDataIndex ) { + /* No filtering if the table does not match */ + if (oSettings.nTable.id != self.options.plugin_uuid + '__table') + return true; + return self._querytable_filter.call(self, oSettings, aData, iDataIndex); + }); + + /* Processing hidden_columns */ + $.each(this.options.hidden_columns, function(i, field) { + //manifold.raise_event(self.options.query_all_uuid, FIELD_REMOVED, field); + //alert (field); + self.hide_column(field); + //self.hide_column(field); + }); + + + this._querytable_draw_callback(); + + }, // initialize_table + + + fnCreateVms:function(e){ + console.log("building json to send to backend"); + + var testbeds=[]; + + + try{ + var rows = $("#univbris_vtam__table").dataTable().fnGetNodes(); + if (rows.length<=0){ + throw("no vm specified"); + } + else{ + for(var i=0;i 0) ? tabIndex[0] : -1; + }, // getColIndex + + + + + new_record: function(record) + { + + }, + + clear_table: function() + { + this.table.fnClearTable(); + }, + + redraw_table: function() + { + this.table.fnDraw(); + }, + + show_column: function(field) + { + var oSettings = this.table.fnSettings(); + var cols = oSettings.aoColumns; + var index = this.getColIndex(field,cols); + if (index != -1) + this.table.fnSetColumnVis(index, true); + }, + + hide_column: function(field) + { + var oSettings = this.table.fnSettings(); + var cols = oSettings.aoColumns; + var index = this.getColIndex(field,cols); + //index=-1; + //alert(field + ": index: " + index ); + if (index != -1) + //alert(field + ": hidden with index: " + index ); + this.table.fnSetColumnVis(index, false); + }, + + // this is used at init-time, at which point only init_key can make sense + // (because the argument record, if it comes from query, might not have canonical_key set + set_checkbox_from_record: function (record, checked) { + if (checked === undefined) checked = true; + var init_id = record[this.init_key]; + if (debug) messages.debug("UnivbrisVtam.set_checkbox_from_record, init_id="+init_id); + // using table.$ to search inside elements that are not visible + var element = this.table.$('[init_id="'+init_id+'"]'); + element.attr('checked',checked); + }, + + // id relates to canonical_key + set_checkbox_from_data: function (id, checked) { + if (checked === undefined) checked = true; + if (debug) messages.debug("UnivbrisVtam.set_checkbox_from_data, id="+id); + // using table.$ to search inside elements that are not visible + var element = this.table.$("[id='"+id+"']"); + element.attr('checked',checked); + }, + + /*************************** QUERY HANDLER ****************************/ + + on_filter_added: function(filter) + { + this.filters.push(filter); + this.redraw_table(); + }, + + on_filter_removed: function(filter) + { + // Remove corresponding filters + this.filters = $.grep(this.filters, function(x) { + return x != filter; + }); + this.redraw_table(); + }, + + on_filter_clear: function() + { + // XXX + this.redraw_table(); + }, + + on_field_added: function(field) + { + this.show_column(field); + }, + + on_field_removed: function(field) + { + this.hide_column(field); + }, + + on_field_clear: function() + { + alert('UnivbrisVtam::clear_fields() not implemented'); + }, + + /* XXX TODO: make this generic a plugin has to subscribe to a set of Queries to avoid duplicated code ! */ + /*************************** ALL QUERY HANDLER ****************************/ + + on_all_filter_added: function(filter) + { + // XXX + this.redraw_table(); + }, + + on_all_filter_removed: function(filter) + { + // XXX + this.redraw_table(); + }, + + on_all_filter_clear: function() + { + // XXX + this.redraw_table(); + }, + + on_all_field_added: function(field) + { + this.show_column(field); + }, + + on_all_field_removed: function(field) + { + this.hide_column(field); + }, + + on_all_field_clear: function() + { + alert('UnivbrisVtam::clear_fields() not implemented'); + }, + + + /*************************** RECORD HANDLER ***************************/ + + on_new_record: function(record) + { + }, + + on_clear_records: function() + { + }, + + // Could be the default in parent + on_query_in_progress: function() + { + this.spin(); + }, + + on_query_done: function() + { + this.received_query = true; + // unspin once we have received both + if (this.received_all_query && this.received_query) this.unspin(); + }, + + on_field_state_changed: function(data) + { + switch(data.request) { + case FIELD_REQUEST_ADD: + case FIELD_REQUEST_ADD_RESET: + this.set_checkbox_from_data(data.value, true); + break; + case FIELD_REQUEST_REMOVE: + case FIELD_REQUEST_REMOVE_RESET: + this.set_checkbox_from_data(data.value, false); + break; + default: + break; + } + }, + + /* XXX TODO: make this generic a plugin has to subscribe to a set of Queries to avoid duplicated code ! */ + // all + on_all_field_state_changed: function(data) + { + switch(data.request) { + case FIELD_REQUEST_ADD: + case FIELD_REQUEST_ADD_RESET: + this.set_checkboxfrom_data(data.value, true); + break; + case FIELD_REQUEST_REMOVE: + case FIELD_REQUEST_REMOVE_RESET: + this.set_checkbox_from_data(data.value, false); + break; + default: + break; + } + }, + + on_all_new_record: function(record) + { + this.new_record(record); + }, + + on_all_clear_records: function() + { + this.clear_table(); + + }, + + on_all_query_in_progress: function() + { + // XXX parent + this.spin(); + }, // on_all_query_in_progress + + on_all_query_done: function() + { + if (debug) messages.debug("1-shot initializing dataTables content with " + this.buffered_lines.length + " lines"); + + + //this.table.fnAddData (this.buffered_lines); + this.buffered_lines=[]; + + var self = this; + // if we've already received the slice query, we have not been able to set + // checkboxes on the fly at that time (dom not yet created) + $.each(this.buffered_records_to_check, function(i, record) { + if (debug) messages.debug ("querytable delayed turning on checkbox " + i + " record= " + record); + self.set_checkbox_from_record(record, true); + }); + this.buffered_records_to_check = []; + + this.received_all_query = true; + // unspin once we have received both + if (this.received_all_query && this.received_query) this.unspin(); + + }, // on_all_query_done + + /************************** PRIVATE METHODS ***************************/ + + /** + * @brief QueryTable filtering function + */ + _querytable_filter: function(oSettings, aData, iDataIndex) + { + var ret = true; + $.each (this.filters, function(index, filter) { + /* XXX How to manage checkbox ? */ + var key = filter[0]; + var op = filter[1]; + var value = filter[2]; + + /* Determine index of key in the table columns */ + var col = $.map(oSettings.aoColumns, function(x, i) {if (x.sTitle == key) return i;})[0]; + + /* Unknown key: no filtering */ + if (typeof(col) == 'undefined') + return; + + col_value=unfold.get_value(aData[col]); + /* Test whether current filter is compatible with the column */ + if (op == '=' || op == '==') { + if ( col_value != value || col_value==null || col_value=="" || col_value=="n/a") + ret = false; + }else if (op == '!=') { + if ( col_value == value || col_value==null || col_value=="" || col_value=="n/a") + ret = false; + } else if(op=='<') { + if ( parseFloat(col_value) >= value || col_value==null || col_value=="" || col_value=="n/a") + ret = false; + } else if(op=='>') { + if ( parseFloat(col_value) <= value || col_value==null || col_value=="" || col_value=="n/a") + ret = false; + } else if(op=='<=' || op=='≤') { + if ( parseFloat(col_value) > value || col_value==null || col_value=="" || col_value=="n/a") + ret = false; + } else if(op=='>=' || op=='≥') { + if ( parseFloat(col_value) < value || col_value==null || col_value=="" || col_value=="n/a") + ret = false; + }else{ + // How to break out of a loop ? + alert("filter not supported"); + return false; + } + + }); + return ret; + }, + + _querytable_draw_callback: function() + { + /* + * Handle clicks on checkboxes: reassociate checkbox click every time + * the table is redrawn + */ + this.elts('querytable-checkbox').unbind('click').click(this, this._check_click); + $("#add_vm").unbind('click').click(this, this.fnAddVm); + $("#submit_vms").unbind('click').click(this, this.fnCreateVms); + $('#univbris_vtam__table .delete').unbind('click').click(this, this.fnDelete); + /*var edits=this.elts.all.find('.edit'); + edits.each(function(){ + this.unbind('click').click(this,this.fnEdit); + } + */ + if (!this.table) + return; + + /* Remove pagination if we show only a few results */ + var wrapper = this.table; //.parent().parent().parent(); + var rowsPerPage = this.table.fnSettings()._iDisplayLength; + var rowsToShow = this.table.fnSettings().fnRecordsDisplay(); + var minRowsPerPage = this.table.fnSettings().aLengthMenu[0]; + + if ( rowsToShow <= rowsPerPage || rowsPerPage == -1 ) { + $('.querytable_paginate', wrapper).css('visibility', 'hidden'); + } else { + $('.querytable_paginate', wrapper).css('visibility', 'visible'); + } + + if ( rowsToShow <= minRowsPerPage ) { + $('.querytable_length', wrapper).css('visibility', 'hidden'); + } else { + $('.querytable_length', wrapper).css('visibility', 'visible'); + } + + + + + }, + + + + _check_click: function(e) + { + e.stopPropagation(); + + var self = e.data; + var id=this.id; + + // this.id = key of object to be added... what about multiple keys ? + if (debug) messages.debug("querytable._check_click key="+this.canonical_key+"->"+id+" checked="+this.checked); + //manifold.raise_event(self.options.query_uuid, this.checked?SET_ADD:SET_REMOVED, id); + //return false; // prevent checkbox to be checked, waiting response from manifold plugin api + + }, + + _selectAll: function() + { + // requires jQuery id + var uuid=this.id.split("-"); + var oTable=$("#querytable-"+uuid[1]).dataTable(); + // Function available in QueryTable 1.9.x + // Filter : displayed data only + var filterData = oTable._('tr', {"filter":"applied"}); + /* TODO: WARNING if too many nodes selected, use filters to reduce nuber of nodes */ + if(filterData.length<=100){ + $.each(filterData, function(index, obj) { + var last=$(obj).last(); + var key_value=unfold.get_value(last[0]); + if(typeof($(last[0]).attr('checked'))=="undefined"){ + $.publish('selected', 'add/'+key_value); + } + }); + } + }, + + }); + + + + $.plugin('UnivbrisVtam', UnivbrisVtam); + + /* define the 'dom-checkbox' type for sorting in datatables + http://datatables.net/examples/plug-ins/dom_sort.html + using trial and error I found that the actual column number + was in fact given as a third argument, and not second + as the various online resources had it - go figure */ + $.fn.dataTableExt.afnSortData['dom-checkbox'] = function ( oSettings, _, iColumn ) { + return $.map( oSettings.oApi._fnGetTrNodes(oSettings), function (tr, i) { + return result=$('td:eq('+iColumn+') input', tr).prop('checked') ? '1' : '0'; + } ); + } + + + +})(jQuery); + + + diff --git a/plugins/univbrisvtam/templates/univbrisvtamplugin.html b/plugins/univbrisvtam/templates/univbrisvtamplugin.html new file mode 100644 index 00000000..bcd7787a --- /dev/null +++ b/plugins/univbrisvtam/templates/univbrisvtamplugin.html @@ -0,0 +1,29 @@ +

+
+ + + + {% for column in columns %} {% endfor %} + {% for column in hidden_columns %} {% endfor %} + + + + + + + {% for column in columns %} {% endfor %} + {% for column in hidden_columns %} {% endfor %} + + +
{{ column }}{{ column }}
{{ column }}{{ column }}
+ + + + + + + + +
+
+
diff --git a/plugins/univbrisvtamform/__init__.py b/plugins/univbrisvtamform/__init__.py new file mode 100644 index 00000000..5f6c0d22 --- /dev/null +++ b/plugins/univbrisvtamform/__init__.py @@ -0,0 +1,43 @@ +from unfold.plugin import Plugin + +class UnivbrisVtamForm (Plugin): + + def __init__ (self, query=None, query_all=None, + checkboxes=False, columns=None, + init_key=None, + datatables_options={}, **settings): + Plugin.__init__(self, **settings) + self.query = query + self.query.uuid = query.query_uuid if query else None + self.query_all = query_all + self.query_all_uuid = query_all.query_uuid if query_all else None + + + def template_file (self): + return "univbrisvtamform.html" + + def template_env (self, request): + env={} + env.update(self.__dict__) + return env + + def requirements (self): + reqs = { + 'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", + "js/dataTables.js", "js/dataTables.bootstrap.js", "js/with-datatables.js", + "js/manifold.js", "js/manifold-query.js", + "js/unfold-helper.js", + "js/univbrisvtamform.js", + ] , + 'css_files': [ "css/dataTables.bootstrap.css", + "css/dataTables.full_numbers.css", + "css/univbrisvtamform.css", + ], + } + return reqs + + def json_settings_list (self): + return ['plugin_uuid', 'domid', + 'query_uuid', 'query_all_uuid', + 'checkboxes', 'datatables_options', + 'hidden_columns', 'init_key',] diff --git a/plugins/univbrisvtamform/static/css/univbrisvtamform.css b/plugins/univbrisvtamform/static/css/univbrisvtamform.css new file mode 100644 index 00000000..cd227cf4 --- /dev/null +++ b/plugins/univbrisvtamform/static/css/univbrisvtamform.css @@ -0,0 +1,65 @@ + +/* the bottom of the datatable needs more space */ +div.univbrisvtamform-spacer { padding: 8px 4px 15px 4px; } + +div.UnivbrisVtamForm table.dataTable th { + font: bold 12px/22px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + color: #4f6b72; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; + border-top: 1px solid #C1DAD7; + letter-spacing: 1px; + text-transform: uppercase; + text-align: left; + padding: 8px 12px 4px 20px; + vertical-align:middle; +/* background: #CAE8EA url(../img/tablesort-header.jpg) no-repeat; */ +} + +div.UnivbrisVtamForm table.dataTable th.checkbox { + padding-left: 14px; +} + +div.UnivbrisVtamForm table.dataTable td, div.UnivbrisVtamForm table.dataTable textarea, div.UnivbrisVtamForm table.dataTable input [type="text"] { + font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + color: #660099; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; +} +div.UnivbrisVtamForm table.dataTable td { + padding: 4px 8px 4px 8px; + /* this applies on even rows only, odd ones have a setting in bootstrap of rbg 249.249.249 */ + background-color: #f4f4f4; + color: #660099; +} +div.UnivbrisVtamForm table.dataTable td a { + font-weight:normal; +} +/* these come from bootstrap */ +div.UnivbrisVtamForm div.dataTables_info { + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +/* one could think or using repeat-x here but that's not working because of the arrows + * we might need to make these wider some day + * and/or to add background-color: #caebea + * which would look less conspicuous in case of overflow +*/ + +div.UnivbrisVtamForm table.dataTable thead .sorting { background: url('../img/tablesort-header-sortable.png') no-repeat; } +div.UnivbrisVtamForm table.dataTable thead .sorting_asc { background: url('../img/tablesort-header-up.png') no-repeat; } +div.UnivbrisVtamForm table.dataTable thead .sorting_desc { background: url('../img/tablesort-header-down.png') no-repeat; } +/* this icons set does not have that exact equivalent - using an approximation for now */ +div.UnivbrisVtamForm table.dataTable thead .sorting_asc_disabled { background: url('../img/tablesort-header.png') repeat-x; } +div.UnivbrisVtamForm table.dataTable thead .sorting_desc_disabled { background: url('../img/tablesort-header.png') repeat-x; } + +/* the footers are not active */ +div.UnivbrisVtamForm table.dataTable tfoot { + background: url('../img/tablesort-header.png') repeat-x; + background-color: #caebea; +} +/* and when sorting is turned off it's useful to set this on header too */ +div.UnivbrisVtamForm table.dataTable thead { + background: url('../img/tablesort-header.png') repeat-x; + background-color: #caebea; +} diff --git a/plugins/univbrisvtamform/static/img/README b/plugins/univbrisvtamform/static/img/README new file mode 100644 index 00000000..5df2d69b --- /dev/null +++ b/plugins/univbrisvtamform/static/img/README @@ -0,0 +1,2 @@ +these styling elements come from plekit with a simple transition to png +they're currently not all used in myslice diff --git a/plugins/univbrisvtamform/static/img/tablesort-bullet1.png b/plugins/univbrisvtamform/static/img/tablesort-bullet1.png new file mode 100644 index 0000000000000000000000000000000000000000..4304f360ff514f28b19261938ad13761c3c40c34 GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRQ!3HGLSWEVS1PVMNiy0WWg+Z8+Vb&Z8pkR@w zi(`m{WOBj+v4j@MFAx5_`>(@efAG$K9v`0n5;G+0j5istkgzb=bU>t0WW(S8TvJ%I z7`Xm7YcZTOJ}A=o;(yN>p8t{&2h>hTR~*c3oXxW7k^TuTwKBF8R)w<#t_tQ2YaGHE mf>_wg^<;kVKfln!$neEe`ZGh$s>49r89ZJ6T-G@yGywoMg+6Hj literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtamform/static/img/tablesort-bullet2.png b/plugins/univbrisvtamform/static/img/tablesort-bullet2.png new file mode 100644 index 0000000000000000000000000000000000000000..4f181e19fcee46275781f8619c3a0445b68e5d63 GIT binary patch literal 464 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 Hu0mjfbe)_L literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtamform/static/img/tablesort-header-sortable.png b/plugins/univbrisvtamform/static/img/tablesort-header-sortable.png new file mode 100644 index 0000000000000000000000000000000000000000..0c169040d877c305d38f32654bf7e9bf7129d98f GIT binary patch literal 3758 zcmV;f4pH%mP)gpoN(kL6uqo|1DG>R8R zp2W!@>bE`veFpjr^cgtB48*g={QJe_<#cj6n-ozp7!2}xK1{PISsC&?59TRJlAxX8 zgWv-+TJvVbA7Dxw33*p}-j&}*lC}j&+wr!|ZwEZ zwH=prT$<9;lwW+1gOcJn4%&BRY${%+zioczm)V=rW96~pGfbaF9xb9g$3>+nmWi@H z%m!>>U^}LHf5yP(Lap7Jw>ep`6LKb3>%4EI8L*BEB{DWN<+oeAf1ZS<;$Q^H$_|d@QiBaS1?s(*_x^j>`s=8$ovEcO!8vfZC3?ZGLM?n$lzCvEs8V zj&X_?y~6vw`VOr1eTz9$2r(9xsdQ(DK0IW#enbTl38PG9G4UIvKtxzl@*hY1=Q; zli^-wxyMh6A}@FS*zkP>sGQHsOBPrdN(-(t;Znu&c?K2$bFi;=YaXol$DX%CiVAx%-nT}^CQ6tFzNjCU5p zUfRn{gf_O4Tk#?8F4|aJOe@O|!!v%yW5qMSRy*^{c$j{M@0y*(%i^-)S-eg0Sos;A z#mn$kd)x6^^<>%sD+JCRk^!E3OrqKR+qZAW$Hyn9Pw-u6h{oz6NEU$d97w^M2P^)u zr_ma3+xT7O(;C;VbXxsdke$wA>^k@>J9H_4T`V@6OK7etG@p z)6-KlXq`pg^frHHe7KWRhzAg_~6)w-ufBg7?D@fzB z)A4wW)na+U2_MoT%EOPV?rR3EJ0L6mvE+@##q_fsI>X}$hhWp{OtsQz#a9TnGqj$E z?PRsqi^a>v*NSJto8qzZGdzoz;jQ+z)+M}pVPY^c|Y-;j3au(so}@>}suC2&`Mo6>LPvBqn~Gd)f5 z?24cHW%jn?Wqz5xTp0BJGeFq&UtCpXvGF*|TRjV<>-`dwD?#>j>l8 zOS^R?x8fg5(pX$ff7d2D(`mIIS{_)uY<#VFmj9-Bto#hm;$?WNz3q6-dM=CN{m1`K zv*85ymy_hj*RTKl$FGB8vB;CrXoQo7qmw6Z-@bivb~c$za65Xj2!HdoJ}@_}3|TMT zWvEAP*UD7Y_?0g5Dloh<9{EN{RU7^QqiTeO`DOeJA0)3a%1x#!fbmm1`Nn&khYu{6 z-}0G=CN_7NgpXyizLn{zXRAiQ@@CBg^ULNN`K6okyGm7&urQryk}mQpFuXDzrYDQT zPdV1-*;U0nN;s^wocTND99S8Xkr*~C$GXF$nv+6 z{`K4Y;&_aOVKSee9v{!HE=Tz3q#^|Z9Tr8LWm!5HluxZLpIZ$oV2%NHecyOpG6#7c zm(h*dO>Q*`c5B8R;A*djx403x-s_`tky5tC%lMg|s>gZ@cuez<`DHrmy>H&i_?aHY zY|TI8skghTm~vrYdf0)2%j{}^y;I|;I^FP5R=X>{ri=pu^uneXFkoW~1M-Ge7c6C$ zL0eI9!LA);=_0QJ!|ToCs%0rlu`n!m{V|?Yig5Y>t$1V!zr2deN9B?bqlybp99^utUz?QKkreA|)rmv| zso0S+i#JG8V+``Z7_@_j+3oR$MKK<09+*xx-@|T>s^&Fup05|_?WZ(y?Qk`I>Igk7nf$UX_dXkBJ-h);bw=hnn^W%!cDhp>7DlQeg+VN zzth>NSb0jk#IkgRmGm}7hgOTuv4Gl^6mHEe6a7}5F6Aa=%Fj9zodnJDRe@$+EwkZBC(&76mD+REKV&~f;uE&*jc>~mD&8<_w28{wc%Htt;;N1e8^ zn|9I|&c6e=6Lk3!i~*!r0C4RWf9#1} zKi2T`&!3BQh?@$y=X^3gO$He-SQuu@-^r+u*BK-*7G7P?Znsq<5{r&dx8-+E9cExq z6FZ^|f@_SAWgfPjhnf_bnwpyb)_A)%j$R(LYTXaWnY!BxRM=dLJ3wfXssOa=Vm2vD z$7**xY*d~PrYU}ZyTGmHr%#@|e*OC5>z7#^&GW@C&tKv@Zuo5sVDJ-rSSqqX_^&-{ zM3i1{*EcMSG}<*Jq2{%T3v~+EtUMCMokf0m(!h@RB68Ce|CJX|!;ciKI)mgjM#j&& zRHu|6@vk1iF6Cv((B>Qg-Dzg{JD?3Jh-)YFkV#{Cv*v-07nyI2pYc$g%TMwB=RecK z#=UFfsN;K+sMV~$lNkj$hxU%GEaD8Q49)#?$o?e!ak)KXkS=WaJTJj&@N;o<#sFSK zgjEZmlarI@&!7MH@e{5ry?F5gUvR^EfN6GwpXioPSBRcXAXO{?sWNbgc#W+osx5fX zMWcgCVPHI~3FC*u@IG!;x8hg*Hhq^PmnzzgwAxy=P@N~ zR+a~b_qwmGTJymCk~CBQjE8nuPIxyP!oYZ#o~`2*M>`)!2yjEzvYQzC4NP zFUO~+k!vdf3*js?cL#ekBku97Y08`~i~3 zELGN}#&3{^;e+5BBh$mWFu#FH7@mTXf zb&~nE^6$S>9x`6QBLsN`mvm<&0I>OQjaPK5BTs-I)k;{^&hoF!)h=r-oAj;0NRtRd zS*n{j)mUnJF*bE4jsO!&HZEqLvqc<@$JfQ|7=QeHc~l%<4Uhiv*T3Og3+Z5p3rc{- z36_S%@+qb84$cigsKtV^$}M@8^Gw~ly;ND%2n!1=2;Rad!m1th2-*WkRgEY}P-^k0 z*v&K#wzjHy@EoaqEkiwEL)x|O^rYA$#6SiG_^=gdt)mt2&b!-dJ7%w!5^CX&Kj+BH zv$N_JJm`WA!eo;wUV|>!6Uz9)bNTg!U?O){{n@nUCGRz3H}TNyUV>ce9m zdlXDRv$Op(T^Mku0iyys`DTNT5Obh*c+#@=sumcA39T|TYhikrmnyz$ar;{1s%LYV z`*IgDU>z^(d}upHtNtp!YH>ApEnZifTdt47MM}AAaWVaBhhQyN!%+)e7;r~HV#cc! zK*vrOsyUJ_>Sq568lWaeE&CU2A5mvBpqF|)g>BD9`a-K2VB^J{TIU1fVFzkfex|>M$LoSB zz@AZM*YGH&3k9a1Y3o{COuy=6053qgFaReMU=&hRv9VKE#YjQBd;YYlFtzNqVAZ2| zb`r(je9S#qK+5*@9l?~f$-la9cC{2sQV1`8R#?6X8;-a YKbWq-ms_8Wga7~l07*qoM6N<$f@fiU0RR91 literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtamform/static/img/tablesort-header-up.png b/plugins/univbrisvtamform/static/img/tablesort-header-up.png new file mode 100644 index 0000000000000000000000000000000000000000..d12fe2a5cbec852a02dc1d7aadd46c31c7022287 GIT binary patch literal 3877 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 literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtamform/static/img/tablesort-header.png b/plugins/univbrisvtamform/static/img/tablesort-header.png new file mode 100644 index 0000000000000000000000000000000000000000..cff526f9c7beb9cb552a669b3c8171583a80c55c GIT binary patch literal 2887 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 literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtamform/static/img/tablesort-td-alt.png b/plugins/univbrisvtamform/static/img/tablesort-td-alt.png new file mode 100644 index 0000000000000000000000000000000000000000..ef5ab358abd77cc238276d77592083cf7c0b5439 GIT binary patch literal 479 zcmeAS@N?(olHy`uVBq!ia0y~yVAKY(H8_}nq^7F(Pawrv;1OBOz`!jG!i)^F=12fl zP4ske45?szd-LGBCIb!Y^6uimj_=)QsD!0+a&U}Blav{=sO&i{jF_TI1lUjFyd{tN2U-m~n}GkEpT zS=ZvVsd>x)?(!{@C65B z2L;Uqjh?kPSxheQ2zYR1Bm~8qG4h%)vrJ-=nsH^iFHkwdKq>#j*vsJHa&KQm4=~0U NJYD@<);T3K0RZy{!7u;- literal 0 HcmV?d00001 diff --git a/plugins/univbrisvtamform/static/img/toggle-hidden.png b/plugins/univbrisvtamform/static/img/toggle-hidden.png new file mode 100755 index 0000000000000000000000000000000000000000..023f22a8d8ffb61841939f0e5b60dc13a70ead9a GIT binary patch literal 4356 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 Wx704#E!RQ-0000 + * Copyright (c) 2012-2013 UPMC Sorbonne Universite - INRIA + * License: GPLv3 + */ + +(function($){ + + vt_servers_list=[]; + testbeds_list=[]; + + var UnivbrisVtamForm = Plugin.extend({ + + init: function(options, element) { + //console.log("hello...................."); + this._super(options, element); + this.filters = Array(); + + // an internal buffer for records that are 'in' and thus need to be checked + this.buffered_records_to_check = []; + // an internal buffer for keeping lines and display them in one call to fnAddData + this.buffered_lines = []; + + + + + //var keys = manifold.metadata.get_key(this.object); + //this.canonical_key = (keys && keys.length == 1) ? keys[0] : undefined; + // + //this.init_key = this.options.init_key; + // have init_key default to canonical_key + //this.init_key = this.init_key || this.canonical_key; + // sanity check + //if ( ! this.init_key ) messages.warning ("UnivbrisVtamForm : cannot find init_key"); + //if ( ! this.canonical_key ) messages.warning ("UnivbrisVtamForm : cannot find canonical_key"); + //if (debug) messages.debug("UnivbrisVtamForm: canonical_key="+this.canonical_key+" init_key="+this.init_key); + + /* Setup query and record handlers */ + this.listen_query(options.query_uuid); + // this.listen_query(options.query_all_uuid, 'all'); + + /* GUI setup and event binding */ + + + $('').appendTo('#vtam_form_buttons'); + $("#cancelvtamform").unbind('click').click(this, this.fnCancelVtamForm); + + $('').appendTo('#vtam_form_buttons'); + $("#addvtamform").unbind('click').click(this, this.fnAddVtamForm); + + jQuery("#univbris_vtam_form").hide(); + + $('#uob_testbed_name').on("change", this.testbedChanged); + + //this.on_new_record("urn:publicid:IDN+i2cat:vtam+node+Rodoreda"); + //this.on_new_record("urn:publicid:IDN+bristol:vtam+node+March"); + //this.on_new_record("urn:publicid:IDN+brazil:vtam+node+Verdaguer"); + //this.on_query_done(); + + // console.log("after"); + }, + + testbedChanged: function(e){ + console.log($('#uob_testbed_name option:selected').text()); + + $('#uob_virtualization_server') + .find('option') + .remove() + .end(); + + for(var i=0;i") + .attr("value",vt_servers_list[i].name) + .text(vt_servers_list[i].name)); + } + } + }, + + + fnCancelVtamForm:function(e){ + jQuery("#univbris_vtam_form").hide(); + jQuery("#univbris_vtam").show(); + console.log("cancel vtam form"); + }, + + fnAddVtamForm:function(e){ + console.log("add vtam form"); + var vmNameVal = /^[a-zA-Z0-9]+$/; + //console.log($("#uob_vm_name").val()); + if (vmNameVal.test($("#uob_vm_name").val())){ + //build form string + var vtam="testbed:"+$('#uob_testbed_name option:selected').text(); + vtam +=",vt_server:"+$('#uob_virtualization_server option:selected').text(); + vtam +=",vm_name:"+$("#uob_vm_name").val(); + var vm_name="

"+$("#uob_vm_name").val()+"

"; + var vtamtable = $("#univbris_vtam__table").dataTable(); + vtamtable.fnAddData([$('#uob_testbed_name option:selected').text(),$('#uob_virtualization_server option:selected').text(), vm_name,'Delete']); + jQuery("#univbris_vtam_form").hide(); + jQuery("#univbris_vtam").show(); + } + else{ + $('#uob_vm_name').addClass('error'); + jQuery('#uob_vm_name_error').show(); + } + }, + + /* PLUGIN EVENTS */ + + on_show: function(e) { + }, + + on_resize: function(e) { + }, + + /* GUI EVENTS */ + + /* GUI MANIPULATION */ + + new_record: function(record) + { + var urn = record['urn']; + var pos = urn.search('vtam'); + if (pos!=-1){ + ///line =new Array(); + var vt_server={}; + var com_ay=urn.split("+"); + vt_server['name']=com_ay[com_ay.length-1]; + var testbed_ay=com_ay[1].split(":"); + vt_server['testbed']=testbed_ay[0]; + this.add_new_vt_server(vt_server); + this.add_new_testbed(testbed_ay[0]); + //this.vt_servers_list.push(vt_server); + } + }, + + clear_table: function() + { + }, + + redraw_table: function() + { + }, + + + add_new_vt_server:function(vt_server){ + var found=false; + for(var i=0;i") + .attr("value",key) + .text(value.testbed)); + });*/ + + $('#uob_testbed_name') + .find('option') + .remove() + .end() + + for(var t=0;t") + .attr("value",testbeds_list[t]) + .text(testbeds_list[t])); + } + + $('#uob_virtualization_server') + .find('option') + .remove() + .end() + + for(var i=0;i") + .attr("value",vt_servers_list[i].name) + .text(vt_servers_list[i].name)); + } + } + + this.unspin(); + }, + + on_field_state_changed: function(data) + { + + }, + + }); //close plugin extend + + $.plugin('UnivbrisVtamForm', UnivbrisVtamForm); + +})(jQuery); + + + + diff --git a/plugins/univbrisvtamform/templates/univbrisvtamform.html b/plugins/univbrisvtamform/templates/univbrisvtamform.html new file mode 100644 index 00000000..b9f7c509 --- /dev/null +++ b/plugins/univbrisvtamform/templates/univbrisvtamform.html @@ -0,0 +1,62 @@ + + +
+ + + + + + + + + + + + + + + + + + + + +
Testbed + +
Virtualization Server + + + +
VM Name + + + + +

name of VM should be alphanumeric

+
+
+
+ diff --git a/portal/sliceresourceview.py b/portal/sliceresourceview.py index eaf7931c..985e775b 100644 --- a/portal/sliceresourceview.py +++ b/portal/sliceresourceview.py @@ -30,7 +30,8 @@ from plugins.univbrisfv import UnivbrisFv from plugins.univbrisfvf import UnivbrisFvf from plugins.univbrisfvfo import UnivbrisFvfo from plugins.univbristopo import UnivbrisTopo - +from plugins.univbrisvtam import UnivbrisVtam as UnivbrisVtamPlugin +from plugins.univbrisvtamform import UnivbrisVtamForm from plugins.columns_editor import ColumnsEditor from plugins.sladialog import SlaDialog @@ -313,9 +314,8 @@ class SliceResourceView (LoginRequiredView, ThemeView): }, ) - #plugin which allows the definition the match criteria on a single OPTICAL flowspace - - univbrisofvform = UnivbrisFvfo( + #plugin which allows the definition the match criteria on a single OPTICAL flowspace + univbrisofvform = UnivbrisFvfo( page = page, title = 'univbris_oflowspace_form', domid = 'univbris_oflowspace_form', @@ -334,9 +334,34 @@ class SliceResourceView (LoginRequiredView, ThemeView): title = 'univbris_topology', domid = 'univbris_topology', query = query_resource_all, - #query = query_resource_all, ) - + + # -------------------------------------------------------------------------- + # Ofelia VTAM Plugin + # Bristol Plugin + + #plugin which display a table where an experimenter will add VMs to according to his needs + univbrisvtamplugin = UnivbrisVtamPlugin( + page = page, + title = 'univbris_vtam', + domid = 'univbris_vtam', + query = None, + ) + + #plugin which display a form where an experimenter will specify where a + univbrisvtamform = UnivbrisVtamForm( + page = page, + title = 'univbris_vtam_form', + domid = 'univbris_vtam_form', + query = query_resource_all, + query_all = None, + datatables_options = { + 'iDisplayLength': 3, + 'bLengthChange' : True, + 'bAutoWidth' : True, + }, + ) + # -------------------------------------------------------------------------- # SLA View and accept dialog @@ -393,7 +418,9 @@ class SliceResourceView (LoginRequiredView, ThemeView): template_env['oflowspaces_form'] = univbrisofvform.render(self.request) template_env['flowspaces_form'] = univbrisfvform.render(self.request) template_env['topology'] = univbristopology.render(self.request) - + template_env['vms_list'] = univbrisvtamplugin.render(self.request) + template_env['vm_form'] = univbrisvtamform.render(self.request) + # template_env['pending_resources'] = pending_resources.render(self.request) template_env['sla_dialog'] = '' # sla_dialog.render(self.request) template_env["theme"] = self.theme diff --git a/portal/templates/slice-resource-view.html b/portal/templates/slice-resource-view.html index 17e13830..ff1fc3e0 100644 --- a/portal/templates/slice-resource-view.html +++ b/portal/templates/slice-resource-view.html @@ -54,6 +54,7 @@ $(document).ready(function() { @@ -91,8 +92,14 @@ $(document).ready(function() {
{{map_resources}}
-
+
+

{{vms_list}}

+

{{vm_form}}

+ +

{{below_table}}

+
+

{{welcome}}

{{flowspaces}}

{{flowspaces_form}}

@@ -101,8 +108,8 @@ $(document).ready(function() {

{{resources}}

{{below_table}}

-
+
{{scheduler}}
diff --git a/portal/templates/univbrisvtam.html b/portal/templates/univbrisvtam.html new file mode 100644 index 00000000..82de78b9 --- /dev/null +++ b/portal/templates/univbrisvtam.html @@ -0,0 +1,15 @@ +{% extends "layout-unfold1.html" %} + +{% block head %} +{% endblock %} + +{% block unfold_main %} + +

Create New Virtual Machines

+ +

{{vms_list}}

+

{{vm_form}}

+ +

{{below_table}}

+ +{% endblock %} diff --git a/portal/univbrisvtam.py b/portal/univbrisvtam.py new file mode 100644 index 00000000..c557998a --- /dev/null +++ b/portal/univbrisvtam.py @@ -0,0 +1,94 @@ +import json +from manifold.core.query import Query +from manifoldapi.manifoldapi import execute_query + +from unfold.page import Page + +from plugins.lists.testbedlist import TestbedList +from plugins.lists.slicelist import SliceList + +from unfold.loginrequired import FreeAccessView +from unfold.loginrequired import LoginRequiredAutoLogoutView + +from ui.topmenu import topmenu_items_live, the_user +from plugins.lists.staticlist import StaticList +from plugins.lists.slicelist import SliceList +from plugins.messages import Messages +from plugins.querytable import QueryTable +from plugins.univbrisfoam import UnivbrisFoam +from plugins.univbrisfv import UnivbrisFv +from plugins.univbrisvtam import UnivbrisVtam as UnivbrisVtamPlugin +from plugins.univbrisvtamform import UnivbrisVtamForm + +#This view requires login +class UnivbrisVtam (LoginRequiredAutoLogoutView): + template_name = "univbrisvtam.html" + + def get_context_data(self, **kwargs): + + page = Page(self.request) + #print "UNIVBRIS page" + + #create new query to manifold----query is not called yet + #need to modify to get i2cat of resources also + univbrisvtamform_query=Query().get('ofelia-i2cat-vt:resource').select('hostname') + #print univbrisfoam_query #.select('urn') + + #queue the query + page.enqueue_query(univbrisvtamform_query) + page.expose_js_metadata() + + + #plugin which display a table where an experimenter will add VMs to according to his needs + univbrisvtamplugin = UnivbrisVtamPlugin( + page = page, + title = 'univbris_vtam', + domid = 'univbris_vtam', + query = None, + ) + + #plugin which display a form where an experimenter will specify where a + univbrisvtamform = UnivbrisVtamForm( + page = page, + title = 'univbris_vtam_form', + domid = 'univbris_vtam_form', + query = univbrisvtamform_query, + query_all = None, + datatables_options = { + 'iDisplayLength': 3, + 'bLengthChange' : True, + 'bAutoWidth' : True, + }, + ) + + #render plugins in each context within a single page, but not all plugins are visible at all time. + context = super(UnivbrisVtam, self).get_context_data(**kwargs) + context['person'] = self.request.user + #context['welcome'] = univbriswelcome.render(self.request) + #context['resources'] = univbrisfoamlist.render(self.request) + context['vms_list']= univbrisvtamplugin.render(self.request) + context['vm_form']= univbrisvtamform.render(self.request) + #context['oflowspaces_form']= univbrisofvform.render(self.request) + #context['flowspaces_form']= univbrisfvform.render(self.request) + #context['topology']=univbristopology.render(self.request) + + + # XXX This is repeated in all pages + # more general variables expected in the template + context['title'] = 'Create New Virtual Machines' + # the menu items on the top + context['topmenu_items'] = topmenu_items_live('univbris', page) + # so we can sho who is logged + context['username'] = the_user(self.request) + + context.update(page.prelude_env()) + page.expose_js_metadata() + + + # the page header and other stuff + context.update(page.prelude_env()) + + context['layout_1_or_2']="layout-unfold2.html" if not context['username'] else "layout-unfold1.html" + + return context + diff --git a/portal/urls.py b/portal/urls.py index 907267c4..8859e624 100644 --- a/portal/urls.py +++ b/portal/urls.py @@ -44,16 +44,18 @@ from portal.validationview import ValidatePendingView #from portal.experimentview import ExperimentView from portal.termsview import TermsView from portal.univbrisview import UnivbrisView +from portal.univbrisvtam import UnivbrisVtam + from portal.manualdelegationview import ManualDelegationView -from portal.servicedirectory import ServiceDirectoryView +from portal.servicedirectory import ServiceDirectoryView from portal.documentationview import DocumentationView from portal.supportview import SupportView from portal.emailactivationview import ActivateEmailView # hopefully these should move in dedicated source files too -from portal.views import PresViewView, pres_view_static, pres_view_methods, pres_view_animation -from portal.django_passresetview import password_reset, password_reset_done, password_reset_confirm, password_reset_complete +from portal.views import PresViewView, pres_view_static, pres_view_methods, pres_view_animation +from portal.django_passresetview import password_reset, password_reset_done, password_reset_confirm, password_reset_complete # DEPRECATED #named_register_forms = ( # DEPRECATED # ("step1", RegisterUserForm), @@ -122,7 +124,8 @@ urlpatterns = patterns('', 'portal.django_passresetview.password_reset_complete'), url(r'^univbris/?$', UnivbrisView.as_view(), name='univbris'), - + url(r'^univbrisvtam/?$', UnivbrisVtam.as_view(), name='univbrisvtam'), + url(r'^servicedirectory/?$', ServiceDirectoryView.as_view(), name='servicedirectory'), ) -- 2.43.0