mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Handle standard menu items defined by Nodes in the browser.
The File menu now includes a "Create" submenu, and Delete/Rename options. Nodes can offer Delete/Rename functionality, and the options on the menu are automatically enabled/disabled based on the selected node. Each node can also offer Create functionality, and specify a list of node types (including itself) from which the option should be made available. The menu is dynamically generated based on the selected node. The Context menu on the treeview works in a similar way, except that nodes can offer any context menu items (we don't allow this on the top menu, as that should stay consistent to avoid user confusion).
This commit is contained in:
parent
af7dcd49b4
commit
751f8383fa
@ -146,6 +146,16 @@ The hook points currently defined for nodes are:
|
||||
|
||||
def get_context_menu_items():
|
||||
"""Return a (set) of dicts of content menu items with name, label, priority and JS"""
|
||||
|
||||
def get_create_menu_items():
|
||||
"""Return a (set) of dicts of create menu items, with a Javascript array of
|
||||
object types on which the option should appear, name, label. priority and
|
||||
the function name (no parens) to call on click."""
|
||||
|
||||
def get_standard_menu_items():
|
||||
"""Return a (set) of dicts of standard menu items (drop/rename), with
|
||||
object type, action, priority and the function name (no parens) to call
|
||||
on click."""
|
||||
|
||||
def get_script_snippets():
|
||||
"""Return the script snippets needed to handle treeview node operations."""
|
||||
|
@ -10,6 +10,7 @@
|
||||
"""Browser integration functions for the About module."""
|
||||
|
||||
from flask import render_template, url_for
|
||||
from flask.ext.babel import gettext
|
||||
|
||||
import config
|
||||
|
||||
@ -17,7 +18,7 @@ def get_help_menu_items():
|
||||
"""Return a (set) of dicts of help menu items, with name, priority, URL,
|
||||
target and onclick code."""
|
||||
return [{'name': 'mnu_about',
|
||||
'label': 'About %s' % (config.APP_NAME),
|
||||
'label': gettext('About %(appname)s', appname=config.APP_NAME),
|
||||
'priority': 999,
|
||||
'url': "#",
|
||||
'onclick': "about_show()"}]
|
||||
|
@ -35,20 +35,28 @@ def get_nodes():
|
||||
return value
|
||||
|
||||
|
||||
def get_file_menu_items():
|
||||
"""Return a (set) of dicts of file menu items, with name, priority, URL,
|
||||
target and onclick code."""
|
||||
def get_standard_menu_items():
|
||||
"""Return a (set) of dicts of standard menu items (create/drop/rename), with
|
||||
object type, action and the function name (no parens) to call on click."""
|
||||
return [
|
||||
{'name': 'mnu_add_server_group', 'label': gettext('Add a server group...'), 'priority': 10, 'url': '#', 'onclick': 'add_server_group()'},
|
||||
{'name': 'mnu_delete_server_group', 'label': gettext('Delete server group'), 'priority': 20, 'url': '#', 'onclick': 'delete_server_group()'},
|
||||
{'name': 'mnu_rename_server_group', 'label': gettext('Rename server group...'), 'priority': 30, 'url': '#', 'onclick': 'rename_server_group()'}
|
||||
{'type': 'server-group', 'action': 'drop', 'priority': 10, 'function': 'drop_server_group'},
|
||||
{'type': 'server-group', 'action': 'rename', 'priority': 20, 'function': 'rename_server_group'}
|
||||
]
|
||||
|
||||
|
||||
def get_create_menu_items():
|
||||
"""Return a (set) of dicts of create menu items, with a Javascript array of
|
||||
object types on which the option should appear, name, label and the function
|
||||
name (no parens) to call on click."""
|
||||
return [
|
||||
{'type': "['server-group']", 'name': 'create_server_group', 'label': gettext('Server Group...'), 'priority': 10, 'function': 'create_server_group'}
|
||||
]
|
||||
|
||||
|
||||
def get_context_menu_items():
|
||||
"""Return a (set) of dicts of content menu items with name, node type, label, priority and JS"""
|
||||
return [
|
||||
{'name': 'delete_server_group', 'type': NODE_TYPE, 'label': gettext('Delete server group'), 'priority': 10, 'onclick': 'delete_server_group(item);'},
|
||||
{'name': 'delete_server_group', 'type': NODE_TYPE, 'label': gettext('Delete server group'), 'priority': 10, 'onclick': 'drop_server_group(item);'},
|
||||
{'name': 'rename_server_group', 'type': NODE_TYPE, 'label': gettext('Rename server group...'), 'priority': 20, 'onclick': 'rename_server_group(item);'}
|
||||
]
|
||||
|
||||
|
@ -28,20 +28,28 @@ def get_nodes(server_group):
|
||||
return value
|
||||
|
||||
|
||||
def get_file_menu_items():
|
||||
"""Return a (set) of dicts of file menu items, with name, priority, URL,
|
||||
target and onclick code."""
|
||||
def get_standard_menu_items():
|
||||
"""Return a (set) of dicts of standard menu items (create/drop/rename), with
|
||||
object type, action, priority and the function to call on click."""
|
||||
return [
|
||||
{'name': 'mnu_add_server', 'label': gettext('Add a server...'), 'priority': 50, 'url': '#', 'onclick': 'add_server()'},
|
||||
{'name': 'mnu_delete_server', 'label': gettext('Delete server'), 'priority': 60, 'url': '#', 'onclick': 'delete_server()'},
|
||||
{'name': 'mnu_rename_server', 'label': gettext('Rename server...'), 'priority': 70, 'url': '#', 'onclick': 'rename_server()'}
|
||||
{'type': 'server', 'action': 'drop', 'priority': 50, 'function': 'drop_server'},
|
||||
{'type': 'server', 'action': 'rename', 'priority': 60, 'function': 'rename_server'}
|
||||
]
|
||||
|
||||
|
||||
def get_create_menu_items():
|
||||
"""Return a (set) of dicts of create menu items, with a Javascript array of
|
||||
object types on which the option should appear, name, label, priority and
|
||||
the function name (no parens) to call on click."""
|
||||
return [
|
||||
{'type': "['server-group', 'server']", 'name': 'create_server', 'label': gettext('Server...'), 'priority': 50, 'function': 'create_server'}
|
||||
]
|
||||
|
||||
|
||||
def get_context_menu_items():
|
||||
"""Return a (set) of dicts of content menu items with name, node type, label, priority and JS"""
|
||||
return [
|
||||
{'name': 'delete_server', 'type': NODE_TYPE, 'label': gettext('Delete server'), 'priority': 50, 'onclick': 'delete_server(item);'},
|
||||
{'name': 'delete_server', 'type': NODE_TYPE, 'label': gettext('Delete server'), 'priority': 50, 'onclick': 'drop_server(item);'},
|
||||
{'name': 'rename_server', 'type': NODE_TYPE, 'label': gettext('Rename server...'), 'priority': 60, 'onclick': 'rename_server(item);'}
|
||||
]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Add a server
|
||||
function add_server() {
|
||||
function create_server() {
|
||||
var alert = alertify.prompt(
|
||||
'{{ _('Add a server') }}',
|
||||
'{{ _('Create a server') }}',
|
||||
'{{ _('Enter a name for the new server') }}',
|
||||
'',
|
||||
function(evt, value) {
|
||||
@ -32,12 +32,12 @@ function add_server() {
|
||||
}
|
||||
|
||||
// Delete a server
|
||||
function delete_server(item) {
|
||||
function drop_server(item) {
|
||||
alertify.confirm(
|
||||
'{{ _('Delete server?') }}',
|
||||
'{{ _('Are you sure you wish to delete the server "{0}"?') }}'.replace('{0}', tree.getLabel(item)),
|
||||
'{{ _('Drop server?') }}',
|
||||
'{{ _('Are you sure you wish to drop the server "{0}"?') }}'.replace('{0}', tree.getLabel(item)),
|
||||
function() {
|
||||
var id = tree.getId(item)
|
||||
var id = tree.getId(item).split('/').pop()
|
||||
$.post("{{ url_for('NODE-server.delete') }}", { id: id })
|
||||
.done(function(data) {
|
||||
if (data.success == 0) {
|
||||
@ -66,7 +66,7 @@ function rename_server(item) {
|
||||
'{{ _('Enter a new name for the server') }}',
|
||||
tree.getLabel(item),
|
||||
function(evt, value) {
|
||||
var id = tree.getId(item)
|
||||
var id = tree.getId(item).split('/').pop()
|
||||
$.post("{{ url_for('NODE-server.rename') }}", { id: id, name: value })
|
||||
.done(function(data) {
|
||||
if (data.success == 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Add a server group
|
||||
function add_server_group() {
|
||||
function create_server_group() {
|
||||
var alert = alertify.prompt(
|
||||
'{{ _('Add a server group') }}',
|
||||
'{{ _('Enter a name for the new server group') }}',
|
||||
@ -32,12 +32,12 @@ function add_server_group() {
|
||||
}
|
||||
|
||||
// Delete a server group
|
||||
function delete_server_group(item) {
|
||||
function drop_server_group(item) {
|
||||
alertify.confirm(
|
||||
'{{ _('Delete server group?') }}',
|
||||
'{{ _('Are you sure you wish to delete the server group "{0}"?') }}'.replace('{0}', tree.getLabel(item)),
|
||||
function() {
|
||||
var id = tree.getId(item)
|
||||
var id = tree.getId(item).split('/').pop()
|
||||
$.post("{{ url_for('NODE-server-group.delete') }}", { id: id })
|
||||
.done(function(data) {
|
||||
if (data.success == 0) {
|
||||
@ -66,7 +66,7 @@ function rename_server_group(item) {
|
||||
'{{ _('Enter a new name for the server group') }}',
|
||||
tree.getLabel(item),
|
||||
function(evt, value) {
|
||||
var id = tree.getId(item)
|
||||
var id = tree.getId(item).split('/').pop()
|
||||
$.post("{{ url_for('NODE-server-group.rename') }}", { id: id, name: value })
|
||||
.done(function(data) {
|
||||
if (data.success == 0) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
"""Defines views for management of server groups"""
|
||||
|
||||
import traceback
|
||||
from flask import Blueprint, Response, current_app, request
|
||||
from flask.ext.babel import gettext
|
||||
from flask.ext.security import current_user, login_required
|
||||
|
@ -17,38 +17,50 @@
|
||||
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
{% if file_items is defined and file_items|count > 0 %}<li class="dropdown">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ _('File') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">{% for file_item in file_items %}
|
||||
<li><a id="{{ file_item.name }}" href="{{ file_item.url }}" target="{{ file_item.target }}" onclick="{{ file_item.onclick|safe }}">{{ file_item.label }}</a></li>{% endfor %}
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li id="mnu_create_dropdown" class="menu-item dropdown dropdown-submenu">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Create</a>
|
||||
<ul id="mnu_create" class="dropdown-menu">
|
||||
<li class="menu-item">
|
||||
<a href="#">Link 1</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a id="mnu_drop_object" href="#" onclick="drop_object()">{{ _('Drop object') }}</a></li>
|
||||
<li><a id="mnu_rename_object" href="#" onclick="rename_object()">{{ _('Rename object') }}</a></li>
|
||||
<li class="divider"></li>
|
||||
{% if file_items is defined and file_items|count > 0 %}{% for file_item in file_items %}
|
||||
<li><a id="{{ file_item.name }}" href="{{ file_item.url }}"{% if file_item.target %} target="{{ file_item.target }}"{% endif %}{% if file_item.onclick %} onclick="{{ file_item.onclick|safe }}"{% endif %}>{{ file_item.label }}</a></li>{% endfor %}{% endif %}
|
||||
</ul>
|
||||
</li>{% endif %}
|
||||
</li>
|
||||
|
||||
{% if edit_items is defined and edit_items|count > 0 %}<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ _('Edit') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">{% for edit_item in edit_items %}
|
||||
<li><a id="{{ edit_item.name }}" href="{{ edit_item.url }}" target="{{ edit_item.target }}" onclick="{{ edit_item.onclick|safe }}">{{ edit_item.label }}</a></li>{% endfor %}
|
||||
<li><a id="{{ edit_item.name }}" href="{{ edit_item.url }}"{% if edit_item.target %} target="{{ edit_item.target }}"{% endif %}{% if edit_item.onclick %} onclick="{{ edit_item.onclick|safe }}"{% endif %}>{{ edit_item.label }}</a></li>{% endfor %}
|
||||
</ul>
|
||||
</li>{% endif %}
|
||||
|
||||
{% if tools_items is defined and tools_items|count > 0 %}<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ _('Tools') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">{% for tools_item in tools_items %}
|
||||
<li><a id="{{ tools_item.name }}" href="{{ tools_item.url }}" target="{{ tools_item.target }}" onclick="{{ tools_item.onclick|safe }}">{{ tools_item.label }}</a></li>{% endfor %}
|
||||
<li><a id="{{ tools_item.name }}" href="{{ tools_item.url }}"{% if tools_item.target %} target="{{ tools_item.target }}"{% endif %}{% if tools_item.onclick %} onclick="{{ tools_item.onclick|safe }}"{% endif %}>{{ tools_item.label }}</a></li>{% endfor %}
|
||||
</ul>
|
||||
</li>{% endif %}
|
||||
|
||||
{% if management_items is defined and management_items|count > 0 %}<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ _('Management') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">{% for management_item in management_items %}
|
||||
<li><a id="{{ management_item.name }}" href="{{ management_item.url }}" target="{{ management_item.target }}" onclick="{{ management_item.onclick|safe }}">{{ management_item.label }}</a></li>{% endfor %}
|
||||
<li><a id="{{ management_item.name }}" href="{{ management_item.url }}"{% if management_item.target %} target="{{ management_item.target }}"{% endif %}{% if management_item.onclick %} onclick="{{ management_item.onclick|safe }}"{% endif %}>{{ management_item.label }}</a></li>{% endfor %}
|
||||
</ul>
|
||||
</li>{% endif %}
|
||||
|
||||
{% if help_items is defined and help_items|count > 0 %}<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ _('Help') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">{% for help_item in help_items %}
|
||||
<li><a id="{{ help_item.name }}" href="{{ help_item.url }}" target="{{ help_item.target }}" onclick="{{ help_item.onclick|safe }}">{{ help_item.label }}</a></li>{% endfor %}
|
||||
<li><a id="{{ help_item.name }}" href="{{ help_item.url }}"{% if help_item.target %} target="{{ help_item.target }}"{% endif %}{% if help_item.onclick %} onclick="{{ help_item.onclick|safe }}"{% endif %}>{{ help_item.label }}</a></li>{% endfor %}
|
||||
</ul>
|
||||
</li>{% endif %}
|
||||
|
||||
|
@ -72,6 +72,142 @@ function buildDefaultLayout() {
|
||||
browserPanel = docker.addPanel('pnl_browser', wcDocker.DOCK_LEFT, browserPanel);
|
||||
}
|
||||
|
||||
function report_error(message, info) {
|
||||
|
||||
text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
|
||||
<div class="panel panel-default">\
|
||||
<div class="panel-heading" role="tab" id="headingOne">\
|
||||
<h4 class="panel-title">\
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">\
|
||||
{{ _('Error message') }}\
|
||||
</a>\
|
||||
</h4>\
|
||||
</div>\
|
||||
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">\
|
||||
<div class="panel-body" style="overflow: scroll;">' + message + '</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
|
||||
if (info != null && info != '') {
|
||||
text += '<div class="panel panel-default">\
|
||||
<div class="panel-heading" role="tab" id="headingTwo">\
|
||||
<h4 class="panel-title">\
|
||||
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">\
|
||||
{{ _('Additional info') }}\
|
||||
</a>\
|
||||
</h4>\
|
||||
</div>\
|
||||
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">\
|
||||
<div class="panel-body" style="overflow: scroll;">' + info + '</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
}
|
||||
|
||||
text += '</div>'
|
||||
|
||||
alertify.alert(
|
||||
'{{ _('An error has occurred') }}',
|
||||
text
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Enable/disable menu options
|
||||
function enable_disable_menus() {
|
||||
|
||||
// Disable everything first
|
||||
$("#mnu_create").html('<li class="menu-item disabled"><a href="#">{{ _('No object selected') }}</a></li>\n');
|
||||
$("#mnu_drop_object").addClass("mnu-disabled");
|
||||
$("#mnu_rename_object").addClass("mnu-disabled");
|
||||
node_type = get_selected_node_type()
|
||||
|
||||
// List the possible standard items, their types and actions
|
||||
var handlers = [{% if standard_items is defined %}{% for standard_item in standard_items %}
|
||||
"{{ standard_item.type }}:{{ standard_item.action }}",{% endfor %}{% endif %}
|
||||
]
|
||||
|
||||
// Check if we have a matching action for the object type in the list, and
|
||||
// if so, enable the menu item
|
||||
if ($.inArray(node_type + ":drop", handlers) >= 0)
|
||||
$("#mnu_drop_object").removeClass("mnu-disabled");
|
||||
|
||||
if ($.inArray(node_type + ":rename", handlers) >= 0)
|
||||
$("#mnu_rename_object").removeClass("mnu-disabled");
|
||||
|
||||
// List the possibe create items
|
||||
var creators = [{% if create_items is defined %}{% for create_item in create_items %}
|
||||
[{{ create_item.type }}, "{{ create_item.name }}", "{{ create_item.label }}", "{{ create_item.function }}"],{% endfor %}{% endif %}
|
||||
]
|
||||
|
||||
// Loop through the list of creators and add links for any that apply to this
|
||||
// node type to the Create menu's UL element
|
||||
items = ''
|
||||
|
||||
for (i = 0; i < creators.length; ++i) {
|
||||
if ($.inArray(node_type, creators[i][0]) >= 0) {
|
||||
items = items + '<li class="menu-item"><a href="#" onclick="' + creators[i][3] + '()">' + creators[i][2] + '</a></li>\n'
|
||||
}
|
||||
}
|
||||
if (items != '')
|
||||
$("#mnu_create").html(items);
|
||||
}
|
||||
|
||||
// Get the selected treeview item type, or nowt
|
||||
function get_selected_node_type() {
|
||||
item = tree.selected()
|
||||
if (!item || item.length != 1)
|
||||
return "";
|
||||
|
||||
return tree.itemData(tree.selected())._type;
|
||||
}
|
||||
|
||||
// Create a new object of the type currently selected
|
||||
function create_object() {
|
||||
node_type = get_selected_node_type()
|
||||
if (node_type == "")
|
||||
return;
|
||||
|
||||
switch(node_type) {
|
||||
{% if standard_items is defined %}{% for standard_item in standard_items %}{% if standard_item.action == 'create' %}
|
||||
case '{{ standard_item.type }}':
|
||||
{{ standard_item.function }}()
|
||||
break;
|
||||
{% endif %}{% endfor %}{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the selected object
|
||||
function drop_object() {
|
||||
node_type = get_selected_node_type()
|
||||
if (node_type == "")
|
||||
return;
|
||||
|
||||
switch(node_type) {
|
||||
{% if standard_items is defined %}{% for standard_item in standard_items %}{% if standard_item.action == 'drop' %}
|
||||
case '{{ standard_item.type }}':
|
||||
{{ standard_item.function }}(tree.selected())
|
||||
break;
|
||||
{% endif %}{% endfor %}{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
// Rename the selected object
|
||||
function rename_object() {
|
||||
node_type = get_selected_node_type()
|
||||
if (node_type == "")
|
||||
return;
|
||||
|
||||
switch(node_type) {
|
||||
{% if standard_items is defined %}{% for standard_item in standard_items %}{% if standard_item.action == 'rename' %}
|
||||
case '{{ standard_item.type }}':
|
||||
{{ standard_item.function }}(tree.selected())
|
||||
break;
|
||||
{% endif %}{% endfor %}{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Setup the browser
|
||||
$(document).ready(function(){
|
||||
|
||||
@ -166,15 +302,23 @@ ALTER TABLE tickets_detail \n\
|
||||
selector: '.aciTreeLine',
|
||||
build: function(element) {
|
||||
var item = tree.itemFrom(element);
|
||||
var menu = {
|
||||
};
|
||||
var menu = { };
|
||||
var createMenu = { };
|
||||
|
||||
{% if create_items is defined %}
|
||||
{% for create_item in create_items %}
|
||||
if ($.inArray(tree.itemData(item)._type, {{ create_item.type }}) >= 0) {
|
||||
createMenu['{{ create_item.name }}'] = { name: '{{ create_item.label }}', callback: function() { {{ create_item.function }}() }};
|
||||
}
|
||||
{% endfor %}{% endif %}
|
||||
|
||||
menu["create"] = { "name": "Create" }
|
||||
menu["create"]["items"] = createMenu
|
||||
|
||||
{% if context_items is defined %}
|
||||
{% for context_item in context_items %}
|
||||
if (tree.itemData(item)._type == '{{ context_item.type }}') {
|
||||
menu['{{ context_item.name }}'] = {
|
||||
name: '{{ context_item.label }}',
|
||||
callback: function() { {{ context_item.onclick }} }
|
||||
};
|
||||
menu['{{ context_item.name }}'] = { name: '{{ context_item.label }}', callback: function() { {{ context_item.onclick }} }};
|
||||
}
|
||||
{% endfor %}{% endif %}
|
||||
return {
|
||||
@ -184,45 +328,19 @@ ALTER TABLE tickets_detail \n\
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Treeview event handler
|
||||
$('#tree').on('acitree', function(event, api, item, eventName, options){
|
||||
switch (eventName){
|
||||
case "selected":
|
||||
enable_disable_menus()
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Setup the menus
|
||||
enable_disable_menus()
|
||||
});
|
||||
|
||||
|
||||
function report_error(message, info) {
|
||||
|
||||
text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
|
||||
<div class="panel panel-default">\
|
||||
<div class="panel-heading" role="tab" id="headingOne">\
|
||||
<h4 class="panel-title">\
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">\
|
||||
{{ _('Error message') }}\
|
||||
</a>\
|
||||
</h4>\
|
||||
</div>\
|
||||
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">\
|
||||
<div class="panel-body" style="overflow: scroll;">' + message + '</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
|
||||
if (info != '') {
|
||||
text += '<div class="panel panel-default">\
|
||||
<div class="panel-heading" role="tab" id="headingTwo">\
|
||||
<h4 class="panel-title">\
|
||||
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">\
|
||||
{{ _('Additional info') }}\
|
||||
</a>\
|
||||
</h4>\
|
||||
</div>\
|
||||
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">\
|
||||
<div class="panel-body" style="overflow: scroll;">' + info + '</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
}
|
||||
|
||||
text += '</div>'
|
||||
|
||||
alertify.alert(
|
||||
'{{ _('An error has occurred') }}',
|
||||
text
|
||||
)
|
||||
}
|
@ -136,10 +136,20 @@ def browser_js():
|
||||
# Load the core browser code first
|
||||
|
||||
# Get the context menu items
|
||||
standard_items = [ ]
|
||||
create_items = [ ]
|
||||
context_items = [ ]
|
||||
panel_items = [ ]
|
||||
|
||||
for module in modules_and_nodes:
|
||||
# Get any standard menu items
|
||||
if 'hooks' in dir(module) and 'get_standard_menu_items' in dir(module.hooks):
|
||||
standard_items.extend(module.hooks.get_standard_menu_items())
|
||||
|
||||
# Get any create menu items
|
||||
if 'hooks' in dir(module) and 'get_create_menu_items' in dir(module.hooks):
|
||||
create_items.extend(module.hooks.get_create_menu_items())
|
||||
|
||||
# Get any context menu items
|
||||
if 'hooks' in dir(module) and 'get_context_menu_items' in dir(module.hooks):
|
||||
context_items.extend(module.hooks.get_context_menu_items())
|
||||
@ -148,6 +158,8 @@ def browser_js():
|
||||
if 'hooks' in dir(module) and 'get_panels' in dir(module.hooks):
|
||||
panel_items += module.hooks.get_panels()
|
||||
|
||||
standard_items = sorted(standard_items, key=lambda k: k['priority'])
|
||||
create_items = sorted(create_items, key=lambda k: k['priority'])
|
||||
context_items = sorted(context_items, key=lambda k: k['priority'])
|
||||
panel_items = sorted(panel_items, key=lambda k: k['priority'])
|
||||
|
||||
@ -155,6 +167,8 @@ def browser_js():
|
||||
|
||||
snippets += render_template('browser/js/browser.js',
|
||||
layout = layout,
|
||||
standard_items = standard_items,
|
||||
create_items = create_items,
|
||||
context_items = context_items,
|
||||
panel_items = panel_items)
|
||||
|
||||
|
@ -11,10 +11,6 @@
|
||||
MODULE_NAME = 'help'
|
||||
|
||||
from flask import Blueprint
|
||||
from flaskext.gravatar import Gravatar
|
||||
from flask.ext.security import login_required
|
||||
from flask.ext.login import current_user
|
||||
from inspect import getmoduleinfo, getmembers
|
||||
|
||||
import config
|
||||
|
||||
|
@ -67,4 +67,62 @@ iframe {
|
||||
/* Prevent tree items wrapping */
|
||||
.aciTree .aciTreeItem {
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
/* Disabled menu items */
|
||||
.mnu-disabled {
|
||||
color: #999999 !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bootstrap 3 remove submenus as they don't work overly well on Mobile. The
|
||||
* following CSS adds them back in - for our purposes they actually work fine
|
||||
* on Mobile and are perfectly responsive
|
||||
*/
|
||||
.dropdown-submenu {
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.dropdown-submenu>.dropdown-menu {
|
||||
top:0;
|
||||
left:100%;
|
||||
margin-top:-6px;
|
||||
margin-left:-1px;
|
||||
-webkit-border-radius:0 6px 6px 6px;
|
||||
-moz-border-radius:0 6px 6px 6px;
|
||||
border-radius:0 6px 6px 6px;
|
||||
}
|
||||
|
||||
.dropdown-submenu:hover>.dropdown-menu {
|
||||
display:block;
|
||||
}
|
||||
|
||||
.dropdown-submenu>a:after {
|
||||
display:block;
|
||||
content:" ";
|
||||
float:right;
|
||||
width:0;
|
||||
height:0;
|
||||
border-color:transparent;
|
||||
border-style:solid;
|
||||
border-width:5px 0 5px 5px;
|
||||
border-left-color:#cccccc;
|
||||
margin-top:5px;
|
||||
margin-right:-10px;
|
||||
}
|
||||
|
||||
.dropdown-submenu:hover>a:after {
|
||||
border-left-color:#ffffff;
|
||||
}
|
||||
|
||||
.dropdown-submenu.pull-left {
|
||||
float:none;
|
||||
}
|
||||
|
||||
.dropdown-submenu.pull-left>.dropdown-menu {
|
||||
left:-100%;
|
||||
margin-left:10px;
|
||||
-webkit-border-radius:6px 0 6px 6px;
|
||||
-moz-border-radius:6px 0 6px 6px;
|
||||
border-radius:6px 0 6px 6px;
|
||||
}
|
@ -144,6 +144,7 @@
|
||||
|
||||
.wcMenuList, .context-menu-list {
|
||||
border: 1px solid #dddddd;
|
||||
z-index: 999 !important;
|
||||
}
|
||||
|
||||
.wcMenuItem, .context-menu-item {
|
||||
@ -201,3 +202,7 @@
|
||||
.wcLayout, .wcLayout tr, .wcLayout td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.context-menu-submenu:after {
|
||||
content: '>' !important;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user