diff --git a/awx/api/fields.py b/awx/api/fields.py
new file mode 100644
index 0000000000..f1acaa7e72
--- /dev/null
+++ b/awx/api/fields.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2016 Ansible, Inc.
+# All Rights Reserved.
+
+# Django
+from django.utils.encoding import force_text
+
+# Django REST Framework
+from rest_framework import serializers
+
+__all__ = ['BooleanNullField', 'CharNullField', 'ChoiceNullField', 'EncryptedPasswordField', 'VerbatimField']
+
+
+class NullFieldMixin(object):
+ '''
+ Mixin to prevent shortcutting validation when we want to allow null input,
+ but coerce the resulting value to another type.
+ '''
+
+ def validate_empty_values(self, data):
+ (is_empty_value, data) = super(NullFieldMixin, self).validate_empty_values(data)
+ if is_empty_value and data is None:
+ return (False, data)
+ return (is_empty_value, data)
+
+
+class BooleanNullField(NullFieldMixin, serializers.NullBooleanField):
+ '''
+ Custom boolean field that allows null and empty string as False values.
+ '''
+
+ def to_internal_value(self, data):
+ return bool(super(BooleanNullField, self).to_internal_value(data))
+
+
+class CharNullField(NullFieldMixin, serializers.CharField):
+ '''
+ Custom char field that allows null as input and coerces to an empty string.
+ '''
+
+ def __init__(self, **kwargs):
+ kwargs['allow_null'] = True
+ super(CharNullField, self).__init__(**kwargs)
+
+ def to_internal_value(self, data):
+ return super(CharNullField, self).to_internal_value(data or u'')
+
+
+class ChoiceNullField(NullFieldMixin, serializers.ChoiceField):
+ '''
+ Custom choice field that allows null as input and coerces to an empty string.
+ '''
+
+ def __init__(self, **kwargs):
+ kwargs['allow_null'] = True
+ super(ChoiceNullField, self).__init__(**kwargs)
+
+ def to_internal_value(self, data):
+ return super(ChoiceNullField, self).to_internal_value(data or u'')
+
+
+class EncryptedPasswordField(CharNullField):
+ '''
+ Custom field to handle encrypted password values (on credentials).
+ '''
+
+ def to_internal_value(self, data):
+ value = super(EncryptedPasswordField, self).to_internal_value(data or u'')
+ # If user submits a value starting with $encrypted$, ignore it.
+ if force_text(value).startswith('$encrypted$'):
+ raise serializers.SkipField
+ return value
+
+ def to_representation(self, value):
+ # Replace the actual encrypted value with the string $encrypted$.
+ if force_text(value).startswith('$encrypted$'):
+ return '$encrypted$'
+ return value
+
+
+class VerbatimField(serializers.Field):
+ '''
+ Custom field that passes the value through without changes.
+ '''
+
+ def to_internal_value(self, data):
+ return data
+
+ def to_representation(self, value):
+ return value
diff --git a/awx/api/serializers.py b/awx/api/serializers.py
index 49dd88c4f0..572e690ce6 100644
--- a/awx/api/serializers.py
+++ b/awx/api/serializers.py
@@ -24,11 +24,13 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError as Django
from django.db import models
# from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text, smart_text
+from django.utils.text import capfirst
# Django REST Framework
from rest_framework.exceptions import ValidationError
from rest_framework import fields
from rest_framework import serializers
+from rest_framework import validators
from rest_framework.utils.serializer_helpers import ReturnList
# Django-Polymorphic
@@ -42,6 +44,7 @@ from awx.main.redact import REPLACE_STR
from awx.main.conf import tower_settings
from awx.api.license import feature_enabled
+from awx.api.fields import BooleanNullField, CharNullField, ChoiceNullField, EncryptedPasswordField, VerbatimField
from awx.fact.models import * # noqa
@@ -202,11 +205,6 @@ class BaseSerializer(serializers.ModelSerializer):
'modified', 'name', 'description')
summary_fields = () # FIXME: List of field names from this serializer that should be used when included as part of another's summary_fields.
summarizable_fields = () # FIXME: List of field names on this serializer that should be included in summary_fields.
- extra_kwargs = {
- 'description': {
- 'allow_null': True,
- },
- }
# add the URL and related resources
type = serializers.SerializerMethodField()
@@ -358,24 +356,50 @@ class BaseSerializer(serializers.ModelSerializer):
# Pass model field default onto the serializer field if field is not read-only.
if model_field.has_default() and not field_kwargs.get('read_only', False):
- field_kwargs['default'] = model_field.get_default()
+ field_kwargs['default'] = field_kwargs['initial'] = model_field.get_default()
+
# Enforce minimum value of 0 for PositiveIntegerFields.
if isinstance(model_field, (models.PositiveIntegerField, models.PositiveSmallIntegerField)) and 'choices' not in field_kwargs:
field_kwargs['min_value'] = 0
+
+ # Use custom boolean field that allows null and empty string as False values.
+ if isinstance(model_field, models.BooleanField) and not field_kwargs.get('read_only', False):
+ field_class = BooleanNullField
+
+ # Use custom char or choice field that coerces null to an empty string.
+ if isinstance(model_field, (models.CharField, models.TextField)) and not field_kwargs.get('read_only', False):
+ if 'choices' in field_kwargs:
+ field_class = ChoiceNullField
+ else:
+ field_class = CharNullField
+
# Update verbosity choices from settings (for job templates, jobs, ad hoc commands).
if field_name == 'verbosity' and 'choices' in field_kwargs:
field_kwargs['choices'] = getattr(settings, 'VERBOSITY_CHOICES', field_kwargs['choices'])
+
+ # Update the message used for the unique validator to use capitalized
+ # verbose name; keeps unique message the same as with DRF 2.x.
+ for validator in field_kwargs.get('validators', []):
+ if isinstance(validator, validators.UniqueValidator):
+ unique_error_message = model_field.error_messages.get('unique', None)
+ if unique_error_message:
+ unique_error_message = unique_error_message % {
+ 'model_name': capfirst(opts.verbose_name),
+ 'field_label': capfirst(model_field.verbose_name),
+ }
+ validator.message = unique_error_message
+
return field_class, field_kwargs
def build_relational_field(self, field_name, relation_info):
field_class, field_kwargs = super(BaseSerializer, self).build_relational_field(field_name, relation_info)
- # Don't include choicse for foreign key fields.
+ # Don't include choices for foreign key fields.
field_kwargs.pop('choices', None)
return field_class, field_kwargs
- def validate_description(self, value):
- # Description should always be empty string, never null.
- return value or u''
+ def get_unique_together_validators(self):
+ # Allow the model's full_clean method to handle the unique together validation.
+ return []
def run_validation(self, data=fields.empty):
try:
@@ -653,7 +677,6 @@ class UserSerializer(BaseSerializer):
fields = ('*', '-name', '-description', '-modified',
'-summary_fields', 'username', 'first_name', 'last_name',
'email', 'is_superuser', 'password', 'ldap_dn')
-
def to_representation(self, obj):
ret = super(UserSerializer, self).to_representation(obj)
@@ -772,17 +795,9 @@ class OrganizationSerializer(BaseSerializer):
class ProjectOptionsSerializer(BaseSerializer):
- scm_clean = serializers.NullBooleanField(default=False)
- scm_delete_on_update = serializers.NullBooleanField(default=False)
-
class Meta:
fields = ('*', 'local_path', 'scm_type', 'scm_url', 'scm_branch',
'scm_clean', 'scm_delete_on_update', 'credential')
- extra_kwargs = {
- 'scm_type': {
- 'allow_null': True,
- },
- }
def get_related(self, obj):
res = super(ProjectOptionsSerializer, self).get_related(obj)
@@ -791,15 +806,6 @@ class ProjectOptionsSerializer(BaseSerializer):
args=(obj.credential.pk,))
return res
- def validate_scm_type(self, value):
- return value or u''
-
- def validate_scm_clean(self, value):
- return bool(value)
-
- def validate_scm_delete_on_update(self, value):
- return bool(value)
-
def validate(self, attrs):
errors = {}
@@ -831,9 +837,7 @@ class ProjectOptionsSerializer(BaseSerializer):
class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer):
- scm_delete_on_next_update = serializers.BooleanField(read_only=True)
- scm_update_on_launch = serializers.NullBooleanField(default=False)
- status = serializers.ChoiceField(choices=Project.PROJECT_STATUS_CHOICES, read_only=True, required=False)
+ status = serializers.ChoiceField(choices=Project.PROJECT_STATUS_CHOICES, read_only=True)
last_update_failed = serializers.BooleanField(read_only=True)
last_updated = serializers.DateTimeField(read_only=True)
@@ -842,9 +846,7 @@ class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer):
fields = ('*', 'scm_delete_on_next_update', 'scm_update_on_launch',
'scm_update_cache_timeout') + \
('last_update_failed', 'last_updated') # Backwards compatibility
-
- def clean_scm_update_on_launch(self, value):
- return bool(value)
+ read_only_fields = ('scm_delete_on_next_update',)
def get_related(self, obj):
res = super(ProjectSerializer, self).get_related(obj)
@@ -1216,14 +1218,6 @@ class InventorySourceOptionsSerializer(BaseSerializer):
class Meta:
fields = ('*', 'source', 'source_path', 'source_script', 'source_vars', 'credential',
'source_regions', 'instance_filters', 'group_by', 'overwrite', 'overwrite_vars')
- extra_kwargs = {
- 'instance_filters': {
- 'allow_null': True,
- },
- 'group_by': {
- 'allow_null': True,
- },
- }
def get_related(self, obj):
res = super(InventorySourceOptionsSerializer, self).get_related(obj)
@@ -1281,7 +1275,7 @@ class InventorySourceOptionsSerializer(BaseSerializer):
class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOptionsSerializer):
- status = serializers.ChoiceField(choices=InventorySource.INVENTORY_SOURCE_STATUS_CHOICES, read_only=True, required=False)
+ status = serializers.ChoiceField(choices=InventorySource.INVENTORY_SOURCE_STATUS_CHOICES, read_only=True)
last_update_failed = serializers.BooleanField(read_only=True)
last_updated = serializers.DateTimeField(read_only=True)
@@ -1440,14 +1434,7 @@ class PermissionSerializer(BaseSerializer):
class CredentialSerializer(BaseSerializer):
- # FIXME: may want to make some of these filtered based on user accessing
-
- password = serializers.CharField(required=False, default='')
- security_token = serializers.CharField(required=False, default='')
- ssh_key_data = serializers.CharField(required=False, default='')
- ssh_key_unlock = serializers.CharField(required=False, default='')
- become_password = serializers.CharField(required=False, default='')
- vault_password = serializers.CharField(required=False, default='')
+ # FIXME: may want to make some fields filtered based on user accessing
class Meta:
model = Credential
@@ -1456,24 +1443,23 @@ class CredentialSerializer(BaseSerializer):
'become_method', 'become_username', 'become_password',
'vault_password')
+ def build_standard_field(self, field_name, model_field):
+ field_class, field_kwargs = super(CredentialSerializer, self).build_standard_field(field_name, model_field)
+ if field_name in Credential.PASSWORD_FIELDS:
+ field_class = EncryptedPasswordField
+ field_kwargs['required'] = False
+ field_kwargs['default'] = ''
+ return field_class, field_kwargs
+
def to_representation(self, obj):
ret = super(CredentialSerializer, self).to_representation(obj)
if obj is not None and 'user' in ret and (not obj.user or not obj.user.is_active):
ret['user'] = None
if obj is not None and 'team' in ret and (not obj.team or not obj.team.active):
ret['team'] = None
- # Replace the actual encrypted value with the string $encrypted$.
- for field in Credential.PASSWORD_FIELDS:
- if field in ret and force_text(ret[field]).startswith('$encrypted$'):
- ret[field] = '$encrypted$'
return ret
def validate(self, attrs):
- # If the value sent to the API startswith $encrypted$, ignore it.
- for field in Credential.PASSWORD_FIELDS:
- if force_text(attrs.get(field, '')).startswith('$encrypted$'):
- attrs.pop(field, None)
-
# If creating a credential from a view that automatically sets the
# parent_key (user or team), set the other value to None.
view = self.context.get('view', None)
@@ -2230,6 +2216,8 @@ class ActivityStreamSerializer(BaseSerializer):
class TowerSettingsSerializer(BaseSerializer):
+ value = VerbatimField()
+
class Meta:
model = TowerSettings
fields = ('key', 'description', 'category', 'value', 'value_type', 'user')
@@ -2263,14 +2251,20 @@ class TowerSettingsSerializer(BaseSerializer):
manifest = settings.TOWER_SETTINGS_MANIFEST
if attrs['key'] not in manifest:
raise serializers.ValidationError(dict(key=["Key {0} is not a valid settings key".format(attrs['key'])]))
- # TODO: Type checking/coercion, contextual validation
- return super(TowerSettingsSerializer, self).validate(attrs)
- def _create(self, validated_data):
- current_val = TowerSettings.objects.filter(key=validated_data['key'])
- if current_val.exists():
- return self.update(current_val[0], validated_data)
- return super(TowerSettingsSerializer, self).create(validated_data)
+ if attrs['value_type'] == 'json':
+ attrs['value'] = json.dumps(attrs['value'])
+ elif attrs['value_type'] == 'list':
+ try:
+ attrs['value'] = ','.join(map(force_text, attrs['value']))
+ except TypeError:
+ attrs['value'] = force_text(attrs['value'])
+ elif attrs['value_type'] == 'bool':
+ attrs['value'] = force_text(bool(attrs['value']))
+ else:
+ attrs['value'] = force_text(attrs['value'])
+
+ return super(TowerSettingsSerializer, self).validate(attrs)
class AuthTokenSerializer(serializers.Serializer):
diff --git a/awx/main/models/configuration.py b/awx/main/models/configuration.py
index 3bd43f5649..208ccbd487 100644
--- a/awx/main/models/configuration.py
+++ b/awx/main/models/configuration.py
@@ -6,7 +6,7 @@ import json
# Django
from django.db import models
-from django.utils.encoding import smart_text
+from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
# Tower
@@ -34,7 +34,9 @@ class TowerSettings(CreatedModifiedModel):
)
description = models.TextField()
category = models.CharField(max_length=128)
- value = models.TextField()
+ value = models.TextField(
+ blank=True,
+ )
value_type = models.CharField(
max_length=12,
choices=SETTINGS_TYPE_CHOICES
@@ -54,9 +56,12 @@ class TowerSettings(CreatedModifiedModel):
elif self.value_type == 'password':
converted_type = self.value
elif self.value_type == 'list':
- converted_type = [x.strip() for x in self.value.split(',')]
+ if self.value:
+ converted_type = [x.strip() for x in self.value.split(',')]
+ else:
+ converted_type = []
elif self.value_type == 'bool':
- converted_type = smart_text(self.value).lower() in ('true', 'yes', '1')
+ converted_type = force_text(self.value).lower() in ('true', 'yes', '1')
elif self.value_type == 'string':
converted_type = self.value
else:
@@ -69,8 +74,11 @@ class TowerSettings(CreatedModifiedModel):
if self.value_type == 'json':
self.value = json.dumps(value)
elif self.value_type == 'list':
- self.value = ','.join(value)
+ try:
+ self.value = ','.join(map(force_text, value))
+ except TypeError:
+ self.value = force_text(value)
elif self.value_type == 'bool':
- self.value = smart_text(bool(value))
+ self.value = force_text(bool(value))
else:
- self.value = smart_text(value)
+ self.value = force_text(value)
diff --git a/awx/main/tests/functional/conftest.py b/awx/main/tests/functional/conftest.py
index ddbad08bac..ad8c994a7d 100644
--- a/awx/main/tests/functional/conftest.py
+++ b/awx/main/tests/functional/conftest.py
@@ -1,17 +1,24 @@
import pytest
+from django.contrib.auth.models import User
+
+from rest_framework.test import (
+ APIRequestFactory,
+ force_authenticate,
+)
+
from awx.main.models.credential import Credential
+from awx.main.models.projects import Project
+from awx.main.models.jobs import JobTemplate
+from awx.main.models.ha import Instance
from awx.main.models.inventory import (
Inventory,
Group,
)
-from awx.main.models.projects import Project
-from awx.main.models.jobs import JobTemplate
from awx.main.models.organization import (
Organization,
Team,
)
-from django.contrib.auth.models import User
@pytest.fixture
def user():
@@ -62,7 +69,11 @@ def user_project(user):
return Project.objects.create(name="test-user-project", created_by=owner, description="test-user-project-desc")
@pytest.fixture
-def organization():
+def instance(settings):
+ return Instance.objects.create(uuid=settings.SYSTEM_UUID, primary=True, hostname="instance.example.org")
+
+@pytest.fixture
+def organization(instance):
return Organization.objects.create(name="test-org", description="test-org-desc")
@pytest.fixture
@@ -92,3 +103,30 @@ def permissions():
'update':False, 'delete':False, 'scm_update':False, 'execute':False, 'use':True,},
}
+@pytest.fixture
+def post():
+ def rf(_cls, _user, _url, pk=None, kwargs={}, middleware=None):
+ view = _cls.as_view()
+ request = APIRequestFactory().post(_url, kwargs, format='json')
+ if middleware:
+ middleware.process_request(request)
+ force_authenticate(request, user=_user)
+ response = view(request, pk=pk)
+ if middleware:
+ middleware.process_response(request, response)
+ return response
+ return rf
+
+@pytest.fixture
+def get():
+ def rf(_cls, _user, _url, pk=None, middleware=None):
+ view = _cls.as_view()
+ request = APIRequestFactory().get(_url, format='json')
+ if middleware:
+ middleware.process_request(request)
+ force_authenticate(request, user=_user)
+ response = view(request, pk=pk)
+ if middleware:
+ middleware.process_response(request, response)
+ return response
+ return rf
diff --git a/awx/main/tests/functional/test_activity_streams.py b/awx/main/tests/functional/test_activity_streams.py
new file mode 100644
index 0000000000..cf2f81c9d9
--- /dev/null
+++ b/awx/main/tests/functional/test_activity_streams.py
@@ -0,0 +1,61 @@
+import mock
+import pytest
+
+from awx.api.views import (
+ ActivityStreamList,
+ ActivityStreamDetail,
+ OrganizationList,
+)
+from awx.main.middleware import ActivityStreamMiddleware
+from awx.main.models.activity_stream import ActivityStream
+from django.core.urlresolvers import reverse
+
+def mock_feature_enabled(feature, bypass_database=None):
+ return True
+
+@mock.patch('awx.api.views.feature_enabled', new=mock_feature_enabled)
+@pytest.mark.django_db
+def test_get_activity_stream_list(monkeypatch, organization, get, user):
+ url = reverse('api:activity_stream_list')
+ response = get(ActivityStreamList, user('admin', True), url)
+
+ assert response.status_code == 200
+
+@mock.patch('awx.api.views.feature_enabled', new=mock_feature_enabled)
+@pytest.mark.django_db
+def test_basic_fields(monkeypatch, organization, get, user):
+ u = user('admin', True)
+ activity_stream = ActivityStream.objects.latest('pk')
+ activity_stream.actor = u
+ activity_stream.save()
+
+ aspk = activity_stream.pk
+ url = reverse('api:activity_stream_detail', args=(aspk,))
+ response = get(ActivityStreamDetail, user('admin', True), url, pk=aspk)
+
+ assert response.status_code == 200
+ assert 'related' in response.data
+ assert 'organization' in response.data['related']
+ assert 'summary_fields' in response.data
+ assert 'organization' in response.data['summary_fields']
+ assert response.data['summary_fields']['organization'][0]['name'] == 'test-org'
+
+@mock.patch('awx.api.views.feature_enabled', new=mock_feature_enabled)
+@pytest.mark.django_db
+def test_middleware_actor_added(monkeypatch, post, get, user):
+ u = user('admin-poster', True)
+
+ url = reverse('api:organization_list')
+ response = post(OrganizationList, u, url,
+ kwargs=dict(name='test-org', description='test-desc'),
+ middleware=ActivityStreamMiddleware())
+ assert response.status_code == 201
+
+ org_id = response.data['id']
+ activity_stream = ActivityStream.objects.filter(organization__pk=org_id).first()
+
+ url = reverse('api:activity_stream_detail', args=(activity_stream.pk,))
+ response = get(ActivityStreamDetail, u, url, pk=activity_stream.pk)
+
+ assert response.status_code == 200
+ assert response.data['summary_fields']['actor']['username'] == 'admin-poster'
diff --git a/awx/main/tests/old/activity_stream.py b/awx/main/tests/old/activity_stream.py
deleted file mode 100644
index 9798695954..0000000000
--- a/awx/main/tests/old/activity_stream.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2015 Ansible, Inc.
-# All Rights Reserved.
-
-# Python
-from django.core.urlresolvers import reverse
-
-# AWX
-from awx.main.models import * # noqa
-from awx.main.tests.base import BaseTest
-
-class ActivityStreamTest(BaseTest):
-
- def collection(self):
- return reverse('api:activity_stream_list')
-
- def item(self, item_id):
- return reverse('api:activity_stream_detail', args=(item_id,))
-
- def setUp(self):
- super(ActivityStreamTest, self).setUp()
- self.setup_instances()
- self.create_test_license_file()
- # TODO: Test non-enterprise license
- self.setup_users()
- self.org_created = self.post(reverse('api:organization_list'), dict(name='test org', description='test descr'), expect=201, auth=self.get_super_credentials())
-
- def test_get_activity_stream_list(self):
- url = self.collection()
-
- with self.current_user(self.super_django_user):
- self.options(url, expect=200)
- self.head(url, expect=200)
- response = self.get(url, expect=200)
- self.check_pagination_and_size(response, 1, previous=None, next=None)
-
- def test_basic_fields(self):
- item_id = ActivityStream.objects.order_by('pk')[0].pk
- org_item = self.item(item_id)
-
- with self.current_user(self.super_django_user):
- response = self.get(org_item, expect=200)
-
- self.assertTrue("related" in response)
- self.assertTrue("organization" in response['related'])
- self.assertTrue("summary_fields" in response)
- self.assertTrue("organization" in response['summary_fields'])
- self.assertTrue(response['summary_fields']['organization'][0]['name'] == self.org_created['name'])
-
- def test_changeby_user(self):
- item_id = ActivityStream.objects.order_by('pk')[0].pk
- org_item = self.item(item_id)
-
- with self.current_user(self.super_django_user):
- response = self.get(org_item, expect=200)
- self.assertEqual(response['summary_fields']['actor']['username'], self.super_django_user.username)
diff --git a/awx/main/tests/old/organizations.py b/awx/main/tests/old/organizations.py
index cf3c64ab87..b3d84a5da4 100644
--- a/awx/main/tests/old/organizations.py
+++ b/awx/main/tests/old/organizations.py
@@ -262,7 +262,9 @@ class OrganizationsTest(BaseTest):
data1 = self.post(self.collection(), new_org, expect=201, auth=self.get_super_credentials())
# duplicate post results in 400
- self.post(self.collection(), new_org, expect=400, auth=self.get_super_credentials())
+ response = self.post(self.collection(), new_org, expect=400, auth=self.get_super_credentials())
+ self.assertTrue('name' in response, response)
+ self.assertTrue('Name' in response['name'][0], response)
# look at what we got back from the post, make sure we added an org
last_org = Organization.objects.order_by('-pk')[0]
diff --git a/awx/main/tests/old/projects.py b/awx/main/tests/old/projects.py
index b0a32ad6a5..45c96ca587 100644
--- a/awx/main/tests/old/projects.py
+++ b/awx/main/tests/old/projects.py
@@ -231,12 +231,19 @@ class ProjectsTest(BaseTransactionTest):
'description': 'Does amazing things',
'local_path': os.path.basename(project_dir),
'scm_type': None,
+ 'scm_update_on_launch': '',
+ 'scm_delete_on_update': None,
+ 'scm_clean': False,
}
# Adding a project with scm_type=None should work, but scm_type will be
- # changed to an empty string.
+ # changed to an empty string. Other boolean fields should accept null
+ # or an empty string for False, but save the value as a boolean.
response = self.post(projects, project_data, expect=201,
auth=self.get_super_credentials())
self.assertEqual(response['scm_type'], u'')
+ self.assertEqual(response['scm_update_on_launch'], False)
+ self.assertEqual(response['scm_delete_on_update'], False)
+ self.assertEqual(response['scm_clean'], False)
# can edit project using same local path.
project_detail = reverse('api:project_detail', args=(response['id'],))
@@ -494,7 +501,9 @@ class ProjectsTest(BaseTransactionTest):
ssh_key_data = TEST_SSH_KEY_DATA_LOCKED,
ssh_key_unlock = TEST_SSH_KEY_DATA_UNLOCK,
ssh_password = 'narf',
- sudo_password = 'troz'
+ sudo_password = 'troz',
+ security_token = '',
+ vault_password = None,
)
# can add credentials to a user (if user or org admin or super user)
@@ -561,13 +570,17 @@ class ProjectsTest(BaseTransactionTest):
# Repeating the same POST should violate a unique constraint.
with self.current_user(self.super_django_user):
data = dict(name='xyz', user=self.super_django_user.pk)
- self.post(url, data, expect=400)
+ response = self.post(url, data, expect=400)
+ self.assertTrue('__all__' in response, response)
+ self.assertTrue('already exists' in response['__all__'][0], response)
- # Test with null where we expect a string value.
+ # Test with null where we expect a string value. Value will be coerced
+ # to an empty string.
with self.current_user(self.super_django_user):
data = dict(name='zyx', user=self.super_django_user.pk, kind='ssh',
become_username=None)
- self.post(url, data, expect=400)
+ response = self.post(url, data, expect=201)
+ self.assertEqual(response['become_username'], '')
# Test with encrypted ssh key and no unlock password.
with self.current_user(self.super_django_user):
@@ -698,14 +711,15 @@ class ProjectsTest(BaseTransactionTest):
# user=user.pk, # no need to specify, this will be automatically filled in
inventory=inventory.pk,
project=project.pk,
- permission_type=PERM_INVENTORY_DEPLOY
+ permission_type=PERM_INVENTORY_DEPLOY,
+ run_ad_hoc_commands=None,
)
team_permission = dict(
name='team can deploy a certain project to a certain inventory',
# team=team.pk, # no need to specify, this will be automatically filled in
inventory=inventory.pk,
project=project.pk,
- permission_type=PERM_INVENTORY_DEPLOY
+ permission_type=PERM_INVENTORY_DEPLOY,
)
url = reverse('api:user_permissions_list', args=(user.pk,))
diff --git a/awx/main/tests/old/settings.py b/awx/main/tests/old/settings.py
index 3f08bd1a7a..f0d7cf63ac 100644
--- a/awx/main/tests/old/settings.py
+++ b/awx/main/tests/old/settings.py
@@ -35,6 +35,13 @@ TEST_TOWER_SETTINGS_MANIFEST = {
"default": ["A", "Simple", "List"],
"type": "list",
"category": "test"
+ },
+ "TEST_SETTING_JSON": {
+ "name": "A JSON Field",
+ "description": "A JSON Field",
+ "default": {"key": "value", "otherkey": ["list", "of", "things"]},
+ "type": "json",
+ "category": "test"
}
}
@@ -46,7 +53,7 @@ class SettingsTest(BaseTest):
self.setup_instances()
self.setup_users()
- def get_settings(self, expected_count=4):
+ def get_settings(self, expected_count=5):
result = self.get(reverse('api:settings_list'), expect=200)
self.assertEqual(result['count'], expected_count)
return result['results']
@@ -74,21 +81,29 @@ class SettingsTest(BaseTest):
with self.current_user(self.super_django_user):
self.get_settings(expected_count=len(TEST_TOWER_SETTINGS_MANIFEST))
- def test_set_and_reset_settings(self):
+ def set_and_reset_setting(self, key, values, expected_values=()):
settings_reset = reverse('api:settings_reset')
+ setting = self.get_individual_setting(key)
+ self.assertEqual(setting['value'], TEST_TOWER_SETTINGS_MANIFEST[key]['default'])
+ for n, value in enumerate(values):
+ self.set_setting(key, value)
+ setting = self.get_individual_setting(key)
+ if len(expected_values) > n:
+ self.assertEqual(setting['value'], expected_values[n])
+ else:
+ self.assertEqual(setting['value'], value)
+ self.post(settings_reset, data={"key": key}, expect=204)
+ setting = self.get_individual_setting(key)
+ self.assertEqual(setting['value'], TEST_TOWER_SETTINGS_MANIFEST[key]['default'])
+
+ def test_set_and_reset_settings(self):
with self.current_user(self.super_django_user):
- # Set and reset a single setting
- setting_int = self.get_individual_setting('TEST_SETTING_INT')
- self.assertEqual(setting_int['value'], TEST_TOWER_SETTINGS_MANIFEST['TEST_SETTING_INT']['default'])
- self.set_setting('TEST_SETTING_INT', 2)
- setting_int = self.get_individual_setting('TEST_SETTING_INT')
- self.assertEqual(setting_int['value'], 2)
- self.set_setting('TEST_SETTING_INT', 3)
- setting_int = self.get_individual_setting('TEST_SETTING_INT')
- self.assertEqual(setting_int['value'], 3)
- self.post(settings_reset, data={"key": 'TEST_SETTING_INT'}, expect=204)
- setting_int = self.get_individual_setting('TEST_SETTING_INT')
- self.assertEqual(setting_int['value'], TEST_TOWER_SETTINGS_MANIFEST['TEST_SETTING_INT']['default'])
+ self.set_and_reset_setting('TEST_SETTING_INT', (2, 0))
+ self.set_and_reset_setting('TEST_SETTING_STRING', ('blah', '', u'\u2620'))
+ self.set_and_reset_setting('TEST_SETTING_BOOL', (True, False))
+ # List values are always saved as strings.
+ self.set_and_reset_setting('TEST_SETTING_LIST', ([4, 5, 6], [], [2]), (['4', '5', '6'], [], ['2']))
+ self.set_and_reset_setting('TEST_SETTING_JSON', ({"k": "v"}, {}, [], [7, 8], 'str'))
def test_clear_all_settings(self):
settings_list = reverse('api:settings_list')
@@ -97,6 +112,7 @@ class SettingsTest(BaseTest):
self.set_setting('TEST_SETTING_STRING', "foo")
self.set_setting('TEST_SETTING_BOOL', False)
self.set_setting('TEST_SETTING_LIST', [1,2,3])
+ self.set_setting('TEST_SETTING_JSON', '{"key": "new value"}')
all_settings = self.get_settings()
for setting_entry in all_settings:
self.assertNotEqual(setting_entry['value'],
diff --git a/awx/main/tests/old/users.py b/awx/main/tests/old/users.py
index c4ec3a87f1..42285ff588 100644
--- a/awx/main/tests/old/users.py
+++ b/awx/main/tests/old/users.py
@@ -207,6 +207,8 @@ class UsersTest(BaseTest):
self.post(url, expect=403, data=new_super_user, auth=self.get_other_credentials())
self.post(url, expect=403, data=new_super_user, auth=self.get_normal_credentials())
self.post(url, expect=201, data=new_super_user, auth=self.get_super_credentials())
+ new_super_user2 = dict(username='nommy2', password='cookie', is_superuser=None)
+ self.post(url, expect=201, data=new_super_user2, auth=self.get_super_credentials())
def test_auth_token_login(self):
auth_token_url = reverse('api:auth_token_view')
diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py
index d8d1fbc9fc..36f39ac3ec 100644
--- a/awx/settings/defaults.py
+++ b/awx/settings/defaults.py
@@ -226,6 +226,7 @@ REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'awx.api.views.api_exception_handler',
'VIEW_NAME_FUNCTION': 'awx.api.generics.get_view_name',
'VIEW_DESCRIPTION_FUNCTION': 'awx.api.generics.get_view_description',
+ 'NON_FIELD_ERRORS_KEY': '__all__',
}
AUTHENTICATION_BACKENDS = (
diff --git a/awx/static/api/api.css b/awx/static/api/api.css
index 0a297f5b89..509d604f2f 100644
--- a/awx/static/api/api.css
+++ b/awx/static/api/api.css
@@ -11,25 +11,39 @@ body {
body {
font-family: 'Open Sans', sans-serif;
font-weight: 400;
- color: #171717;
- background-color: #f6f6f6;
+ color: #161B1F;
+ background-color: #F6F6F6;
padding-top: 50px;
min-height: 100%;
position: relative;
}
+body a {
+ color: #1678C4;
+}
+body a:hover {
+ color: #4498DA;
+}
+body code {
+ color: #FF5850;
+ background-color: #FFF5F5;
+}
+body pre code {
+ color: inherit;
+ background-color: transparent;
+}
body .navbar {
background-color: #FFFFFF;
border-color: #E8E8E8;
}
body .navbar .navbar-brand {
- color: #707070;
+ color: #848992;
padding: 0;
font-size: 14px;
}
body .navbar .navbar-brand:focus,
body .navbar .navbar-brand:hover {
- color: #707070;
+ color: #848992;
}
body .navbar .navbar-brand img {
display: inline-block;
@@ -45,7 +59,7 @@ body .navbar .navbar-brand > span {
body .navbar .navbar-title {
float: left;
height: 50px;
- color: #707070;
+ color: #848992;
padding: 0;
font-size: 14px;
display: none;
@@ -60,11 +74,19 @@ body.show-title .navbar .navbar-title {
}
body .navbar .navbar-nav > li > a {
color: #848992;
+ display: flex;
+ justify-content: center;
}
body .navbar .navbar-nav > li > a:focus,
body .navbar .navbar-nav > li > a:hover {
color: #848992;
}
+body .navbar .navbar-nav > li > a > span.glyphicon {
+ font-size: 20px;
+ padding-right: 5px;
+ padding-left: 5px;
+ color: #B7B7B7;
+}
body .page-header {
margin-top: 20px;
@@ -77,6 +99,17 @@ body .page-header .toggle-description span.glyphicon {
font-size: 14px;
vertical-align: top;
padding: 2px;
+ color: #A9A9A9;
+}
+body .page-header .toggle-description:hover span.glyphicon {
+ color: #171717;
+}
+body .description .hide-description span.glyphicon {
+ color: #E1E1E1;
+ font-size: 20px;
+}
+body .description .hide-description:hover span.glyphicon {
+ color: #B7B7B7;
}
body ul.breadcrumb,
body .description,
@@ -103,6 +136,18 @@ body .resource-description,
body .response-info {
margin-bottom: 0;
}
+body pre,
+body .prettyprint .pln,
+body .request-info .prettyprint .lit {
+ color: #161B1F;
+}
+body .prettyprint .lit {
+ color: #1678C4;
+}
+body .prettyprint .str {
+ color: #FF5850;
+}
+
body .well.tab-content {
padding: 20px;
}
@@ -118,6 +163,110 @@ body .form-group {
body .form-actions button {
margin-left: 5px;
}
+body .form-horizontal .control-label {
+ text-transform: uppercase;
+ font-weight: normal;
+ color: #848992;
+}
+body textarea.form-control {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+ font-size: 12px;
+ padding: 6px;
+}
+body .form-control,
+body .description pre {
+ border-color: #E1E1E1;
+ background-color: #F6F6F6;
+ color: #161B1F;
+}
+
+body .tooltip.bottom .tooltip-arrow {
+ border-bottom-color: #848992;
+}
+body .tooltip.top .tooltip-arrow {
+ border-top-color: #848992;
+}
+body .tooltip.left .tooltip-arrow {
+ border-left-color: #848992;
+}
+body .tooltip.right .tooltip-arrow {
+ border-right-color: #848992;
+}
+body .tooltip.in {
+ opacity: 1;
+}
+body .tooltip-inner {
+ background-color: #848992;
+}
+
+body .btn {
+ transition: background-color 0.2s;
+}
+.btn-primary {
+ background-color: #FFFFFF;
+ color: #848992;
+ border: 1px solid #E8E8E8;
+}
+.btn-primary:hover,
+.btn-primary.focus,
+.btn-primary:focus,
+.btn-primary.active,
+.btn-primary:active,
+.btn-primary.active.focus,
+.btn-primary.active:focus,
+.btn-primary.active:hover,
+.btn-primary:active.focus,
+.btn-primary:active:focus,
+.btn-primary:active:hover,
+.open>.dropdown-toggle.btn-primary.focus,
+.open>.dropdown-toggle.btn-primary:focus,
+.open>.dropdown-toggle.btn-primary:hover,
+.open>.dropdown-toggle.btn-primary {
+ background-color: #FAFAFA;
+ color: #848992;
+ border: 1px solid #E8E8E8;
+}
+
+body .tab-content .btn-primary {
+ background-color: #3CB878;
+ color: #FFFFFF;
+ border: 1px solid #3CB878;
+}
+body .tab-content .btn-primary:hover,
+body .tab-content .btn-primary.focus,
+body .tab-content .btn-primary:focus,
+body .tab-content .btn-primary.active,
+body .tab-content .btn-primary:active,
+body .tab-content .btn-primary.active.focus,
+body .tab-content .btn-primary.active:focus,
+body .tab-content .btn-primary.active:hover,
+body .tab-content .btn-primary:active.focus,
+body .tab-content .btn-primary:active:focus,
+body .tab-content .btn-primary:active:hover {
+ background-color: #60D66F;
+ color: #FFFFFF;
+ border: 1px solid #60D66F;
+}
+
+.btn-danger {
+ background-color: #FF5850;
+ border-color: #FF5850;
+}
+.btn-danger:hover,
+.btn-danger:hover,
+.btn-danger.focus,
+.btn-danger:focus,
+.btn-danger.active,
+.btn-danger:active,
+.btn-danger.active.focus,
+.btn-danger.active:focus,
+.btn-danger.active:hover,
+.btn-danger:active.focus,
+.btn-danger:active:focus,
+.btn-danger:active:hover {
+ background-color: #FF1105;
+ border-color: #FF1105;
+}
body .wrapper {
min-height: 100%;
@@ -170,20 +319,28 @@ body #footer .footer-copyright a {
display: none;
}
body .navbar .navbar-toggle {
- background-color: #337ab7;
- border-color: #2e6da4;
+ background-color: #FFFFFF;
+ border-color: #E8E8E8;
}
body .navbar .navbar-toggle:active,
body .navbar .navbar-toggle:hover {
- background-color: #286090;
- border-color: #204d74;
+ background-color: #FAFAFA;
+ border-color: #E8E8E8;
}
body .navbar .navbar-toggle .icon-bar {
- background-color: #fff;
+ background-color: #B7B7B7;
}
body .navbar .tooltip {
visibility: hidden;
}
+ body .navbar .navbar-nav > li > a {
+ display: block;
+ padding-top: 8px;
+ padding-bottom: 12px;
+ }
+ body .navbar .navbar-nav > li > a > span.glyphicon {
+ top: 4px;
+ }
body .page-header h1 {
font-size: 24px;
}
diff --git a/awx/static/api/api.js b/awx/static/api/api.js
index bce915a247..177770fb8f 100644
--- a/awx/static/api/api.js
+++ b/awx/static/api/api.js
@@ -6,6 +6,10 @@
$(function() {
+ // Add syntax highlighting to examples in description.
+ $('.description pre').addClass('prettyprint');
+ prettyPrint();
+
// Make links from relative URLs to resources.
$('span.str').each(function() {
var s = $(this).html();
diff --git a/awx/templates/rest_framework/api.html b/awx/templates/rest_framework/api.html
index bdd3123dac..7ae3c811f8 100644
--- a/awx/templates/rest_framework/api.html
+++ b/awx/templates/rest_framework/api.html
@@ -17,7 +17,7 @@
{{ block.super }}
diff --git a/awx/ui/client/legacy-styles/ansible-ui.less b/awx/ui/client/legacy-styles/ansible-ui.less
index 57b8adebc4..a9c4e6fc85 100644
--- a/awx/ui/client/legacy-styles/ansible-ui.less
+++ b/awx/ui/client/legacy-styles/ansible-ui.less
@@ -774,10 +774,6 @@ select.page-size {
vertical-align: middle;
}
- #search_value_input {
- padding-right: 25px;
- }
-
#search-widget-spacer {
height: 20px;
}
diff --git a/awx/ui/client/legacy-styles/forms.less b/awx/ui/client/legacy-styles/forms.less
index c8f034cc32..8c3de00020 100644
--- a/awx/ui/client/legacy-styles/forms.less
+++ b/awx/ui/client/legacy-styles/forms.less
@@ -141,13 +141,20 @@
padding-right: 50px;
}
-.Form-textArea{
+.Form-textAreaLabel{
width:100%;
}
+.Form-textArea{
+ background-color: @field-secondary-bg!important;
+ background-color: @field-secondary-bg!important;
+ border-radius: 5px;
+ color: @field-input-text;
+}
+
.Form-textInput{
- height: 30px;
- background-color: @field-secondary-bg;
+ height: 30px!important;
+ background-color: @field-secondary-bg!important;
border-radius: 5px;
border:1px solid @field-border;
color: @field-input-text;
@@ -157,9 +164,146 @@
border:1px solid @field-border-sel;
}
+.ui-spinner{
+ height: 30px;
+ background-color: @field-secondary-bg;
+ border-radius: 5px;
+ border:1px solid @field-border;
+ color: @field-input-text;
+}
+
+.ui-spinner-input{
+ color: @field-input-text;
+ background-color: @field-secondary-bg;
+}
+
+.ui-spinner-input:focus{
+ outline: none;
+}
+
+.ui-spinner-button{
+ border-left:1px solid @field-border!important;
+ background-color: @field-button-bg !important;
+}
+
+.ui-spinner-button:hover{
+ background-color:@field-button-hov !important;
+ cursor: pointer!important;
+}
+
+.Form-numberInputButton{
+ color: @field-label!important;
+ font-size: 14px;
+
+}
+
+.Form-dropDown {
+ height: 30px !important;
+ background-color: @field-secondary-bg!important;
+ border-radius: 5px !important;
+ border:1px solid @field-border!important;
+ color: @field-input-text!important;
+}
+
+.select2-selection__arrow{
+ border-left:1px solid @field-border;
+ border-bottom-right-radius: 5px;
+ border-top-right-radius: 5px;
+ background-color: @field-button-bg !important;
+ width: 30px!important;
+ height: 28px!important;
+}
+
+.select2-selection__arrow:hover{
+ background-color:@field-button-hov !important;
+}
+
+.select2-results__option{
+ color: @field-label !important;
+ height: 30px!important;
+}
+
+.select2-container--default .select2-results__option--highlighted[aria-selected]{
+ background-color: @field-button-hov !important;
+}
+
+.select2-container--default .select2-results__option[aria-selected=true]{
+ background-color: @field-border !important;
+}
+
+.select2-container--default .select2-selection--single .select2-selection__arrow b{
+ border-color: @field-dropdown-icon transparent transparent transparent !important;
+}
+
+.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{
+ border-color: transparent transparent @field-dropdown-icon transparent!important;
+}
+
+.select2-dropdown{
+ border:1px solid @field-border;
+}
+
+.Form-dropDown:focus{
+ outline: none!important;
+}
+
+.Form-dropDown--scmType{
+ width: 100%;
+}
+
+.Form-passwordButton{
+ height: 30px;
+ color: @field-lookup-btn-icon!important;
+ text-transform: uppercase;
+ line-height: 1;
+ padding-left: 7px;
+ padding-right: 7px;
+ background-color: @field-lookup-btn-bg;
+ border:1px solid @field-border;
+}
+
+.Form-passwordButton:hover {
+ cursor: pointer;
+ background-color: @field-lookup-btn-hov-bg;
+ border: 1px solid @field-border;
+ color: @field-lookup-btn-icon;
+}
+
+.Form-passwordButton:focus{
+ border: 1px solid @field-border;
+ background-color: @field-lookup-btn-hov-bg;
+}
+
+.Form-passwordButton:active {
+ border: 1px solid @field-border;
+ background-color: @field-lookup-btn-hov-bg;
+}
+
+.Form-lookupButton {
+ height: 30px;
+ width: 30px;
+ color: @field-lookup-btn-icon!important;
+ font-size: 16px;
+ background-color: @field-lookup-btn-bg;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border:1px solid @field-border;
+}
+
+.Form-lookupButton:hover {
+ cursor: pointer;
+ background-color: @field-lookup-btn-hov-bg;
+ border: 1px solid @field-border;
+ color: @field-lookup-btn-icon;
+}
+
+.Form-lookupButton:focus {
+ border: 1px solid @field-border;
+}
+
.CodeMirror{
border-radius: 5px;
- font-family: 'Open Sans';
font-style: normal;
color: @field-input-text;
}
@@ -206,6 +350,7 @@ input[type='radio']:checked:before {
font-weight: normal;
font-size: small;
padding-right:5px;
+ width: 100%;
}
.Form-buttons{
diff --git a/awx/ui/client/legacy-styles/lists.less b/awx/ui/client/legacy-styles/lists.less
index 0dd92dbdff..020d306dfc 100644
--- a/awx/ui/client/legacy-styles/lists.less
+++ b/awx/ui/client/legacy-styles/lists.less
@@ -173,6 +173,16 @@ table, tbody {
justify-content: flex-end;
display: flex;
margin-top: -10px;
+ margin-left: 10px;
+}
+
+.List-auxAction {
+ justify-content: flex-end;
+ display: flex;
+}
+
+.List-auxActionStream {
+ width: 175px;
}
.List-buttonSubmit {
@@ -201,6 +211,28 @@ table, tbody {
.List-searchDropdown {
border-top-left-radius: 5px!important;
border-bottom-left-radius: 5px!important;
+ height: 34px!important;
+ border-color: @default-second-border;
+ color: @default-icon;
+ background-color: @default-bg;
+ border-right: none;
+}
+
+.List-searchDropdown:focus,
+.List-searchDropdown:active,
+.List-searchDropdown.active
+{
+ color: @default-icon;
+ background-color: @default-tertiary-bg;
+}
+
+.List-searchDropdown:hover {
+ background-color: @default-tertiary-bg;
+ color: @default-icon;
+}
+
+.List-searchDropdownCarat {
+ border-top-color: @default-icon!important;
}
.List-searchInput {
@@ -208,8 +240,10 @@ table, tbody {
font-size: 14px!important;
color: @list-srch-inpt-txt!important;
border-color: @list-srch-inpt-bord!important;
- border-radius: 5px!important;
+ border-radius: 0px 5px 5px 0px!important;
padding-left: 15px!important;
+ height: 34px!important;
+ padding-right: 45px!important;
}
.List-searchInput:placeholder-shown {
@@ -229,7 +263,7 @@ table, tbody {
float: right;
position: relative;
top: -33px;
- left: -1px;
+ left: -2px;
z-index: 10;
font-size: 16px;
background-color: @list-srch-btn-bg;
@@ -260,6 +294,7 @@ table, tbody {
border: 1px solid @list-no-items-bord;
background-color: @list-no-items-bg;
color: @list-no-items-txt;
+ text-transform: uppercase;
}
.List-editButton--selected {
@@ -285,6 +320,15 @@ table, tbody {
padding-right: 0px!important;
}
+.List-staticColumn--toggle {
+ width: 55px;
+ padding-right: 0px !important;
+}
+
+.List-staticColumn--schedulerTime {
+ max-width: 164px;
+}
+
.List-staticColumnAdjacent {
padding-left: 10px!important;
}
diff --git a/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js b/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js
index a45cfcab31..7ed581a09f 100644
--- a/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js
+++ b/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js
@@ -406,6 +406,13 @@ angular.module('AngularScheduler', ['underscore'])
return validity;
};
+
+ var that = this;
+
+ that.scope.$on("loadSchedulerDetailPane", function() {
+ that.isValid();
+ });
+
// Returns an rrule object
this.getRRule = function() {
var options = this.getOptions();
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/.bower.json b/awx/ui/client/lib/select2-bootstrap-theme/.bower.json
deleted file mode 100644
index 545b43c759..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/.bower.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "select2-bootstrap-theme",
- "version": "0.1.0-beta.4",
- "main": [
- "dist/select2-bootstrap.css",
- "dist/select2-bootstrap.min.css"
- ],
- "ignore": [
- "**/.*",
- "node_modules",
- "components"
- ],
- "devDependencies": {
- "bootstrap": "~3.3.5",
- "bootstrap-sass-official": "~3.3.5",
- "respond": "~1.4.2",
- "anchor-js": "~1.1.1"
- },
- "homepage": "https://github.com/fk/select2-bootstrap-theme",
- "_release": "0.1.0-beta.4",
- "_resolution": {
- "type": "version",
- "tag": "0.1.0-beta.4",
- "commit": "2fe20fd58120bf323fb6846d99ca91e6dbf11109"
- },
- "_source": "git://github.com/fk/select2-bootstrap-theme.git",
- "_target": "~0.1.0-beta.4",
- "_originalSource": "select2-bootstrap-theme",
- "_direct": true
-}
\ No newline at end of file
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/Gruntfile.js b/awx/ui/client/lib/select2-bootstrap-theme/Gruntfile.js
deleted file mode 100755
index d2c9b9bfe5..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/Gruntfile.js
+++ /dev/null
@@ -1,128 +0,0 @@
-module.exports = function(grunt) {
- // Load all grunt tasks.
- require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
-
- // Project configuration.
- grunt.initConfig({
- nodeunit: {
- all: ['tests/*_test.js']
- },
-
- sass: {
- options: {
- style: 'expanded',
- sourcemap: 'none',
- // Increase Sass' default (5) precision to 9 to match Less output.
- //
- // @see https://github.com/twbs/bootstrap-sass#sass-number-precision
- // @see https://github.com/sass/node-sass/issues/673#issue-57581701
- // @see https://github.com/sass/sass/issues/1122
- precision: 9
- },
- dist: {
- files: {
- 'docs/css/select2-bootstrap.css': 'src/build.scss',
- 'dist/select2-bootstrap.css': 'src/build.scss'
- }
- },
- test: {
- files: {
- 'tmp/select2-bootstrap.css': 'src/build.scss'
- }
- }
- },
-
- cssmin: {
- target: {
- files: {
- 'dist/select2-bootstrap.min.css': 'dist/select2-bootstrap.css'
- }
- }
- },
-
- jshint: {
- all: ['Gruntfile.js', '*.json']
- },
-
- bump: {
- options: {
- files: [
- 'package.json',
- 'bower.json'
- ],
- push: false,
- createTag: false
- }
- },
-
- copy: {
- main: {
- files: [
- {
- src: 'bower_components/bootstrap/dist/css/bootstrap.min.css',
- dest: 'docs/css/bootstrap.min.css',
- expand: false
- },
- {
- src: 'bower_components/bootstrap/dist/js/bootstrap.min.js',
- dest: 'docs/js/bootstrap.min.js',
- expand: false
- },
- {
- src: 'bower_components/respond/dest/respond.min.js',
- dest: 'docs/js/respond.min.js',
- expand: false
- },
- {
- cwd: 'bower_components/bootstrap/dist/fonts',
- src: ['**/*'],
- dest: 'docs/fonts',
- expand: true
- },
- {
- src: 'bower_components/anchor-js/anchor.min.js',
- dest: 'docs/js/anchor.min.js',
- expand: false
- }
- ]
- }
- },
-
- 'gh-pages': {
- options: {
- base: 'docs/_site',
- message: 'Update gh-pages.'
- },
- src: ['**/*']
- },
-
- jekyll: {
- options: {
- src: 'docs',
- dest: 'docs/_site',
- sourcemaps: false
- },
- build: {
- d: null
- },
- serve: {
- options: {
- serve: true,
- watch: true
- }
- }
- },
-
- watch: {
- files: 'src/select2-bootstrap.scss',
- tasks: ['sass'],
- options: {
- livereload: true
- }
- }
- });
-
- // Default tasks.
- grunt.registerTask('build', ['sass', 'cssmin', 'copy', 'jekyll:build']);
- grunt.registerTask('serve', ['jekyll:serve']);
-};
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/LICENSE b/awx/ui/client/lib/select2-bootstrap-theme/LICENSE
deleted file mode 100755
index 406d19a3c3..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2012-2015 Florian Kissling and contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/README.md b/awx/ui/client/lib/select2-bootstrap-theme/README.md
deleted file mode 100755
index 52a4793dff..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/README.md
+++ /dev/null
@@ -1,58 +0,0 @@
-A Select2 v4 [Theme](https://select2.github.io/examples.html#themes) for Bootstrap 3
-
-**Note: Work in progress – depending on your use case, select2-bootstrap-theme might not be production-ready yet!**
-
-Demonstrations available at
-http://select2.github.io/select2-bootstrap-theme/
-
-Tested with Bootstrap v3.3.5 and Select2 v4.0.0
-in latest Chrome.
-
-##### Installation
-
-The Select2 Bootstrap Theme only works with Select2 v4.x. Applying the theme requires `select2-bootstrap.css` referenced after the default `select2.css` that comes with Select2:
-
-
-
-
-To apply the theme, tell Select2 to do so by passing `bootstrap` to the [`theme`](https://select2.github.io/examples.html#themes) option when initializing Select2:
-
- $( "#dropdown" ).select2({
- theme: "bootstrap"
- });
-
-##### Changelog
-
-###### 0.1.0-beta.4
-
- * Added missing styles for `.select2-container--focus`. [[#18](https://github.com/select2/select2-bootstrap-theme/issues/18)]
- * Added support for Bootstrap's [`.form-inline`](http://getbootstrap.com/css/#forms-inline). [[#13](https://github.com/select2/select2-bootstrap-theme/pull/13)]
- * Added basic styles for `.select2-selection__clear` in `.select2-selection--multiple`. [[#11](https://github.com/select2/select2-bootstrap-theme/issues/11)]
- * Brought Less source in line with the Sass version and fixed Less patch file and test. [[`3e86f34](https://github.com/select2/select2-bootstrap-theme/commit/3e86f34f6c94302cd8b4d6c3d751c5fb70fe61f6)]
-
-###### 0.1.0-beta.3
-
- * Fixed specifity problems with `.form-control.select2-hidden-accessible`.
-
-###### 0.1.0-beta.2
-
- * Added Less version.
-
-###### 0.1.0-beta.1
-
-##### Contributing
-
-The project offers [Less](http://lesscss.org/) and [Sass](http://sass-lang.com/) sources for building `select2-bootstrap.css`; both make use of variables from either [Bootstrap](https://github.com/twbs/bootstrap) (Less) or [Bootstrap for Sass](https://github.com/twbs/bootstrap-sass). The demo pages are built using [Jekyll](http://jekyllrb.com/) and there are a bunch of [Grunt](http://gruntjs.com/) tasks to ease development.
-
-With [Ruby](https://www.ruby-lang.org/en/downloads/) and [RubyGems](http://rubygems.org/pages/download), [Jekyll](http://jekyllrb.com/), [Bower](http://bower.io/), [node.js](http://nodejs.org/), [Less](http://lesscss.org/) and [Sass](http://sass-lang.com/) installed, run
-
- npm install && bower install
-
-to install all necessary development dependencies.
-
- * `grunt copy` copies assets from `components` to `_jekyll` – use this in case a new version of Twitter Bootstrap or Select2 are out and need to be tested
- * `grunt build` builds `docs`
- * `grunt serve` builds `docs` and serves them via Jekyll's `--watch` flag on http://localhost:4000
- * `grunt watch` watches for changes in `src/select2-bootstrap.scss` ([livereload](https://github.com/gruntjs/grunt-contrib-watch#optionslivereload) is enabled)
-
-Develop in `src/select2-bootstrap.scss` and test your changes using `grunt watch` and `grunt serve`. Ideally, port your changes to `lib/select2-bootstrap.less` and make sure tests are passing to verify that Less and Sass compile down to the target CSS via `npm test`.
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/bower.json b/awx/ui/client/lib/select2-bootstrap-theme/bower.json
deleted file mode 100755
index a1933febec..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "select2-bootstrap-theme",
- "version": "0.1.0-beta.4",
- "main": [
- "dist/select2-bootstrap.css",
- "dist/select2-bootstrap.min.css"
- ],
- "ignore": [
- "**/.*",
- "node_modules",
- "components"
- ],
- "devDependencies": {
- "bootstrap": "~3.3.5",
- "bootstrap-sass-official": "~3.3.5",
- "respond": "~1.4.2",
- "anchor-js": "~1.1.1"
- }
-}
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/dist/select2-bootstrap.css b/awx/ui/client/lib/select2-bootstrap-theme/dist/select2-bootstrap.css
deleted file mode 100755
index a2385b5440..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/dist/select2-bootstrap.css
+++ /dev/null
@@ -1,598 +0,0 @@
-/*! Select2 Bootstrap Theme v0.1.0-beta.4 | MIT License | github.com/select2/select2-bootstrap-theme */
-.select2-container--bootstrap {
- display: block;
- /*------------------------------------*\
- #COMMON STYLES
- \*------------------------------------*/
- /**
- * Search field in the Select2 dropdown.
- */
- /**
- * No outline for all search fields - in the dropdown
- * and inline in multi Select2s.
- */
- /**
- * Adjust Select2's choices hover and selected styles to match
- * Bootstrap 3's default dropdown styles.
- *
- * @see http://getbootstrap.com/components/#dropdowns
- */
- /**
- * Clear the selection.
- */
- /**
- * Address disabled Select2 styles.
- *
- * @see https://select2.github.io/examples.html#disabled
- * @see http://getbootstrap.com/css/#forms-control-disabled
- */
- /*------------------------------------*\
- #DROPDOWN
- \*------------------------------------*/
- /**
- * Dropdown border color and box-shadow.
- */
- /**
- * Limit the dropdown height.
- */
- /*------------------------------------*\
- #SINGLE SELECT2
- \*------------------------------------*/
- /*------------------------------------*\
- #MULTIPLE SELECT2
- \*------------------------------------*/
- /**
- * Address Bootstrap control sizing classes
- *
- * 1. Reset Bootstrap defaults.
- * 2. Adjust the dropdown arrow button icon position.
- *
- * @see http://getbootstrap.com/css/#forms-control-sizes
- */
- /* 1 */
- /*------------------------------------*\
- #RTL SUPPORT
- \*------------------------------------*/
-}
-.select2-container--bootstrap .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- background-color: #fff;
- border: 1px solid #ccc;
- border-radius: 4px;
- color: #555555;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
- outline: 0;
-}
-.select2-container--bootstrap .select2-search--dropdown .select2-search__field {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- background-color: #fff;
- border: 1px solid #ccc;
- border-radius: 4px;
- color: #555555;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
-}
-.select2-container--bootstrap .select2-search__field {
- outline: 0;
- /* Firefox 18- */
- /**
- * Firefox 19+
- *
- * @see http://stackoverflow.com/questions/24236240/color-for-styled-placeholder-text-is-muted-in-firefox
- */
-}
-.select2-container--bootstrap .select2-search__field::-webkit-input-placeholder {
- color: #999;
-}
-.select2-container--bootstrap .select2-search__field:-moz-placeholder {
- color: #999;
-}
-.select2-container--bootstrap .select2-search__field::-moz-placeholder {
- color: #999;
- opacity: 1;
-}
-.select2-container--bootstrap .select2-search__field:-ms-input-placeholder {
- color: #999;
-}
-.select2-container--bootstrap .select2-results__option {
- /**
- * Disabled results.
- *
- * @see https://select2.github.io/examples.html#disabled-results
- */
- /**
- * Hover state.
- */
- /**
- * Selected state.
- */
-}
-.select2-container--bootstrap .select2-results__option[role=group] {
- padding: 0;
-}
-.select2-container--bootstrap .select2-results__option[aria-disabled=true] {
- color: #777777;
- cursor: not-allowed;
-}
-.select2-container--bootstrap .select2-results__option[aria-selected=true] {
- background-color: #f5f5f5;
- color: #262626;
-}
-.select2-container--bootstrap .select2-results__option--highlighted[aria-selected] {
- background-color: #337ab7;
- color: #fff;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option {
- padding: 6px 12px;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__group {
- padding-left: 0;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option {
- margin-left: -12px;
- padding-left: 24px;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
- margin-left: -24px;
- padding-left: 36px;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
- margin-left: -36px;
- padding-left: 48px;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
- margin-left: -48px;
- padding-left: 60px;
-}
-.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
- margin-left: -60px;
- padding-left: 72px;
-}
-.select2-container--bootstrap .select2-results__group {
- color: #777777;
- display: block;
- padding: 6px 12px;
- font-size: 12px;
- line-height: 1.428571429;
- white-space: nowrap;
-}
-.select2-container--bootstrap.select2-container--focus .select2-selection, .select2-container--bootstrap.select2-container--open .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- border-color: #66afe9;
-}
-.select2-container--bootstrap.select2-container--open {
- /**
- * Make the dropdown arrow point up while the dropdown is visible.
- */
- /**
- * Handle border radii of the container when the dropdown is showing.
- */
-}
-.select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b {
- border-color: transparent transparent #999 transparent;
- border-width: 0 4px 4px 4px;
-}
-.select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection {
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
- border-bottom-color: transparent;
-}
-.select2-container--bootstrap.select2-container--open.select2-container--above .select2-selection {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
- border-top-color: transparent;
-}
-.select2-container--bootstrap .select2-selection__clear {
- color: #999;
- cursor: pointer;
- float: right;
- font-weight: bold;
- margin-right: 10px;
-}
-.select2-container--bootstrap .select2-selection__clear:hover {
- color: #333;
-}
-.select2-container--bootstrap.select2-container--disabled .select2-selection {
- border-color: #ccc;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.select2-container--bootstrap.select2-container--disabled .select2-selection,
-.select2-container--bootstrap.select2-container--disabled .select2-search__field {
- cursor: not-allowed;
-}
-.select2-container--bootstrap.select2-container--disabled .select2-selection,
-.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice {
- background-color: #eeeeee;
-}
-.select2-container--bootstrap.select2-container--disabled .select2-selection__clear,
-.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove {
- display: none;
-}
-.select2-container--bootstrap .select2-dropdown {
- -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- border-color: #66afe9;
- overflow-x: hidden;
- margin-top: -1px;
-}
-.select2-container--bootstrap .select2-dropdown--above {
- margin-top: 1px;
-}
-.select2-container--bootstrap .select2-results > .select2-results__options {
- max-height: 200px;
- overflow-y: auto;
-}
-.select2-container--bootstrap .select2-selection--single {
- height: 34px;
- line-height: 1.428571429;
- padding: 6px 24px 6px 12px;
- /**
- * Adjust the single Select2's dropdown arrow button appearance.
- */
-}
-.select2-container--bootstrap .select2-selection--single .select2-selection__arrow {
- position: absolute;
- bottom: 0;
- right: 12px;
- top: 0;
- width: 4px;
-}
-.select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
- border-color: #999 transparent transparent transparent;
- border-style: solid;
- border-width: 4px 4px 0 4px;
- height: 0;
- left: 0;
- margin-left: -4px;
- margin-top: -2px;
- position: absolute;
- top: 50%;
- width: 0;
-}
-.select2-container--bootstrap .select2-selection--single .select2-selection__rendered {
- color: #555555;
- padding: 0;
-}
-.select2-container--bootstrap .select2-selection--single .select2-selection__placeholder {
- color: #999;
-}
-.select2-container--bootstrap .select2-selection--multiple {
- min-height: 34px;
- /**
- * Make Multi Select2's choices match Bootstrap 3's default button styles.
- */
- /**
- * Minus 2px borders.
- */
- /**
- * Clear the selection.
- */
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered {
- box-sizing: border-box;
- display: block;
- line-height: 1.428571429;
- list-style: none;
- margin: 0;
- overflow: hidden;
- padding: 0;
- width: 100%;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder {
- color: #999;
- float: left;
- margin-top: 5px;
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
- color: #555555;
- background: #fff;
- border: 1px solid #ccc;
- border-radius: 4px;
- cursor: default;
- float: left;
- margin: 5px 0 0 6px;
- padding: 0 6px;
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
- background: transparent;
- padding: 0 12px;
- height: 32px;
- line-height: 1.428571429;
- margin-top: 0;
- min-width: 5em;
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove {
- color: #999;
- cursor: pointer;
- display: inline-block;
- font-weight: bold;
- margin-right: 3px;
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove:hover {
- color: #333;
-}
-.select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
- margin-top: 6px;
-}
-.select2-container--bootstrap.input-sm, .select2-container--bootstrap.input-lg {
- border-radius: 0;
- font-size: 12px;
- height: auto;
- line-height: 1;
- padding: 0;
-}
-.select2-container--bootstrap.input-sm .select2-selection--single, .input-group-sm .select2-container--bootstrap .select2-selection--single, .form-group-sm .select2-container--bootstrap .select2-selection--single {
- border-radius: 3px;
- font-size: 12px;
- height: 30px;
- line-height: 1.5;
- padding: 5px 22px 5px 10px;
- /* 2 */
-}
-.select2-container--bootstrap.input-sm .select2-selection--single .select2-selection__arrow b, .input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, .form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
- margin-left: -5px;
-}
-.select2-container--bootstrap.input-sm .select2-selection--multiple, .input-group-sm .select2-container--bootstrap .select2-selection--multiple, .form-group-sm .select2-container--bootstrap .select2-selection--multiple {
- min-height: 30px;
-}
-.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__choice, .input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, .form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
- font-size: 12px;
- line-height: 1.5;
- margin: 4px 0 0 5px;
- padding: 0 5px;
-}
-.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-search--inline .select2-search__field, .input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
- padding: 0 10px;
- font-size: 12px;
- height: 28px;
- line-height: 1.5;
-}
-.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__clear, .input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, .form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
- margin-top: 5px;
-}
-.select2-container--bootstrap.input-lg .select2-selection--single, .input-group-lg .select2-container--bootstrap .select2-selection--single, .form-group-lg .select2-container--bootstrap .select2-selection--single {
- border-radius: 6px;
- font-size: 18px;
- height: 46px;
- line-height: 1.3333333;
- padding: 10px 31px 10px 16px;
- /* 1 */
-}
-.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow, .input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow, .form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow {
- width: 5px;
-}
-.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow b, .input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, .form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
- border-width: 5px 5px 0 5px;
- margin-left: -5px;
- margin-left: -10px;
- margin-top: -2.5px;
-}
-.select2-container--bootstrap.input-lg .select2-selection--multiple, .input-group-lg .select2-container--bootstrap .select2-selection--multiple, .form-group-lg .select2-container--bootstrap .select2-selection--multiple {
- min-height: 46px;
-}
-.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__choice, .input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, .form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
- font-size: 18px;
- line-height: 1.3333333;
- border-radius: 4px;
- margin: 9px 0 0 8px;
- padding: 0 10px;
-}
-.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-search--inline .select2-search__field, .input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
- padding: 0 16px;
- font-size: 18px;
- height: 44px;
- line-height: 1.3333333;
-}
-.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__clear, .input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, .form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
- margin-top: 10px;
-}
-.select2-container--bootstrap.input-lg.select2-container--open .select2-selection--single {
- /**
- * Make the dropdown arrow point up while the dropdown is visible.
- */
-}
-.select2-container--bootstrap.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b {
- border-color: transparent transparent #999 transparent;
- border-width: 0 5px 5px 5px;
-}
-.input-group-lg .select2-container--bootstrap.select2-container--open .select2-selection--single {
- /**
- * Make the dropdown arrow point up while the dropdown is visible.
- */
-}
-.input-group-lg .select2-container--bootstrap.select2-container--open .select2-selection--single .select2-selection__arrow b {
- border-color: transparent transparent #999 transparent;
- border-width: 0 5px 5px 5px;
-}
-.select2-container--bootstrap[dir="rtl"] {
- /**
- * Single Select2
- *
- * 1. Makes sure that .select2-selection__placeholder is positioned
- * correctly.
- */
- /**
- * Multiple Select2
- */
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--single {
- padding-left: 24px;
- padding-right: 12px;
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__rendered {
- padding-right: 0;
- padding-left: 0;
- text-align: right;
- /* 1 */
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__clear {
- float: left;
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__arrow {
- left: 12px;
- right: auto;
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__arrow b {
- margin-left: 0;
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice,
-.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder {
- float: right;
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
- margin-left: 0;
- margin-right: 6px;
-}
-.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
- margin-left: 2px;
- margin-right: auto;
-}
-
-/*------------------------------------*\
- #ADDITIONAL GOODIES
-\*------------------------------------*/
-/**
- * Address Bootstrap's validation states
- *
- * If a Select2 widget parent has one of Bootstrap's validation state modifier
- * classes, adjust Select2's border colors and focus states accordingly.
- * You may apply said classes to the Select2 dropdown (body > .select2-container)
- * via JavaScript match Bootstraps' to make its styles match.
- *
- * @see http://getbootstrap.com/css/#forms-control-validation
- */
-.has-warning .select2-dropdown,
-.has-warning .select2-selection {
- border-color: #8a6d3b;
-}
-.has-warning .select2-container--focus .select2-selection,
-.has-warning .select2-container--open .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
- border-color: #66512c;
-}
-.has-warning.select2-drop-active {
- border-color: #66512c;
-}
-.has-warning.select2-drop-active.select2-drop.select2-drop-above {
- border-top-color: #66512c;
-}
-
-.has-error .select2-dropdown,
-.has-error .select2-selection {
- border-color: #a94442;
-}
-.has-error .select2-container--focus .select2-selection,
-.has-error .select2-container--open .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
- border-color: #843534;
-}
-.has-error.select2-drop-active {
- border-color: #843534;
-}
-.has-error.select2-drop-active.select2-drop.select2-drop-above {
- border-top-color: #843534;
-}
-
-.has-success .select2-dropdown,
-.has-success .select2-selection {
- border-color: #3c763d;
-}
-.has-success .select2-container--focus .select2-selection,
-.has-success .select2-container--open .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
- border-color: #2b542c;
-}
-.has-success.select2-drop-active {
- border-color: #2b542c;
-}
-.has-success.select2-drop-active.select2-drop.select2-drop-above {
- border-top-color: #2b542c;
-}
-
-/**
- * Select2 widgets in Bootstrap Input Groups
- *
- * When Select2 widgets are combined with other elements using Bootstraps
- * "Input Group" component, we don't want specific edges of the Select2
- * container to have a border-radius.
- *
- * Use .select2-bootstrap-prepend and .select2-bootstrap-append on
- * a Bootstrap 3 .input-group to let the contained Select2 widget know which
- * edges should not be rounded as they are directly followed by another element.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
-/**
- * Mimick Bootstraps .input-group .form-control styles.
- *
- * @see https://github.com/twbs/bootstrap/blob/master/less/input-groups.less
- */
-.input-group .select2-container--bootstrap {
- display: table;
- table-layout: fixed;
- position: relative;
- z-index: 2;
- float: left;
- width: 100%;
- margin-bottom: 0;
-}
-
-.input-group.select2-bootstrap-prepend .select2-container--bootstrap .select2-selection {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-
-.input-group.select2-bootstrap-append .select2-container--bootstrap .select2-selection {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-
-/**
- * Adjust alignment of Bootstrap buttons in Bootstrap Input Groups to address
- * Multi Select2's height which - depending on how many elements have been selected -
- * may grow taller than its initial size.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
-.select2-bootstrap-append .select2-container--bootstrap,
-.select2-bootstrap-append .input-group-btn,
-.select2-bootstrap-append .input-group-btn .btn,
-.select2-bootstrap-prepend .select2-container--bootstrap,
-.select2-bootstrap-prepend .input-group-btn,
-.select2-bootstrap-prepend .input-group-btn .btn {
- vertical-align: top;
-}
-
-/**
- * Temporary fix for https://github.com/select2/select2-bootstrap-theme/issues/9
- *
- * Provides `!important` for certain properties of the class applied to the
- * original `
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.5",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.5",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.5",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
\ No newline at end of file
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/docs/js/respond.min.js b/awx/ui/client/lib/select2-bootstrap-theme/docs/js/respond.min.js
deleted file mode 100755
index 80a7b69dcc..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/docs/js/respond.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
- * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
- * */
-
-!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b .select2-results__options {
- max-height: 200px;
- overflow-y: auto;
- }
-
-
-
-
-
- /*------------------------------------*\
- #SINGLE SELECT2
- \*------------------------------------*/
-
- .select2-selection--single {
- height: @input-height-base;
- line-height: @line-height-base;
- padding: @padding-base-vertical @padding-base-horizontal + @caret-width-base*3 @padding-base-vertical @padding-base-horizontal;
-
- /**
- * Adjust the single Select2's dropdown arrow button appearance.
- */
-
- .select2-selection__arrow {
- position: absolute;
- bottom: 0;
- right: @padding-base-horizontal;
- top: 0;
- width: @caret-width-base;
-
- b {
- border-color: @dropdown-arrow-color transparent transparent transparent;
- border-style: solid;
- border-width: @caret-width-base @caret-width-base 0 @caret-width-base;
- height: 0;
- left: 0;
- margin-left: -@caret-width-base;
- margin-top: -@caret-width-base/2;
- position: absolute;
- top: 50%;
- width: 0;
- }
- }
-
- .select2-selection__rendered {
- color: @input-color;
- padding: 0;
- }
-
- .select2-selection__placeholder {
- color: @input-color-placeholder;
- }
- }
-
-
-
-
-
- /*------------------------------------*\
- #MULTIPLE SELECT2
- \*------------------------------------*/
-
- .select2-selection--multiple {
- min-height: @input-height-base;
-
- .select2-selection__rendered {
- box-sizing: border-box;
- display: block;
- line-height: @line-height-base;
- list-style: none;
- margin: 0;
- overflow: hidden;
- padding: 0;
- width: 100%;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .select2-selection__placeholder {
- color: @input-color-placeholder;
- float: left;
- margin-top: 5px;
- }
-
- /**
- * Make Multi Select2's choices match Bootstrap 3's default button styles.
- */
-
- .select2-selection__choice {
- color: @input-color;
- background: @btn-default-bg;
- border: 1px solid @btn-default-border;
- border-radius: 4px;
- cursor: default;
- float: left;
- margin: (@padding-base-vertical - 1) 0 0 @padding-base-horizontal/2;
- padding: 0 @padding-base-vertical;
- }
-
- /**
- * Minus 2px borders.
- */
-
- .select2-search--inline {
- .select2-search__field {
- background: transparent;
- padding: 0 @padding-base-horizontal;
- height: @input-height-base - 2;
- line-height: @line-height-base;
- margin-top: 0;
- min-width: 5em;
- }
- }
-
- .select2-selection__choice__remove {
- color: #999;
- cursor: pointer;
- display: inline-block;
- font-weight: bold;
- margin-right: @padding-base-vertical / 2;
-
- &:hover {
- color: #333;
- }
- }
-
- /**
- * Clear the selection.
- */
-
- .select2-selection__clear {
- margin-top: @padding-base-vertical;
- }
- }
-
-
-
-
-
- /**
- * Address Bootstrap control sizing classes
- *
- * 1. Reset Bootstrap defaults.
- * 2. Adjust the dropdown arrow button icon position.
- *
- * @see http://getbootstrap.com/css/#forms-control-sizes
- */
-
- /* 1 */
- &.input-sm,
- &.input-lg {
- border-radius: 0;
- font-size: 12px;
- height: auto;
- line-height: 1;
- padding: 0;
- }
-
- &.input-sm,
- .input-group-sm &,
- .form-group-sm & {
- .select2-selection--single {
- border-radius: @border-radius-small;
- font-size: @font-size-small;
- height: @input-height-small;
- line-height: @line-height-small;
- padding: @padding-small-vertical @padding-small-horizontal + @caret-width-base*3 @padding-small-vertical @padding-small-horizontal;
-
- /* 2 */
- .select2-selection__arrow b {
- margin-left: -@padding-small-vertical;
- }
- }
-
- .select2-selection--multiple {
- min-height: @input-height-small;
-
- .select2-selection__choice {
- font-size: @font-size-small;
- line-height: @line-height-small;
- margin: (@padding-small-vertical - 1) 0 0 @padding-small-horizontal/2;
- padding: 0 @padding-small-vertical;
- }
-
- .select2-search--inline .select2-search__field {
- padding: 0 @padding-small-horizontal;
- font-size: @font-size-small;
- height: @input-height-small - 2;
- line-height: @line-height-small;
- }
-
- .select2-selection__clear {
- margin-top: @padding-small-vertical;
- }
- }
- }
-
- &.input-lg,
- .input-group-lg &,
- .form-group-lg & {
- .select2-selection--single {
- border-radius: @border-radius-large;
- font-size: @font-size-large;
- height: @input-height-large;
- line-height: @line-height-large;
- padding: @padding-large-vertical @padding-large-horizontal + @caret-width-large*3 @padding-large-vertical @padding-large-horizontal;
-
- /* 1 */
- .select2-selection__arrow {
- width: @caret-width-large;
-
- b {
- border-width: @caret-width-large @caret-width-large 0 @caret-width-large;
- margin-left: -@caret-width-large;
- margin-left: -@padding-large-vertical;
- margin-top: -@caret-width-large/2;
- }
- }
- }
-
- .select2-selection--multiple {
- min-height: @input-height-large;
-
- .select2-selection__choice {
- font-size: @font-size-large;
- line-height: @line-height-large;
- border-radius: 4px;
- margin: (@padding-large-vertical - 1) 0 0 @padding-large-horizontal/2;
- padding: 0 @padding-large-vertical;
- }
-
- .select2-search--inline .select2-search__field {
- padding: 0 @padding-large-horizontal;
- font-size: @font-size-large;
- height: @input-height-large - 2;
- line-height: @line-height-large;
- }
-
- .select2-selection__clear {
- margin-top: @padding-large-vertical;
- }
- }
- }
-
- &.input-lg.select2-container--open {
- .dropdown-arrow;
- }
-
- .input-group-lg & {
- &.select2-container--open {
- .dropdown-arrow;
- }
- }
-
-
-
-
-
- /*------------------------------------*\
- #RTL SUPPORT
- \*------------------------------------*/
-
- &[dir="rtl"] {
-
- /**
- * Single Select2
- *
- * 1. Makes sure that .select2-selection__placeholder is positioned
- * correctly.
- */
-
- .select2-selection--single {
- padding-left: @padding-base-horizontal + @caret-width-base*3;
- padding-right: @padding-base-horizontal;
- .select2-selection__rendered {
- padding-right: 0;
- padding-left: 0;
- text-align: right; /* 1 */
- }
-
- .select2-selection__clear {
- float: left;
- }
-
- .select2-selection__arrow {
- left: @padding-base-horizontal;
- right: auto;
-
- b {
- margin-left: 0;
- }
- }
- }
-
- /**
- * Multiple Select2
- */
-
- .select2-selection--multiple {
- .select2-selection__choice,
- .select2-selection__placeholder {
- float: right;
- }
-
- .select2-selection__choice {
- margin-left: 0;
- margin-right: @padding-base-horizontal/2;
- }
-
- .select2-selection__choice__remove {
- margin-left: 2px;
- margin-right: auto;
- }
- }
- }
-}
-
-
-
-
-
-/*------------------------------------*\
- #ADDITIONAL GOODIES
-\*------------------------------------*/
-
-/**
- * Address Bootstrap's validation states
- *
- * If a Select2 widget parent has one of Bootstrap's validation state modifier
- * classes, adjust Select2's border colors and focus states accordingly.
- * You may apply said classes to the Select2 dropdown (body > .select2-container)
- * via JavaScript match Bootstraps' to make its styles match.
- *
- * @see http://getbootstrap.com/css/#forms-control-validation
- */
-
-.has-warning {
- .validation-state-focus(@state-warning-text);
-}
-
-.has-error {
- .validation-state-focus(@state-danger-text);
-}
-
-.has-success {
- .validation-state-focus(@state-success-text);
-}
-
-/**
- * Select2 widgets in Bootstrap Input Groups
- *
- * When Select2 widgets are combined with other elements using Bootstraps
- * "Input Group" component, we don't want specific edges of the Select2
- * container to have a border-radius.
- *
- * Use .select2-bootstrap-prepend and .select2-bootstrap-append on
- * a Bootstrap 3 .input-group to let the contained Select2 widget know which
- * edges should not be rounded as they are directly followed by another element.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
-
-/**
- * Mimick Bootstraps .input-group .form-control styles.
- *
- * @see https://github.com/twbs/bootstrap/blob/master/less/input-groups.less
- */
-
-.input-group .select2-container--bootstrap {
- display: table;
- table-layout: fixed;
- position: relative;
- z-index: 2;
- float: left;
- width: 100%;
- margin-bottom: 0;
-}
-
-.input-group.select2-bootstrap-prepend .select2-container--bootstrap {
- .select2-selection {
- .border-left-radius(0);
- }
-}
-
-.input-group.select2-bootstrap-append .select2-container--bootstrap {
- .select2-selection {
- .border-right-radius(0);
- }
-}
-
-/**
- * Adjust alignment of Bootstrap buttons in Bootstrap Input Groups to address
- * Multi Select2's height which - depending on how many elements have been selected -
- * may grow taller than its initial size.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
-
-.select2-bootstrap-append,
-.select2-bootstrap-prepend {
- .select2-container--bootstrap,
- .input-group-btn,
- .input-group-btn .btn {
- vertical-align: top;
- }
-}
-
-/**
- * Temporary fix for https://github.com/select2/select2-bootstrap-theme/issues/9
- *
- * Provides `!important` for certain properties of the class applied to the
- * original `` element to hide it.
- *
- * @see https://github.com/select2/select2/pull/3301
- * @see https://github.com/fk/select2/commit/31830c7b32cb3d8e1b12d5b434dee40a6e753ada
- */
-
-.form-control.select2-hidden-accessible {
- position: absolute !important;
- width: 1px !important;
-}
-
-/**
- * Display override for inline forms
-*/
-
-.form-inline .select2-container--bootstrap {
- display: inline-block;
-}
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/src/select2-bootstrap.scss b/awx/ui/client/lib/select2-bootstrap-theme/src/select2-bootstrap.scss
deleted file mode 100755
index 5fb6b5dfc5..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/src/select2-bootstrap.scss
+++ /dev/null
@@ -1,768 +0,0 @@
-/*! Select2 Bootstrap Theme v0.1.0-beta.4 | MIT License | github.com/select2/select2-bootstrap-theme */
-
-//
-// Variables
-// --------------------------------------------------
-
-// Bootstrap defaults not available as pre-defined variables
-// These should not be overridden.
-// @see https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_forms.scss#L127
-
-$form-control-default-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
-
-// @see https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/mixins/_forms.scss#L43
-$form-control-focus-box-shadow: $form-control-default-box-shadow, 0 0 8px rgba($input-border-focus, 0.6);
-
-// @see https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_forms.scss#L128
-$form-control-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-
-// Custom variables
-// -------------------------
-
-$dropdown-arrow-color: $input-color-placeholder !default;
-$dropdown-box-shadow: 0 6px 12px rgba(0,0,0,.175) !default;
-$clear-selection-color: $dropdown-arrow-color !default;
-
-
-
-
-
-//
-// Mixins
-// --------------------------------------------------
-
-// @see https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_forms.scss#L115
-@mixin bootstrap-input-defaults {
- @include box-shadow($form-control-default-box-shadow);
- background-color: $input-bg;
- border: 1px solid $input-border;
- border-radius: $input-border-radius;
- color: $input-color;
- font-family: $font-family-base;
- font-size: $font-size-base;
-}
-
-// @see http://getbootstrap.com/css/#forms-control-validation
-// @see https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_forms.scss#L388
-@mixin validation-state-focus($color) {
- $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($color, 20%);
-
- .select2-dropdown,
- .select2-selection {
- border-color: $color;
- }
-
- .select2-container--focus .select2-selection,
- .select2-container--open .select2-selection {
- @include box-shadow($shadow);
- border-color: darken($color, 10%);
- }
-
- &.select2-drop-active {
- border-color: darken($color, 10%);
-
- &.select2-drop.select2-drop-above {
- border-top-color: darken($color, 10%);
- }
- }
-}
-
-// dropdown arrow when dropdown is open
-@mixin dropdown-arrow {
- .select2-selection--single {
- /**
- * Make the dropdown arrow point up while the dropdown is visible.
- */
-
- .select2-selection__arrow b {
- border-color: transparent transparent $dropdown-arrow-color transparent;
- border-width: 0 $caret-width-large $caret-width-large $caret-width-large;
- }
- }
-}
-
-
-
-
-
-.select2-container--bootstrap {
- display: block;
-
-
-
-
-
- /*------------------------------------*\
- #COMMON STYLES
- \*------------------------------------*/
-
- .select2-selection {
- @include bootstrap-input-defaults;
- outline: 0;
- }
-
- /**
- * Search field in the Select2 dropdown.
- */
-
- .select2-search--dropdown {
- .select2-search__field {
- @include bootstrap-input-defaults;
- }
- }
-
- /**
- * No outline for all search fields - in the dropdown
- * and inline in multi Select2s.
- */
-
- .select2-search__field {
- outline: 0;
-
- &::-webkit-input-placeholder {
- color: $input-color-placeholder;
- }
-
- /* Firefox 18- */
- &:-moz-placeholder {
- color: $input-color-placeholder;
- }
-
- /**
- * Firefox 19+
- *
- * @see http://stackoverflow.com/questions/24236240/color-for-styled-placeholder-text-is-muted-in-firefox
- */
- &::-moz-placeholder {
- color: $input-color-placeholder;
- opacity: 1;
- }
-
- &:-ms-input-placeholder {
- color: $input-color-placeholder;
- }
- }
-
- /**
- * Adjust Select2's choices hover and selected styles to match
- * Bootstrap 3's default dropdown styles.
- *
- * @see http://getbootstrap.com/components/#dropdowns
- */
-
- .select2-results__option {
-
- &[role=group] {
- padding: 0;
- }
-
- /**
- * Disabled results.
- *
- * @see https://select2.github.io/examples.html#disabled-results
- */
-
- &[aria-disabled=true] {
- color: $dropdown-link-disabled-color;
- cursor: $cursor-disabled;
- }
-
- /**
- * Hover state.
- */
-
- &[aria-selected=true] {
- background-color: $dropdown-link-hover-bg;
- color: $dropdown-link-hover-color;
- }
-
- /**
- * Selected state.
- */
-
- &--highlighted[aria-selected] {
- background-color: $dropdown-link-active-bg;
- color: $dropdown-link-active-color;
- }
-
- .select2-results__option {
- padding: $padding-base-vertical $padding-base-horizontal;
-
- .select2-results__group {
- padding-left: 0;
- }
-
- .select2-results__option {
- margin-left: -$padding-base-horizontal;
- padding-left: $padding-base-horizontal*2;
-
- .select2-results__option {
- margin-left: -$padding-base-horizontal*2;
- padding-left: $padding-base-horizontal*3;
-
- .select2-results__option {
- margin-left: -$padding-base-horizontal*3;
- padding-left: $padding-base-horizontal*4;
-
- .select2-results__option {
- margin-left: -$padding-base-horizontal*4;
- padding-left: $padding-base-horizontal*5;
-
- .select2-results__option {
- margin-left: -$padding-base-horizontal*5;
- padding-left: $padding-base-horizontal*6;
- }
- }
- }
- }
- }
- }
- }
-
- .select2-results__group {
- color: $dropdown-header-color;
- display: block;
- padding: $padding-base-vertical $padding-base-horizontal;
- font-size: $font-size-small;
- line-height: $line-height-base;
- white-space: nowrap;
- }
-
- &.select2-container--focus,
- &.select2-container--open {
- .select2-selection {
- @include box-shadow($form-control-focus-box-shadow);
- @include transition($form-control-transition);
- border-color: $input-border-focus;
- }
- }
-
- &.select2-container--open {
- /**
- * Make the dropdown arrow point up while the dropdown is visible.
- */
-
- .select2-selection .select2-selection__arrow b {
- border-color: transparent transparent $dropdown-arrow-color transparent;
- border-width: 0 $caret-width-base $caret-width-base $caret-width-base;
- }
-
- /**
- * Handle border radii of the container when the dropdown is showing.
- */
-
- &.select2-container--below {
- .select2-selection {
- @include border-bottom-radius(0);
- border-bottom-color: transparent;
- }
- }
-
- &.select2-container--above {
- .select2-selection {
- @include border-top-radius(0);
- border-top-color: transparent;
- }
- }
- }
-
- /**
- * Clear the selection.
- */
-
- .select2-selection__clear {
- color: $clear-selection-color;
- cursor: pointer;
- float: right;
- font-weight: bold;
- margin-right: 10px;
-
- &:hover {
- color: #333;
- }
- }
-
- /**
- * Address disabled Select2 styles.
- *
- * @see https://select2.github.io/examples.html#disabled
- * @see http://getbootstrap.com/css/#forms-control-disabled
- */
-
- &.select2-container--disabled {
-
- .select2-selection {
- border-color: $input-border;
- @include box-shadow(none);
- }
-
- .select2-selection,
- .select2-search__field {
- cursor: $cursor-disabled;
- }
-
- .select2-selection,
- .select2-selection--multiple .select2-selection__choice {
- background-color: $input-bg-disabled;
- }
-
- .select2-selection__clear,
- .select2-selection--multiple .select2-selection__choice__remove {
- display: none;
- }
- }
-
-
-
-
-
- /*------------------------------------*\
- #DROPDOWN
- \*------------------------------------*/
-
- /**
- * Dropdown border color and box-shadow.
- */
-
- .select2-dropdown {
- @include box-shadow($dropdown-box-shadow);
- border-color: $input-border-focus;
- overflow-x: hidden;
- margin-top: -1px;
- &--above {
- margin-top: 1px;
- }
- }
-
- /**
- * Limit the dropdown height.
- */
-
- .select2-results > .select2-results__options {
- max-height: 200px;
- overflow-y: auto;
- }
-
-
-
-
-
- /*------------------------------------*\
- #SINGLE SELECT2
- \*------------------------------------*/
-
- .select2-selection--single {
- height: $input-height-base;
- line-height: $line-height-base;
- padding: $padding-base-vertical $padding-base-horizontal + $caret-width-base*3 $padding-base-vertical $padding-base-horizontal;
-
- /**
- * Adjust the single Select2's dropdown arrow button appearance.
- */
-
- .select2-selection__arrow {
- position: absolute;
- bottom: 0;
- right: $padding-base-horizontal;
- top: 0;
- width: $caret-width-base;
-
- b {
- border-color: $dropdown-arrow-color transparent transparent transparent;
- border-style: solid;
- border-width: $caret-width-base $caret-width-base 0 $caret-width-base;
- height: 0;
- left: 0;
- margin-left: -$caret-width-base;
- margin-top: -$caret-width-base/2;
- position: absolute;
- top: 50%;
- width: 0;
- }
- }
-
- .select2-selection__rendered {
- color: $input-color;
- padding: 0;
- }
-
- .select2-selection__placeholder {
- color: $input-color-placeholder;
- }
- }
-
-
-
-
-
- /*------------------------------------*\
- #MULTIPLE SELECT2
- \*------------------------------------*/
-
- .select2-selection--multiple {
- min-height: $input-height-base;
-
- .select2-selection__rendered {
- box-sizing: border-box;
- display: block;
- line-height: $line-height-base;
- list-style: none;
- margin: 0;
- overflow: hidden;
- padding: 0;
- width: 100%;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .select2-selection__placeholder {
- color: $input-color-placeholder;
- float: left;
- margin-top: 5px;
- }
-
- /**
- * Make Multi Select2's choices match Bootstrap 3's default button styles.
- */
-
- .select2-selection__choice {
- color: $input-color;
- background: $btn-default-bg;
- border: 1px solid $btn-default-border;
- border-radius: 4px;
- cursor: default;
- float: left;
- margin: ($padding-base-vertical - 1) 0 0 $padding-base-horizontal/2;
- padding: 0 $padding-base-vertical;
- }
-
- /**
- * Minus 2px borders.
- */
-
- .select2-search--inline {
- .select2-search__field {
- background: transparent;
- padding: 0 $padding-base-horizontal;
- height: $input-height-base - 2;
- line-height: $line-height-base;
- margin-top: 0;
- min-width: 5em;
- }
- }
-
- .select2-selection__choice__remove {
- color: #999;
- cursor: pointer;
- display: inline-block;
- font-weight: bold;
- margin-right: $padding-base-vertical / 2;
-
- &:hover {
- color: #333;
- }
- }
-
- /**
- * Clear the selection.
- */
-
- .select2-selection__clear {
- margin-top: $padding-base-vertical;
- }
- }
-
-
-
-
-
- /**
- * Address Bootstrap control sizing classes
- *
- * 1. Reset Bootstrap defaults.
- * 2. Adjust the dropdown arrow button icon position.
- *
- * @see http://getbootstrap.com/css/#forms-control-sizes
- */
-
- /* 1 */
- &.input-sm,
- &.input-lg {
- border-radius: 0;
- font-size: 12px;
- height: auto;
- line-height: 1;
- padding: 0;
- }
-
- &.input-sm,
- .input-group-sm &,
- .form-group-sm & {
- .select2-selection--single {
- border-radius: $border-radius-small;
- font-size: $font-size-small;
- height: $input-height-small;
- line-height: $line-height-small;
- padding: $padding-small-vertical $padding-small-horizontal + $caret-width-base*3 $padding-small-vertical $padding-small-horizontal;
-
- /* 2 */
- .select2-selection__arrow b {
- margin-left: -$padding-small-vertical;
- }
- }
-
- .select2-selection--multiple {
- min-height: $input-height-small;
-
- .select2-selection__choice {
- font-size: $font-size-small;
- line-height: $line-height-small;
- margin: ($padding-small-vertical - 1) 0 0 $padding-small-horizontal/2;
- padding: 0 $padding-small-vertical;
- }
-
- .select2-search--inline .select2-search__field {
- padding: 0 $padding-small-horizontal;
- font-size: $font-size-small;
- height: $input-height-small - 2;
- line-height: $line-height-small;
- }
-
- .select2-selection__clear {
- margin-top: $padding-small-vertical;
- }
- }
- }
-
- &.input-lg,
- .input-group-lg &,
- .form-group-lg & {
- .select2-selection--single {
- border-radius: $border-radius-large;
- font-size: $font-size-large;
- height: $input-height-large;
- line-height: $line-height-large;
- padding: $padding-large-vertical $padding-large-horizontal + $caret-width-large*3 $padding-large-vertical $padding-large-horizontal;
-
- /* 1 */
- .select2-selection__arrow {
- width: $caret-width-large;
-
- b {
- border-width: $caret-width-large $caret-width-large 0 $caret-width-large;
- margin-left: -$caret-width-large;
- margin-left: -$padding-large-vertical;
- margin-top: -$caret-width-large/2;
- }
- }
- }
-
- .select2-selection--multiple {
- min-height: $input-height-large;
-
- .select2-selection__choice {
- font-size: $font-size-large;
- line-height: $line-height-large;
- border-radius: 4px;
- margin: ($padding-large-vertical - 1) 0 0 $padding-large-horizontal/2;
- padding: 0 $padding-large-vertical;
- }
-
- .select2-search--inline .select2-search__field {
- padding: 0 $padding-large-horizontal;
- font-size: $font-size-large;
- height: $input-height-large - 2;
- line-height: $line-height-large;
- }
-
- .select2-selection__clear {
- margin-top: $padding-large-vertical;
- }
- }
- }
-
- &.input-lg.select2-container--open {
- @include dropdown-arrow;
- }
-
- .input-group-lg & {
- &.select2-container--open {
- @include dropdown-arrow;
- }
- }
-
-
-
-
-
- /*------------------------------------*\
- #RTL SUPPORT
- \*------------------------------------*/
-
- &[dir="rtl"] {
-
- /**
- * Single Select2
- *
- * 1. Makes sure that .select2-selection__placeholder is positioned
- * correctly.
- */
-
- .select2-selection--single {
- padding-left: $padding-base-horizontal + $caret-width-base*3;
- padding-right: $padding-base-horizontal;
- .select2-selection__rendered {
- padding-right: 0;
- padding-left: 0;
- text-align: right; /* 1 */
- }
-
- .select2-selection__clear {
- float: left;
- }
-
- .select2-selection__arrow {
- left: $padding-base-horizontal;
- right: auto;
-
- b {
- margin-left: 0;
- }
- }
- }
-
- /**
- * Multiple Select2
- */
-
- .select2-selection--multiple {
- .select2-selection__choice,
- .select2-selection__placeholder {
- float: right;
- }
-
- .select2-selection__choice {
- margin-left: 0;
- margin-right: $padding-base-horizontal/2;
- }
-
- .select2-selection__choice__remove {
- margin-left: 2px;
- margin-right: auto;
- }
- }
- }
-}
-
-
-
-
-
-/*------------------------------------*\
- #ADDITIONAL GOODIES
-\*------------------------------------*/
-
-/**
- * Address Bootstrap's validation states
- *
- * If a Select2 widget parent has one of Bootstrap's validation state modifier
- * classes, adjust Select2's border colors and focus states accordingly.
- * You may apply said classes to the Select2 dropdown (body > .select2-container)
- * via JavaScript match Bootstraps' to make its styles match.
- *
- * @see http://getbootstrap.com/css/#forms-control-validation
- */
-
-.has-warning {
- @include validation-state-focus($state-warning-text);
-}
-
-.has-error {
- @include validation-state-focus($state-danger-text);
-}
-
-.has-success {
- @include validation-state-focus($state-success-text);
-}
-
-/**
- * Select2 widgets in Bootstrap Input Groups
- *
- * When Select2 widgets are combined with other elements using Bootstraps
- * "Input Group" component, we don't want specific edges of the Select2
- * container to have a border-radius.
- *
- * Use .select2-bootstrap-prepend and .select2-bootstrap-append on
- * a Bootstrap 3 .input-group to let the contained Select2 widget know which
- * edges should not be rounded as they are directly followed by another element.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
-
-/**
- * Mimick Bootstraps .input-group .form-control styles.
- *
- * @see https://github.com/twbs/bootstrap/blob/master/less/input-groups.less
- */
-
-.input-group .select2-container--bootstrap {
- display: table;
- table-layout: fixed;
- position: relative;
- z-index: 2;
- float: left;
- width: 100%;
- margin-bottom: 0;
-}
-
-.input-group.select2-bootstrap-prepend .select2-container--bootstrap {
- .select2-selection {
- @include border-left-radius(0);
- }
-}
-
-.input-group.select2-bootstrap-append .select2-container--bootstrap {
- .select2-selection {
- @include border-right-radius(0);
- }
-}
-
-/**
- * Adjust alignment of Bootstrap buttons in Bootstrap Input Groups to address
- * Multi Select2's height which - depending on how many elements have been selected -
- * may grow taller than its initial size.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
-
-.select2-bootstrap-append,
-.select2-bootstrap-prepend {
- .select2-container--bootstrap,
- .input-group-btn,
- .input-group-btn .btn {
- vertical-align: top;
- }
-}
-
-/**
- * Temporary fix for https://github.com/select2/select2-bootstrap-theme/issues/9
- *
- * Provides `!important` for certain properties of the class applied to the
- * original `` element to hide it.
- *
- * @see https://github.com/select2/select2/pull/3301
- * @see https://github.com/fk/select2/commit/31830c7b32cb3d8e1b12d5b434dee40a6e753ada
- */
-
-.form-control.select2-hidden-accessible {
- position: absolute !important;
- width: 1px !important;
-}
-
-/**
- * Display override for inline forms
-*/
-
-.form-inline .select2-container--bootstrap {
- display: inline-block;
-}
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/tests/less_test.js b/awx/ui/client/lib/select2-bootstrap-theme/tests/less_test.js
deleted file mode 100755
index 1f9878b560..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/tests/less_test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-exports.compileLess = function(test){
- var grunt = require('grunt'),
- fs = require('fs'),
- jsdiff = require('diff'),
- t = test,
- filename = 'select2-bootstrap.css',
- patchfile = 'tests/support/less.patch',
-
- child = grunt.util.spawn({
- cmd: 'lessc',
- args: ['--verbose', 'src/build.less', 'tmp/'+filename]
- }, function() {
- var readFile = function(name) { return fs.readFileSync(name, {encoding: 'utf8'}) },
- orig = readFile('dist/'+filename),
- generated = readFile('tmp/'+filename),
- patch = readFile(patchfile),
- diff = jsdiff.createPatch(filename, orig, generated);
-
- // Save the output for future tests.
- // fs.writeFileSync(patchfile, diff);
-
- t.equal(patch, diff);
- t.done();
- });
-};
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/tests/scss_test.js b/awx/ui/client/lib/select2-bootstrap-theme/tests/scss_test.js
deleted file mode 100755
index 0fa5353f80..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/tests/scss_test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-exports.compileScss = function(test){
- var grunt = require('grunt'),
- fs = require('fs'),
- jsdiff = require('diff'),
- t = test,
- filename = 'select2-bootstrap.css',
- patchfile = 'tests/support/scss.patch',
-
- child = grunt.util.spawn({
- cmd: 'grunt',
- args: ['sass:test']
- }, function() {
- var readFile = function(name) { return fs.readFileSync(name, {encoding: 'utf8'}) },
- orig = readFile('dist/'+filename),
- generated = readFile('tmp/'+filename),
- patch = readFile(patchfile),
- diff = jsdiff.createPatch(filename, orig, generated);
-
- // Save the output for future tests.
- // fs.writeFileSync(patchfile, diff);
-
- t.equal(patch, diff);
- t.done();
- });
-};
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/tests/support/less.patch b/awx/ui/client/lib/select2-bootstrap-theme/tests/support/less.patch
deleted file mode 100755
index c8e69cb88b..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/tests/support/less.patch
+++ /dev/null
@@ -1,610 +0,0 @@
-Index: select2-bootstrap.css
-===================================================================
---- select2-bootstrap.css
-+++ select2-bootstrap.css
-@@ -1,65 +1,79 @@
- /*! Select2 Bootstrap Theme v0.1.0-beta.4 | MIT License | github.com/select2/select2-bootstrap-theme */
- .select2-container--bootstrap {
- display: block;
- /*------------------------------------*\
-+ #COMMON STYLES
-+ \*------------------------------------*/
-+
-- #COMMON STYLES
-- \*------------------------------------*/
- /**
-+ * Search field in the Select2 dropdown.
-+ */
-+
-- * Search field in the Select2 dropdown.
-- */
- /**
-+ * No outline for all search fields - in the dropdown
-+ * and inline in multi Select2s.
-+ */
-+
-- * No outline for all search fields - in the dropdown
-- * and inline in multi Select2s.
-- */
- /**
-+ * Adjust Select2's choices hover and selected styles to match
-+ * Bootstrap 3's default dropdown styles.
-+ *
-+ * @see http://getbootstrap.com/components/#dropdowns
-+ */
-+
-- * Adjust Select2's choices hover and selected styles to match
-- * Bootstrap 3's default dropdown styles.
-- *
-- * @see http://getbootstrap.com/components/#dropdowns
-- */
- /**
-+ * Clear the selection.
-+ */
-+
-- * Clear the selection.
-- */
- /**
-+ * Address disabled Select2 styles.
-+ *
-+ * @see https://select2.github.io/examples.html#disabled
-+ * @see http://getbootstrap.com/css/#forms-control-disabled
-+ */
-+
-- * Address disabled Select2 styles.
-- *
-- * @see https://select2.github.io/examples.html#disabled
-- * @see http://getbootstrap.com/css/#forms-control-disabled
-- */
- /*------------------------------------*\
-+ #DROPDOWN
-+ \*------------------------------------*/
-+
-- #DROPDOWN
-- \*------------------------------------*/
- /**
-+ * Dropdown border color and box-shadow.
-+ */
-+
-- * Dropdown border color and box-shadow.
-- */
- /**
-+ * Limit the dropdown height.
-+ */
-+
-- * Limit the dropdown height.
-- */
- /*------------------------------------*\
-+ #SINGLE SELECT2
-+ \*------------------------------------*/
-+
-- #SINGLE SELECT2
-- \*------------------------------------*/
- /*------------------------------------*\
-+ #MULTIPLE SELECT2
-+ \*------------------------------------*/
-+
-- #MULTIPLE SELECT2
-- \*------------------------------------*/
- /**
-+ * Address Bootstrap control sizing classes
-+ *
-+ * 1. Reset Bootstrap defaults.
-+ * 2. Adjust the dropdown arrow button icon position.
-+ *
-+ * @see http://getbootstrap.com/css/#forms-control-sizes
-+ */
-+
-- * Address Bootstrap control sizing classes
-- *
-- * 1. Reset Bootstrap defaults.
-- * 2. Adjust the dropdown arrow button icon position.
-- *
-- * @see http://getbootstrap.com/css/#forms-control-sizes
-- */
- /* 1 */
-+
- /*------------------------------------*\
-+ #RTL SUPPORT
-+ \*------------------------------------*/
-+
-- #RTL SUPPORT
-- \*------------------------------------*/
- }
- .select2-container--bootstrap .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-+ background-color: #ffffff;
-+ border: 1px solid #cccccc;
-- background-color: #fff;
-- border: 1px solid #ccc;
- border-radius: 4px;
- color: #555555;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
-@@ -67,49 +81,54 @@
- }
- .select2-container--bootstrap .select2-search--dropdown .select2-search__field {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-+ background-color: #ffffff;
-+ border: 1px solid #cccccc;
-- background-color: #fff;
-- border: 1px solid #ccc;
- border-radius: 4px;
- color: #555555;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
- }
- .select2-container--bootstrap .select2-search__field {
- outline: 0;
- /* Firefox 18- */
-+
- /**
-+ * Firefox 19+
-+ *
-+ * @see http://stackoverflow.com/questions/24236240/color-for-styled-placeholder-text-is-muted-in-firefox
-+ */
-+
-- * Firefox 19+
-- *
-- * @see http://stackoverflow.com/questions/24236240/color-for-styled-placeholder-text-is-muted-in-firefox
-- */
- }
- .select2-container--bootstrap .select2-search__field::-webkit-input-placeholder {
-+ color: #999999;
-- color: #999;
- }
- .select2-container--bootstrap .select2-search__field:-moz-placeholder {
-+ color: #999999;
-- color: #999;
- }
- .select2-container--bootstrap .select2-search__field::-moz-placeholder {
-+ color: #999999;
-- color: #999;
- opacity: 1;
- }
- .select2-container--bootstrap .select2-search__field:-ms-input-placeholder {
-+ color: #999999;
-- color: #999;
- }
- .select2-container--bootstrap .select2-results__option {
- /**
-+ * Disabled results.
-+ *
-+ * @see https://select2.github.io/examples.html#disabled-results
-+ */
-+
-- * Disabled results.
-- *
-- * @see https://select2.github.io/examples.html#disabled-results
-- */
- /**
-+ * Hover state.
-+ */
-+
-- * Hover state.
-- */
- /**
-+ * Selected state.
-+ */
-+
-- * Selected state.
-- */
- }
- .select2-container--bootstrap .select2-results__option[role=group] {
- padding: 0;
- }
-@@ -122,9 +141,9 @@
- color: #262626;
- }
- .select2-container--bootstrap .select2-results__option--highlighted[aria-selected] {
- background-color: #337ab7;
-+ color: #ffffff;
-- color: #fff;
- }
- .select2-container--bootstrap .select2-results__option .select2-results__option {
- padding: 6px 12px;
- }
-@@ -158,9 +177,10 @@
- font-size: 12px;
- line-height: 1.428571429;
- white-space: nowrap;
- }
-+.select2-container--bootstrap.select2-container--focus .select2-selection,
-+.select2-container--bootstrap.select2-container--open .select2-selection {
--.select2-container--bootstrap.select2-container--focus .select2-selection, .select2-container--bootstrap.select2-container--open .select2-selection {
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
-@@ -168,16 +188,18 @@
- border-color: #66afe9;
- }
- .select2-container--bootstrap.select2-container--open {
- /**
-+ * Make the dropdown arrow point up while the dropdown is visible.
-+ */
-+
-- * Make the dropdown arrow point up while the dropdown is visible.
-- */
- /**
-+ * Handle border radii of the container when the dropdown is showing.
-+ */
-+
-- * Handle border radii of the container when the dropdown is showing.
-- */
- }
- .select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b {
-+ border-color: transparent transparent #999999 transparent;
-- border-color: transparent transparent #999 transparent;
- border-width: 0 4px 4px 4px;
- }
- .select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection {
- border-bottom-right-radius: 0;
-@@ -189,9 +211,9 @@
- border-top-left-radius: 0;
- border-top-color: transparent;
- }
- .select2-container--bootstrap .select2-selection__clear {
-+ color: #999999;
-- color: #999;
- cursor: pointer;
- float: right;
- font-weight: bold;
- margin-right: 10px;
-@@ -199,9 +221,9 @@
- .select2-container--bootstrap .select2-selection__clear:hover {
- color: #333;
- }
- .select2-container--bootstrap.select2-container--disabled .select2-selection {
-+ border-color: #cccccc;
-- border-color: #ccc;
- -webkit-box-shadow: none;
- box-shadow: none;
- }
- .select2-container--bootstrap.select2-container--disabled .select2-selection,
-@@ -234,10 +256,11 @@
- height: 34px;
- line-height: 1.428571429;
- padding: 6px 24px 6px 12px;
- /**
-+ * Adjust the single Select2's dropdown arrow button appearance.
-+ */
-+
-- * Adjust the single Select2's dropdown arrow button appearance.
-- */
- }
- .select2-container--bootstrap .select2-selection--single .select2-selection__arrow {
- position: absolute;
- bottom: 0;
-@@ -245,9 +268,9 @@
- top: 0;
- width: 4px;
- }
- .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
-+ border-color: #999999 transparent transparent transparent;
-- border-color: #999 transparent transparent transparent;
- border-style: solid;
- border-width: 4px 4px 0 4px;
- height: 0;
- left: 0;
-@@ -261,21 +284,24 @@
- color: #555555;
- padding: 0;
- }
- .select2-container--bootstrap .select2-selection--single .select2-selection__placeholder {
-+ color: #999999;
-- color: #999;
- }
- .select2-container--bootstrap .select2-selection--multiple {
- min-height: 34px;
- /**
-+ * Make Multi Select2's choices match Bootstrap 3's default button styles.
-+ */
-+
-- * Make Multi Select2's choices match Bootstrap 3's default button styles.
-- */
- /**
-+ * Minus 2px borders.
-+ */
-+
-- * Minus 2px borders.
-- */
- /**
-+ * Clear the selection.
-+ */
-+
-- * Clear the selection.
-- */
- }
- .select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered {
- box-sizing: border-box;
- display: block;
-@@ -288,16 +314,16 @@
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder {
-+ color: #999999;
-- color: #999;
- float: left;
- margin-top: 5px;
- }
- .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
- color: #555555;
-+ background: #ffffff;
-+ border: 1px solid #cccccc;
-- background: #fff;
-- border: 1px solid #ccc;
- border-radius: 4px;
- cursor: default;
- float: left;
- margin: 5px 0 0 6px;
-@@ -323,108 +349,141 @@
- }
- .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
- margin-top: 6px;
- }
-+.select2-container--bootstrap.input-sm,
-+.select2-container--bootstrap.input-lg {
--.select2-container--bootstrap.input-sm, .select2-container--bootstrap.input-lg {
- border-radius: 0;
- font-size: 12px;
- height: auto;
- line-height: 1;
- padding: 0;
- }
-+.select2-container--bootstrap.input-sm .select2-selection--single,
-+.input-group-sm .select2-container--bootstrap .select2-selection--single,
-+.form-group-sm .select2-container--bootstrap .select2-selection--single {
--.select2-container--bootstrap.input-sm .select2-selection--single, .input-group-sm .select2-container--bootstrap .select2-selection--single, .form-group-sm .select2-container--bootstrap .select2-selection--single {
- border-radius: 3px;
- font-size: 12px;
- height: 30px;
- line-height: 1.5;
- padding: 5px 22px 5px 10px;
- /* 2 */
-+
- }
-+.select2-container--bootstrap.input-sm .select2-selection--single .select2-selection__arrow b,
-+.input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,
-+.form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
--.select2-container--bootstrap.input-sm .select2-selection--single .select2-selection__arrow b, .input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, .form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
- margin-left: -5px;
- }
-+.select2-container--bootstrap.input-sm .select2-selection--multiple,
-+.input-group-sm .select2-container--bootstrap .select2-selection--multiple,
-+.form-group-sm .select2-container--bootstrap .select2-selection--multiple {
--.select2-container--bootstrap.input-sm .select2-selection--multiple, .input-group-sm .select2-container--bootstrap .select2-selection--multiple, .form-group-sm .select2-container--bootstrap .select2-selection--multiple {
- min-height: 30px;
- }
-+.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__choice,
-+.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,
-+.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
--.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__choice, .input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, .form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
- font-size: 12px;
- line-height: 1.5;
- margin: 4px 0 0 5px;
- padding: 0 5px;
- }
-+.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-search--inline .select2-search__field,
-+.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,
-+.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
--.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-search--inline .select2-search__field, .input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
- padding: 0 10px;
- font-size: 12px;
- height: 28px;
- line-height: 1.5;
- }
-+.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__clear,
-+.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,
-+.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
--.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__clear, .input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, .form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
- margin-top: 5px;
- }
-+.select2-container--bootstrap.input-lg .select2-selection--single,
-+.input-group-lg .select2-container--bootstrap .select2-selection--single,
-+.form-group-lg .select2-container--bootstrap .select2-selection--single {
--.select2-container--bootstrap.input-lg .select2-selection--single, .input-group-lg .select2-container--bootstrap .select2-selection--single, .form-group-lg .select2-container--bootstrap .select2-selection--single {
- border-radius: 6px;
- font-size: 18px;
- height: 46px;
- line-height: 1.3333333;
- padding: 10px 31px 10px 16px;
- /* 1 */
-+
- }
-+.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow,
-+.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,
-+.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow {
--.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow, .input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow, .form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow {
- width: 5px;
- }
-+.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow b,
-+.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,
-+.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
--.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow b, .input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, .form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b {
- border-width: 5px 5px 0 5px;
- margin-left: -5px;
- margin-left: -10px;
- margin-top: -2.5px;
- }
-+.select2-container--bootstrap.input-lg .select2-selection--multiple,
-+.input-group-lg .select2-container--bootstrap .select2-selection--multiple,
-+.form-group-lg .select2-container--bootstrap .select2-selection--multiple {
--.select2-container--bootstrap.input-lg .select2-selection--multiple, .input-group-lg .select2-container--bootstrap .select2-selection--multiple, .form-group-lg .select2-container--bootstrap .select2-selection--multiple {
- min-height: 46px;
- }
-+.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__choice,
-+.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,
-+.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
--.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__choice, .input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, .form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice {
- font-size: 18px;
- line-height: 1.3333333;
- border-radius: 4px;
- margin: 9px 0 0 8px;
- padding: 0 10px;
- }
-+.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-search--inline .select2-search__field,
-+.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,
-+.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
--.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-search--inline .select2-search__field, .input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field {
- padding: 0 16px;
- font-size: 18px;
- height: 44px;
- line-height: 1.3333333;
- }
-+.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__clear,
-+.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,
-+.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
--.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__clear, .input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, .form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear {
- margin-top: 10px;
- }
- .select2-container--bootstrap.input-lg.select2-container--open .select2-selection--single {
- /**
-+ * Make the dropdown arrow point up while the dropdown is visible.
-+ */
-+
-- * Make the dropdown arrow point up while the dropdown is visible.
-- */
- }
- .select2-container--bootstrap.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b {
-+ border-color: transparent transparent #999999 transparent;
-- border-color: transparent transparent #999 transparent;
- border-width: 0 5px 5px 5px;
- }
- .input-group-lg .select2-container--bootstrap.select2-container--open .select2-selection--single {
- /**
-+ * Make the dropdown arrow point up while the dropdown is visible.
-+ */
-+
-- * Make the dropdown arrow point up while the dropdown is visible.
-- */
- }
- .input-group-lg .select2-container--bootstrap.select2-container--open .select2-selection--single .select2-selection__arrow b {
-+ border-color: transparent transparent #999999 transparent;
-- border-color: transparent transparent #999 transparent;
- border-width: 0 5px 5px 5px;
- }
- .select2-container--bootstrap[dir="rtl"] {
- /**
-+ * Single Select2
-+ *
-+ * 1. Makes sure that .select2-selection__placeholder is positioned
-+ * correctly.
-+ */
-+
-- * Single Select2
-- *
-- * 1. Makes sure that .select2-selection__placeholder is positioned
-- * correctly.
-- */
- /**
-+ * Multiple Select2
-+ */
-+
-- * Multiple Select2
-- */
- }
- .select2-container--bootstrap[dir="rtl"] .select2-selection--single {
- padding-left: 24px;
- padding-right: 12px;
-@@ -433,8 +492,9 @@
- padding-right: 0;
- padding-left: 0;
- text-align: right;
- /* 1 */
-+
- }
- .select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__clear {
- float: left;
- }
-@@ -456,9 +516,8 @@
- .select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
- margin-left: 2px;
- margin-right: auto;
- }
--
- /*------------------------------------*\
- #ADDITIONAL GOODIES
- \*------------------------------------*/
- /**
-@@ -486,9 +545,8 @@
- }
- .has-warning.select2-drop-active.select2-drop.select2-drop-above {
- border-top-color: #66512c;
- }
--
- .has-error .select2-dropdown,
- .has-error .select2-selection {
- border-color: #a94442;
- }
-@@ -503,9 +561,8 @@
- }
- .has-error.select2-drop-active.select2-drop.select2-drop-above {
- border-top-color: #843534;
- }
--
- .has-success .select2-dropdown,
- .has-success .select2-selection {
- border-color: #3c763d;
- }
-@@ -520,9 +577,8 @@
- }
- .has-success.select2-drop-active.select2-drop.select2-drop-above {
- border-top-color: #2b542c;
- }
--
- /**
- * Select2 widgets in Bootstrap Input Groups
- *
- * When Select2 widgets are combined with other elements using Bootstraps
-@@ -548,35 +604,31 @@
- float: left;
- width: 100%;
- margin-bottom: 0;
- }
--
- .input-group.select2-bootstrap-prepend .select2-container--bootstrap .select2-selection {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
- }
--
- .input-group.select2-bootstrap-append .select2-container--bootstrap .select2-selection {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
- }
--
- /**
- * Adjust alignment of Bootstrap buttons in Bootstrap Input Groups to address
- * Multi Select2's height which - depending on how many elements have been selected -
- * may grow taller than its initial size.
- *
- * @see http://getbootstrap.com/components/#input-groups
- */
- .select2-bootstrap-append .select2-container--bootstrap,
-+.select2-bootstrap-prepend .select2-container--bootstrap,
- .select2-bootstrap-append .input-group-btn,
-+.select2-bootstrap-prepend .input-group-btn,
- .select2-bootstrap-append .input-group-btn .btn,
--.select2-bootstrap-prepend .select2-container--bootstrap,
--.select2-bootstrap-prepend .input-group-btn,
- .select2-bootstrap-prepend .input-group-btn .btn {
- vertical-align: top;
- }
--
- /**
- * Temporary fix for https://github.com/select2/select2-bootstrap-theme/issues/9
- *
- * Provides `!important` for certain properties of the class applied to the
-@@ -588,9 +640,8 @@
- .form-control.select2-hidden-accessible {
- position: absolute !important;
- width: 1px !important;
- }
--
- /**
- * Display override for inline forms
- */
- .form-inline .select2-container--bootstrap {
diff --git a/awx/ui/client/lib/select2-bootstrap-theme/tests/support/scss.patch b/awx/ui/client/lib/select2-bootstrap-theme/tests/support/scss.patch
deleted file mode 100755
index 4b2016d8c6..0000000000
--- a/awx/ui/client/lib/select2-bootstrap-theme/tests/support/scss.patch
+++ /dev/null
@@ -1,4 +0,0 @@
-Index: select2-bootstrap.css
-===================================================================
---- select2-bootstrap.css
-+++ select2-bootstrap.css
diff --git a/awx/ui/client/src/activity-stream/activitystream.route.js b/awx/ui/client/src/activity-stream/activitystream.route.js
index 74151e32df..82e85b15f0 100644
--- a/awx/ui/client/src/activity-stream/activitystream.route.js
+++ b/awx/ui/client/src/activity-stream/activitystream.route.js
@@ -15,13 +15,34 @@ export default {
label: "ACTIVITY STREAM"
},
resolve: {
+ features: ['FeaturesService', 'ProcessErrors', '$state', function(FeaturesService, ProcessErrors, $state) {
+ FeaturesService.get()
+ .then(function(features) {
+ if(FeaturesService.featureEnabled('activity_streams')) {
+ // Good to go - pass the features along to the controller.
+ return features;
+ }
+ else {
+ // The activity stream feature isn't enabled. Take the user
+ // back to the dashboard
+ $state.go('dashboard');
+ }
+ })
+ .catch(function (response) {
+ ProcessErrors(null, response.data, response.status, null, {
+ hdr: 'Error!',
+ msg: 'Failed to get feature info. GET returned status: ' +
+ response.status
+ });
+ });
+ }],
subTitle:
[ '$stateParams',
'Rest',
- 'ModelToPlural',
+ 'ModelToBasePathKey',
'GetBasePath',
'ProcessErrors',
- function($stateParams, rest, ModelToPlural, getBasePath, ProcessErrors) {
+ function($stateParams, rest, ModelToBasePathKey, getBasePath, ProcessErrors) {
// If we have a target and an ID then we want to go grab the name of the object
// that we're examining with the activity stream. This name will be used in the
// subtitle.
@@ -29,7 +50,7 @@ export default {
var target = $stateParams.target;
var id = $stateParams.id;
- var url = getBasePath(ModelToPlural(target)) + id + '/';
+ var url = getBasePath(ModelToBasePathKey(target)) + id + '/';
rest.setUrl(url);
return rest.get()
.then(function(data) {
diff --git a/awx/ui/client/src/activity-stream/main.js b/awx/ui/client/src/activity-stream/main.js
index 1b3f169de2..381c421c87 100644
--- a/awx/ui/client/src/activity-stream/main.js
+++ b/awx/ui/client/src/activity-stream/main.js
@@ -7,8 +7,13 @@
import activityStreamRoute from './activitystream.route';
import activityStreamController from './activitystream.controller';
-export default angular.module('activityStream', [])
+import streamDropdownNav from './streamDropdownNav/stream-dropdown-nav.directive';
+
+import streamDetailModal from './streamDetailModal/main';
+
+export default angular.module('activityStream', [streamDetailModal.name])
.controller('activityStreamController', activityStreamController)
+ .directive('streamDropdownNav', streamDropdownNav)
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(activityStreamRoute);
}]);
diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/main.js b/awx/ui/client/src/activity-stream/streamDetailModal/main.js
new file mode 100644
index 0000000000..03533073aa
--- /dev/null
+++ b/awx/ui/client/src/activity-stream/streamDetailModal/main.js
@@ -0,0 +1,11 @@
+/*************************************************
+ * Copyright (c) 2015 Ansible, Inc.
+ *
+ * All Rights Reserved
+ *************************************************/
+
+import streamDetailModalDirective from './streamDetailModal.directive';
+
+export default
+ angular.module('streamDetailModal', [])
+ .directive('streamDetailModal', streamDetailModalDirective);
diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less
new file mode 100644
index 0000000000..ae6de6cdae
--- /dev/null
+++ b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less
@@ -0,0 +1,35 @@
+@import "../shared/branding/colors.default.less";
+
+.StreamDetail-actionButton {
+ padding: 4px 25px!important;
+}
+
+.StreamDetail-inlineRow {
+ margin-bottom: 20px;
+ display: flex;
+}
+
+.StreamDetail-rowTitle {
+ color: @default-interface-txt;
+}
+
+.StreamDetail-inlineRowTitle {
+ flex: 0 0 110px;
+}
+
+.StreamDetail-inlineRowData {
+ flex: 1 0;
+}
+
+.StreamDetail-changesRowTitle {
+ margin-bottom: 5px;
+}
+
+.StreamDetail-changes {
+ border: none;
+ background-color: @default-secondary-bg;
+ margin-bottom: 0;
+ max-height: 200px;
+ overflow: scroll;
+ color: @as-detail-changes-txt;
+}
diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.directive.js b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.directive.js
new file mode 100644
index 0000000000..e144663f96
--- /dev/null
+++ b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.directive.js
@@ -0,0 +1,18 @@
+/*************************************************
+ * Copyright (c) 2015 Ansible, Inc.
+ *
+ * All Rights Reserved
+ *************************************************/
+
+/* jshint unused: vars */
+export default
+ [ 'templateUrl',
+ function(templateUrl) {
+ return {
+ restrict: 'E',
+ scope: true,
+ replace: true,
+ templateUrl: templateUrl('activity-stream/streamDetailModal/streamDetailModal')
+ };
+ }
+ ];
diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html
new file mode 100644
index 0000000000..34c322c72b
--- /dev/null
+++ b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
CHANGES
+
{{ changes | json : spacing}}
+
+
+
+
+
+
diff --git a/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.directive.js b/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.directive.js
new file mode 100644
index 0000000000..b7c71e338a
--- /dev/null
+++ b/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.directive.js
@@ -0,0 +1,51 @@
+/*************************************************
+ * Copyright (c) 2016 Ansible, Inc.
+ *
+ * All Rights Reserved
+ *************************************************/
+
+export default ['templateUrl', function(templateUrl) {
+ return {
+ restrict: 'E',
+ scope: true,
+ replace: true,
+ templateUrl: templateUrl('activity-stream/streamDropdownNav/stream-dropdown-nav'),
+ controller: ['$scope', '$state', 'CreateSelect2', function($scope, $state, CreateSelect2) {
+
+ $scope.streamTarget = ($state.params && $state.params.target) ? $state.params.target : 'dashboard';
+
+ $scope.options = [
+ {label: 'Credentials', value: 'credential'},
+ {label: 'Dashboard', value: 'dashboard'},
+ {label: 'Hosts', value: 'host'},
+ {label: 'Inventories', value: 'inventory'},
+ {label: 'Inventory Scripts', value: 'inventory_script'},
+ {label: 'Job Templates', value: 'job_template'},
+ {label: 'Management Jobs', value: 'management_job'},
+ {label: 'Organizations', value: 'organization'},
+ {label: 'Projects', value: 'project'},
+ {label: 'Schedules', value: 'schedule'},
+ {label: 'Teams', value: 'team'},
+ {label: 'Users', value: 'user'}
+ ];
+
+ CreateSelect2({
+ element:'#stream-dropdown-nav',
+ multiple: false
+ });
+
+ $scope.changeStreamTarget = function(){
+
+ if($scope.streamTarget && $scope.streamTarget == 'dashboard') {
+ // Just navigate to the base activity stream
+ $state.go('activityStream', {}, {inherit: false, reload: true});
+ }
+ else {
+ // Attach the taget to the query parameters
+ $state.go('activityStream', {target: $scope.streamTarget});
+ }
+
+ }
+ }],
+ };
+}];
diff --git a/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.partial.html b/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.partial.html
new file mode 100644
index 0000000000..d70b0ce2f8
--- /dev/null
+++ b/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.partial.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js
index 4bcb2f8e10..c0b72d9dcf 100644
--- a/awx/ui/client/src/app.js
+++ b/awx/ui/client/src/app.js
@@ -557,6 +557,11 @@ var tower = angular.module('Tower', [
url: '/inventories/:inventory_id/manage?groups',
templateUrl: urlPrefix + 'partials/inventory-manage.html',
controller: InventoriesManage,
+ data: {
+ activityStream: true,
+ activityStreamTarget: 'inventory',
+ activityStreamId: 'inventory_id'
+ },
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
@@ -1008,7 +1013,13 @@ var tower = angular.module('Tower', [
}
$rootScope.removeConfigReady = $rootScope.$on('ConfigReady', function() {
// initially set row edit indicator for crud pages
- if ($location.$$path.split("/")[2]) {
+ if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
+ var list = $location.$$path.split("/")[3];
+ var id = $location.$$path.split("/")[4];
+ $rootScope.listBeingEdited = list;
+ $rootScope.rowBeingEdited = id;
+ $rootScope.initialIndicatorLoad = true;
+ } else if ($location.$$path.split("/")[2]) {
var list = $location.$$path.split("/")[1];
var id = $location.$$path.split("/")[2];
$rootScope.listBeingEdited = list;
@@ -1149,7 +1160,19 @@ var tower = angular.module('Tower', [
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
// broadcast event change if editing crud object
- if ($location.$$path.split("/")[2]) {
+ if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
+ var list = $location.$$path.split("/")[3];
+ var id = $location.$$path.split("/")[4];
+
+ if (!$rootScope.initialIndicatorLoad) {
+ delete $rootScope.listBeingEdited;
+ delete $rootScope.rowBeingEdited;
+ } else {
+ delete $rootScope.initialIndicatorLoad;
+ }
+
+ $rootScope.$broadcast("EditIndicatorChange", list, id);
+ } else if ($location.$$path.split("/")[2]) {
var list = $location.$$path.split("/")[1];
var id = $location.$$path.split("/")[2];
diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.directive.js b/awx/ui/client/src/bread-crumb/bread-crumb.directive.js
index 3a0f2ac876..be7ba6ae14 100644
--- a/awx/ui/client/src/bread-crumb/bread-crumb.directive.js
+++ b/awx/ui/client/src/bread-crumb/bread-crumb.directive.js
@@ -1,7 +1,5 @@
-/* jshint unused: vars */
-
export default
- [ 'templateUrl', '$state', function(templateUrl, $state) {
+ [ 'templateUrl', '$state', 'FeaturesService', 'ProcessErrors', function(templateUrl, $state, FeaturesService, ProcessErrors) {
return {
restrict: 'E',
templateUrl: templateUrl('bread-crumb/bread-crumb'),
@@ -32,10 +30,35 @@ export default
streamConfig = (toState && toState.data) ? toState.data : {};
if(streamConfig && streamConfig.activityStream) {
- scope.showActivityStreamButton = true;
+
+ // Check to see if activity_streams is an enabled feature. $stateChangeSuccess fires
+ // after the resolve on the state declaration so features should be available at this
+ // point. We use the get() function call here just in case the features aren't available.
+ // The get() function will only fire off the server call if the features aren't already
+ // attached to the $rootScope.
+
+ FeaturesService.get()
+ .then(function(features) {
+ if(FeaturesService.featureEnabled('activity_streams')) {
+ scope.showActivityStreamButton = true;
+ }
+ else {
+ scope.showActivityStreamButton = false;
+ }
+ })
+ .catch(function (response) {
+ ProcessErrors(null, response.data, response.status, null, {
+ hdr: 'Error!',
+ msg: 'Failed to get feature info. GET returned status: ' +
+ response.status
+ });
+ });
+
}
else {
+
scope.showActivityStreamButton = false;
+
}
});
diff --git a/awx/ui/client/src/config.js b/awx/ui/client/src/config.js
index d420608c51..392489c425 100644
--- a/awx/ui/client/src/config.js
+++ b/awx/ui/client/src/config.js
@@ -26,6 +26,8 @@
var datepicker = $.fn.datepicker.noConflict();
$.fn.systemTrackingDP = datepicker;
+ $.fn.modal.Constructor.DEFAULTS.backdrop = 'static';
+
return {
// custom_logo: true // load /var/lib/awx/public/static/assets/custom_console_logo.png as the login modal header. if false, will load the standard tower console logo
// custom_login_info: "example notice" // have a notice displayed in the login modal for users. note that, as a security measure, custom html is not supported and will be escaped.
diff --git a/awx/ui/client/src/controllers/Credentials.js b/awx/ui/client/src/controllers/Credentials.js
index ddd664c89e..1b951a568e 100644
--- a/awx/ui/client/src/controllers/Credentials.js
+++ b/awx/ui/client/src/controllers/Credentials.js
@@ -14,7 +14,7 @@
export function CredentialsList($scope, $rootScope, $location, $log,
$stateParams, Rest, Alert, CredentialList, GenerateList, Prompt, SearchInit,
PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath,
- SelectionInit, GetChoices, Wait, Stream, $state) {
+ SelectionInit, GetChoices, Wait, $state) {
ClearScope();
@@ -88,11 +88,6 @@ export function CredentialsList($scope, $rootScope, $location, $log,
callback: 'choicesReadyCredential'
});
-
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.addCredential = function () {
$state.transitionTo('credentials.add');
};
@@ -130,7 +125,7 @@ CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log',
'$stateParams', 'Rest', 'Alert', 'CredentialList', 'generateList', 'Prompt',
'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'SelectionInit', 'GetChoices', 'Wait',
- 'Stream', '$state'
+ '$state'
];
@@ -138,7 +133,7 @@ export function CredentialsAdd($scope, $rootScope, $compile, $location, $log,
$stateParams, CredentialForm, GenerateForm, Rest, Alert, ProcessErrors,
ReturnToCaller, ClearScope, GenerateList, SearchInit, PaginateInit,
LookUpInit, UserList, TeamList, GetBasePath, GetChoices, Empty, KindChange,
- OwnerChange, FormSave, $state) {
+ OwnerChange, FormSave, $state, CreateSelect2) {
ClearScope();
@@ -168,6 +163,16 @@ export function CredentialsAdd($scope, $rootScope, $compile, $location, $log,
variable: 'become_options'
});
+ CreateSelect2({
+ element: '#credential_become_method',
+ multiple: false
+ });
+
+ CreateSelect2({
+ element: '#credential_kind',
+ multiple: false
+ });
+
LookUpInit({
scope: $scope,
form: form,
@@ -302,7 +307,7 @@ CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location',
'ProcessErrors', 'ReturnToCaller', 'ClearScope', 'generateList',
'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList',
'GetBasePath', 'GetChoices', 'Empty', 'KindChange', 'OwnerChange',
- 'FormSave', '$state'
+ 'FormSave', '$state', 'CreateSelect2'
];
@@ -310,7 +315,7 @@ export function CredentialsEdit($scope, $rootScope, $compile, $location, $log,
$stateParams, CredentialForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt,
GetBasePath, GetChoices, KindChange, UserList, TeamList, LookUpInit, Empty,
- OwnerChange, FormSave, Stream, Wait, $state) {
+ OwnerChange, FormSave, Wait, $state, CreateSelect2) {
ClearScope();
@@ -454,6 +459,16 @@ export function CredentialsEdit($scope, $rootScope, $compile, $location, $log,
}
master.kind = $scope.kind;
+ CreateSelect2({
+ element: '#credential_become_method',
+ multiple: false
+ });
+
+ CreateSelect2({
+ element: '#credential_kind',
+ multiple: false
+ });
+
switch (data.kind) {
case 'aws':
$scope.access_key = data.username;
@@ -502,9 +517,6 @@ export function CredentialsEdit($scope, $rootScope, $compile, $location, $log,
field: 'become_method',
variable: 'become_options'
});
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
// Save changes to the parent
$scope.formSave = function () {
@@ -619,5 +631,5 @@ CredentialsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices',
'KindChange', 'UserList', 'TeamList', 'LookUpInit', 'Empty', 'OwnerChange',
- 'FormSave', 'Stream', 'Wait', '$state'
+ 'FormSave', 'Wait', '$state', 'CreateSelect2'
];
diff --git a/awx/ui/client/src/controllers/Home.js b/awx/ui/client/src/controllers/Home.js
index 6dc921a1ab..d857330d4b 100644
--- a/awx/ui/client/src/controllers/Home.js
+++ b/awx/ui/client/src/controllers/Home.js
@@ -22,7 +22,7 @@
*/
export function Home($scope, $compile, $stateParams, $rootScope, $location, $log, Wait,
- ClearScope, Stream, Rest, GetBasePath, ProcessErrors, $window, graphData){
+ ClearScope, Rest, GetBasePath, ProcessErrors, $window, graphData){
ClearScope('home');
@@ -103,13 +103,6 @@ export function Home($scope, $compile, $stateParams, $rootScope, $location, $log
$scope.$emit('dashboardDataLoadComplete');
});
-
- $scope.showActivity = function () {
- Stream({
- scope: $scope
- });
- };
-
$scope.refresh = function () {
Wait('start');
Rest.setUrl(GetBasePath('dashboard'));
@@ -145,7 +138,7 @@ export function Home($scope, $compile, $stateParams, $rootScope, $location, $log
}
Home.$inject = ['$scope', '$compile', '$stateParams', '$rootScope', '$location', '$log','Wait',
- 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', '$window', 'graphData'
+ 'ClearScope', 'Rest', 'GetBasePath', 'ProcessErrors', '$window', 'graphData'
];
@@ -157,7 +150,7 @@ Home.$inject = ['$scope', '$compile', '$stateParams', '$rootScope', '$location',
*
*/
export function HomeGroups($rootScope, $log, $scope, $filter, $compile, $location, $stateParams, LogViewer, HomeGroupList, GenerateList, ProcessErrors, ReturnToCaller, ClearScope,
- GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Stream, GroupsEdit, Wait,
+ GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, GroupsEdit, Wait,
Alert, Rest, Empty, InventoryUpdate, Find, GroupsCancelUpdate, Store) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
@@ -364,12 +357,6 @@ export function HomeGroups($rootScope, $log, $scope, $filter, $compile, $locatio
}
});
- scope.showActivity = function () {
- Stream({
- scope: scope
- });
- };
-
scope.editGroup = function (group_id, inventory_id) {
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({
@@ -579,7 +566,7 @@ export function HomeGroups($rootScope, $log, $scope, $filter, $compile, $locatio
HomeGroups.$inject = ['$rootScope', '$log', '$scope', '$filter', '$compile', '$location', '$stateParams', 'LogViewer', 'HomeGroupList', 'generateList', 'ProcessErrors', 'ReturnToCaller',
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'GetHostsStatusMsg', 'GetSyncStatusMsg', 'ViewUpdateStatus',
- 'Stream', 'GroupsEdit', 'Wait', 'Alert', 'Rest', 'Empty', 'InventoryUpdate', 'Find', 'GroupsCancelUpdate', 'Store', 'Socket'
+ 'GroupsEdit', 'Wait', 'Alert', 'Rest', 'Empty', 'InventoryUpdate', 'Find', 'GroupsCancelUpdate', 'Store', 'Socket'
];
/**
@@ -591,7 +578,7 @@ HomeGroups.$inject = ['$rootScope', '$log', '$scope', '$filter', '$compile', '$l
*/
export function HomeHosts($scope, $location, $stateParams, HomeHostList, GenerateList, ProcessErrors, ReturnToCaller, ClearScope,
- GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Stream, Find, ShowJobSummary, ViewJob) {
+ GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Find, ShowJobSummary, ViewJob) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@@ -664,12 +651,6 @@ export function HomeHosts($scope, $location, $stateParams, HomeHostList, Generat
ViewJob({ scope: $scope, id: id });
};
- $scope.showActivity = function () {
- Stream({
- scope: $scope
- });
- };
-
$scope.toggleHostEnabled = function (id, sources) {
ToggleHostEnabled({
host_id: id,
@@ -705,6 +686,6 @@ export function HomeHosts($scope, $location, $stateParams, HomeHostList, Generat
}
HomeHosts.$inject = ['$scope', '$location', '$stateParams', 'HomeHostList', 'generateList', 'ProcessErrors', 'ReturnToCaller',
- 'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'SetStatus', 'ToggleHostEnabled', 'HostsEdit', 'Stream',
+ 'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'SetStatus', 'ToggleHostEnabled', 'HostsEdit',
'Find', 'ShowJobSummary', 'ViewJob'
];
diff --git a/awx/ui/client/src/controllers/Inventories.js b/awx/ui/client/src/controllers/Inventories.js
index b4b17f3fa9..a506d78ead 100644
--- a/awx/ui/client/src/controllers/Inventories.js
+++ b/awx/ui/client/src/controllers/Inventories.js
@@ -15,7 +15,7 @@ import '../job-templates/main';
export function InventoriesList($scope, $rootScope, $location, $log,
$stateParams, $compile, $filter, sanitizeFilter, Rest, Alert, InventoryList,
generateList, Prompt, SearchInit, PaginateInit, ReturnToCaller,
- ClearScope, ProcessErrors, GetBasePath, Wait, Stream,
+ ClearScope, ProcessErrors, GetBasePath, Wait,
EditInventoryProperties, Find, Empty, LogViewer, $state) {
var list = InventoryList,
@@ -301,10 +301,6 @@ export function InventoriesList($scope, $rootScope, $location, $log,
});
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.editInventoryProperties = function (inventory_id) {
EditInventoryProperties({ scope: $scope, inventory_id: inventory_id });
};
@@ -368,7 +364,7 @@ export function InventoriesList($scope, $rootScope, $location, $log,
InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$stateParams', '$compile', '$filter', 'sanitizeFilter', 'Rest', 'Alert', 'InventoryList', 'generateList',
'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
- 'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties', 'Find', 'Empty', 'LogViewer', '$state'
+ 'GetBasePath', 'Wait', 'EditInventoryProperties', 'Find', 'Empty', 'LogViewer', '$state'
];
@@ -462,7 +458,7 @@ export function InventoriesEdit($scope, $rootScope, $compile, $location,
$log, $stateParams, InventoryForm, GenerateForm, Rest, Alert, ProcessErrors,
ReturnToCaller, ClearScope, generateList, OrganizationList, SearchInit,
PaginateInit, LookUpInit, GetBasePath, ParseTypeChange, Wait, ToJSON,
- ParseVariableString, Stream, RelatedSearchInit, RelatedPaginateInit,
+ ParseVariableString, RelatedSearchInit, RelatedPaginateInit,
Prompt, PlaybookRun, CreateDialog, deleteJobTemplate, $state) {
ClearScope();
@@ -590,10 +586,6 @@ export function InventoriesEdit($scope, $rootScope, $compile, $location,
$location.path($location.path() + '/manage');
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.formCancel = function () {
$state.transitionTo('inventories');
};
@@ -776,7 +768,7 @@ InventoriesEdit.$inject = ['$scope', '$rootScope', '$compile', '$location',
'ProcessErrors', 'ReturnToCaller', 'ClearScope', 'generateList',
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit',
'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON', 'ParseVariableString',
- 'Stream', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
+ 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
'PlaybookRun', 'CreateDialog', 'deleteJobTemplate', '$state'
];
@@ -788,7 +780,7 @@ export function InventoriesManage ($log, $scope, $rootScope, $location,
InjectHosts, Find, HostsReload, SearchInit, PaginateInit, GetSyncStatusMsg,
GetHostsStatusMsg, GroupsEdit, InventoryUpdate, GroupsCancelUpdate,
ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete,
- EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary,
+ EditInventoryProperties, ToggleHostEnabled, ShowJobSummary,
InventoryGroupsHelp, HelpDialog, ViewJob,
GroupsCopy, HostsCopy, $stateParams) {
@@ -1248,53 +1240,6 @@ export function InventoriesManage ($log, $scope, $rootScope, $location,
});
};
- $scope.showGroupActivity = function () {
- var url, title, group;
- if ($scope.selected_group_id) {
- url = GetBasePath('activity_stream') + '?group__id=' + $scope.selected_group_id;
- title = 'Showing all activities for group ' + group.name;
- } else {
- title = 'Showing all activities for all ' + $scope.inventory.name + ' groups';
- url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory.id;
- }
- Stream({
- scope: $scope,
- inventory_name: $scope.inventory.name,
- url: url,
- title: title,
- search_iterator: 'group',
- onClose: 'GroupStreamClosed'
- });
- };
-
- if ($scope.removeGroupStreamClosed) {
- $scope.removeGroupStreamClosed();
- }
- $scope.removeGroupStreamClosed = $scope.$on('GroupStreamClosed', function() {
- $scope.refreshGroups();
- });
-
- hostScope.showHostActivity = function () {
- var url, title;
- title = 'Showing all activities for all ' + $scope.inventory.name + ' hosts';
- url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory.id;
- Stream({
- scope: hostScope,
- inventory_name: $scope.inventory.name,
- url: url,
- title: title,
- search_iterator: 'host',
- onClose: 'HostStreamClosed'
- });
- };
-
- if (hostScope.removeHostStreamClosed) {
- hostScope.removeHostStreamClosed();
- }
- hostScope.removeHostStreamClosed = hostScope.$on('HostStreamClosed', function() {
- $scope.refreshGroups();
- });
-
hostScope.showJobSummary = function (job_id) {
ShowJobSummary({
job_id: job_id
@@ -1347,7 +1292,7 @@ InventoriesManage.$inject = ['$log', '$scope', '$rootScope', '$location',
'SearchInit', 'PaginateInit', 'GetSyncStatusMsg', 'GetHostsStatusMsg',
'GroupsEdit', 'InventoryUpdate', 'GroupsCancelUpdate', 'ViewUpdateStatus',
'GroupsDelete', 'Store', 'HostsEdit', 'HostsDelete',
- 'EditInventoryProperties', 'ToggleHostEnabled', 'Stream', 'ShowJobSummary',
+ 'EditInventoryProperties', 'ToggleHostEnabled', 'ShowJobSummary',
'InventoryGroupsHelp', 'HelpDialog', 'ViewJob', 'GroupsCopy',
'HostsCopy', '$stateParams'
];
diff --git a/awx/ui/client/src/controllers/JobTemplates.js b/awx/ui/client/src/controllers/JobTemplates.js
index 6c1969ea53..b01dc04a48 100644
--- a/awx/ui/client/src/controllers/JobTemplates.js
+++ b/awx/ui/client/src/controllers/JobTemplates.js
@@ -15,7 +15,7 @@ export function JobTemplatesList($scope, $rootScope, $location, $log,
$stateParams, Rest, Alert, JobTemplateList, GenerateList, Prompt,
SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
GetBasePath, JobTemplateForm, CredentialList, LookUpInit, PlaybookRun,
- Wait, Stream, CreateDialog, $compile, $state) {
+ Wait, CreateDialog, $compile, $state) {
ClearScope();
@@ -58,12 +58,6 @@ export function JobTemplatesList($scope, $rootScope, $location, $log,
$scope.search(list.iterator);
-
-
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.addJobTemplate = function () {
$state.transitionTo('jobTemplates.add');
};
@@ -239,14 +233,14 @@ export function JobTemplatesList($scope, $rootScope, $location, $log,
$scope.scheduleJob = function (id) {
$state.go('jobTemplateSchedules', {id: id});
- }
+ };
}
JobTemplatesList.$inject = ['$scope', '$rootScope', '$location', '$log',
'$stateParams', 'Rest', 'Alert', 'JobTemplateList', 'generateList',
'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'JobTemplateForm', 'CredentialList',
- 'LookUpInit', 'PlaybookRun', 'Wait', 'Stream', 'CreateDialog' , '$compile',
+ 'LookUpInit', 'PlaybookRun', 'Wait', 'CreateDialog' , '$compile',
'$state'
];
@@ -255,7 +249,7 @@ export function JobTemplatesAdd(Refresh, $filter, $scope, $rootScope, $compile,
ProcessErrors, ReturnToCaller, ClearScope, GetBasePath, InventoryList,
CredentialList, ProjectList, LookUpInit, md5Setup, ParseTypeChange, Wait,
Empty, ToJSON, CallbackHelpInit, SurveyControllerInit, Prompt, GetChoices,
- $state) {
+ $state, CreateSelect2) {
ClearScope();
@@ -377,6 +371,21 @@ export function JobTemplatesAdd(Refresh, $filter, $scope, $rootScope, $compile,
msg: 'Failed to lookup inventory: ' + data.id + '. GET returned status: ' + status });
});
}
+ CreateSelect2({
+ element:'#job_templates_job_type',
+ multiple: false
+ });
+
+ CreateSelect2({
+ element:'#playbook-select',
+ multiple: false
+ });
+
+ CreateSelect2({
+ element:'#job_templates_verbosity',
+ multiple: false
+ });
+
$scope.$emit('lookUpInitialize');
}
});
@@ -675,7 +684,8 @@ JobTemplatesAdd.$inject = ['Refresh', '$filter', '$scope', '$rootScope', '$compi
'Rest', 'Alert', 'ProcessErrors', 'ReturnToCaller', 'ClearScope',
'GetBasePath', 'InventoryList', 'CredentialList', 'ProjectList',
'LookUpInit', 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON',
- 'CallbackHelpInit', 'initSurvey', 'Prompt', 'GetChoices', '$state'
+ 'CallbackHelpInit', 'initSurvey', 'Prompt', 'GetChoices', '$state',
+ 'CreateSelect2'
];
@@ -684,9 +694,10 @@ export function JobTemplatesEdit($filter, $scope, $rootScope, $compile,
ProcessErrors, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller,
ClearScope, InventoryList, CredentialList, ProjectList, LookUpInit,
GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate, Wait,
- Stream, Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit,
+ Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit,
JobsControllerInit, JobsListUpdate, GetChoices, SchedulesListInit,
- SchedulesList, CallbackHelpInit, PlaybookRun, SurveyControllerInit, $state){
+ SchedulesList, CallbackHelpInit, PlaybookRun, SurveyControllerInit, $state,
+ CreateSelect2){
ClearScope();
@@ -852,6 +863,21 @@ export function JobTemplatesEdit($filter, $scope, $rootScope, $compile,
$scope.removeJobTemplateLoadFinished();
}
$scope.removeJobTemplateLoadFinished = $scope.$on('jobTemplateLoadFinished', function () {
+ CreateSelect2({
+ element:'#job_templates_job_type',
+ multiple: false
+ });
+
+ CreateSelect2({
+ element:'#playbook-select',
+ multiple: false
+ });
+
+ CreateSelect2({
+ element:'#job_templates_verbosity',
+ multiple: false
+ });
+
for (var set in relatedSets) {
$scope.search(relatedSets[set].iterator);
}
@@ -1157,12 +1183,6 @@ export function JobTemplatesEdit($filter, $scope, $rootScope, $compile,
};
- $scope.showActivity = function () {
- Stream({
- scope: $scope
- });
- };
-
$scope.formCancel = function () {
$state.transitionTo('jobTemplates');
};
@@ -1245,9 +1265,9 @@ JobTemplatesEdit.$inject = ['$filter', '$scope', '$rootScope', '$compile',
'Rest', 'Alert', 'ProcessErrors', 'RelatedSearchInit',
'RelatedPaginateInit','ReturnToCaller', 'ClearScope', 'InventoryList',
'CredentialList', 'ProjectList', 'LookUpInit', 'GetBasePath', 'md5Setup',
- 'ParseTypeChange', 'JobStatusToolTip', 'FormatDate', 'Wait', 'Stream',
+ 'ParseTypeChange', 'JobStatusToolTip', 'FormatDate', 'Wait',
'Empty', 'Prompt', 'ParseVariableString', 'ToJSON',
'SchedulesControllerInit', 'JobsControllerInit', 'JobsListUpdate',
'GetChoices', 'SchedulesListInit', 'SchedulesList', 'CallbackHelpInit',
- 'PlaybookRun' , 'initSurvey', '$state'
+ 'PlaybookRun' , 'initSurvey', '$state', 'CreateSelect2'
];
diff --git a/awx/ui/client/src/controllers/Organizations.js b/awx/ui/client/src/controllers/Organizations.js
index e0e5e9e36d..c4966d257c 100644
--- a/awx/ui/client/src/controllers/Organizations.js
+++ b/awx/ui/client/src/controllers/Organizations.js
@@ -13,7 +13,7 @@
export function OrganizationsList($stateParams, $scope, $rootScope, $location,
$log, Rest, Alert, Prompt, ClearScope, ProcessErrors, GetBasePath, Wait,
- Stream, $state) {
+ $state) {
ClearScope();
@@ -111,10 +111,6 @@ export function OrganizationsList($stateParams, $scope, $rootScope, $location,
$('#prompt-modal').modal('hide');
});
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.addOrganization = function () {
$state.transitionTo('organizations.add');
};
@@ -156,7 +152,7 @@ export function OrganizationsList($stateParams, $scope, $rootScope, $location,
OrganizationsList.$inject = ['$stateParams', '$scope', '$rootScope',
'$location', '$log', 'Rest', 'Alert', 'Prompt', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'Wait',
- 'Stream', '$state'
+ '$state'
];
@@ -217,7 +213,7 @@ OrganizationsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location',
export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
$stateParams, OrganizationForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath,
- Wait, Stream, $state) {
+ Wait, $state) {
ClearScope();
@@ -306,12 +302,6 @@ export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
});
};
- $scope.showActivity = function () {
- Stream({
- scope: $scope
- });
- };
-
$scope.formCancel = function () {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
@@ -363,5 +353,5 @@ export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
OrganizationsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location',
'$log', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
- 'ClearScope', 'GetBasePath', 'Wait', 'Stream', '$state'
+ 'ClearScope', 'GetBasePath', 'Wait', '$state'
];
diff --git a/awx/ui/client/src/controllers/Portal.js b/awx/ui/client/src/controllers/Portal.js
index 9707e84676..3af1791528 100644
--- a/awx/ui/client/src/controllers/Portal.js
+++ b/awx/ui/client/src/controllers/Portal.js
@@ -19,7 +19,7 @@
*
*
*/
-export function PortalController($scope, $compile, $stateParams, $rootScope, $location, $log, Wait, ClearScope, Stream, Rest, GetBasePath, ProcessErrors,
+export function PortalController($scope, $compile, $stateParams, $rootScope, $location, $log, Wait, ClearScope, Rest, GetBasePath, ProcessErrors,
PortalJobsWidget, GenerateList, PortalJobTemplateList, SearchInit, PaginateInit, PlaybookRun){
ClearScope('portal');
@@ -137,6 +137,6 @@ export function PortalController($scope, $compile, $stateParams, $rootScope, $lo
}
-PortalController.$inject = ['$scope', '$compile', '$stateParams', '$rootScope', '$location', '$log','Wait', 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors',
+PortalController.$inject = ['$scope', '$compile', '$stateParams', '$rootScope', '$location', '$log','Wait', 'ClearScope', 'Rest', 'GetBasePath', 'ProcessErrors',
'PortalJobsWidget', 'generateList' , 'PortalJobTemplateList', 'SearchInit', 'PaginateInit', 'PlaybookRun'
];
diff --git a/awx/ui/client/src/controllers/Projects.js b/awx/ui/client/src/controllers/Projects.js
index 45b9180497..d7f5786b6d 100644
--- a/awx/ui/client/src/controllers/Projects.js
+++ b/awx/ui/client/src/controllers/Projects.js
@@ -14,7 +14,7 @@
export function ProjectsList ($scope, $rootScope, $location, $log, $stateParams,
Rest, Alert, ProjectList, GenerateList, Prompt, SearchInit,
PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath,
- SelectionInit, ProjectUpdate, Refresh, Wait, Stream, GetChoices, Empty,
+ SelectionInit, ProjectUpdate, Refresh, Wait, GetChoices, Empty,
Find, LogViewer, GetProjectIcon, GetProjectToolTip, $filter, $state) {
ClearScope();
@@ -192,10 +192,6 @@ export function ProjectsList ($scope, $rootScope, $location, $log, $stateParams,
callback: 'choicesReadyProjectList'
});
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.addProject = function () {
$state.transitionTo('projects.add');
};
@@ -377,7 +373,7 @@ ProjectsList.$inject = ['$scope', '$rootScope', '$location', '$log',
'$stateParams', 'Rest', 'Alert', 'ProjectList', 'generateList', 'Prompt',
'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'SelectionInit', 'ProjectUpdate',
- 'Refresh', 'Wait', 'Stream', 'GetChoices', 'Empty', 'Find',
+ 'Refresh', 'Wait', 'GetChoices', 'Empty', 'Find',
'LogViewer', 'GetProjectIcon', 'GetProjectToolTip', '$filter', '$state'
];
@@ -385,7 +381,8 @@ ProjectsList.$inject = ['$scope', '$rootScope', '$location', '$log',
export function ProjectsAdd(Refresh, $scope, $rootScope, $compile, $location, $log,
$stateParams, ProjectsForm, GenerateForm, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, LookUpInit,
- OrganizationList, CredentialList, GetChoices, DebugForm, Wait, $state) {
+ OrganizationList, CredentialList, GetChoices, DebugForm, Wait, $state,
+ CreateSelect2) {
ClearScope();
@@ -413,6 +410,12 @@ export function ProjectsAdd(Refresh, $scope, $rootScope, $compile, $location, $l
break;
}
}
+
+ CreateSelect2({
+ element: '#project_scm_type',
+ multiple: false
+ });
+
$scope.scmRequired = false;
master.scm_type = $scope.scm_type;
});
@@ -527,7 +530,7 @@ ProjectsAdd.$inject = ['Refresh', '$scope', '$rootScope', '$compile', '$location
'$stateParams', 'ProjectsForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ReturnToCaller',
'GetProjectPath', 'LookUpInit', 'OrganizationList', 'CredentialList',
- 'GetChoices', 'DebugForm', 'Wait', '$state'
+ 'GetChoices', 'DebugForm', 'Wait', '$state', 'CreateSelect2'
];
@@ -535,8 +538,8 @@ export function ProjectsEdit($scope, $rootScope, $compile, $location, $log,
$stateParams, ProjectsForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath,
ReturnToCaller, GetProjectPath, Authorization, CredentialList, LookUpInit,
- GetChoices, Empty, DebugForm, Wait, Stream, SchedulesControllerInit,
- SchedulesListInit, SchedulesList, ProjectUpdate, $state) {
+ GetChoices, Empty, DebugForm, Wait, SchedulesControllerInit,
+ SchedulesListInit, SchedulesList, ProjectUpdate, $state, CreateSelect2) {
ClearScope('htmlTemplate');
@@ -673,6 +676,10 @@ export function ProjectsEdit($scope, $rootScope, $compile, $location, $log,
}
master.scm_type = $scope.scm_type;
+ CreateSelect2({
+ element: '#project_scm_type',
+ multiple: false
+ });
$scope.scmBranchLabel = ($scope.scm_type.value === 'svn') ? 'Revision #' : 'SCM Branch';
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
@@ -761,10 +768,6 @@ export function ProjectsEdit($scope, $rootScope, $compile, $location, $log,
});
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
// Related set: Add button
$scope.add = function (set) {
$rootScope.flashMessage = null;
@@ -830,6 +833,6 @@ ProjectsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
'ClearScope', 'GetBasePath', 'ReturnToCaller', 'GetProjectPath',
'Authorization', 'CredentialList', 'LookUpInit', 'GetChoices', 'Empty',
- 'DebugForm', 'Wait', 'Stream', 'SchedulesControllerInit',
- 'SchedulesListInit', 'SchedulesList', 'ProjectUpdate', '$state'
+ 'DebugForm', 'Wait', 'SchedulesControllerInit', 'SchedulesListInit',
+ 'SchedulesList', 'ProjectUpdate', '$state', 'CreateSelect2'
];
diff --git a/awx/ui/client/src/controllers/Schedules.js b/awx/ui/client/src/controllers/Schedules.js
index 3fbff0d3ee..3245776e64 100644
--- a/awx/ui/client/src/controllers/Schedules.js
+++ b/awx/ui/client/src/controllers/Schedules.js
@@ -12,7 +12,7 @@
export function ScheduleEditController($scope, $compile, $location, $stateParams, SchedulesList, Rest, ProcessErrors, ReturnToCaller, ClearScope,
-GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices, Stream) {
+GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices) {
ClearScope();
@@ -70,10 +70,6 @@ GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices, Stre
$scope.search(SchedulesList.iterator);
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
Wait('start');
GetChoices({
@@ -86,4 +82,4 @@ GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices, Stre
}
ScheduleEditController.$inject = [ '$scope', '$compile', '$location', '$stateParams', 'SchedulesList', 'Rest', 'ProcessErrors', 'ReturnToCaller', 'ClearScope',
- 'GetBasePath', 'Wait', 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices', 'Stream' ];
+ 'GetBasePath', 'Wait', 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices'];
diff --git a/awx/ui/client/src/controllers/Teams.js b/awx/ui/client/src/controllers/Teams.js
index ec2421a765..7d71bd8ee2 100644
--- a/awx/ui/client/src/controllers/Teams.js
+++ b/awx/ui/client/src/controllers/Teams.js
@@ -14,7 +14,7 @@
export function TeamsList($scope, $rootScope, $location, $log, $stateParams,
Rest, Alert, TeamList, GenerateList, Prompt, SearchInit, PaginateInit,
ReturnToCaller, ClearScope, ProcessErrors, SetTeamListeners, GetBasePath,
- SelectionInit, Wait, Stream, $state, Refresh) {
+ SelectionInit, Wait, $state, Refresh) {
ClearScope();
@@ -79,10 +79,6 @@ export function TeamsList($scope, $rootScope, $location, $log, $stateParams,
});
$scope.search(list.iterator);
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.addTeam = function () {
$state.transitionTo('teams.add');
};
@@ -126,7 +122,7 @@ TeamsList.$inject = ['$scope', '$rootScope', '$location', '$log',
'$stateParams', 'Rest', 'Alert', 'TeamList', 'generateList', 'Prompt',
'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors', 'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait',
- 'Stream', '$state', 'Refresh'
+ '$state', 'Refresh'
];
@@ -196,7 +192,7 @@ export function TeamsEdit($scope, $rootScope, $compile, $location, $log,
$stateParams, TeamForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope,
LookUpInit, Prompt, GetBasePath, CheckAccess, OrganizationList, Wait,
- Stream, fieldChoices, fieldLabels, permissionsSearchSelect, $state) {
+ fieldChoices, fieldLabels, permissionsSearchSelect, $state) {
ClearScope();
@@ -327,10 +323,6 @@ export function TeamsEdit($scope, $rootScope, $compile, $location, $log,
}
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
// Save changes to the parent
$scope.formSave = function () {
var data = {}, fld;
@@ -440,6 +432,6 @@ TeamsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log',
'$stateParams', 'TeamForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt', 'GetBasePath',
- 'CheckAccess', 'OrganizationList', 'Wait', 'Stream', 'fieldChoices',
+ 'CheckAccess', 'OrganizationList', 'Wait', 'fieldChoices',
'fieldLabels', 'permissionsSearchSelect', '$state'
];
diff --git a/awx/ui/client/src/controllers/Users.js b/awx/ui/client/src/controllers/Users.js
index 06e1e0f881..f6b6b74a13 100644
--- a/awx/ui/client/src/controllers/Users.js
+++ b/awx/ui/client/src/controllers/Users.js
@@ -14,7 +14,7 @@
export function UsersList($scope, $rootScope, $location, $log, $stateParams,
Rest, Alert, UserList, GenerateList, Prompt, SearchInit, PaginateInit,
ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit,
- Wait, Stream, $state, Refresh) {
+ Wait, $state, Refresh) {
ClearScope();
@@ -71,10 +71,6 @@ export function UsersList($scope, $rootScope, $location, $log, $stateParams,
});
$scope.search(list.iterator);
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.addUser = function () {
$state.transitionTo('users.add');
};
@@ -115,7 +111,7 @@ export function UsersList($scope, $rootScope, $location, $log, $stateParams,
UsersList.$inject = ['$scope', '$rootScope', '$location', '$log',
'$stateParams', 'Rest', 'Alert', 'UserList', 'generateList', 'Prompt',
'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
- 'ProcessErrors', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream', '$state',
+ 'ProcessErrors', 'GetBasePath', 'SelectionInit', 'Wait', '$state',
'Refresh'
];
@@ -226,7 +222,7 @@ UsersAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log',
export function UsersEdit($scope, $rootScope, $compile, $location, $log,
$stateParams, UserForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope,
- GetBasePath, Prompt, CheckAccess, ResetForm, Wait, Stream, fieldChoices,
+ GetBasePath, Prompt, CheckAccess, ResetForm, Wait, fieldChoices,
fieldLabels, permissionsSearchSelect, $state) {
ClearScope();
@@ -399,10 +395,6 @@ export function UsersEdit($scope, $rootScope, $compile, $location, $log,
}
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
$scope.formCancel = function () {
$state.transitionTo('users');
};
@@ -551,6 +543,6 @@ UsersEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log',
'$stateParams', 'UserForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'GetBasePath', 'Prompt', 'CheckAccess',
- 'ResetForm', 'Wait', 'Stream', 'fieldChoices', 'fieldLabels',
+ 'ResetForm', 'Wait', 'fieldChoices', 'fieldLabels',
'permissionsSearchSelect', '$state'
];
diff --git a/awx/ui/client/src/forms/ActivityDetail.js b/awx/ui/client/src/forms/ActivityDetail.js
index 88a6dde4e5..7c879f778d 100644
--- a/awx/ui/client/src/forms/ActivityDetail.js
+++ b/awx/ui/client/src/forms/ActivityDetail.js
@@ -41,7 +41,7 @@ export default
changes: {
label: 'Changes',
type: 'textarea',
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
ngHide: "!changes || changes =='' || changes == 'null'",
readonly: true
}
diff --git a/awx/ui/client/src/forms/Credentials.js b/awx/ui/client/src/forms/Credentials.js
index 1673b84b6a..9921b3a27c 100644
--- a/awx/ui/client/src/forms/Credentials.js
+++ b/awx/ui/client/src/forms/Credentials.js
@@ -263,7 +263,7 @@ export default
variable: 'key_required',
init: true
},
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
hintText: "{{ key_hint }}",
addRequired: false,
editRequired: false,
diff --git a/awx/ui/client/src/forms/Groups.js b/awx/ui/client/src/forms/Groups.js
index de27d45d57..186ff5134f 100644
--- a/awx/ui/client/src/forms/Groups.js
+++ b/awx/ui/client/src/forms/Groups.js
@@ -39,7 +39,7 @@ export default
variables: {
label: 'Variables',
type: 'textarea',
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
addRequired: false,
editRequird: false,
rows: 12,
diff --git a/awx/ui/client/src/forms/JobTemplates.js b/awx/ui/client/src/forms/JobTemplates.js
index d8fe7267a4..d8511147f8 100644
--- a/awx/ui/client/src/forms/JobTemplates.js
+++ b/awx/ui/client/src/forms/JobTemplates.js
@@ -177,6 +177,7 @@ export default
rows: 1,
addRequired: false,
editRequired: false,
+ 'elementClass': 'Form-textInput',
column: 2,
awPopOver: "Provide a comma separated list of tags.
\n" +
"Tags are useful when you have a large playbook, and you want to run a specific part of a play or task.
" +
@@ -191,7 +192,7 @@ export default
variables: {
label: 'Extra Variables',
type: 'textarea',
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
rows: 6,
addRequired: false,
editRequired: false,
diff --git a/awx/ui/client/src/forms/Projects.js b/awx/ui/client/src/forms/Projects.js
index 0260229773..3019bc9a69 100644
--- a/awx/ui/client/src/forms/Projects.js
+++ b/awx/ui/client/src/forms/Projects.js
@@ -58,6 +58,7 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
scm_type: {
label: 'SCM Type',
type: 'select',
+ class: 'Form-dropDown--scmType',
ngOptions: 'type.label for type in scm_type_options track by type.value',
ngChange: 'scmChange()',
addRequired: true,
diff --git a/awx/ui/client/src/forms/Source.js b/awx/ui/client/src/forms/Source.js
index 4b3f8838db..1eee07b344 100644
--- a/awx/ui/client/src/forms/Source.js
+++ b/awx/ui/client/src/forms/Source.js
@@ -126,7 +126,7 @@ export default
label: 'Environment Variables', //"{{vars_label}}" ,
ngShow: "source && source.value=='custom' ",
type: 'textarea',
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
addRequired: false,
editRequired: false,
rows: 6,
@@ -145,7 +145,7 @@ export default
label: 'Source Variables', //"{{vars_label}}" ,
ngShow: "source && (source.value == 'file' || source.value == 'ec2')",
type: 'textarea',
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
addRequired: false,
editRequird: false,
rows: 6,
@@ -172,7 +172,7 @@ export default
"source.value == 'openstack')",
type: 'textarea',
addRequired: false,
- class: 'Form-textArea',
+ class: 'Form-textAreaLabel',
editRequird: false,
rows: 6,
'default': '---',
diff --git a/awx/ui/client/src/helpers/ApiModel.js b/awx/ui/client/src/helpers/ApiModel.js
index 6a63d24583..ff1923ce0a 100644
--- a/awx/ui/client/src/helpers/ApiModel.js
+++ b/awx/ui/client/src/helpers/ApiModel.js
@@ -12,88 +12,45 @@
export default
angular.module('ApiModelHelper', ['Utilities'])
- .factory('ModelToSingular', [
+ .factory('ModelToBasePathKey', [
function () {
return function (model) {
- // This function takes in the plural model string and spits out the singular
- // version.
+ // This function takes in the singular model string and returns the key needed
+ // to get the base path from $rootScope/local storage.
- var singularModel;
-
- switch(model) {
- case 'projects':
- singularModel = 'project';
- break;
- case 'inventories':
- singularModel = 'inventory';
- break;
- case 'job_templates':
- singularModel = 'job_template';
- break;
- case 'credentials':
- singularModel = 'credential';
- break;
- case 'users':
- singularModel = 'user';
- break;
- case 'teams':
- singularModel = 'team';
- break;
- case 'organizations':
- singularModel = 'organization';
- break;
- case 'management_jobs':
- singularModel = 'management_job';
- break;
- case 'inventory_scripts':
- singularModel = 'inventory_script';
- break;
- }
-
- return singularModel;
-
- };
- }
- ])
- .factory('ModelToPlural', [
- function () {
- return function (model) {
- // This function takes in the singular model string and spits out the plural
- // version.
-
- var pluralModel;
+ var basePathKey;
switch(model) {
case 'project':
- pluralModel = 'projects';
+ basePathKey = 'projects';
break;
case 'inventory':
- pluralModel = 'inventories';
+ basePathKey = 'inventory';
break;
case 'job_template':
- pluralModel = 'job_templates';
+ basePathKey = 'job_templates';
break;
case 'credential':
- pluralModel = 'credentials';
+ basePathKey = 'credentials';
break;
case 'user':
- pluralModel = 'users';
+ basePathKey = 'users';
break;
case 'team':
- pluralModel = 'teams';
+ basePathKey = 'teams';
break;
case 'organization':
- pluralModel = 'organizations';
+ basePathKey = 'organizations';
break;
case 'management_job':
- pluralModel = 'management_jobs';
+ basePathKey = 'management_jobs';
break;
case 'inventory_script':
- pluralModel = 'inventory_scripts';
+ basePathKey = 'inventory_scripts';
break;
}
- return pluralModel;
+ return basePathKey;
};
}
diff --git a/awx/ui/client/src/helpers/Groups.js b/awx/ui/client/src/helpers/Groups.js
index d1c34783f3..920c4641bc 100644
--- a/awx/ui/client/src/helpers/Groups.js
+++ b/awx/ui/client/src/helpers/Groups.js
@@ -236,8 +236,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', listGenerator.name
* TODO: Document
*
*/
-.factory('SourceChange', ['GetBasePath', 'CredentialList', 'LookUpInit', 'Empty', 'Wait', 'ParseTypeChange', 'inventoryScriptsListObject', 'CreateSelect2',
- function (GetBasePath, CredentialList, LookUpInit, Empty, Wait, ParseTypeChange, inventoryScriptsListObject, CreateSelect2) {
+.factory('SourceChange', ['GetBasePath', 'CredentialList', 'LookUpInit',
+ 'Empty', 'Wait', 'ParseTypeChange', 'inventoryScriptsListObject',
+ 'CreateSelect2',
+ function (GetBasePath, CredentialList, LookUpInit, Empty, Wait,
+ ParseTypeChange, inventoryScriptsListObject, CreateSelect2) {
return function (params) {
var scope = params.scope,
@@ -258,9 +261,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', listGenerator.name
if (scope.source.value === 'rax') {
scope.source_region_choices = scope.rax_regions;
$('#source_form').addClass('squeeze');
- CreateSelect2({
- element: '#source_source_regions'
- });
+ CreateSelect2({
+ element: '#source_source_regions'
+ });
} else if (scope.source.value === 'ec2') {
scope.source_region_choices = scope.ec2_regions;
scope.group_by_choices = scope.ec2_group_by;
@@ -279,10 +282,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', listGenerator.name
});
} else if (scope.source.value === 'azure') {
scope.source_region_choices = scope.azure_regions;
- $('#source_form').addClass('squeeze');
- CreateSelect2({
- element: '#source_source_regions'
- });
+ $('#source_form').addClass('squeeze');
+ CreateSelect2({
+ element: '#source_source_regions'
+ });
}
if(scope.source.value==="custom"){
// need to filter the possible custom scripts by the organization defined for the current inventory
@@ -1152,6 +1155,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', listGenerator.name
sources_scope.removeChoicesReady();
}
sources_scope.removeChoicesReady = sources_scope.$on('choicesReadyGroup', function () {
+ CreateSelect2({
+ element: '#source_source',
+ multiple: false
+ });
choicesReady++;
if (choicesReady === 2) {
if (mode === 'edit') {
diff --git a/awx/ui/client/src/helpers/related-search.js b/awx/ui/client/src/helpers/related-search.js
index 750864d60a..cad094d349 100644
--- a/awx/ui/client/src/helpers/related-search.js
+++ b/awx/ui/client/src/helpers/related-search.js
@@ -86,7 +86,7 @@ export default
if (form.related[set].fields[f].searchType &&
(form.related[set].fields[f].searchType === 'boolean' || form.related[set].fields[f].searchType === 'select')) {
scope[iterator + 'SelectShow'] = true;
- scope[iterator + 'SearchSelectOpts'] = form.fields[f].searchOptions;
+ scope[iterator + 'SearchSelectOpts'] = form.related[set].fields[f].searchOptions;
}
if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType === 'gtzero') {
scope[iterator + "InputHide"] = true;
@@ -162,13 +162,6 @@ export default
scope[iterator + 'Loading'] = false;
scope[iterator + 'HoldInput'] = true;
- if(scope[iterator + 'SearchValue'] && scope[iterator + 'SearchValue'] != '') {
- scope[iterator + '_active_search'] = true;
- }
- else {
- scope[iterator + '_active_search'] = false;
- }
-
if (scope[iterator + 'SearchValue']) {
// User typed a value in input field
scope[iterator + 'ShowStartBtn'] = false;
diff --git a/awx/ui/client/src/helpers/search.js b/awx/ui/client/src/helpers/search.js
index 5f42d8d27a..33f7ec5c86 100644
--- a/awx/ui/client/src/helpers/search.js
+++ b/awx/ui/client/src/helpers/search.js
@@ -333,6 +333,8 @@ export default
var i, modifier,
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
+ scope[iterator + '_active_search'] = false;
+
for (i = 1; i <= widgets; i++) {
modifier = (i === 1) ? '' : i;
if ($('#search-widget-container' + modifier)) {
@@ -342,6 +344,7 @@ export default
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchObject !== 'all') {
// An object type is selected
scope[iterator + 'HideAllStartBtn' + modifier] = false;
+ scope[iterator + '_active_search'] = true;
if (scope[iterator + 'SearchValue' + modifier]) {
// A search value was entered
scope[iterator + 'ShowStartBtn' + modifier] = false;
@@ -369,6 +372,7 @@ export default
}
}
}
+
e.stopPropagation();
scope.$emit('prepareSearch2', iterator, page, load, calcOnly, deferWaitStop);
@@ -401,6 +405,7 @@ export default
(scope[iterator + 'SelectShow' + modifier] && scope[iterator + 'SearchSelectValue' + modifier]) ||
(list.fields[scope[iterator + 'SearchField' + modifier]] &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero')) {
+ scope[iterator + '_active_search'] = true;
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchField) {
scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].searchField + '__';
} else if (list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel) {
diff --git a/awx/ui/client/src/inventory-scripts/list/list.controller.js b/awx/ui/client/src/inventory-scripts/list/list.controller.js
index 1dad7b230d..293bd7c4a4 100644
--- a/awx/ui/client/src/inventory-scripts/list/list.controller.js
+++ b/awx/ui/client/src/inventory-scripts/list/list.controller.js
@@ -7,11 +7,11 @@
export default
[ '$rootScope','Wait', 'generateList', 'inventoryScriptsListObject',
'GetBasePath' , 'SearchInit' , 'PaginateInit',
- 'Rest' , 'ProcessErrors', 'Prompt', '$state', 'Stream',
+ 'Rest' , 'ProcessErrors', 'Prompt', '$state',
function(
$rootScope,Wait, GenerateList, inventoryScriptsListObject,
GetBasePath, SearchInit, PaginateInit,
- Rest, ProcessErrors, Prompt, $state, Stream
+ Rest, ProcessErrors, Prompt, $state
) {
var scope = $rootScope.$new(),
defaultUrl = GetBasePath('inventory_scripts'),
@@ -49,10 +49,6 @@ export default
});
};
- scope.showActivity = function () {
- Stream({ scope: scope });
- };
-
scope.deleteCustomInv = function(id, name){
var action = function () {
diff --git a/awx/ui/client/src/lists/HomeHosts.js b/awx/ui/client/src/lists/HomeHosts.js
index 9d36d7dc2c..ffa5fc2d52 100644
--- a/awx/ui/client/src/lists/HomeHosts.js
+++ b/awx/ui/client/src/lists/HomeHosts.js
@@ -13,6 +13,7 @@ export default
iterator: 'host',
selectTitle: 'Add Existing Hosts',
editTitle: 'Hosts',
+ listTitle: 'Hosts',
index: false,
hover: true,
well: true,
diff --git a/awx/ui/client/src/lists/Schedules.js b/awx/ui/client/src/lists/Schedules.js
index c6bed3edfa..2dfe3fc120 100644
--- a/awx/ui/client/src/lists/Schedules.js
+++ b/awx/ui/client/src/lists/Schedules.js
@@ -18,29 +18,40 @@ export default
hover: true,
fields: {
+ toggleSchedule: {
+ label: '',
+ columnClass: 'List-staticColumn--toggle',
+ type: "toggle",
+ ngClick: "toggleSchedule($event, schedule.id)",
+ awToolTip: "{{ schedule.play_tip }}",
+ dataTipWatch: "schedule.play_tip",
+ dataPlacement: "right",
+ searchable: false,
+ nosort: true,
+ },
name: {
key: true,
label: 'Name',
ngClick: "editSchedule(schedule.id)",
- columnClass: "col-md-3 col-sm-3 col-xs-3"
+ columnClass: "col-md-3 col-sm-3 col-xs-6"
},
dtstart: {
label: 'First Run',
filter: "longDate",
searchable: false,
- columnClass: "col-md-2 col-sm-3 hidden-xs"
+ columnClass: "List-staticColumn--schedulerTime hidden-sm hidden-xs"
},
next_run: {
label: 'Next Run',
filter: "longDate",
searchable: false,
- columnClass: "col-md-2 col-sm-3 col-xs-3"
+ columnClass: "List-staticColumn--schedulerTime hidden-xs"
},
dtend: {
label: 'Final Run',
filter: "longDate",
searchable: false,
- columnClass: "col-md-2 col-sm-3 hidden-xs"
+ columnClass: "List-staticColumn--schedulerTime hidden-xs"
}
},
@@ -63,14 +74,6 @@ export default
},
fieldActions: {
- "play": {
- mode: "all",
- ngClick: "toggleSchedule($event, schedule.id)",
- awToolTip: "{{ schedule.play_tip }}",
- dataTipWatch: "schedule.play_tip",
- iconClass: "{{ 'fa icon-schedule-enabled-' + schedule.enabled }}",
- dataPlacement: "top"
- },
edit: {
label: 'Edit',
ngClick: "editSchedule(schedule.id)",
diff --git a/awx/ui/client/src/lists/Streams.js b/awx/ui/client/src/lists/Streams.js
index 1cc99c4d7c..4cf443c0b8 100644
--- a/awx/ui/client/src/lists/Streams.js
+++ b/awx/ui/client/src/lists/Streams.js
@@ -14,11 +14,13 @@ export default
editTitle: 'Activity Stream',
listTitle: 'Activity Stream{{streamSubTitle}}',
listTitleBadge: false,
+ emptyListText: 'There are no events to display at this time',
selectInstructions: '',
index: false,
hover: true,
"class": "table-condensed",
searchWidgets: 3,
+ toolbarAuxAction: "",
fields: {
timestamp: {
diff --git a/awx/ui/client/src/management-jobs/list/list.controller.js b/awx/ui/client/src/management-jobs/card/card.controller.js
similarity index 89%
rename from awx/ui/client/src/management-jobs/list/list.controller.js
rename to awx/ui/client/src/management-jobs/card/card.controller.js
index fbc098f0b1..e9d5c4409c 100644
--- a/awx/ui/client/src/management-jobs/list/list.controller.js
+++ b/awx/ui/client/src/management-jobs/card/card.controller.js
@@ -7,49 +7,37 @@
// import listGenerator from 'tower/shared/list-generator/main';
export default
- [ 'Wait', '$location' , '$compile', 'CreateDialog', 'generateList',
+ [ 'Wait', '$location' , '$compile', 'CreateDialog',
'GetBasePath' , 'SearchInit' , 'PaginateInit',
'SchedulesList',
'Rest' , 'ProcessErrors', 'managementJobsListObject', '$rootScope',
- '$state', 'Stream',
- function( Wait, $location, $compile, CreateDialog, GenerateList,
+ '$state','$scope',
+ function( Wait, $location, $compile, CreateDialog,
GetBasePath, SearchInit, PaginateInit,
SchedulesList,
Rest, ProcessErrors, managementJobsListObject, $rootScope,
- $state, Stream) {
+ $state, $scope) {
+
+ var defaultUrl = GetBasePath('system_job_templates');
+ var getManagementJobs = function(){
+ Rest.setUrl(defaultUrl);
+ Rest.get()
+ .success(function(data){
+ $scope.mgmtCards = data.results;
+ Wait('stop');
+ })
+ .error(function(data, status){
+ ProcessErrors($scope, data, status, null, {hdr: 'Error!',
+ msg: 'Call to '+ defaultUrl + ' failed. Return status: '+ status});
+ });
+ };
+ getManagementJobs();
var scope = $rootScope.$new(),
parent_scope = scope,
- defaultUrl = GetBasePath('system_job_templates'),
- list = managementJobsListObject,
- view = GenerateList;
-
+ list = managementJobsListObject;
scope.cleanupJob = true;
- view.inject( list, {
- mode: 'edit',
- scope: scope,
- showSearch: true
- });
-
- SearchInit({
- scope: scope,
- set: 'configure_jobs',
- list: list,
- url: defaultUrl
- });
-
- PaginateInit({
- scope: scope,
- list: list,
- url: defaultUrl
- });
-
- scope.search(list.iterator);
-
- scope.showActivity = function () {
- Stream({ scope: scope });
- };
// Cancel
scope.cancelConfigure = function () {
@@ -71,7 +59,7 @@ export default
}
};
- scope.submitCleanupJob = function(id, name){
+ $scope.submitCleanupJob = function(id, name){
defaultUrl = GetBasePath('system_job_templates')+id+'/launch/';
CreateDialog({
id: 'prompt-for-days-facts',
@@ -174,7 +162,7 @@ export default
});
};
- scope.submitJob = function (id, name) {
+ $scope.submitJob = function (id, name) {
Wait('start');
if(this.configure_job.job_type === "cleanup_facts"){
scope.submitCleanupJob(id, name);
@@ -250,10 +238,10 @@ export default
}
};
- scope.configureSchedule = function() {
+ $scope.configureSchedule = function() {
$state.transitionTo('managementJobsSchedule', {
- management_job: this.configure_job,
- management_job_id: this.configure_job.id
+ management_job: this.job_type,
+ management_job_id: this.card.id
});
};
diff --git a/awx/ui/client/src/management-jobs/card/card.partial.html b/awx/ui/client/src/management-jobs/card/card.partial.html
new file mode 100644
index 0000000000..3b4cfec9ba
--- /dev/null
+++ b/awx/ui/client/src/management-jobs/card/card.partial.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
{{card.description || "Place organization description here"}}
+
+
+
\ No newline at end of file
diff --git a/awx/ui/client/src/management-jobs/list/list.route.js b/awx/ui/client/src/management-jobs/card/card.route.js
similarity index 85%
rename from awx/ui/client/src/management-jobs/list/list.route.js
rename to awx/ui/client/src/management-jobs/card/card.route.js
index 7301ebffe2..7f177b9b5a 100644
--- a/awx/ui/client/src/management-jobs/list/list.route.js
+++ b/awx/ui/client/src/management-jobs/card/card.route.js
@@ -9,8 +9,8 @@ import {templateUrl} from '../../shared/template-url/template-url.factory';
export default {
name: 'managementJobsList',
route: '/management_jobs',
- templateUrl: templateUrl('management-jobs/list/list'),
- controller: 'managementJobsListController',
+ templateUrl: templateUrl('management-jobs/card/card'),
+ controller: 'managementJobsCardController',
data: {
activityStream: true,
activityStreamTarget: 'management_job'
diff --git a/awx/ui/client/src/management-jobs/list/main.js b/awx/ui/client/src/management-jobs/card/main.js
similarity index 61%
rename from awx/ui/client/src/management-jobs/list/main.js
rename to awx/ui/client/src/management-jobs/card/main.js
index 85c1367893..e21f7f7e73 100644
--- a/awx/ui/client/src/management-jobs/list/main.js
+++ b/awx/ui/client/src/management-jobs/card/main.js
@@ -4,12 +4,12 @@
* All Rights Reserved
*************************************************/
-import route from './list.route';
-import controller from './list.controller';
+import route from './card.route';
+import controller from './card.controller';
export default
- angular.module('managementJobsList', [])
- .controller('managementJobsListController', controller)
+ angular.module('managementJobsCard', [])
+ .controller('managementJobsCardController', controller)
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route);
}]);
diff --git a/awx/ui/client/src/management-jobs/card/mgmtcards.block.less b/awx/ui/client/src/management-jobs/card/mgmtcards.block.less
new file mode 100644
index 0000000000..1f83e43df2
--- /dev/null
+++ b/awx/ui/client/src/management-jobs/card/mgmtcards.block.less
@@ -0,0 +1,116 @@
+/** @define MgmtCards */
+
+.MgmtCards {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.MgmtCards-card {
+ background-color: #fff;
+ padding: 20px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+ margin-top: 20px;
+}
+
+.MgmtCards-card--selected {
+ padding-left: 16px;
+ border-left: 5px solid #1678C4;
+}
+
+.MgmtCards-header {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: baseline;
+ width: 100%;
+}
+
+.MgmtCards-label {
+ margin-top: 0px;
+ text-transform: uppercase;
+ font-size: 14px;
+ font-weight: bold;
+ color: #848992;
+ margin-bottom: 25px;
+ white-space: nowrap;
+}
+
+.MgmtCards-actionItems {
+ margin-left: auto;
+ display: flex;
+ flex-wrap: nowrap;
+}
+
+.MgmtCards-actionItem {
+ margin-left: 15px;
+}
+
+.MgmtCards-description {
+ margin-bottom: 20px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.MgmtCards-links {
+ width: 100%;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
+
+.MgmtCards-link {
+ flex: initial;
+ width: ~"calc(50% - 20px)";
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-bottom: 20px;
+}
+
+.MgmtCards-linkBadge {
+ margin-right: 10px;
+}
+
+@media (min-width: 1179px) {
+ .MgmtCards-card {
+ width: ~"calc(25% - 15px)";
+ margin-right: 20px;
+ }
+
+ .MgmtCards-card:nth-child(4n+4) {
+ margin-right: 0px;
+ }
+}
+
+@media (min-width: 901px) and (max-width: 1178px) {
+ .MgmtCards-card {
+ width: ~"calc(33% - 11px)";
+ margin-right: 20px;
+ }
+
+ .MgmtCards-card:nth-child(3n+3) {
+ margin-right: 0px;
+ }
+}
+
+@media (min-width: 616px) and (max-width: 900px) {
+ .MgmtCards-card {
+ width: ~"calc(50% - 10px)";
+ margin-right: 20px;
+ }
+
+ .MgmtCards-card:nth-child(2n+2) {
+ margin-right: 0px;
+ }
+}
+
+@media (max-width: 615px) {
+ .MgmtCards-card {
+ width: 100%;
+ margin-right: 0px;
+ }
+}
diff --git a/awx/ui/client/src/management-jobs/list/list.partial.html b/awx/ui/client/src/management-jobs/list/list.partial.html
deleted file mode 100644
index 4a42a0a48d..0000000000
--- a/awx/ui/client/src/management-jobs/list/list.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/awx/ui/client/src/management-jobs/main.js b/awx/ui/client/src/management-jobs/main.js
index 392e5edd41..b374b84857 100644
--- a/awx/ui/client/src/management-jobs/main.js
+++ b/awx/ui/client/src/management-jobs/main.js
@@ -4,13 +4,13 @@
* All Rights Reserved
*************************************************/
-import managementJobsList from './list/main';
+import managementJobsCard from './card/main';
import managementJobsSchedule from './schedule/main';
import list from './management-jobs.list';
export default
angular.module('managementJobs', [
- managementJobsList.name,
+ managementJobsCard.name,
managementJobsSchedule.name
])
.factory('managementJobsListObject', list);
diff --git a/awx/ui/client/src/management-jobs/schedule/schedule.controller.js b/awx/ui/client/src/management-jobs/schedule/schedule.controller.js
index a25c997e7e..c83b378674 100644
--- a/awx/ui/client/src/management-jobs/schedule/schedule.controller.js
+++ b/awx/ui/client/src/management-jobs/schedule/schedule.controller.js
@@ -13,10 +13,10 @@
export default [
'$scope', '$location', '$stateParams', 'SchedulesList', 'Rest',
'ProcessErrors', 'GetBasePath', 'Wait','LoadSchedulesScope', 'GetChoices',
- 'Stream', 'management_job', '$rootScope',
+ 'management_job', '$rootScope',
function($scope, $location, $stateParams, SchedulesList, Rest,
ProcessErrors, GetBasePath, Wait, LoadSchedulesScope, GetChoices,
- Stream, management_job, $rootScope) {
+ management_job, $rootScope) {
var base, id, url, parentObject;
$scope.management_job = management_job;
base = $location.path().replace(/^\//, '').split('/')[0];
@@ -76,10 +76,6 @@ export default [
$scope.search(SchedulesList.iterator);
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
Wait('start');
GetChoices({
diff --git a/awx/ui/client/src/partials/subhome.html b/awx/ui/client/src/partials/subhome.html
index bb93d2d709..626c7e4b23 100644
--- a/awx/ui/client/src/partials/subhome.html
+++ b/awx/ui/client/src/partials/subhome.html
@@ -1,13 +1,13 @@
-
+
-
\ No newline at end of file
+
diff --git a/awx/ui/client/src/scheduler/repeatFrequencyOptions.block.less b/awx/ui/client/src/scheduler/repeatFrequencyOptions.block.less
new file mode 100644
index 0000000000..956ad9e3ce
--- /dev/null
+++ b/awx/ui/client/src/scheduler/repeatFrequencyOptions.block.less
@@ -0,0 +1,139 @@
+/** @define RepeatFrequencyOptions */
+
+.RepeatFrequencyOptions {
+ width: ~"calc(100% + 21px)";
+ padding: 20px;
+ border-left: 5px solid #e8e8e8;
+ margin-left: -20px;
+ padding-left: 17px;
+ padding-right: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ align-items: flex-start;
+}
+
+.RepeatFrequencyOptions-formGroup {
+ padding-right: 0px;
+}
+
+@media (min-width: 901px) {
+ .RepeatFrequencyOptions-formGroup {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ width: ~"calc(33% - 32px)";
+ margin-right: 50px;
+ }
+
+ .RepeatFrequencyOptions-formGroup:nth-child(3n+3) {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ margin-right: 0px;
+ }
+}
+
+@media (min-width: 651px) and (max-width: 900px) {
+ .RepeatFrequencyOptions-formGroup {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ width: ~"calc(50% - 25px)";
+ margin-right: 50px;
+ }
+
+ .RepeatFrequencyOptions-formGroup:nth-child(2n+2) {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ margin-right: 0px;
+ }
+}
+
+@media (max-width: 650px) {
+ .RepeatFrequencyOptions-formGroup {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ width: 100%;
+ margin-right: 0px;
+ }
+}
+
+.RepeatFrequencyOptions-label {
+ width: 100%;
+ margin-top: -2px;
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #848992;
+ font-size: 13px;
+ margin-left: -20px;
+ border-left: 5px solid #e8e8e8;
+ padding-left: 15px;
+ padding-bottom: 15px;
+}
+
+.RepeatFrequencyOptions-weekButtonContainer {
+ width: 100%;
+}
+
+.RepeatFrequencyOptions-weekButtonGroup {
+ height: 27px;
+ width: 100%;
+ display: flex;
+}
+
+.RepeatFrequencyOptions-weekButton {
+ height: 27px;
+ padding-top: 2px;
+ padding-right: 4px;
+ padding-left: 4px;
+ flex: 1;
+}
+
+.RepeatFrequencyOptions-everyGroup {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+}
+
+.RepeatFrequencyOptions-inlineLabel {
+ font-weight: normal;
+ color: #848992;
+ text-transform: uppercase;
+ flex: initial;
+ width: 54px;
+ margin-left: 10px;
+ font-size: 13px;
+}
+
+.RepeatFrequencyOptions-occurencesGroup {
+ width: 100%;
+}
+
+.RepeatFrequencyOptions-radioLabel {
+ margin-top: 0px;
+ margin-bottom: 5px;
+}
+
+.RepeatFrequencyOptions-everyLabel {
+ margin-top: 2px;
+}
+
+.RepeatFrequencyOptions-spacedSelect {
+ margin-bottom: 10px;
+}
+
+.RepeatFrequencyOptions-subFormBorderFixer {
+ height: 25px;
+ width: 5px;
+ background: #ffffff;
+ margin-left: -20px;
+ margin-top: -25px;
+ margin-right: 50px;
+}
+
+.RepeatFrequencyOptions-monthlyOccurence,
+.RepeatFrequencyOptions-yearlyOccurence {
+ text-transform: capitalize;
+}
+
+.RepeatFrequencyOptions-error {
+ flex: initial;
+ width: 100%;
+}
diff --git a/awx/ui/client/src/scheduler/scheduleToggle.block.less b/awx/ui/client/src/scheduler/scheduleToggle.block.less
new file mode 100644
index 0000000000..f7015f4dc1
--- /dev/null
+++ b/awx/ui/client/src/scheduler/scheduleToggle.block.less
@@ -0,0 +1,52 @@
+/** @define ScheduleToggle */
+
+.ScheduleToggle {
+ border-radius: 5px;
+ border: 1px solid #b7b7b7;
+ background-color: #b7b7b7;
+ width: 40px;
+ margin-top: 2px;
+ cursor: pointer;
+}
+
+.ScheduleToggle-switch {
+ color: #848992;
+ background-color: #fff;
+ margin-left: 4px;
+ border-left: 1px solid #b7b7b7;
+ margin-right: 0px;
+ text-align: center;
+ text-transform: uppercase;
+ font-size: 11px;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+
+.ScheduleToggle.is-on {
+ border-color: #1678c4;
+ background-color: #fff;
+}
+
+.ScheduleToggle-switch.is-on {
+ margin-right: 5px;
+ margin-left: 0px;
+ background-color: #1678c4;
+ color: #fff;
+ border-left: 0;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0px;
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+
+.ScheduleToggle-switch:hover {
+ background-color: #fafafa;
+}
+
+.ScheduleToggle.is-on:hover {
+ border-color: #4498DA;
+}
+
+.ScheduleToggle-switch.is-on:hover {
+ background-color: #4498DA;
+}
diff --git a/awx/ui/client/src/scheduler/scheduler.controller.js b/awx/ui/client/src/scheduler/scheduler.controller.js
index e014eae18b..d53ea19e28 100644
--- a/awx/ui/client/src/scheduler/scheduler.controller.js
+++ b/awx/ui/client/src/scheduler/scheduler.controller.js
@@ -13,11 +13,10 @@
export default [
'$scope', '$compile', '$location', '$stateParams', 'SchedulesList', 'Rest', 'ProcessErrors', 'ReturnToCaller', 'ClearScope',
- 'GetBasePath', 'Wait', 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices', 'Stream',
+ 'GetBasePath', 'Wait', 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices',
function ($scope, $compile, $location, $stateParams,
SchedulesList, Rest, ProcessErrors, ReturnToCaller, ClearScope,
- GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices,
- Stream) {
+ GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices) {
ClearScope();
@@ -79,10 +78,6 @@ export default [
$scope.search(SchedulesList.iterator);
};
- $scope.showActivity = function () {
- Stream({ scope: $scope });
- };
-
Wait('start');
GetChoices({
diff --git a/awx/ui/client/src/scheduler/schedulerAdd.controller.js b/awx/ui/client/src/scheduler/schedulerAdd.controller.js
index c04db19cab..a6eb3e12be 100644
--- a/awx/ui/client/src/scheduler/schedulerAdd.controller.js
+++ b/awx/ui/client/src/scheduler/schedulerAdd.controller.js
@@ -1,21 +1,41 @@
-export default ['$compile', '$state', '$stateParams', 'AddSchedule', 'Wait', '$scope', function($compile, $state, $stateParams, AddSchedule, Wait, $scope) {
+export default ['$compile', '$state', '$stateParams', 'AddSchedule', 'Wait', '$scope', '$rootScope', function($compile, $state, $stateParams, AddSchedule, Wait, $scope, $rootScope) {
$scope.$on("ScheduleFormCreated", function(e, scope) {
$scope.hideForm = false;
$scope = angular.extend($scope, scope);
- $scope.$watchGroup(["schedulerStartDt",
+
+ $scope.$on("formUpdated", function() {
+ $rootScope.$broadcast("loadSchedulerDetailPane");
+ });
+
+ $scope.$watchGroup(["schedulerName",
+ "schedulerStartDt",
"schedulerStartHour",
"schedulerStartMinute",
"schedulerStartSecond",
"schedulerTimeZone",
"schedulerFrequency",
- "schedulerInterval"], function(val) {
- if (!$scope.scheduler_form.$invalid) {
- $scope.schedulerIsValid = true;
- } else {
- $scope.schedulerIsValid = false;
- }
- return val;
- });
+ "schedulerInterval",
+ "monthlyRepeatOption",
+ "monthDay",
+ "monthlyOccurrence",
+ "monthlyWeekDay",
+ "yearlyRepeatOption",
+ "yearlyMonth",
+ "yearlyMonthDay",
+ "yearlyOccurrence",
+ "yearlyWeekDay",
+ "yearlyOtherMonth",
+ "schedulerEnd",
+ "schedulerOccurrenceCount",
+ "schedulerEndDt"
+ ], function() {
+ $scope.$emit("formUpdated");
+ }, true);
+
+ $scope.$watch("weekDays", function() {
+ $scope.$emit("formUpdated");
+ }, true);
+
Wait('stop');
});
diff --git a/awx/ui/client/src/scheduler/schedulerEdit.controller.js b/awx/ui/client/src/scheduler/schedulerEdit.controller.js
index b23836f98a..82d9fa26e4 100644
--- a/awx/ui/client/src/scheduler/schedulerEdit.controller.js
+++ b/awx/ui/client/src/scheduler/schedulerEdit.controller.js
@@ -1,24 +1,47 @@
-export default ['$compile', '$state', '$stateParams', 'EditSchedule', 'Wait', '$scope', function($compile, $state, $stateParams, EditSchedule, Wait, $scope) {
+export default ['$compile', '$state', '$stateParams', 'EditSchedule', 'Wait', '$scope', '$rootScope', function($compile, $state, $stateParams, EditSchedule, Wait, $scope, $rootScope) {
$scope.$on("ScheduleFormCreated", function(e, scope) {
$scope.hideForm = false;
$scope = angular.extend($scope, scope);
- $scope.$watchGroup(["schedulerStartDt",
+
+ $scope.$on("formUpdated", function() {
+ $rootScope.$broadcast("loadSchedulerDetailPane");
+ });
+
+ $scope.$watchGroup(["schedulerName",
+ "schedulerStartDt",
"schedulerStartHour",
"schedulerStartMinute",
"schedulerStartSecond",
"schedulerTimeZone",
"schedulerFrequency",
- "schedulerInterval"], function(val) {
- if (!$scope.scheduler_form.$invalid) {
- $scope.schedulerIsValid = true;
- } else {
- $scope.schedulerIsValid = false;
- }
- return val;
- });
+ "schedulerInterval",
+ "monthlyRepeatOption",
+ "monthDay",
+ "monthlyOccurrence",
+ "monthlyWeekDay",
+ "yearlyRepeatOption",
+ "yearlyMonth",
+ "yearlyMonthDay",
+ "yearlyOccurrence",
+ "yearlyWeekDay",
+ "yearlyOtherMonth",
+ "schedulerEnd",
+ "schedulerOccurrenceCount",
+ "schedulerEndDt"
+ ], function() {
+ $scope.$emit("formUpdated");
+ }, true);
+
+ $scope.$watch("weekDays", function() {
+ $scope.$emit("formUpdated");
+ }, true);
+
+ $rootScope.$broadcast("loadSchedulerDetailPane");
Wait('stop');
});
+ $scope.isEdit = true;
+
$scope.hideForm = true;
$scope.formCancel = function() {
diff --git a/awx/ui/client/src/scheduler/schedulerForm.block.less b/awx/ui/client/src/scheduler/schedulerForm.block.less
new file mode 100644
index 0000000000..9cba269e75
--- /dev/null
+++ b/awx/ui/client/src/scheduler/schedulerForm.block.less
@@ -0,0 +1,44 @@
+/** @define SchedulerForm */
+
+.SchedulerForm-formGroup {
+ padding-right: 0px;
+}
+
+@media (min-width: 901px) {
+ .SchedulerForm-formGroup {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ width: ~"calc(33% - 32px)";
+ margin-right: 50px;
+ }
+
+ .SchedulerForm-formGroup:nth-child(3n+3) {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ margin-right: 0px;
+ }
+}
+
+@media (min-width: 651px) and (max-width: 900px) {
+ .SchedulerForm-formGroup {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ width: ~"calc(50% - 25px)";
+ margin-right: 50px;
+ }
+
+ .SchedulerForm-formGroup:nth-child(2n+2) {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ margin-right: 0px;
+ }
+}
+
+@media (max-width: 650px) {
+ .SchedulerForm-formGroup {
+ flex: 0 0 auto;
+ margin-bottom: 25px;
+ width: 100%;
+ margin-right: 0px;
+ }
+}
diff --git a/awx/ui/client/src/scheduler/schedulerForm.partial.html b/awx/ui/client/src/scheduler/schedulerForm.partial.html
index 6c545ab941..af503a49ce 100644
--- a/awx/ui/client/src/scheduler/schedulerForm.partial.html
+++ b/awx/ui/client/src/scheduler/schedulerForm.partial.html
@@ -1,6 +1,7 @@