diff options
author | Petr Vobornik <pvoborni@redhat.com> | 2014-05-16 17:54:11 +0200 |
---|---|---|
committer | Petr Vobornik <pvoborni@redhat.com> | 2014-06-11 14:36:00 +0200 |
commit | c8a2d28237cf6d1a386687c7e57c2b7e9b3f600a (patch) | |
tree | cf55cc3d82e6fdf781d44e3b4c310a290b609d03 | |
parent | cbf16ef15121212255b4683fdfc5715276728b76 (diff) | |
download | freeipa-plugin-apibrowser.tar.gz freeipa-plugin-apibrowser.tar.xz freeipa-plugin-apibrowser.zip |
API browser pluginplugin-apibrowser
This is a crude example of a plugin which:
- adds custom dropdown menu to utility area of navigation
- have it's own structure of hash part of URL - custom route+handler
- have a custom facet with custom widget
NOTE: this is ONLY an EXAMPLE. Never add plugins which should be part of
core server to this directory.
-rw-r--r-- | install/ui/src/plugins/apibrowser/apibrowser.js | 243 | ||||
-rw-r--r-- | install/ui/src/plugins/apibrowser/jsl.conf | 128 |
2 files changed, 371 insertions, 0 deletions
diff --git a/install/ui/src/plugins/apibrowser/apibrowser.js b/install/ui/src/plugins/apibrowser/apibrowser.js new file mode 100644 index 000000000..94e98a81e --- /dev/null +++ b/install/ui/src/plugins/apibrowser/apibrowser.js @@ -0,0 +1,243 @@ + +define([ + 'dojo/_base/lang', + 'dojo/_base/declare', + 'dojo/dom-construct', + 'dojo/on', + 'freeipa/jquery', + 'freeipa/json2', + 'freeipa/extend', + 'freeipa/navigation', + 'freeipa/phases', + 'freeipa/reg', + 'freeipa/facets/Facet', + 'freeipa/widgets/DropdownWidget' +],function(lang, declare, construct, on, $, JSON, extend, navigation, phases, reg, Facet, DropdownWidget) { + +/** + * Widget which display facet's public state. + * + * Public state usually corresponds to hash part of URL (facet doesn't care, + * it's handle by different subsystem. + * + * The simplest widget just has to implement `create` or `render` method and + * set couple properties (handled by mixing-in spec) + * + * @class + */ +var StateWidget = declare([], { + + init: function() { + // not really nice code. It should be injected into the widget. + var facet = this.facet || this.parent; + if (facet) { + on(facet, 'facet-state-change', lang.hitch(this, this.on_state_change)); + } + }, + + on_state_change: function(event) { + if (!this.dom_node) return; + this.render_hash(); + }, + + render: function() { + this.dom_node = construct.create('div', { + 'class': this['class'] + }); + + if (this.container_node) { + construct.place(this.dom_node, this.container_node); + } + this.render_hash(); + return this.dom_node; + }, + + render_hash: function() { + construct.empty(this.dom_node); + this.dom_node.innerHTML = JSON.stringify(this.parent.state.clone()); + }, + + constructor: function(spec) { + spec = spec || {}; + declare.safeMixin(this, spec); + } + +}); + +/** + * BrowserFacet + * + * We require custom facet because of non-standard URL hash part. + * + * @class + */ +var BrowserFacet = declare([Facet], { + + /** + * Custom serialization of facet state into URL hash. + * + * This method might be removed and moved to different component since + * it should not be Facet's responsibility. + * + * @return {string} hash + */ + create_hash: function(router) { + + var state = this.state.clone(); + var path = [router.route_prefix, 'api']; + if (state.uri) { + path.push(state.uri); + } + if (state.urlparam) { + path.push(state.urlparam); + } + + var hash = path.join('/'); + window.console.log(hash); + return hash; + } +}); + + + +/** + * API Browser plugin + * + * Browse API + * + * @class apibrowser + * @singleton + */ +var apibrowser = { + + menu_dropdown: null, + + facet_spec: { + name: 'apibrowser', + + // use: + // - `main` to show navigation on the top + // - `simple` to fill entire page + preferred_container: 'main', + + 'class': 'container-fluid', // for styling + widgets: [ + // some widgets + { + $type: 'html', + name: 'html', + html: '<h1>API Browser</h1>' + }, + { + $type: 'api_state', + name: 'state' + } + ] + }, + + /** + * Create and add dropdown menu to utility area of navigation + */ + create_menu_dropdown: function() { + + this.menu_dropdown = new DropdownWidget({ + el_type: 'li', + name: 'api-browser-menu', + right_aligned: true, + // can be uncommented if you don't want to implement `create_menu_toggle` + // toggle_text: 'API Browser ', + // toggle_class: '', + // toggle_icon: 'fa fa-angle-down', + items: [ + { + name: 'browser', + label: 'Browser', + icon: 'fa-user', + data: '/api/foo' + }, + { + 'class': 'divider' + }, + { + name: 'about', + label: 'Browser 2', + icon: 'fa-question', + data: '/api/foo/bar/abc=baz' + } + ] + }); + on(this.menu_dropdown, 'item-click', lang.hitch(this, this.on_dropdown_click)); + + this.menu_dropdown.set('toggle_content', this.create_menu_toggle()); + var el = this.menu_dropdown.render(); + + extend.add_menu_utility(el); + }, + + /** + * This is optional but it's a way to add icon before text + */ + create_menu_toggle: function() { + var nodes = []; + nodes.push(construct.create('span', { 'class': 'fa fa-star' })); + nodes.push(construct.create('span', { innerHTML: ' API browser' })); + nodes.push(construct.create('b', { 'class': 'caret' })); + return nodes; + }, + + on_dropdown_click: function (item) { + + // you can make decision on item properties + // + // by default just pass hash to router + + var facet = reg.facet.get('apibrowser'); + navigation.show_generic(item.data, facet); + // there is a bug that it doesn't collapse the menu on small screens + }, + + /** + * Handler of our custom route + */ + route_handler: function(event, router) { + if (router.check_clear_ignore()) return; + + // always get apibrowser facet + var facet = reg.facet.get('apibrowser'); + facet.reset_state(event.params); + router.show_facet(facet); + }, + + register: function () { + var fa = reg.facet; + var w = reg.widget; + + fa.register({ + type: 'apibrowser', + factory: BrowserFacet, + spec: this.facet_spec + }); + + w.register('api_state', StateWidget); + w.register_post_op('api_state', function(obj, spec, context) { + obj.init(); + return obj; + }); + }, + + initialize: function () { + this.create_menu_dropdown(); + var self = this; + + // add route to router + extend.add_route('/api/*urlparam', function(event) { + self.route_handler(event, this); + }); + } +}; + +phases.on('registration', lang.hitch(apibrowser, apibrowser.register)); +phases.on('init', lang.hitch(apibrowser, apibrowser.initialize), 20); + + return apibrowser; +});
\ No newline at end of file diff --git a/install/ui/src/plugins/apibrowser/jsl.conf b/install/ui/src/plugins/apibrowser/jsl.conf new file mode 100644 index 000000000..ef43a7cdb --- /dev/null +++ b/install/ui/src/plugins/apibrowser/jsl.conf @@ -0,0 +1,128 @@ +# +# Configuration File for JavaScript Lint 0.3.0 +# Developed by Matthias Miller (http://www.JavaScriptLint.com) +# +# This configuration file can be used to lint a collection of scripts, or to enable +# or disable warnings for scripts that are linted via the command line. +# + +### Warnings +# Enable or disable warnings based on requirements. +# Use "+WarningName" to display or "-WarningName" to suppress. +# ++no_return_value # function {0} does not always return a value ++duplicate_formal # duplicate formal argument {0} ++equal_as_assign # test for equality (==) mistyped as assignment (=)?{0} ++var_hides_arg # variable {0} hides argument ++redeclared_var # redeclaration of {0} {1} ++anon_no_return_value # anonymous function does not always return a value ++missing_semicolon # missing semicolon ++meaningless_block # meaningless block; curly braces have no impact ++comma_separated_stmts # multiple statements separated by commas (use semicolons?) ++unreachable_code # unreachable code ++missing_break # missing break statement ++missing_break_for_last_case # missing break statement for last case in switch ++comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) ++inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement ++useless_void # use of the void type may be unnecessary (void is always undefined) ++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs ++use_of_label # use of label +-block_without_braces # block statement without curly braces ++leading_decimal_point # leading decimal point may indicate a number or an object member ++trailing_decimal_point # trailing decimal point may indicate a number or an object member ++octal_number # leading zeros make an octal number ++nested_comment # nested comment ++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma ++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement ++empty_statement # empty statement or extra semicolon +-missing_option_explicit # the "option explicit" control comment is missing ++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag ++dup_option_explicit # duplicate "option explicit" control comment ++useless_assign # useless assignment ++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity ++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent) ++missing_default_case # missing default case in switch statement ++duplicate_case_in_switch # duplicate case in switch statements ++default_not_at_end # the default case is not at the end of the switch statement ++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax ++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax ++useless_comparison # useless comparison; comparing identical expressions ++with_statement # with statement hides undeclared variables; use temporary variable instead ++trailing_comma_in_array # extra comma is not recommended in array initializers ++assign_to_function_call # assignment to a function call ++parseint_missing_radix # parseInt missing radix parameter + + +### Output format +# Customize the format of the error message. +# __FILE__ indicates current file path +# __FILENAME__ indicates current file name +# __LINE__ indicates current line +# __ERROR__ indicates error message +# +# Visual Studio syntax (default): ++output-format __FILE__(__LINE__): __ERROR__ +# Alternative syntax: +#+output-format __FILE__:__LINE__: __ERROR__ + + +### Context +# Show the in-line position of the error. +# Use "+context" to display or "-context" to suppress. +# ++context + + +### Semicolons +# By default, assignments of an anonymous function to a variable or +# property (such as a function prototype) must be followed by a semicolon. +# ++lambda_assign_requires_semicolon + + +### Control Comments +# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for +# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is +# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason, +# although legacy control comments are enabled by default for backward compatibility. +# ++legacy_control_comments + + +### JScript Function Extensions +# JScript allows member functions to be defined like this: +# function MyObj() { /*constructor*/ } +# function MyObj.prototype.go() { /*member function*/ } +# +# It also allows events to be attached like this: +# function window::onload() { /*init page*/ } +# +# This is a Microsoft-only JavaScript extension. Enable this setting to allow them. +# +-jscript_function_extensions + + +### Defining identifiers +# By default, "option explicit" is enabled on a per-file basis. +# To enable this for all files, use "+always_use_option_explicit" +#-always_use_option_explicit ++always_use_option_explicit + +# Define certain identifiers of which the lint is not aware. +# (Use this in conjunction with the "undeclared identifier" warning.) +# +# Common uses for webpages might be: ++define window ++define document ++define alert ++define define ++define require + +### Files +# Specify which files to lint +# Use "+recurse" to enable recursion (disabled by default). +# To add a set of files, use "+process FileName", "+process Folder\Path\*.js", +# or "+process Folder\Path\*.htm". +# + ++process ./*.js
\ No newline at end of file |