[views] Add master/slave dependency between keyword type and possible vocabularies
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 16 Mar 2017 11:24:40 +0100
changeset 2497 d1278ff559b9
parent 2496 492163cc78b8
child 2498 1b26f8fc74f0
[views] Add master/slave dependency between keyword type and possible vocabularies as specified in extranet #12351787. Some UI tweaks will be done later to make it more robust (removing the possibility to add/remove the type inlined form).
cubicweb_seda/data/cubes.skoscomplete.js
cubicweb_seda/views/archiveunit.py
cubicweb_seda/views/widgets.py
--- a/cubicweb_seda/data/cubes.skoscomplete.js	Thu Mar 16 11:02:55 2017 +0100
+++ b/cubicweb_seda/data/cubes.skoscomplete.js	Thu Mar 16 11:24:40 2017 +0100
@@ -85,3 +85,50 @@
         cw.jqNode(slaveSelectId).val('');
     }
 };
+
+typed_vocabularies = {
+    initKeywordTypeMasterWidget: function(masterSelectId, slaveSelectBaseName, allVocabularies) {
+        typed_vocabularies.allVocabularies = allVocabularies;
+        var $masterSelect = cw.jqNode(masterSelectId);
+        var $slaveSelect = $('select[name*="' + slaveSelectBaseName + '"]');
+        if ($slaveSelect.length === 0) {
+            // simple keyword, don't do anything
+            return
+        }
+        // bind keyword type select to update possible vocabularies on value change
+        $masterSelect.change(function() {
+            typed_vocabularies.updatePossibleVocabularies($masterSelect, $slaveSelect);
+        });
+        // initialize possible vocabularies by looking the value of the master field
+        typed_vocabularies.updatePossibleVocabularies($masterSelect, $slaveSelect);
+    },
+
+    updatePossibleVocabularies: function($masterSelect, $slaveSelect) {
+        if (typeof $masterSelect != 'undefined') {
+            var selected_type = $masterSelect.val();
+        } else {
+            var selected_type = '__cubicweb_internal_field__';
+        }
+        var selected_vocab = $slaveSelect.val();
+        // empty possible vocabularies, then refill it with vocabularies that match selected type
+        // (or every vocabulary if there is no selected type)
+        $slaveSelect.empty();
+        $slaveSelect.append('<option value="__cubicweb_internal_field__"></option>');
+        for (i=0; i < typed_vocabularies.allVocabularies.length; i++) {
+            var vocabulary = typed_vocabularies.allVocabularies[i];
+            if (selected_type == '__cubicweb_internal_field__'
+                    || selected_type == vocabulary.keyword_type) {
+                var selected = '';
+                if (selected_vocab == vocabulary.eid) {
+                    selected = ' selected="1"'
+                }
+                $slaveSelect.append(
+                    '<option value="' + vocabulary.eid+ '"' + selected + '>'
+                        + vocabulary.title + '</option>');
+            }
+        }
+        // we've to trigger the change event by ourselves to kick in concept_autocomplete,
+        // probably because we did not changed the value but rather rebuilt the select values
+        $slaveSelect.trigger('change');
+    },
+};
--- a/cubicweb_seda/views/archiveunit.py	Thu Mar 16 11:02:55 2017 +0100
+++ b/cubicweb_seda/views/archiveunit.py	Thu Mar 16 11:24:40 2017 +0100
@@ -612,6 +612,10 @@
 # but one ordering is enough to rule them all
 affk.set_fields_order('SEDAKeyword', ['keyword_content', ('seda_keyword_reference_from', 'object')])
 
+affk.set_field_kwargs('SEDAKeywordType', 'seda_keyword_type_to',
+                      widget=widgets.KeywordTypeMasterWidget(
+                          slave_base_name='seda_keyword_reference_to_scheme'))
+
 
 class ComplexKeywordAutomaticEntityForm(autoform.AutomaticEntityForm):
     __select__ = (is_instance('SEDAKeyword') & ~is_simple_keyword())
--- a/cubicweb_seda/views/widgets.py	Thu Mar 16 11:02:55 2017 +0100
+++ b/cubicweb_seda/views/widgets.py	Thu Mar 16 11:24:40 2017 +0100
@@ -106,6 +106,37 @@
             yield (subfield, equivalent_eids)
 
 
+class KeywordTypeMasterWidget(fw.Select):
+    """
+    Usage::
+
+      affk = uicfg.autoform_field_kwargs
+      affk.set_field_kwargs('KeywordType', 'keyword_type_to',
+                            widget=widgets.KeywordTypeMasterWidget(
+                            slave_base_name='seda_keyword_reference_to_scheme'))
+    """
+
+    def __init__(self, slave_base_name, **kwargs):
+        super(KeywordTypeMasterWidget, self).__init__(**kwargs)
+        self.slave_base_name = slave_base_name
+
+    def _render(self, form, field, render):
+        req = form._cw
+
+        vocabularies_data = []
+        for eid, title, uri, keyword_type in req.execute(
+                'Any CS,CST,CSU,CSKT WHERE CS title CST, CS cwuri CSU, CS code_keyword_type CSKT?'):
+            vocabularies_data.append({'eid': eid, 'title': title or uri,
+                                      'keyword_type': keyword_type})
+        vocabularies_data.sort(key=lambda x: x['title'])
+
+        req.add_js(('cubicweb.js', 'cubicweb.ajax.js', 'cubes.skoscomplete.js'))
+        req.add_onload(js.typed_vocabularies.initKeywordTypeMasterWidget(
+            field.dom_id(form, self.suffix), self.slave_base_name, vocabularies_data))
+
+        return super(KeywordTypeMasterWidget, self)._render(form, field, render)
+
+
 class ConceptAutoCompleteWidget(fw.TextInput):
     """Derive from simple text input to create an autocompletion widget if a scheme is specified,
     otherwise free text is fine if `optional` argument is true. In such case: