Merge "Replaces multi select combos with transfer tables"
This commit is contained in:
commit
84cac65360
|
@ -14,3 +14,6 @@ ADD_INSTALLED_APPS = ['gbpui', ]
|
|||
PANEL_GROUP = 'GroupPolicyPanels'
|
||||
PANEL_GROUP_NAME = 'Policy'
|
||||
PANEL_GROUP_DASHBOARD = 'project'
|
||||
|
||||
AUTO_DISCOVER_STATIC_FILES = True
|
||||
ADD_ANGULAR_MODULES = ['gbpui', ]
|
||||
|
|
|
@ -16,6 +16,11 @@ from django.forms import TextInput
|
|||
from django.forms import widgets
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from django.forms.utils import flatatt
|
||||
from django.utils.html import format_html
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class DynamicMultiSelectWidget(widgets.SelectMultiple):
|
||||
|
||||
|
@ -84,3 +89,78 @@ class DropdownEditWidget(TextInput):
|
|||
data_list += '<option value="%s">' % item
|
||||
data_list += '</datalist>'
|
||||
return mark_safe(text_html + data_list)
|
||||
|
||||
|
||||
class TransferTableWidget(widgets.SelectMultiple):
|
||||
actions_list = []
|
||||
add_item_link = None
|
||||
max_items = None
|
||||
allocated_filter = False
|
||||
|
||||
allocated_help_text = None
|
||||
available_help_text = None
|
||||
no_allocated_text = None
|
||||
no_available_text = None
|
||||
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
# css class currently breaks the layout for some reason,
|
||||
self.attrs.pop('class', None)
|
||||
|
||||
final_attrs = self.build_attrs(attrs, name=name)
|
||||
|
||||
selected = [] if value is None else value
|
||||
|
||||
options = self.render_options(choices, selected)
|
||||
|
||||
if self.add_item_link is not None:
|
||||
final_attrs['add_item_link'] = urlresolvers.reverse(
|
||||
self.add_item_link
|
||||
)
|
||||
|
||||
if self.max_items is not None:
|
||||
final_attrs['max_items'] = self.max_items
|
||||
|
||||
if self.allocated_filter:
|
||||
final_attrs['allocated_filter'] = "True"
|
||||
|
||||
final_attrs['allocated_help_text'] = self.allocated_help_text
|
||||
final_attrs['available_help_text'] = self.available_help_text
|
||||
final_attrs['no_allocated_text'] = self.no_allocated_text
|
||||
final_attrs['no_available_text'] = self.no_available_text
|
||||
|
||||
open_tag = format_html('<d-table {}>', flatatt(final_attrs))
|
||||
|
||||
output = [open_tag, options, '</d-table>']
|
||||
|
||||
return mark_safe('\n'.join(output))
|
||||
|
||||
# ...this adds the 'add item button' just by existing and returning a
|
||||
# true-y value
|
||||
def get_add_item_url(self):
|
||||
return None
|
||||
|
||||
|
||||
class TransferTableField(fields.MultipleChoiceField):
|
||||
widget = TransferTableWidget
|
||||
|
||||
def __init__(self, add_item_link=None, max_items=-1,
|
||||
allocated_filter=False,
|
||||
allocated_help_text="",
|
||||
available_help_text="",
|
||||
no_allocated_text=_("Select items from bellow"),
|
||||
no_available_text=_("No available items"),
|
||||
*args, **kwargs):
|
||||
super(TransferTableField, self).__init__(*args, **kwargs)
|
||||
|
||||
self.widget.add_item_link = add_item_link
|
||||
self.widget.max_items = max_items
|
||||
self.widget.allocated_filter = allocated_filter
|
||||
|
||||
self.widget.allocated_help_text = allocated_help_text
|
||||
self.widget.available_help_text = available_help_text
|
||||
|
||||
self.widget.no_allocated_text = no_allocated_text
|
||||
self.widget.no_available_text = no_available_text
|
||||
|
||||
def validate(self, *args, **kwargs):
|
||||
return True
|
||||
|
|
|
@ -55,7 +55,7 @@ class BaseUpdateForm(forms.SelfHandlingForm):
|
|||
class UpdatePolicyRuleSetForm(BaseUpdateForm):
|
||||
name = forms.CharField(label=_("Name"))
|
||||
description = forms.CharField(label=_("Description"), required=False)
|
||||
policy_rules = forms.MultipleChoiceField(label=_("Policy Rules"),)
|
||||
policy_rules = fields.TransferTableField(label=_("Policy Rules"), )
|
||||
shared = forms.BooleanField(label=_("Shared"), required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
|
@ -298,7 +298,11 @@ class UpdatePolicyRuleForm(BaseUpdateForm):
|
|||
name = forms.CharField(max_length=80, label=_("Name"), required=False)
|
||||
description = forms.CharField(label=_("Description"), required=False)
|
||||
policy_classifier_id = forms.ChoiceField(label=_("Policy Classifier"))
|
||||
policy_actions = forms.MultipleChoiceField(label=_("Policy Actions"))
|
||||
policy_actions = fields.TransferTableField(
|
||||
label=_("Policy Actions"),
|
||||
required=False,
|
||||
)
|
||||
|
||||
shared = forms.BooleanField(label=_("Shared"), required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
|
@ -306,17 +310,19 @@ class UpdatePolicyRuleForm(BaseUpdateForm):
|
|||
try:
|
||||
policyrule_id = self.initial['policyrule_id']
|
||||
rule = client.policyrule_get(request, policyrule_id)
|
||||
|
||||
for item in ['name', 'description',
|
||||
'policy_classifier_id', 'policy_actions', 'shared']:
|
||||
self.fields[item].initial = getattr(rule, item)
|
||||
|
||||
actions = client.policyaction_list(request,
|
||||
tenant_id=request.user.tenant_id)
|
||||
action_list = [a.id for a in actions]
|
||||
for action in actions:
|
||||
action.set_id_as_name_if_empty()
|
||||
actions = sorted(actions, key=lambda action: action.name)
|
||||
action_list = [(a.id, a.name) for a in actions]
|
||||
self.fields['policy_actions'].choices = action_list
|
||||
|
||||
classifiers = client.policyclassifier_list(request,
|
||||
tenant_id=request.user.tenant_id)
|
||||
classifier_list = [(c.id, c.name) for c in classifiers]
|
||||
|
|
|
@ -21,6 +21,7 @@ from horizon import workflows
|
|||
from gbpui import client
|
||||
from gbpui import fields
|
||||
|
||||
|
||||
ADD_POLICY_ACTION_URL = "horizon:project:application_policy:addpolicyaction"
|
||||
ADD_POLICY_CLASSIFIER_URL = "horizon:project:application_policy:"
|
||||
ADD_POLICY_CLASSIFIER_URL = ADD_POLICY_CLASSIFIER_URL + "addpolicyclassifier"
|
||||
|
@ -28,11 +29,12 @@ ADD_POLICY_RULE_URL = "horizon:project:application_policy:addpolicyrule"
|
|||
|
||||
|
||||
class SelectPolicyRuleAction(workflows.Action):
|
||||
policy_rules = fields.DynamicMultiChoiceField(
|
||||
policy_rules = fields.TransferTableField(
|
||||
label=_("Policy Rules"),
|
||||
required=False,
|
||||
add_item_link=ADD_POLICY_RULE_URL,
|
||||
help_text=_("Create a policy rule set with selected rules."))
|
||||
help_text=_("Create a policy rule set with selected rules.")
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
name = _("Rules")
|
||||
|
@ -162,11 +164,17 @@ class SelectPolicyClassifierAction(workflows.Action):
|
|||
|
||||
|
||||
class SelectPolicyActionAction(workflows.Action):
|
||||
actions = fields.DynamicMultiChoiceField(
|
||||
actions = fields.TransferTableField(
|
||||
label=_("Policy Action"),
|
||||
required=False,
|
||||
help_text=_("Create a policy-rule with selected action."),
|
||||
add_item_link=ADD_POLICY_ACTION_URL)
|
||||
add_item_link=ADD_POLICY_ACTION_URL,
|
||||
help_text=_("Create a policy-rule with selected action.")
|
||||
)
|
||||
|
||||
def __init__(self, request, context, *args, **kwargs):
|
||||
super(SelectPolicyActionAction, self).__init__(
|
||||
request, context, *args, **kwargs
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
name = _("actions")
|
||||
|
@ -176,14 +184,11 @@ class SelectPolicyActionAction(workflows.Action):
|
|||
try:
|
||||
actions = client.policyaction_list(request,
|
||||
tenant_id=request.user.tenant_id)
|
||||
action_list = [a.id for a in actions]
|
||||
for action in actions:
|
||||
action.set_id_as_name_if_empty()
|
||||
actions = sorted(actions,
|
||||
key=lambda action: action.name)
|
||||
action_list = [(a.id, a.name) for a in actions]
|
||||
if len(action_list) > 0:
|
||||
self.fields['actions'].initial = action_list[0]
|
||||
except Exception as e:
|
||||
action_list = []
|
||||
exceptions.handle(request,
|
||||
|
|
|
@ -63,10 +63,11 @@ class AddL3PolicyForm(forms.SelfHandlingForm):
|
|||
label=_("Subnet Prefix Length"),
|
||||
help_text=_("Between 2 - 30 for IP4"
|
||||
"and 2-127 for IP6."),)
|
||||
external_segments = \
|
||||
fields.CustomMultiChoiceField(label=_("External Segments"),
|
||||
add_item_link=EXT_SEG_PARAM_URL,
|
||||
required=False)
|
||||
external_segments = fields.TransferTableField(
|
||||
label=_("External Segments"),
|
||||
add_item_link=EXT_SEG_PARAM_URL,
|
||||
required=False
|
||||
)
|
||||
shared = forms.BooleanField(label=_("Shared"),
|
||||
initial=False,
|
||||
required=False)
|
||||
|
@ -296,9 +297,11 @@ class CreateServicePolicyForm(forms.SelfHandlingForm):
|
|||
name = forms.CharField(max_length=80, label=_("Name"))
|
||||
description = forms.CharField(
|
||||
max_length=80, label=_("Description"), required=False)
|
||||
network_service_params = fields.CustomMultiChoiceField(label=_(
|
||||
"Network Service Parameters"), add_item_link=NETWORK_PARAM_URL,
|
||||
required=False)
|
||||
network_service_params = fields.TransferTableField(
|
||||
label=_("Network Service Parameters"),
|
||||
add_item_link=NETWORK_PARAM_URL,
|
||||
required=False
|
||||
)
|
||||
shared = forms.BooleanField(label=_("Shared"),
|
||||
initial=False, required=False)
|
||||
|
||||
|
@ -555,9 +558,11 @@ class CreateExternalConnectivityForm(forms.SelfHandlingForm):
|
|||
"(e.g. 192.168.0.0/24,"
|
||||
"2001:DB8::/48)"),
|
||||
version=forms.IPv4 | forms.IPv6, mask=True)
|
||||
external_routes = fields.CustomMultiChoiceField(
|
||||
label=_("External Routes"), add_item_link=ROUTE_URL,
|
||||
required=False)
|
||||
external_routes = fields.TransferTableField(
|
||||
label=_("External Routes"),
|
||||
add_item_link=ROUTE_URL,
|
||||
required=False
|
||||
)
|
||||
subnet_id = forms.ChoiceField(label=_("Subnet ID"), required=False)
|
||||
port_address_translation = forms.BooleanField(
|
||||
label=_("Port Address Translation"),
|
||||
|
|
|
@ -22,6 +22,7 @@ from horizon import forms
|
|||
from horizon import messages
|
||||
|
||||
from gbpui import client
|
||||
from gbpui import fields
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -31,10 +32,12 @@ class UpdatePolicyTargetForm(forms.SelfHandlingForm):
|
|||
label=_("Name"), required=False)
|
||||
description = forms.CharField(max_length=80,
|
||||
label=_("Description"), required=False)
|
||||
provided_policy_rule_sets = forms.MultipleChoiceField(
|
||||
label=_("Provided Policy Rule Set"), required=False)
|
||||
consumed_policy_rule_sets = forms.MultipleChoiceField(
|
||||
label=_("Consumed Policy Rule Set"), required=False)
|
||||
provided_policy_rule_sets = fields.TransferTableField(
|
||||
label=_("Provided Policy Rule Set"), required=False
|
||||
)
|
||||
consumed_policy_rule_sets = fields.TransferTableField(
|
||||
label=_("Consumed Policy Rule Set"), required=False
|
||||
)
|
||||
l2_policy_id = forms.ChoiceField(
|
||||
label=_("Network Policy"),
|
||||
required=False,
|
||||
|
@ -141,9 +144,9 @@ class UpdateExternalPolicyTargetForm(forms.SelfHandlingForm):
|
|||
label=_("Name"), required=False)
|
||||
description = forms.CharField(max_length=80,
|
||||
label=_("Description"), required=False)
|
||||
provided_policy_rule_sets = forms.MultipleChoiceField(
|
||||
provided_policy_rule_sets = fields.TransferTableField(
|
||||
label=_("Provided Policy Rule Set"), required=False)
|
||||
consumed_policy_rule_sets = forms.MultipleChoiceField(
|
||||
consumed_policy_rule_sets = fields.TransferTableField(
|
||||
label=_("Consumed Policy Rule Set"), required=False)
|
||||
external_segments = forms.MultipleChoiceField(
|
||||
label=_("External Connectivity"), required=True,
|
||||
|
|
|
@ -48,12 +48,12 @@ ADD_EXTERNAL_CONNECTIVITY = \
|
|||
|
||||
|
||||
class SelectPolicyRuleSetAction(workflows.Action):
|
||||
provided_policy_rule_set = fields.DynamicMultiChoiceField(
|
||||
provided_policy_rule_set = fields.TransferTableField(
|
||||
label=_("Provided Policy Rule Set"),
|
||||
help_text=_("Choose a policy rule set for an Group."),
|
||||
add_item_link=POLICY_RULE_SET_URL,
|
||||
required=False)
|
||||
consumed_policy_rule_set = fields.DynamicMultiChoiceField(
|
||||
consumed_policy_rule_set = fields.TransferTableField(
|
||||
label=_("Consumed Policy Rule Set"),
|
||||
help_text=_("Select consumed policy rule set for Group."),
|
||||
add_item_link=POLICY_RULE_SET_URL,
|
||||
|
@ -64,8 +64,10 @@ class SelectPolicyRuleSetAction(workflows.Action):
|
|||
help_text = _("Select Policy Rule Set for Group.")
|
||||
|
||||
def _policy_rule_set_list(self, request):
|
||||
policy_rule_sets = client.policy_rule_set_list(request,
|
||||
tenant_id=request.user.tenant_id)
|
||||
policy_rule_sets = client.policy_rule_set_list(
|
||||
request,
|
||||
tenant_id=request.user.tenant_id
|
||||
)
|
||||
for c in policy_rule_sets:
|
||||
c.set_id_as_name_if_empty()
|
||||
policy_rule_sets = sorted(policy_rule_sets,
|
||||
|
@ -75,12 +77,8 @@ class SelectPolicyRuleSetAction(workflows.Action):
|
|||
def populate_provided_policy_rule_set_choices(self, request, context):
|
||||
policy_rule_set_list = []
|
||||
try:
|
||||
rsets = self._policy_rule_set_list(request)
|
||||
if len(rsets) == 0:
|
||||
rsets.extend([('None', 'No Provided Policy Rule Sets')])
|
||||
policy_rule_set_list = rsets
|
||||
policy_rule_set_list = self._policy_rule_set_list(request)
|
||||
except Exception as e:
|
||||
policy_rule_set_list = []
|
||||
msg = _('Unable to retrieve policy rule set. %s.') % (str(e))
|
||||
exceptions.handle(request, msg)
|
||||
return policy_rule_set_list
|
||||
|
@ -88,9 +86,7 @@ class SelectPolicyRuleSetAction(workflows.Action):
|
|||
def populate_consumed_policy_rule_set_choices(self, request, context):
|
||||
policy_rule_set_list = []
|
||||
try:
|
||||
policy_rule_set_list = [('None', 'No Consumed Policy Rule Sets')]
|
||||
policy_rule_set_list =\
|
||||
self._policy_rule_set_list(request)
|
||||
policy_rule_set_list = self._policy_rule_set_list(request)
|
||||
except Exception as e:
|
||||
msg = _('Unable to retrieve policy rule set. %s.') % (str(e))
|
||||
exceptions.handle(request, msg)
|
||||
|
@ -342,6 +338,7 @@ class SetAccessControlsAction(workflows.Action):
|
|||
help_text=_("Key pair to use for "
|
||||
"authentication."),
|
||||
add_item_link=KEYPAIR_IMPORT_URL)
|
||||
|
||||
admin_pass = forms.RegexField(
|
||||
label=_("Admin Password"),
|
||||
required=False,
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
(function () {
|
||||
angular
|
||||
.module('gbpui', ['gbpui.transfer-table-bridge'])
|
||||
.config(module_config);
|
||||
|
||||
module_config.$inject = ["$provide","$windowProvider"];
|
||||
|
||||
function module_config($provide, $windowProvider) {
|
||||
var path = $windowProvider.$get().STATIC_URL + 'dashboard/gbpui/';
|
||||
$provide.constant('gbpui.basePath', path);
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
(function () {
|
||||
angular
|
||||
.module('gbpui.transfer-table-bridge')
|
||||
.directive('dSelect', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: true,
|
||||
link: function ($scope, $elem, $attrs, $ctrl) {
|
||||
|
||||
|
||||
$.each($scope.tableData.available, function (index, optionObject) {
|
||||
var option = $("<option></option>");
|
||||
option.attr("value", optionObject.id);
|
||||
option.append(optionObject.name);
|
||||
$elem.append(option);
|
||||
});
|
||||
|
||||
// This change listener watches for changes to the raw
|
||||
// HTML select element; since the select should be hidden,
|
||||
// the only possible change is the creation of a new
|
||||
// option using the horizon add button.
|
||||
$elem.change(function () {
|
||||
// Find the last option in the select, since the
|
||||
// addition is done by Horizon appending the a new
|
||||
// option element
|
||||
var option = $(this).find("option").last();
|
||||
|
||||
// Create a valid option object and make it available
|
||||
// at the end of the available list
|
||||
var val = {
|
||||
'id': option.attr('value'),
|
||||
'name': option.text()
|
||||
};
|
||||
$scope.tableData.available.push(val);
|
||||
|
||||
// Deallocate all the objects using the built in
|
||||
// transfer table controller deallocation method
|
||||
var toDeallocate = $scope.tableData.allocated.slice();
|
||||
$.each(toDeallocate, function (index, object) {
|
||||
$scope.trCtrl.deallocate(object);
|
||||
});
|
||||
// Notify the scope of the deallocations
|
||||
$scope.$apply();
|
||||
|
||||
// Allocate the new option; this mimicks te behaviour
|
||||
// of the normal Horizon based adding
|
||||
$scope.trCtrl.allocate(val);
|
||||
|
||||
// Notify the scope of the allocation changes
|
||||
$scope.$apply();
|
||||
});
|
||||
|
||||
// The directive watches for a changes in the allocated
|
||||
// list to dynamically set values for the hidden element.
|
||||
$scope.$watchCollection(
|
||||
function (scope) {
|
||||
return $scope.tableData.allocated;
|
||||
},
|
||||
function (newValue, oldValue) {
|
||||
var values = $.map(
|
||||
newValue, function (value, index) {
|
||||
return value.id;
|
||||
});
|
||||
$elem.val(values);
|
||||
}
|
||||
);
|
||||
|
||||
// Sets initial values as allocated when appropriate
|
||||
$.each($scope.initial, function (index, initialObject) {
|
||||
$scope.trCtrl.allocate(initialObject);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
(function () {
|
||||
angular
|
||||
.module('gbpui.transfer-table-bridge')
|
||||
.directive('dTable', ['gbpui.basePath', function(basePath){
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: true,
|
||||
templateUrl: basePath +
|
||||
"transfer-table-bridge/transfer-table-bridge.html",
|
||||
transclude: true,
|
||||
link: function($scope, $elem, $attrs, $ctrl, $transclude) {
|
||||
|
||||
var initial = [];
|
||||
var available = [];
|
||||
|
||||
var transcluded = $transclude();
|
||||
|
||||
transcluded.each(function(index, element) {
|
||||
if(element.localName=="option") {
|
||||
var val = {
|
||||
'id': $(element).attr('value'),
|
||||
'name': $(element).text()
|
||||
};
|
||||
available.push(val);
|
||||
|
||||
if($(element).prop('selected')) {
|
||||
initial.push(val);
|
||||
}
|
||||
}
|
||||
});
|
||||
$scope.initial = initial;
|
||||
|
||||
var allocated = [];
|
||||
|
||||
$scope.tableData = {
|
||||
available: available,
|
||||
allocated: allocated,
|
||||
displayedAvailable: [],
|
||||
displayedAllocated: [],
|
||||
minItems: -1
|
||||
};
|
||||
|
||||
var maxAllocation = "maxItems" in $attrs
|
||||
? Number($attrs["maxItems"])
|
||||
: -1;
|
||||
$scope.tableLimits = {
|
||||
maxAllocation: maxAllocation
|
||||
};
|
||||
|
||||
$scope.tableHelpText = {
|
||||
allocHelpText: $attrs['allocatedHelpText'],
|
||||
availHelpText: $attrs['availableHelpText'],
|
||||
noAllocText: $attrs['noAllocatedText'],
|
||||
noAvailText: $attrs['noAvailableText']
|
||||
};
|
||||
|
||||
$scope.facets = [{
|
||||
label: gettext("Name"),
|
||||
name: "name",
|
||||
singleton: true
|
||||
}];
|
||||
|
||||
if("addItemLink" in $attrs) {
|
||||
$scope.addItemLink = $attrs["addItemLink"];
|
||||
}
|
||||
|
||||
if("allocatedFilter" in $attrs) {
|
||||
$scope.allocatedFilter = true;
|
||||
}
|
||||
|
||||
$scope.id = $attrs["id"];
|
||||
$scope.name = $attrs["name"];
|
||||
|
||||
}
|
||||
}
|
||||
}])
|
||||
|
||||
})();
|
|
@ -0,0 +1,114 @@
|
|||
<transfer-table tr-model="tableData" limits="tableLimits" help-text="tableHelpText">
|
||||
|
||||
<allocated ng-model="tableData.allocated.length">
|
||||
<table st-table="tableData.displayedAllocated"
|
||||
st-safe-src="tableData.allocated"
|
||||
hz-table
|
||||
class="table table-striped table-rsp table-detail table-condensed">
|
||||
<thead>
|
||||
<tr ng-if="allocatedFilter">
|
||||
<th colspan="2">
|
||||
<hz-magic-search-bar filter-facets="facets"></hz-magic-search-bar>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="tableData.allocated.length === 0">
|
||||
<td colspan="{{ addItemLink ? 2 : 1 }}">
|
||||
<div class="no-rows-help">
|
||||
{$ ::tableHelpText.noAllocText $}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="row in tableData.displayedAllocated track by row.id">
|
||||
<td>
|
||||
{$ row.name $}
|
||||
</td>
|
||||
<td class="actions_column">
|
||||
<action-list>
|
||||
<button tabIndex="0"
|
||||
ng-class="'btn btn-default'"
|
||||
ng-click="trCtrl.deallocate(row)"
|
||||
type="button">
|
||||
<span class="fa fa-arrow-down"></span>
|
||||
</button>
|
||||
</action-list>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</allocated>
|
||||
|
||||
<available>
|
||||
<table
|
||||
st-table="tableData.displayedAvailable"
|
||||
st-safe-src="tableData.available"
|
||||
hz-table
|
||||
class="table table-striped table-rsp table-detail table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="{$ addItemLink ? 1 : 2 $}">
|
||||
<hz-magic-search-bar filter-facets="facets"></hz-magic-search-bar>
|
||||
</th>
|
||||
<th ng-if="addItemLink">
|
||||
<span class="input-group-btn">
|
||||
<a href="{$ addItemLink $}" data-add-to-field="{$ id $}_select" class="btn btn-default ajax-add ajax-modal">
|
||||
<span class="fa fa-plus"></span>
|
||||
</a>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr ng-if="trCtrl.numAvailable() === 0">
|
||||
<td colspan="{{ addItemLink ? 2 : 1 }}">
|
||||
<div class="no-rows-help">
|
||||
{$ ::tableHelpText.noAvailText $}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-repeat="row in tableData.displayedAvailable track by row.id"
|
||||
ng-if="!trCtrl.allocatedIds[row.id]"
|
||||
>
|
||||
<td>{$ row.name $}</td>
|
||||
<td class="actions_column">
|
||||
<action-list button-tooltip="row.warningMessage"
|
||||
bt-model="ctrl.tooltipModel"
|
||||
bt-disabled="!row.disabled"
|
||||
warning-classes="'invalid'">
|
||||
<notifications>
|
||||
<span class="fa fa-exclamation-circle invalid"
|
||||
ng-show="row.disabled"></span>
|
||||
</notifications>
|
||||
<button tabIndex="0"
|
||||
ng-class="'btn btn-default'"
|
||||
ng-click="trCtrl.allocate(row)"
|
||||
type="button">
|
||||
<span class="fa fa-arrow-up"></span>
|
||||
</button>
|
||||
</action-list>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div style="display:None">
|
||||
<select
|
||||
d-select
|
||||
id="{$ id $}_select"
|
||||
data-add-item-url
|
||||
multiple
|
||||
name="{$ name $}" >
|
||||
</select>
|
||||
</div>
|
||||
</available>
|
||||
|
||||
</transfer-table>
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
(function () {
|
||||
angular
|
||||
.module('gbpui.transfer-table-bridge', ['horizon.app.core.workflow']);
|
||||
})();
|
Loading…
Reference in New Issue