Skip to content
This repository was archived by the owner on Nov 25, 2020. It is now read-only.

Commit 6ced826

Browse files
committed
[meta.user] New "tags" type with auto-completion and special display. Expose meta definitions directly in plugin params and load them statically. We should remove the other way to pass the meta_fields values.
1 parent 23776c8 commit 6ced826

File tree

3 files changed

+208
-9
lines changed

3 files changed

+208
-9
lines changed

core/src/plugins/meta.user/class.MetaCellRenderer.js

Lines changed: 162 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
* The latest code can be found at <http://pyd.io/>.
1919
* Description : Static class for renderers
2020
*/
21-
Class.create("MetaCellRenderer", {
21+
Class.create("MetaCellRenderer", {
22+
2223
initialize: function(){
2324
this.cssList = new Hash({
2425
'low': {cssClass:'meta_low', label:MessageHash['meta.user.4'], sortValue:'5'},
@@ -38,8 +39,36 @@ Class.create("MetaCellRenderer", {
3839
});
3940
head.insert(cssNode);
4041
}
42+
4143
},
4244

45+
staticGetMetaConfigs: function(){
46+
if(pydio && pydio.user && pydio.user.activeRepository && MetaCellRenderer.configsCache && MetaCellRenderer.configsCache.get(pydio.user.activeRepository )){
47+
return MetaCellRenderer.configsCache.get(pydio.user.activeRepository);
48+
}
49+
var configs = $H();
50+
try{
51+
configs = $H(pydio.getPluginConfigs("meta.user").get("meta_definitions").evalJSON());
52+
configs.each(function(pair){
53+
var type = pair.value.type;
54+
if(type == 'choice' && pair.value.data){
55+
var values = {};
56+
$A(pair.value.data.split(",")).each(function(keyLabel){
57+
var parts = keyLabel.split("|");
58+
values[parts[0]] = parts[1];
59+
});
60+
pair.value.data = values;
61+
}
62+
});
63+
}catch(e){
64+
}
65+
if(pydio && pydio.user && pydio.user.activeRepository){
66+
if(!MetaCellRenderer.configsCache) MetaCellRenderer.configsCache = $H();
67+
MetaCellRenderer.configsCache.set(pydio.user.activeRepository, configs);
68+
}
69+
return configs;
70+
},
71+
4372
/* SELECTORS */
4473
selectorsFilter : function(element, ajxpNode, type, metadataDef, ajxpNodeObject){
4574
if(!metadataDef) return;
@@ -70,21 +99,33 @@ Class.create("MetaCellRenderer", {
7099
}
71100
element.writeAttribute("data-sorter_value", nodeMetaValue);
72101
}else{
102+
if(element.down('.text_label') && values[element.down('.text_label').innerHTML.stripTags()]){
103+
element.down('.text_label').update(values[element.down('.text_label').innerHTML.stripTags()]);
104+
}
73105
element.writeAttribute("data-"+metadataDef.attributeName+"-sorter_value", nodeMetaValue);
74106
}
75107
}
76108
},
77109

78110
formPanelSelectorFilter: function(formElement, form){
79-
if(MetaCellRenderer.staticMetadataCache && MetaCellRenderer.staticMetadataCache.get(formElement.name)){
80-
var selectorValues = MetaCellRenderer.staticMetadataCache.get(formElement.name);
111+
var selectorValues;
112+
try{
113+
selectorValues = MetaCellRenderer.staticMetadataCache.get(formElement.name);
114+
}catch(e){}
115+
if(!selectorValues){
116+
var definitions = MetaCellRenderer.prototype.staticGetMetaConfigs();
117+
selectorValues = definitions.get(formElement.name).data;
118+
}
119+
if(selectorValues){
81120
if(!selectorValues) return;
82121
var value = formElement.getValue();
83-
var select = new Element('select', {name: formElement.name,style:'width:56%;height:24px;'});
122+
var select = new Element('select', {name: formElement.name, className:'select_meta_selector'});
123+
select.insert(new Element("option", {value:''}).update(''));
84124
$H(selectorValues).each(function(pair){
85125
select.insert(new Element("option", {value:pair.key}).update(pair.value));
86126
if(value) select.setValue(value);
87127
});
128+
if(formElement.id) select.id = formElement.id;
88129
formElement.replace(select);
89130
}
90131
},
@@ -205,7 +246,7 @@ Class.create("MetaCellRenderer", {
205246
}
206247
},
207248

208-
infoPanelModifier : function(htmlElement){
249+
infoPanelModifier : function(htmlElement, ajxpNode){
209250
var obj = new MetaCellRenderer();
210251
htmlElement.select('[data-metatype]').each(function(td){
211252
var metaType = td.readAttribute("data-metatype");
@@ -233,6 +274,10 @@ Class.create("MetaCellRenderer", {
233274
}
234275
}
235276
break;
277+
case "tags":
278+
var value = td.innerHTML.strip();
279+
this.displayTagsAsBlocks(td, value, ajxpNode);
280+
break;
236281
case "text":
237282
case "string":
238283
case "textarea":
@@ -372,5 +417,116 @@ Class.create("MetaCellRenderer", {
372417
var cont = new Element('textarea', {name:formElement.name,style:'float: left;width: 161px;border-radius: 3px;padding: 2px;height:100px;'});
373418
cont.innerHTML = formElement.value;
374419
formElement.replace(cont);
375-
}
420+
},
421+
422+
423+
formPanelTags: function(formElement, form){
424+
425+
var fieldName = formElement.name;
426+
var completer = new MetaTagsCompleter(formElement, fieldName);
427+
428+
},
429+
430+
displayTagsAsBlocks: function(element, value, ajxpNode){
431+
if(!value) return;
432+
var values = $A(value.split(",")).invoke("strip");
433+
element.update('');
434+
values.each(function(v){
435+
var tag = new Element('span', {className:"meta_user_tag_block"}).update(v + " <span class='icon-remove' style='cursor: pointer;'></span>");
436+
element.insert(tag);
437+
var remove = tag.down(".icon-remove");
438+
remove.observe("click", function(){
439+
var conn = new Connexion();
440+
conn.setParameters($H({
441+
get_action:"edit_user_meta",
442+
file: ajxpNode.getPath(),
443+
tags: values.without(v).join(", ")
444+
}));
445+
conn.onComplete = function(transport){
446+
pydio.actionBar.parseXmlMessage(transport.responseXML);
447+
};
448+
conn.sendAsync();
449+
});
450+
});
451+
}
452+
453+
});
454+
455+
/**
456+
* Encapsulation of the Prototype Autocompleter for Pydio purposes.
457+
* Should be ported for local provides
458+
*/
459+
Class.create("MetaTagsCompleter", Autocompleter.Base, {
460+
461+
valuesLoaded: null,
462+
/**
463+
* Constructor
464+
* @param element HTMLElement
465+
* @param fieldName String
466+
*/
467+
initialize: function(element, fieldName) {
468+
var update = "meta_tags_complete_"+fieldName;
469+
if(Object.isString(update) && !$(update)){
470+
$$('body')[0].insert(new Element('div', {
471+
id:update,
472+
className:"autocomplete",
473+
style:"position:absolute;z-index:100000;margin-top: 0;"
474+
}));
475+
}
476+
var options = {fieldName: fieldName, tokens: ","};
477+
this.baseInitialize(element, update, options);
478+
this.options.defaultParams = this.options.parameters || null;
479+
this.options.minChars = 0;
480+
481+
element.observe("click", function(){
482+
this.activate();
483+
}.bind(this));
484+
},
485+
486+
valuesToChoices: function(search){
487+
var currentValues = $A(this.element.getValue().split(",")).invoke("strip");
488+
var choices = "";
489+
if(search && this.valuesLoaded.indexOf(search)) {
490+
choices += "<li>"+search+"</li>";
491+
}
492+
this.valuesLoaded.each(function(v){
493+
if(v.indexOf(search) === 0 && currentValues.indexOf(v) === -1){
494+
choices += "<li>"+v+"</li>";
495+
}
496+
}.bind(this));
497+
choices = "<ul>"+ choices + "</ul>";
498+
this.updateChoices(choices);
499+
return choices;
500+
},
501+
502+
/**
503+
* Gets the choices
504+
*/
505+
getUpdatedChoices: function() {
506+
this.startIndicator();
507+
var value = this.getToken().strip();
508+
if(this.valuesLoaded){
509+
var choices = this.valuesToChoices(value);
510+
this.updateChoices(choices);
511+
return choices;
512+
}
513+
514+
var connexion = new Connexion();
515+
connexion.setParameters($H({get_action:'meta_user_list_tags'}));
516+
if(this.options.fieldName){
517+
connexion.addParameter("meta_field_name", this.options.fieldName);
518+
}
519+
connexion.onComplete = function(transport){
520+
this.valuesLoaded = $A(transport.responseJSON);
521+
var choices = this.valuesToChoices(value);
522+
this.updateChoices(choices);
523+
this.stopIndicator();
524+
return choices;
525+
}.bind(this);
526+
527+
connexion.sendAsync();
528+
529+
return "";
530+
}
531+
376532
});

core/src/plugins/meta.user/class.UserMetaManager.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public function initMeta($accessDriver)
5555

5656
//$messages = ConfService::getMessages();
5757
$def = $this->getMetaDefinition();
58+
foreach($def as $k => &$d){
59+
if(isSet($this->fieldsAdditionalData[$k])) $d["data"] = $this->fieldsAdditionalData[$k];
60+
}
61+
$this->exposeConfigInManifest("meta_definitions", json_encode($def));
5862
if(!isSet($this->options["meta_visibility"])) $visibilities = array("visible");
5963
else $visibilities = explode(",", $this->options["meta_visibility"]);
6064
$editButton = '';
@@ -112,8 +116,11 @@ public function initMeta($accessDriver)
112116
$col->setAttribute("modifier", "MetaCellRenderer.prototype.selectorsFilter");
113117
$col->setAttribute("sortType", "CellSorterValue");
114118
$col->setAttribute("metaAdditional", $this->fieldsAdditionalData[$key]);
115-
$searchablesRenderers[$key] = "MetaCellRenderer.prototype.selectorsFilter";
119+
$searchablesRenderers[$key] = "MetaCellRenderer.prototype.formPanelSelectorFilter";
116120
break;
121+
case "tags":
122+
$searchables[$key] = $label;
123+
$searchablesRenderers[$key] = "MetaCellRenderer.prototype.formPanelTags";
117124
default:
118125
break;
119126
}
@@ -238,6 +245,9 @@ public function editMeta($actionName, $httpVars, $fileVars)
238245
foreach ($def as $key => $data) {
239246
if (isSet($httpVars[$key])) {
240247
$newValues[$key] = AJXP_Utils::decodeSecureMagic($httpVars[$key]);
248+
if($data["type"] == "tags"){
249+
$this->updateTags(AJXP_Utils::decodeSecureMagic($httpVars[$key]));
250+
}
241251
} else {
242252
if (!isset($original)) {
243253
$original = $ajxpNode->retrieveMetadata("users_meta", false, AJXP_METADATA_SCOPE_GLOBAL);
@@ -348,4 +358,30 @@ public function updateMetaLocation($oldNode, $newNode = null, $copy = false)
348358
}
349359
}
350360

361+
public function listTags($actionName, &$httpVars, &$fileVars){
362+
363+
HTMLWriter::charsetHeader("application/json");
364+
$tags = $this->loadTags();
365+
if(empty($tags)) $tags = array();
366+
echo json_encode($tags);
367+
368+
}
369+
370+
protected function loadTags(){
371+
$store = ConfService::getConfStorageImpl();
372+
if(!is_a($store, "sqlConfDriver")) return array();
373+
$data = array();
374+
$store->simpleStoreGet("meta_user_tags", ConfService::getRepository()->getId(), "serial", $data);
375+
return $data;
376+
}
377+
378+
protected function updateTags($tagString){
379+
$store = ConfService::getConfStorageImpl();
380+
if(!is_a($store, "sqlConfDriver")) return;
381+
$tags = $this->loadTags();
382+
$tags = array_merge($tags, array_map("trim", explode(",", $tagString)));
383+
$tags = array_unique($tags);
384+
$store->simpleStoreSet("meta_user_tags", ConfService::getRepository()->getId(), array_values($tags), "serial");
385+
}
386+
351387
}

core/src/plugins/meta.user/manifest.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<!--<param name="meta_file_name" type="string" label="CONF_MESSAGE[Meta File]" description="CONF_MESSAGE[Hidden file used inside folders to save meta data]" mandatory="true" default=".ajxp_meta"/>-->
1313
<param name="meta_fields" type="string" replicationGroup="group1" label="CONF_MESSAGE[Field ID]" description="CONF_MESSAGE[Id of fiels, use standard characters here.]" mandatory="true" default="comment_field"/>
1414
<param name="meta_labels" type="string" replicationGroup="group1" label="CONF_MESSAGE[Label]" description="CONF_MESSAGE[Label of the field, human friendly]" mandatory="true" default="My Comments"/>
15-
<param name="meta_types" type="select" choices="string|CONF_MESSAGE[Short text],textarea|CONF_MESSAGE[Long text],creator|CONF_MESSAGE[Created by...],updater|CONF_MESSAGE[Last updated by...],stars_rate|CONF_MESSAGE[Stars Rating],css_label|CONF_MESSAGE[Color labels],choice|CONF_MESSAGE[Selection (set choices in Additional Info)]" replicationGroup="group1" label="CONF_MESSAGE[Field Type]" description="CONF_MESSAGE[Type of field]" mandatory="true" default="string"/>
15+
<param name="meta_types" type="select" choices="string|CONF_MESSAGE[Short text],textarea|CONF_MESSAGE[Long text],creator|CONF_MESSAGE[Created by...],updater|CONF_MESSAGE[Last updated by...],stars_rate|CONF_MESSAGE[Stars Rating],css_label|CONF_MESSAGE[Color labels],choice|CONF_MESSAGE[Selection (set choices in Additional Info)],tags|CONF_MESSAGE[Tags (extensible sets of values)]" replicationGroup="group1" label="CONF_MESSAGE[Field Type]" description="CONF_MESSAGE[Type of field]" mandatory="true" default="string"/>
1616
<param name="meta_visibility" type="select" replicationGroup="group1" label="CONF_MESSAGE[Column visibility]" description="CONF_MESSAGE[Set default visibility.]" mandatory="true" default="visible" choices="visible|CONF_MESSAGE[Visible],hidden|CONF_MESSAGE[Hidden]"/>
1717
<param name="meta_additional" type="string" replicationGroup="group1" label="CONF_MESSAGE[Additional info]" description="CONF_MESSAGE[Depending on the field type. Currently used for selection only]" mandatory="false"/>
1818
</server_settings>
@@ -24,7 +24,7 @@
2424
<client_configs>
2525
<template_part ajxpId="search_container" ajxpClass="SearchEngine" ajxpOptions="{}"/>
2626
<template_part ajxpId="search_container" ajxpClass="SearchEngine" ajxpOptions='{"toggleResultsVisibility":"search_results_cont", "fitMarginBottom":20}' theme="vision"/>
27-
<template_part ajxpId="search_container" ajxpClass="SearchEngine" ajxpOptions='{"toggleResultsVisibility":"search_results_cont", "searchChooserAsResultsHeader":true, "openSearchInput":"true", "toggleResultsFitTo":"cpane_tabs", "fitMarginBottom":0, "toggleResultsOffsetRight":0, "toggleResultsOffsetTop":0, "detailThumbSize":24}' theme="orbit"/>
27+
<template_part ajxpId="search_container" ajxpClass="SearchEngine" ajxpOptions='{"toggleResultsVisibility":"search_results_cont", "searchChooserAsResultsHeader":true, "openSearchInput":"true", "openSearchStickLeftTo":"topPane", "toggleResultsFitTo":"cpane_tabs", "fitMarginBottom":0, "toggleResultsOffsetRight":0, "toggleResultsOffsetTop":0, "detailThumbSize":24}' theme="orbit"/>
2828
<component_config className="FilesList">
2929
<columns><!-- Dynamically generated by the plugin --></columns>
3030
</component_config>
@@ -35,6 +35,11 @@
3535
</component_config>
3636
</client_configs>
3737
<actions>
38+
<action name="meta_user_list_tags">
39+
<processing>
40+
<serverCallback methodName="listTags"/>
41+
</processing>
42+
</action>
3843
<action name="edit_user_meta_mass">
3944
<gui text="meta.user.1" title="meta.user.1" src="meta_user/ICON_SIZE/tag.png" iconClass="icon-tags" hasAccessKey="false">
4045
<context selection="true" dir="" recycle="hidden"
@@ -85,6 +90,8 @@
8590
MetaCellRenderer.prototype.formTextarea(element, form);
8691
}else if(fieldType == 'choice'){
8792
MetaCellRenderer.prototype.formPanelSelectorFilter(element, form);
93+
}else if(fieldType == 'tags'){
94+
MetaCellRenderer.prototype.formPanelTags(element, form);
8895
}else if(fieldType == 'updater' || fieldType == 'creator'){
8996
element.disabled = true;
9097
}

0 commit comments

Comments
 (0)