mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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>
This commit is contained in:
committed by
Tomas Babej
parent
392809f984
commit
2a976334c2
@@ -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",
|
||||
|
||||
@@ -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; }
|
||||
@@ -24,6 +24,7 @@ define([
|
||||
'./plugins/sync_otp',
|
||||
'./plugins/login',
|
||||
'./plugins/login_process',
|
||||
'./plugins/api_browser',
|
||||
// entities
|
||||
'./aci',
|
||||
'./automember',
|
||||
|
||||
@@ -206,6 +206,12 @@ var nav = {};
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'apibrowser',
|
||||
label: 'API browser',
|
||||
facet: 'apibrowser',
|
||||
args: { 'type': 'command' }
|
||||
},
|
||||
{ entity: 'config' }
|
||||
]
|
||||
}
|
||||
|
||||
106
install/ui/src/freeipa/plugins/api_browser.js
Normal file
106
install/ui/src/freeipa/plugins/api_browser.js
Normal file
@@ -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;
|
||||
|
||||
});
|
||||
383
install/ui/src/freeipa/widgets/APIBrowserWidget.js
Normal file
383
install/ui/src/freeipa/widgets/APIBrowserWidget.js
Normal file
@@ -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;
|
||||
});
|
||||
503
install/ui/src/freeipa/widgets/browser_widgets.js
Normal file
503
install/ui/src/freeipa/widgets/browser_widgets.js
Normal file
@@ -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;
|
||||
});
|
||||
Reference in New Issue
Block a user