1 from unfold.plugin import Plugin
3 class QueryTable (Plugin):
5 """A plugin for displaying a query as a list
7 More accurately, we consider a subject entity (say, a slice)
8 that can be linked to any number of related entities (say, resources, or users)
9 The 'query' argument will correspond to the subject, while
10 'query_all' will fetch the complete list of
11 possible candidates for the relationship.
13 Current implementation makes the following assumptions
14 * query will only retrieve for the related items a list of fields
15 that corresponds to the initial set of fields displayed in the table
16 * query_all on the contrary is expected to return the complete set of
17 available attributes that may be of interest, so that using a QueryEditor
18 one can easily extend this table without having to query the backend
19 * checkboxes is a boolean flag, set to true if a rightmost column
20 with checkboxes is desired
21 * optionally pass columns as the initial set of columns
22 if None then this is taken from the query's fields
23 * init_key is the name of a column that should appear in both queries
24 and used internally in the plugin for checkboxes initialization.
25 If not specified, metadata will be used to find out a primary key.
26 However in the case of nodes & slice for example, the default key
27 as returned by the metadata would be 'urn', but 'urn' could only
28 be used for this purpose if it gets displayed initially, which is
29 not necessarily a good idea.
30 This is why a slice view would use 'hrn' here instead.
31 * datatables_options are passed to dataTables as-is;
32 however please refrain from passing an 'aoColumns'
33 as we use 'aoColumnDefs' instead.
37 'network_hrn' : 'Testbed',
38 'hostname' : 'Resource name',
42 def __init__ (self, query=None, query_all=None,
43 checkboxes=False, columns=None,
45 datatables_options={}, **settings):
46 Plugin.__init__ (self, **settings)
48 # Until we have a proper way to access queries in Python
49 self.query_all = query_all
50 self.query_all_uuid = query_all.query_uuid if query_all else None
51 self.checkboxes = checkboxes
53 # XXX We need to have some hidden columns until we properly handle dynamic queries
54 if columns is not None:
58 _columns = [field for field in self.query.fields if not field == 'urn']
60 # We need a list because sets are not JSON-serializable
61 _hidden_columns = list(self.query_all.fields - self.query.fields)
62 _hidden_columns.append('urn')
69 print "_columns=", _columns
70 self.columns = { self.MAP.get(c, c) : c for c in _columns }
71 self.hidden_columns = { self.MAP.get(c, c) : c for c in _hidden_columns }
72 print "self.columns", self.columns
74 self.init_key=init_key
75 self.datatables_options=datatables_options
76 # if checkboxes were required, we tell datatables about this column's type
77 # so that sorting can take place on a selected-first basis (or -last of course)
78 # this relies on the template exposing the checkboxes 'th' with class 'checkbox'
80 # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns
81 if 'aoColumns' in self.datatables_options:
82 print 'WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded'
83 del self.datatables_options['aoColumns']
84 # set aoColumnDefs in datatables_options - might already have stuff in there
85 aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[])
86 # here 'checkbox' is the class that we give to the <th> dom elem
87 # dom-checkbox is a sorting type that we define in querytable.js
88 #aoColumnDefs.insert (0, {'aTargets': ['checkbox'], 'sSortDataType': 'dom-checkbox' } )
90 def template_file (self):
91 return "querytable.html"
93 def template_env (self, request):
95 env.update(self.__dict__)
96 env['columns']=self.columns
99 def requirements (self):
101 'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
102 "js/dataTables.js", "js/dataTables.bootstrap.js", "js/with-datatables.js",
103 "js/manifold.js", "js/manifold-query.js",
104 "js/unfold-helper.js",
105 # querytable.js needs to be loaded after dataTables.js as it extends
106 # dataTableExt.afnSortData
109 'css_files': [ #"css/dataTables.bootstrap.css",
110 # hopefully temporary, when/if datatables supports sPaginationType=bootstrap3
111 # for now we use full_numbers, with our own ad hoc css
112 #"css/dataTables.full_numbers.css",
113 "css/querytable.css" ,
118 # the list of things passed to the js plugin
119 def json_settings_list (self):
120 return ['plugin_uuid', 'domid',
121 'query_uuid', 'query_all_uuid',
122 'checkboxes', 'datatables_options',
123 'hidden_columns', 'init_key',]