summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Vobornik <pvoborni@redhat.com>2015-06-05 19:03:46 +0200
committerTomas Babej <tbabej@redhat.com>2015-07-03 10:42:16 +0200
commit2a976334c2160c91a61fb0c477777e7adbbd3150 (patch)
treec72de1426f0eb19855c559a295ab30c13f125d76
parent392809f9847eee21c8022f53153463033cd53966 (diff)
downloadfreeipa-2a976334c2160c91a61fb0c477777e7adbbd3150.tar.gz
freeipa-2a976334c2160c91a61fb0c477777e7adbbd3150.tar.xz
freeipa-2a976334c2160c91a61fb0c477777e7adbbd3150.zip
webui: API browser
First part of API browser - displaying metadata in more consumable way. https://fedorahosted.org/freeipa/ticket/3129 Reviewed-By: Martin Kosek <mkosek@redhat.com> Reviewed-By: Tomas Babej <tbabej@redhat.com>
-rw-r--r--install/ui/doc/categories.json4
-rw-r--r--install/ui/less/widgets.less14
-rw-r--r--install/ui/src/freeipa/app.js1
-rw-r--r--install/ui/src/freeipa/navigation/menu_spec.js6
-rw-r--r--install/ui/src/freeipa/plugins/api_browser.js106
-rw-r--r--install/ui/src/freeipa/widgets/APIBrowserWidget.js383
-rw-r--r--install/ui/src/freeipa/widgets/browser_widgets.js503
7 files changed, 1016 insertions, 1 deletions
diff --git a/install/ui/doc/categories.json b/install/ui/doc/categories.json
index 83c24c5ef..3a7c2ebc2 100644
--- a/install/ui/doc/categories.json
+++ b/install/ui/doc/categories.json
@@ -39,7 +39,8 @@
"classes": [
"facet.facet",
"facets.Facet",
- "*_facet"
+ "*_facet",
+ "*Facet"
]
},
{
@@ -254,6 +255,7 @@
"stageuser",
"topology",
"user",
+ "plugins.api_browser",
"plugins.load",
"plugins.login",
"plugins.login_process",
diff --git a/install/ui/less/widgets.less b/install/ui/less/widgets.less
index 066e074a0..7778f6bf4 100644
--- a/install/ui/less/widgets.less
+++ b/install/ui/less/widgets.less
@@ -117,5 +117,19 @@
padding-left: 10px
}
+.apibrowser {
+ .item-select input[type=text] {
+ width: 100%;
+ padding-left: 5px;
+ }
+ .label {
+ margin-left: 5px; // spacing between param flags
+ }
+ .prop-label {
+ text-align: right;
+ font-weight: 300;
+ }
+}
+
// workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=409254
tbody:empty { display: none; } \ No newline at end of file
diff --git a/install/ui/src/freeipa/app.js b/install/ui/src/freeipa/app.js
index 9b290ab0e..f05e8213c 100644
--- a/install/ui/src/freeipa/app.js
+++ b/install/ui/src/freeipa/app.js
@@ -24,6 +24,7 @@ define([
'./plugins/sync_otp',
'./plugins/login',
'./plugins/login_process',
+ './plugins/api_browser',
// entities
'./aci',
'./automember',
diff --git a/install/ui/src/freeipa/navigation/menu_spec.js b/install/ui/src/freeipa/navigation/menu_spec.js
index c35445f12..120cba37d 100644
--- a/install/ui/src/freeipa/navigation/menu_spec.js
+++ b/install/ui/src/freeipa/navigation/menu_spec.js
@@ -206,6 +206,12 @@ var nav = {};
}
]
},
+ {
+ name: 'apibrowser',
+ label: 'API browser',
+ facet: 'apibrowser',
+ args: { 'type': 'command' }
+ },
{ entity: 'config' }
]
}
diff --git a/install/ui/src/freeipa/plugins/api_browser.js b/install/ui/src/freeipa/plugins/api_browser.js
new file mode 100644
index 000000000..88dbe59c7
--- /dev/null
+++ b/install/ui/src/freeipa/plugins/api_browser.js
@@ -0,0 +1,106 @@
+//
+// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+//
+
+define(['dojo/_base/declare',
+ 'dojo/_base/lang',
+ 'dojo/on',
+ '../facets/Facet',
+ '../phases',
+ '../reg',
+ '../widget',
+ '../widgets/APIBrowserWidget',
+ '../builder'
+ ],
+
+ function(declare, lang, on, Facet, phases, reg, widget,
+ APIBrowserWidget, builder) {
+
+
+var plugins = {}; // dummy namespace object
+
+/**
+ * API browser plugin
+ *
+ * @class
+ * @singleton
+ */
+plugins.api_browser = {};
+
+plugins.api_browser.facet_spec = {
+ name: 'apibrowser',
+ 'class': 'apibrowser container-fluid',
+ widgets: [
+ {
+ $type: 'activity',
+ name: 'activity',
+ text: 'Working',
+ visible: false
+ },
+ {
+ $type: 'apibrowser',
+ name: 'apibrowser'
+ }
+ ]
+};
+
+/**
+ * API browser facet
+ * @class
+ */
+plugins.api_browser.APIBrowserFacet = declare([Facet], {
+
+ init: function(spec) {
+ this.inherited(arguments);
+ var browser = this.get_widget('apibrowser');
+
+ on(this, 'show', lang.hitch(this, function(args) {
+
+ var state = this.get_state();
+ var t = state.type;
+ var n = state.name;
+
+ if (t && n) {
+ browser.show_item(t, n);
+ return;
+ } else if (t) {
+ if (t == 'command') {
+ browser.show_default_command();
+ return;
+ } else {
+ browser.show_default_object();
+ return;
+ }
+ }
+ browser.show_default();
+ return;
+ }));
+
+ // Reflect item change in facet state and therefore URL hash
+ browser.watch('current', lang.hitch(this, function(name, old, value) {
+ var state = {};
+ if (value.type && value.name) {
+ state = { type: value.type, name: value.name };
+ }
+ this.set_state(state);
+ }));
+ }
+});
+
+phases.on('registration', function() {
+
+ var fa = reg.facet;
+ var w = reg.widget;
+
+ w.register('apibrowser', APIBrowserWidget);
+
+ fa.register({
+ type: 'apibrowser',
+ factory: plugins.api_browser.APIBrowserFacet,
+ spec: plugins.api_browser.facet_spec
+ });
+});
+
+return plugins.api_browser;
+
+}); \ No newline at end of file
diff --git a/install/ui/src/freeipa/widgets/APIBrowserWidget.js b/install/ui/src/freeipa/widgets/APIBrowserWidget.js
new file mode 100644
index 000000000..149a22fff
--- /dev/null
+++ b/install/ui/src/freeipa/widgets/APIBrowserWidget.js
@@ -0,0 +1,383 @@
+//
+// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+//
+
+define([
+ 'dojo/_base/declare',
+ 'dojo/_base/lang',
+ 'dojo/on',
+ 'dojo/Evented',
+ 'dojo/Stateful',
+ '../jquery',
+ '../ipa',
+ '../metadata',
+ '../reg',
+ '../text',
+ '../util',
+ './ListViewWidget',
+ './browser_widgets'
+], function(declare, lang, on, Evented, Stateful, $, IPA, metadata, reg, text,
+ util, ListViewWidget, browser_widgets) {
+
+var widgets = {};
+
+/**
+ * API browser widget
+ *
+ * Consists of two parts: command browser and details.
+ *
+ * Command browser consist of:
+ * - filter
+ * - list view with commands
+ *
+ * Details could be:
+ * - command
+ * - object
+ * - param
+ *
+ * @class
+ */
+widgets.APIBrowserWidget = declare([Stateful, Evented], {
+
+ // widgets
+ filter_w: null,
+ list_w: null,
+ object_detail_w: null,
+ command_detail_w: null,
+ param_detail_w: null,
+ current_details_w: null, // Current details widget, one of the three above
+
+ // nodes
+ container_node: null,
+ el: null,
+ default_view_el: null,
+ details_view_el: null,
+ current_view: null, // either default_view_el or details_view_el
+ filter_el: null,
+ list_el: null,
+ sidebar_el: null,
+ details_el: null,
+
+ /**
+ * Currently displayed item or view
+ *
+ * Monitor this property to reflect the change of item
+ *
+ * @property {Object}
+ */
+ current: {},
+
+
+ metadata_map: {
+ 'object': '@mo:',
+ 'command': '@mc:',
+ 'param': '@mo-param:'
+ },
+
+ _to_list: function(objects) {
+ var names = [];
+ for (name in objects) {
+ if (objects.hasOwnProperty(name)) {
+ names.push(name);
+ }
+ }
+ names.sort();
+ var new_objects = [];
+ var o;
+ for (var i=0,l=names.length; i<l; i++) {
+ o = objects[names[i]];
+ if (!o.name) o.name = names[i];
+ if (o.only_webui) continue;
+ new_objects.push(o);
+ }
+ return new_objects;
+ },
+
+ _get_commands: function() {
+ var commands = metadata.get('@m:commands');
+ commands = this._to_list(commands);
+ return [{
+ name: "commands",
+ label: "Commands",
+ items: commands
+ }];
+ },
+
+ _get_objects: function() {
+ var objects = metadata.get('@m:objects');
+ objects = this._to_list(objects);
+ return [{
+ name: "commands",
+ label: "Objects",
+ items: objects
+ }];
+ },
+
+ _get_params: function(name) {
+ var object = metadata.get('@mo:'+name);
+ var params = object.takes_params;
+ return [{
+ name: object.name,
+ label:object.label_singular + ' params',
+ items: params
+ }];
+ },
+
+ _get_list: function(type, name, filter) {
+
+ var groups = null;
+ if (type === 'object') {
+ groups = this._get_objects();
+ } else if (type === 'command') {
+ groups = this._get_commands();
+ } else if (type === 'param') {
+ var parts = name.split(':');
+ groups = this._get_params(parts[0]);
+ }
+
+ if (filter) {
+ filter = filter.toLowerCase();
+ var new_groups = [];
+ for (var i=0,l=groups.length; i<l; i++) {
+ var filtered_list = [];
+ var items = groups[i].items;
+ for (var j=0,m=items.length; j<m; j++) {
+ var item = items[j];
+ if (item.name.match(filter) ||
+ (item.label && item.label.toLowerCase().match(filter))) {
+ filtered_list.push(item);
+ }
+ }
+ groups[i].items = filtered_list;
+ if (filtered_list.length > 0) {
+ new_groups.push(groups[i]);
+ }
+ }
+ return new_groups;
+ } else {
+ return groups;
+ }
+ },
+
+ /**
+ * Search metadata for object of given type and name. Display it if found.
+ * Display default view otherwise.
+ *
+ * Supported types and values:
+ * - 'object', value is object name, e.g., 'user'
+ * - 'command', value is command name, e.g., 'user_show'
+ * - 'param', value is tuple 'object_name:param_name', e.g., 'user:cn'
+ *
+ * @param {string} type Type of the object
+ * @param {string} name Object identifier
+ */
+ show_item: function (type, name) {
+ var item;
+ if (!this.metadata_map[type]) {
+ IPA.notify("Invalid object type requested: "+type, 'error');
+ this.show_default();
+ } else {
+ item = metadata.get(this.metadata_map[type] + name);
+ if (!item) {
+ IPA.notify("Requested "+ type +" does not exist: " + name, 'error');
+ this.show_default();
+ return;
+ }
+ }
+ this._set_item(type, item, name);
+ },
+
+ /**
+ * Show default view.
+ *
+ * For now a fallback if item is not found. Later could be extended to
+ * contain help info how to use the API.
+ */
+ show_default: function() {
+ // switch view
+ if (this.current_view !== this.default_view_el) {
+ this.el.empty();
+ this.el.append(this.default_view_el);
+ this.current_view = this.default_view_el;
+ }
+ this.set('current', {
+ view: 'default'
+ });
+ },
+
+ /**
+ * Shows default command
+ */
+ show_default_command: function() {
+ this.show_item('command', 'user_show'); // TODO: change
+ },
+
+ /**
+ * Shows default object
+ */
+ show_default_object: function() {
+ this.show_item('object', 'user'); // TODO: change
+ },
+
+ /**
+ * Show item
+ *
+ * @param {string} type Type of item
+ * @param {Object} item The item
+ * @param {string} name Name of the item
+ */
+ _set_item: function(type, item, name) {
+
+ // get widget
+ var widget = null;
+ if (type === 'object') {
+ widget = this.object_detail_w;
+ } else if (type === 'command') {
+ widget = this.command_detail_w;
+ } else if (type === 'param') {
+ widget = this.param_detail_w;
+ } else {
+ IPA.notify("Invalid type", 'error');
+ this.show_default();
+ }
+
+ // switch view
+ if (!this.details_view_el) {
+ this._render_details_view();
+ }
+ if (this.current_view !== this.details_view_el) {
+ this.el.empty();
+ this.el.append(this.details_view_el);
+ this.current_view = this.details_view_el;
+ }
+
+ // switch widget
+ if (!widget.el) widget.render();
+ if (this.current_details_w !== widget) {
+ this.details_el.empty();
+ this.details_el.append(widget.el);
+ }
+
+ // set list
+ var list = this._get_list(type, name, this.current.filter);
+ this.list_w.set('groups', list);
+ this.list_w.select(item);
+
+ // set item
+ widget.set('item', item);
+ this.set('current', {
+ item: item,
+ type: type,
+ name: name,
+ filter: this.current.filter,
+ view: 'details'
+ });
+
+ // update sidebar
+ $(window).trigger('resize');
+
+ $('html, body').animate({
+ scrollTop: 0
+ }, 500);
+ },
+
+ render: function() {
+ this.el = $('<div/>', { 'class': this.css_class });
+ this._render_default_view().appendTo(this.el);
+ if (this.container_node) {
+ this.el.appendTo(this.container_node);
+ }
+ return this.el;
+ },
+
+ _render_details_view: function() {
+ this.details_view_el = $('<div/>', { 'class': 'details-view' });
+ var row = $('<div/>', { 'class': 'row' });
+ this.sidebar_el = $('<div/>', { 'class': 'sidebar-pf sidebar-pf-left col-sm-4 col-md-3 col-sm-pull-8 col-md-pull-9' });
+ this.details_el = $('<div/>', { 'class': 'col-sm-8 col-md-9 col-sm-push-4 col-md-push-3' });
+ this.details_el.appendTo(row);
+ this.sidebar_el.appendTo(row);
+ row.appendTo(this.details_view_el);
+ this._render_select().appendTo(this.sidebar_el);
+ return this.details_view_el;
+ },
+
+ _render_select: function() {
+ var el = $('<div/>', { 'class': 'item-select' });
+
+ $('<div/>', { 'class': 'nav-category' }).
+ append($('<h2/>', {
+ 'class': 'item-select',
+ text: 'Browse'
+ })).
+ appendTo(el);
+
+ this.filter_el = this.filter_w.render();
+ this.list_el = this.list_w.render();
+ this.filter_el.appendTo(el);
+ this.list_el.appendTo(el);
+ return el;
+ },
+
+ _render_default_view: function() {
+ this.default_view_el = $('<div/>', { 'class': 'default-view' });
+ $('<h1/>', { text: "API Browser" }).appendTo(this.default_view_el);
+ var commands = $('<div/>').appendTo(this.default_view_el);
+ $('<p/>').append($('<a/>', {
+ href: "#/p/apibrowser/type=command",
+ text: "Browse Commands"
+ })).appendTo(commands);
+ var objects = $('<div/>').appendTo(this.default_view_el);
+ $('<p/>').append($('<a/>', {
+ href: "#/p/apibrowser/type=object",
+ text: "Browse Objects"
+ })).appendTo(commands);
+ return this.default_view_el;
+ },
+
+ _apply_filter: function(filter) {
+ var current = this.current;
+ current.filter = filter;
+ var list = this._get_list(current.type, current.name, current.filter);
+ this.list_w.set('groups', list);
+ this.list_w.select(current.item);
+ // reset min height so that PatternFly can set proper min height
+ this.sidebar_el.css({'min-height': 0});
+ this.details_el.css({'min-height': 0});
+ $(window).trigger('resize');
+ },
+
+ _item_selected: function(item) {
+ var t = this.current.type;
+ var n = item.name;
+ if (t == 'param') {
+ var obj = this.current.name.split(':')[0];
+ n = [obj, n].join(':');
+ }
+ this.show_item(t, n);
+ },
+
+ _init_widgets: function() {
+ this.filter_w = new browser_widgets.FilterWidget();
+ this.filter_w.watch('filter', lang.hitch(this, function(name, old, value) {
+ this._apply_filter(value);
+ }));
+
+ this.list_w = new ListViewWidget();
+ this.object_detail_w = new browser_widgets.ObjectDetailWidget();
+ this.command_detail_w = new browser_widgets.CommandDetailWidget();
+ this.param_detail_w = new browser_widgets.ParamDetailWidget();
+
+ on(this.list_w, 'item-click', lang.hitch(this, function(args) {
+ this._item_selected(args.context);
+ }));
+ },
+
+ constructor: function(spec) {
+ lang.mixin(this, spec);
+ this._init_widgets();
+ }
+});
+
+ return widgets.APIBrowserWidget;
+}); \ No newline at end of file
diff --git a/install/ui/src/freeipa/widgets/browser_widgets.js b/install/ui/src/freeipa/widgets/browser_widgets.js
new file mode 100644
index 000000000..b40a183a3
--- /dev/null
+++ b/install/ui/src/freeipa/widgets/browser_widgets.js
@@ -0,0 +1,503 @@
+//
+// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+//
+
+//
+// Contains API browser widgets
+//
+
+define([
+ 'dojo/_base/declare',
+ 'dojo/_base/lang',
+ 'dojo/on',
+ 'dojo/Evented',
+ 'dojo/Stateful',
+ '../jquery',
+ '../ipa',
+ '../metadata',
+ '../navigation',
+ '../reg',
+ '../text',
+ '../util'
+], function(declare, lang, on, Evented, Stateful, $, IPA, metadata, navigation,
+ reg, text, util) {
+
+var widgets = { browser_widgets: {} }; //namespace
+
+var apibrowser_facet = 'apibrowser';
+
+/**
+ * Browser Widget Base
+ *
+ * Candidate for a base class for all widgets
+ *
+ * @class
+ */
+widgets.browser_widgets.Base = declare([Stateful, Evented], {
+
+ // nodes
+ el: null,
+
+ /**
+ * Render widget's HTML
+ * @return {jQuery} base node
+ */
+ render: function() {
+ this.el = $('<div/>', { 'class': this.css_class });
+ this.render_content();
+ return this.el;
+ },
+
+ /**
+ * Should be overridden
+ */
+ render_content: function() {
+ },
+
+ constructor: function(spec) {
+ lang.mixin(this, spec);
+ }
+});
+
+/**
+ * Detail Base
+ *
+ * A base class for showing details of various API objects
+ *
+ * @class
+ * @extends {widgets.browser_widgets.Base}
+ */
+widgets.browser_widgets.DetailBase = declare([widgets.browser_widgets.Base], {
+
+ /**
+ * Item to be displayed
+ * @property {Object}
+ */
+ item: null,
+
+ common_options: [
+ 'all', 'rights', 'raw', 'version', 'addattr', 'setattr', 'delattr',
+ 'getattr', 'timelimit', 'sizelimit', 'pkey_only'
+ ],
+
+ _itemSetter: function(value) {
+ this.item = value;
+ if (this.el) {
+ this.render_content();
+ }
+ },
+
+ _get_object: function(obj_name) {
+ var obj = metadata.get('@mo:' + obj_name);
+ if (!obj || obj.only_webui) return null;
+ return obj;
+ },
+
+ _get_command_object: function(command_name) {
+ var obj_name = command_name.split('_')[0];
+ var obj = this._get_object(obj_name);
+ return obj;
+ },
+
+ _get_objectparam: function(command_name, param_name) {
+ var obj = this._get_command_object(command_name);
+ if (!obj) return null;
+ var param = metadata.get('@mo-param:' + obj.name + ':' + param_name);
+ return param;
+ },
+
+ _get_cli_option: function(name) {
+ if (!name) return name;
+ return '--' + name.replace('_', '-');
+ },
+
+ render_object_link: function(obj_name, text) {
+ var facet = reg.facet.get(apibrowser_facet);
+ var link = $('<a/>', {
+ href: "#" + navigation.create_hash(facet, {
+ type: 'object',
+ name: obj_name
+ }),
+ text: text || obj_name
+ });
+ return link;
+ },
+
+ render_command_link: function(command_name, text) {
+ var facet = reg.facet.get(apibrowser_facet);
+ var link = $('<a/>', {
+ href: "#" + navigation.create_hash(facet, {
+ type: 'command',
+ name: command_name
+ }),
+ text: text || command_name
+ });
+ return link;
+ },
+
+ render_param_link: function(obj_name, param_name, text) {
+ var name = obj_name + ':' + param_name;
+ var facet = reg.facet.get(apibrowser_facet);
+ var link = $('<a/>', {
+ href: "#" + navigation.create_hash(facet, {
+ type: 'param',
+ name: name
+ }),
+ text: text || param_name
+ });
+ return link;
+ },
+
+
+ render_title: function(type, text) {
+ var title = $('<h1/>', { 'class': 'api-title' });
+ $('<span/>', {
+ 'class': 'api-title-type',
+ text: type
+ }).appendTo(title);
+ $('<span/>', {
+ 'class': 'api-title-text',
+ text: text
+ }).appendTo(title);
+ return title;
+ },
+
+ render_doc: function(text) {
+ return $('<p/>', { text: text });
+ },
+
+ render_section_header: function(text, link) {
+ return $('<h2/>', {
+ text: text,
+ id: link
+ });
+ },
+
+ render_value_container: function() {
+ return $('<div/>', {
+ 'class': 'properties'
+ });
+ },
+
+ render_value: function(label, value_node, container) {
+ if (!text) return $('');
+
+ var row = $('<div/>', {
+ 'class': 'row'
+ });
+ $('<div/>', {
+ 'class': 'col-sm-4 prop-label',
+ text: label
+ }).appendTo(row);
+ $('<div/>', {
+ 'class': 'col-sm-8 prop-value'
+ }).append(value_node).appendTo(row);
+
+ if (container) {
+ container.append(row);
+ }
+ return row;
+ },
+
+ render_text_all: function(label, text, container) {
+ if (text === null || text === undefined) return $('');
+ var node = document.createTextNode(text);
+ return this.render_value(label, node, container);
+ },
+
+ render_text: function(label, text, container) {
+ if (!text) return $('');
+ var node = document.createTextNode(text);
+ return this.render_value(label, node, container);
+ },
+
+ render_array: function(label, value, container) {
+ if (!value || value.length === 0) return $('');
+ var text = value.join(', ');
+ return this.render_text(label, text, container);
+ },
+
+ render_object: function(label, obj, container) {
+ if (obj === undefined || obj === null) return $('');
+ var text = JSON.stringify(obj);
+ return this.render_text(label, text, container);
+ },
+
+ render_command_object_link: function(label, command_name, container) {
+ var obj = this._get_command_object(command_name);
+ if (!obj) return $('');
+ var link = this.render_object_link(obj.name, obj.label_singular);
+ return this.render_value(label, link, container);
+ },
+
+
+ render_flags: function(flags, cnt) {
+ if (!flags) return null;
+ if (!cnt) cnt = $('<div/>');
+ for (var i=0,l=flags.length; i<l; i++) {
+ $('<span/>', {
+ 'class': 'label label-default',
+ text: flags[i]
+ }).appendTo(cnt);
+ }
+ return cnt;
+ },
+
+ render_param: function(param, is_arg, container) {
+ var prop_cnt = this.render_value_container();
+ var header = $('<h3/>', {
+ text: param.name
+ });
+ header.appendTo(prop_cnt);
+ this.render_param_properties(param, is_arg, prop_cnt, header);
+ if (container) {
+ container.append(prop_cnt);
+ }
+ return prop_cnt;
+ },
+
+ render_param_properties: function(param, is_arg, container, flags_container) {
+
+ var flags = [];
+ if (param.required) flags.push('required');
+ if (param.multivalue) flags.push('multivalued');
+ //if (param.primary_key) flags.push('primary key');
+
+ this.render_doc(param.doc).appendTo(container);
+ this.render_flags(flags, flags_container);
+ if (param.label && param.label[0] !== '<') {
+ this.render_text("label", param.label, container);
+ }
+ this.render_text("type", param.type, container);
+ this.render_text_all("default value", param['default'], container);
+ this.render_array("default value created from", param['default_from'], container);
+ if (param.values) {
+ this.render_array("possible values", param.values, container);
+ }
+
+ // Str values
+ this.render_text("minimum length", param.minlength, container);
+ this.render_text("maximum length", param.maxlength, container);
+ this.render_text("pattern", param.pattern, container);
+
+ // Int, Decimal
+ this.render_text("minimum value", param.minvalue, container);
+ this.render_text("maximum value", param.maxvalue, container);
+ this.render_text("precision", param.precision, container);
+
+ // CLI
+ if (!is_arg) {
+ this.render_text("CLI option name", this._get_cli_option(param.cli_name), container);
+ }
+
+ this.render_text("option_group", param.option_group, container);
+ }
+});
+
+var base = widgets.browser_widgets.DetailBase;
+
+/**
+ * Object detail
+ * @class
+ * @extends {widgets.browser_widgets.DetailBase
+ */
+widgets.browser_widgets.ObjectDetailWidget = declare([base], {
+
+ render_content: function() {
+ var link, obj;
+ this.el.empty();
+ if (!this.item) {
+ this.el.append('No object selected');
+ return;
+ }
+ var item = this.item;
+ this.render_title('Object: ', item.name).appendTo(this.el);
+ if (item.doc) this.render_doc(item.doc).appendTo(this.el);
+ if (item.parent_object) {
+ obj = this._get_object(item.parent_object);
+ if (obj) {
+ link = this.render_object_link(item.parent_object, obj.label_singular);
+ this.render_value('parent_object', link, this.el);
+ }
+ }
+ //this.render_text("parent_object", item.parent_object, this.el);
+ this.render_text("label", item.label, this.el);
+ this.render_text("label_singular", item.label_singular, this.el);
+ this.render_text("container_dn", item.container_dn, this.el);
+ this.render_text("object_class", item.object_class, this.el);
+ this.render_text("object_class_config", item.object_class_config, this.el);
+ this.render_text("object_name", item.object_name, this.el);
+ this.render_text("object_name_plural", item.object_name_plural, this.el);
+ this.render_text("uuid_attribute", item.uuid_attribute, this.el);
+ this.render_text("rdn_attribute", item.rdn_attribute, this.el);
+ this.render_text("bindable", item.bindable, this.el);
+ this.render_array("aciattrs", item.aciattrs, this.el);
+ this.render_text("can_have_permissions", item.can_have_permissions, this.el);
+ this.render_array("default_attributes", item.default_attributes, this.el);
+ this.render_array("hidden_attributes", item.hidden_attributes, this.el);
+ this.render_object("attribute_members", item.attribute_members, this.el);
+ this.render_object("relationships", item.relationships, this.el);
+
+ if (item.methods) {
+ this.render_section_header('Methods').appendTo(this.el);
+ var cnt = $('<div/>');
+ for (i=0, l=item.methods.length; i<l; i++) {
+ var method_name = item.methods[i];
+ if (i>0) {
+ cnt.append(', ');
+ }
+ var command_name = item.name + '_' + method_name;
+ link = this.render_command_link(command_name, method_name);
+ cnt.append(link);
+ }
+ this.render_value('', cnt, this.el);
+ }
+
+ if (item.takes_params) {
+ this.render_section_header('Params').appendTo(this.el);
+ for (var i=0,l=item.takes_params.length; i<l; i++) {
+ var opt = item.takes_params[i];
+ this.render_param(opt, true).appendTo(this.el);
+ }
+ }
+ }
+});
+
+/**
+ * Command Detail
+ * @class
+ * @extends {widgets.browser_widgets.DetailBase
+ */
+widgets.browser_widgets.CommandDetailWidget = declare([base], {
+
+ render_content: function() {
+ var i = 0, l = 0;
+ this.el.empty();
+ if (!this.item) {
+ this.el.append('No command selected');
+ return;
+ }
+ var item = this.item;
+ var obj = this._get_command_object(item.name);
+ this.render_title('Command: ', item.name).appendTo(this.el);
+ if (item.doc) this.render_doc(item.doc).appendTo(this.el);
+ this.render_command_object_link('object', item.name, this.el);
+ if (item.takes_args && item.takes_args.length > 0) {
+ this.render_section_header('Arguments').appendTo(this.el);
+ for (i=0, l=item.takes_args.length; i<l; i++) {
+ var arg = item.takes_args[i];
+ this.render_param(arg, true).appendTo(this.el);
+ }
+ }
+ if (item.takes_options && item.takes_options.length > 0) {
+ var options = [];
+ var common_options = [];
+
+ for (i=0, l=item.takes_options.length; i<l; i++) {
+ var opt = item.takes_options[i];
+ if (opt.include && opt.include.indexOf('server') === -1) continue;
+ if (opt.exclude && opt.exclude.indexOf('server') > -1) continue;
+ if (this.common_options.indexOf(opt.name) > -1) {
+ common_options.push(opt);
+ } else {
+ options.push(opt);
+ }
+ }
+
+ if (options.length) {
+ this.render_section_header('Options').appendTo(this.el);
+ }
+ for (i=0, l=options.length; i<l; i++) {
+ this.render_param(options[i], false).appendTo(this.el);
+ }
+
+ if (common_options.length) {
+ this.render_section_header('Common Options').appendTo(this.el);
+ }
+ for (i=0, l=common_options.length; i<l; i++) {
+ this.render_param(common_options[i], false).appendTo(this.el);
+ }
+ }
+ if (item.output_params && item.output_params.length > 0) {
+ this.render_section_header('Output Params').appendTo(this.el);
+ var out_params_cnt = $('<div/>');
+ for (i=0, l=item.output_params.length; i<l; i++) {
+ var param_name = item.output_params[i];
+ var param = this._get_objectparam(item.name, param_name);
+ if (i>0) {
+ out_params_cnt.append(', ');
+ }
+ if (!param) {
+ out_params_cnt.append(param_name);
+ } else {
+ var link = this.render_param_link(obj.name, param_name);
+ out_params_cnt.append(link);
+ }
+ }
+ out_params_cnt.appendTo(this.el);
+ }
+ }
+});
+
+/**
+ * Param Detail
+ * @class
+ * @extends {widgets.browser_widgets.DetailBase
+ */
+widgets.browser_widgets.ParamDetailWidget = declare([base], {
+
+ render_content: function() {
+ this.el.empty();
+ if (!this.item) {
+ this.el.append('No param selected');
+ return;
+ }
+ var item = this.item;
+ this.render_title('Param: ', item.name).appendTo(this.el);
+ var flags = $('<div/>').appendTo(this.el);
+ this.render_param_properties(item, this.el, flags);
+ }
+});
+
+/**
+ * Filter input
+ *
+ * @class
+ * @extends {widgets.browser_widgets.DetailBase
+ */
+widgets.browser_widgets.FilterWidget = declare([widgets.browser_widgets.Base], {
+
+ /**
+ * Filter text
+ * @property {String}
+ */
+ filter: '',
+
+ _filter_el: null,
+
+ _filterSetter: function(value) {
+ this.filter = value;
+ if (this.el) {
+ this._filter_el.val(value);
+ }
+ },
+
+ render_content: function() {
+ this.el.empty();
+ this._filter_el = $('<input/>', {
+ type: 'text',
+ name: 'filter',
+ placeholder: 'type to filter...',
+ title: 'accepts case insensitive regular expression'
+ });
+ this._filter_el.bind('input', lang.hitch(this, function() {
+ var filter = this._filter_el.val();
+ this.set('filter', filter);
+ }));
+ this._filter_el.appendTo(this.el);
+ }
+});
+
+
+ return widgets.browser_widgets;
+}); \ No newline at end of file