diff --git a/.gitignore b/.gitignore
index 7e0f07a83c..9e7a41e6cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,8 +34,6 @@ awx/ui_next/coverage/
awx/ui_next/build
awx/ui_next/.env.local
rsyslog.pid
-/tower-license
-/tower-license/**
tools/prometheus/data
tools/docker-compose/Dockerfile
@@ -147,3 +145,4 @@ use_dev_supervisor.txt
.idea/*
*.unison.tmp
*.#
+/tools/docker-compose/overrides/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f04a26ae3..c50243b1e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,22 @@
This is a list of high-level changes for each release of AWX. A full list of commits can be found at `https://github.com/ansible/awx/releases/tag/`.
+## 15.0.1 (October 20, 2020)
+- Added several optimizations to improve performance for a variety of high-load simultaneous job launch use cases https://github.com/ansible/awx/pull/8403
+- Added the ability to source roles and collections from requirements.yaml files (not just requirements.yml) - https://github.com/ansible/awx/issues/4540
+- awx.awx collection modules now provide a clearer error message for incompatible versions of awxkit - https://github.com/ansible/awx/issues/8127
+- Fixed a bug in notification messages that contain certain unicode characters - https://github.com/ansible/awx/issues/7400
+- Fixed a bug that prevents the deletion of Workflow Approval records - https://github.com/ansible/awx/issues/8305
+- Fixed a bug that broke the selection of webhook credentials - https://github.com/ansible/awx/issues/7892
+- Fixed a bug which can cause confusing behavior for social auth logins across distinct browser tabs - https://github.com/ansible/awx/issues/8154
+- Fixed several bugs in the output of Workflow Job Templates using the `awx export` tool - https://github.com/ansible/awx/issues/7798 https://github.com/ansible/awx/pull/7847
+- Fixed a race condition that can lead to missing hosts when running parallel inventory syncs - https://github.com/ansible/awx/issues/5571
+- Fixed an HTTP 500 error when certain LDAP group parameters aren't properly set - https://github.com/ansible/awx/issues/7622
+- Updated a few dependencies in response to several CVEs:
+ * CVE-2020-7720
+ * CVE-2020-7743
+ * CVE-2020-7676
+
## 15.0.0 (September 30, 2020)
- Added improved support for fetching Ansible collections from private Galaxy content sources (such as https://github.com/ansible/galaxy_ng) - https://github.com/ansible/awx/issues/7813
**Note:** as part of this change, new Organizations created in the AWX API will _no longer_ automatically synchronize roles and collections from galaxy.ansible.com by default. More details on this change can be found at: https://github.com/ansible/awx/issues/8341#issuecomment-707310633
diff --git a/INSTALL.md b/INSTALL.md
index 6bc3f869d0..dfbd0cbe7e 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -78,6 +78,8 @@ Before you can run a deployment, you'll need the following installed in your loc
- [docker](https://pypi.org/project/docker/) Python module
+ This is incompatible with `docker-py`. If you have previously installed `docker-py`, please uninstall it.
+ We use this module instead of `docker-py` because it is what the `docker-compose` Python module requires.
+- [community.general.docker_image collection](https://docs.ansible.com/ansible/latest/collections/community/general/docker_image_module.html)
+ + This is only required if you are using Ansible >= 2.10
- [GNU Make](https://www.gnu.org/software/make/)
- [Git](https://git-scm.com/) Requires Version 1.8.4+
- Python 3.6+
diff --git a/MANIFEST.in b/MANIFEST.in
index 6260b87cea..1466361602 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,8 +4,6 @@ recursive-include awx *.mo
recursive-include awx/static *
recursive-include awx/templates *.html
recursive-include awx/api/templates *.md *.html
-recursive-include awx/ui/templates *.html
-recursive-include awx/ui/static *
recursive-include awx/ui_next/build *.html
recursive-include awx/ui_next/build *
recursive-include awx/playbooks *.yml
diff --git a/Makefile b/Makefile
index ca76648499..6a7d4af5a5 100644
--- a/Makefile
+++ b/Makefile
@@ -56,11 +56,6 @@ WHEEL_COMMAND ?= bdist_wheel
SDIST_TAR_FILE ?= $(SDIST_TAR_NAME).tar.gz
WHEEL_FILE ?= $(WHEEL_NAME)-py2-none-any.whl
-# UI flag files
-UI_DEPS_FLAG_FILE = awx/ui/.deps_built
-UI_RELEASE_DEPS_FLAG_FILE = awx/ui/.release_deps_built
-UI_RELEASE_FLAG_FILE = awx/ui/.release_built
-
I18N_FLAG_FILE = .i18n_built
.PHONY: awx-link clean clean-tmp clean-venv requirements requirements_dev \
@@ -70,22 +65,6 @@ I18N_FLAG_FILE = .i18n_built
ui-docker-machine ui-docker ui-release ui-devel \
ui-test ui-deps ui-test-ci VERSION
-# remove ui build artifacts
-clean-ui: clean-languages
- rm -rf awx/ui/static/
- rm -rf awx/ui/node_modules/
- rm -rf awx/ui/test/unit/reports/
- rm -rf awx/ui/test/spec/reports/
- rm -rf awx/ui/test/e2e/reports/
- rm -rf awx/ui/client/languages/
- rm -rf awx/ui_next/node_modules/
- rm -rf node_modules
- rm -rf awx/ui_next/coverage/
- rm -rf awx/ui_next/build/locales/_build/
- rm -f $(UI_DEPS_FLAG_FILE)
- rm -f $(UI_RELEASE_DEPS_FLAG_FILE)
- rm -f $(UI_RELEASE_FLAG_FILE)
-
clean-tmp:
rm -rf tmp/
@@ -214,7 +193,11 @@ requirements_awx_dev:
requirements_collections:
mkdir -p $(COLLECTION_BASE)
- ansible-galaxy collection install -r requirements/collections_requirements.yml -p $(COLLECTION_BASE)
+ n=0; \
+ until [ "$$n" -ge 5 ]; do \
+ ansible-galaxy collection install -r requirements/collections_requirements.yml -p $(COLLECTION_BASE) && break; \
+ n=$$((n+1)); \
+ done
requirements: requirements_ansible requirements_awx requirements_collections
@@ -476,110 +459,23 @@ else
@echo No PO files
endif
-# generate UI .pot
-pot: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run pot
-
-# generate django .pot .po
-LANG = "en-us"
-messages:
- @if [ "$(VENV_BASE)" ]; then \
- . $(VENV_BASE)/awx/bin/activate; \
- fi; \
- $(PYTHON) manage.py makemessages -l $(LANG) --keep-pot
-
-# generate l10n .json .mo
-languages: $(I18N_FLAG_FILE)
-
-$(I18N_FLAG_FILE): $(UI_RELEASE_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run languages
- $(PYTHON) tools/scripts/compilemessages.py
- touch $(I18N_FLAG_FILE)
-
-# End l10n TASKS
-# --------------------------------------
-
-# UI RELEASE TASKS
-# --------------------------------------
-ui-release: $(UI_RELEASE_FLAG_FILE)
-
-$(UI_RELEASE_FLAG_FILE): $(I18N_FLAG_FILE) $(UI_RELEASE_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run build-release
- touch $(UI_RELEASE_FLAG_FILE)
-
-$(UI_RELEASE_DEPS_FLAG_FILE):
- PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 $(NPM_BIN) --unsafe-perm --prefix awx/ui ci --no-save awx/ui
- touch $(UI_RELEASE_DEPS_FLAG_FILE)
-
-# END UI RELEASE TASKS
-# --------------------------------------
# UI TASKS
# --------------------------------------
-ui-deps: $(UI_DEPS_FLAG_FILE)
-
-$(UI_DEPS_FLAG_FILE):
- @if [ -f ${UI_RELEASE_DEPS_FLAG_FILE} ]; then \
- rm -rf awx/ui/node_modules; \
- rm -f ${UI_RELEASE_DEPS_FLAG_FILE}; \
- fi; \
- $(NPM_BIN) --unsafe-perm --prefix awx/ui ci --no-save awx/ui
- touch $(UI_DEPS_FLAG_FILE)
-
-ui-docker-machine: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run ui-docker-machine -- $(MAKEFLAGS)
-
-# Native docker. Builds UI and raises BrowserSync & filesystem polling.
-ui-docker: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run ui-docker -- $(MAKEFLAGS)
-
-# Builds UI with development UI without raising browser-sync or filesystem polling.
-ui-devel: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run build-devel -- $(MAKEFLAGS)
-
-ui-test: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run test
-
-ui-lint: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) run --prefix awx/ui jshint
- $(NPM_BIN) run --prefix awx/ui lint
-
-# A standard go-to target for API developers to use building the frontend
-ui: clean-ui ui-devel
-
-ui-test-ci: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) --prefix awx/ui run test:ci
- $(NPM_BIN) --prefix awx/ui run unit
-
-jshint: $(UI_DEPS_FLAG_FILE)
- $(NPM_BIN) run --prefix awx/ui jshint
- $(NPM_BIN) run --prefix awx/ui lint
-
-ui-zuul-lint-and-test:
- CHROMIUM_BIN=$(CHROMIUM_BIN) ./awx/ui/build/zuul_download_chromium.sh
- CHROMIUM_BIN=$(CHROMIUM_BIN) PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 $(NPM_BIN) --unsafe-perm --prefix awx/ui ci --no-save awx/ui
- CHROMIUM_BIN=$(CHROMIUM_BIN) $(NPM_BIN) run --prefix awx/ui jshint
- CHROMIUM_BIN=$(CHROMIUM_BIN) $(NPM_BIN) run --prefix awx/ui lint
- CHROME_BIN=$(CHROMIUM_BIN) $(NPM_BIN) --prefix awx/ui run test:ci
- CHROME_BIN=$(CHROMIUM_BIN) $(NPM_BIN) --prefix awx/ui run unit
-
-# END UI TASKS
-# --------------------------------------
-
-# UI NEXT TASKS
-# --------------------------------------
-
awx/ui_next/node_modules:
$(NPM_BIN) --prefix awx/ui_next install
-ui-release-next:
- mkdir -p awx/ui_next/build/static
- touch awx/ui_next/build/static/.placeholder
+clean-ui:
+ rm -rf node_modules
+ rm -rf awx/ui_next/node_modules
+ rm -rf awx/ui_next/build
-ui-devel-next: awx/ui_next/node_modules
+ui-release: ui-devel
+ui-devel: awx/ui_next/node_modules
$(NPM_BIN) --prefix awx/ui_next run extract-strings
$(NPM_BIN) --prefix awx/ui_next run compile-strings
$(NPM_BIN) --prefix awx/ui_next run build
+ git checkout awx/ui_next/src/locales
mkdir -p awx/public/static/css
mkdir -p awx/public/static/js
mkdir -p awx/public/static/media
@@ -587,19 +483,12 @@ ui-devel-next: awx/ui_next/node_modules
cp -r awx/ui_next/build/static/js/* awx/public/static/js
cp -r awx/ui_next/build/static/media/* awx/public/static/media
-clean-ui-next:
- rm -rf node_modules
- rm -rf awx/ui_next/node_modules
- rm -rf awx/ui_next/build
-
-ui-next-zuul-lint-and-test:
+ui-zuul-lint-and-test:
$(NPM_BIN) --prefix awx/ui_next install
$(NPM_BIN) run --prefix awx/ui_next lint
$(NPM_BIN) run --prefix awx/ui_next prettier-check
$(NPM_BIN) run --prefix awx/ui_next test
-# END UI NEXT TASKS
-# --------------------------------------
# Build a pip-installable package into dist/ with a timestamped version number.
dev_build:
@@ -609,10 +498,10 @@ dev_build:
release_build:
$(PYTHON) setup.py release_build
-dist/$(SDIST_TAR_FILE): ui-release ui-release-next VERSION
+dist/$(SDIST_TAR_FILE): ui-release VERSION
$(PYTHON) setup.py $(SDIST_COMMAND)
-dist/$(WHEEL_FILE): ui-release ui-release-next
+dist/$(WHEEL_FILE): ui-release
$(PYTHON) setup.py $(WHEEL_COMMAND)
sdist: dist/$(SDIST_TAR_FILE)
@@ -646,9 +535,11 @@ awx/projects:
docker-compose-isolated: awx/projects
CURRENT_UID=$(shell id -u) TAG=$(COMPOSE_TAG) DEV_DOCKER_TAG_BASE=$(DEV_DOCKER_TAG_BASE) docker-compose -f tools/docker-compose.yml -f tools/docker-isolated-override.yml up
+COMPOSE_UP_OPTS ?=
+
# Docker Compose Development environment
docker-compose: docker-auth awx/projects
- CURRENT_UID=$(shell id -u) OS="$(shell docker info | grep 'Operating System')" TAG=$(COMPOSE_TAG) DEV_DOCKER_TAG_BASE=$(DEV_DOCKER_TAG_BASE) docker-compose -f tools/docker-compose.yml up --no-recreate awx
+ CURRENT_UID=$(shell id -u) OS="$(shell docker info | grep 'Operating System')" TAG=$(COMPOSE_TAG) DEV_DOCKER_TAG_BASE=$(DEV_DOCKER_TAG_BASE) docker-compose -f tools/docker-compose.yml $(COMPOSE_UP_OPTS) up --no-recreate awx
docker-compose-cluster: docker-auth awx/projects
CURRENT_UID=$(shell id -u) TAG=$(COMPOSE_TAG) DEV_DOCKER_TAG_BASE=$(DEV_DOCKER_TAG_BASE) docker-compose -f tools/docker-compose-cluster.yml up
diff --git a/VERSION b/VERSION
index 94188a7483..2bbd2b4b42 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-15.0.0
+15.0.1
diff --git a/awx/api/generics.py b/awx/api/generics.py
index fce5bb9b49..ac9ab03907 100644
--- a/awx/api/generics.py
+++ b/awx/api/generics.py
@@ -47,8 +47,6 @@ from awx.main.utils import (
get_object_or_400,
decrypt_field,
get_awx_version,
- get_licenser,
- StubLicense
)
from awx.main.utils.db import get_all_field_names
from awx.main.views import ApiErrorView
@@ -189,7 +187,8 @@ class APIView(views.APIView):
'''
Log warning for 400 requests. Add header with elapsed time.
'''
-
+ from awx.main.utils import get_licenser
+ from awx.main.utils.licensing import OpenLicense
#
# If the URL was rewritten, and we get a 404, we should entirely
# replace the view in the request context with an ApiErrorView()
@@ -225,7 +224,8 @@ class APIView(views.APIView):
response = super(APIView, self).finalize_response(request, response, *args, **kwargs)
time_started = getattr(self, 'time_started', None)
response['X-API-Product-Version'] = get_awx_version()
- response['X-API-Product-Name'] = 'AWX' if isinstance(get_licenser(), StubLicense) else 'Red Hat Ansible Tower'
+ response['X-API-Product-Name'] = 'AWX' if isinstance(get_licenser(), OpenLicense) else 'Red Hat Ansible Tower'
+
response['X-API-Node'] = settings.CLUSTER_HOST_ID
if time_started:
time_elapsed = time.time() - self.time_started
diff --git a/awx/api/serializers.py b/awx/api/serializers.py
index 2e70d2c8c9..abd30a7fab 100644
--- a/awx/api/serializers.py
+++ b/awx/api/serializers.py
@@ -453,7 +453,7 @@ class BaseSerializer(serializers.ModelSerializer, metaclass=BaseSerializerMetacl
if 'capability_map' not in self.context:
if hasattr(self, 'polymorphic_base'):
model = self.polymorphic_base.Meta.model
- prefetch_list = self.polymorphic_base._capabilities_prefetch
+ prefetch_list = self.polymorphic_base.capabilities_prefetch
else:
model = self.Meta.model
prefetch_list = self.capabilities_prefetch
@@ -640,12 +640,9 @@ class EmptySerializer(serializers.Serializer):
class UnifiedJobTemplateSerializer(BaseSerializer):
- # As a base serializer, the capabilities prefetch is not used directly
- _capabilities_prefetch = [
- 'admin', 'execute',
- {'copy': ['jobtemplate.project.use', 'jobtemplate.inventory.use',
- 'organization.workflow_admin']}
- ]
+ # As a base serializer, the capabilities prefetch is not used directly,
+ # instead they are derived from the Workflow Job Template Serializer and the Job Template Serializer, respectively.
+ capabilities_prefetch = []
class Meta:
model = UnifiedJobTemplate
@@ -695,7 +692,7 @@ class UnifiedJobTemplateSerializer(BaseSerializer):
serializer.polymorphic_base = self
# capabilities prefetch is only valid for these models
if isinstance(obj, (JobTemplate, WorkflowJobTemplate)):
- serializer.capabilities_prefetch = self._capabilities_prefetch
+ serializer.capabilities_prefetch = serializer_class.capabilities_prefetch
else:
serializer.capabilities_prefetch = None
return serializer.to_representation(obj)
@@ -1333,6 +1330,8 @@ class ProjectOptionsSerializer(BaseSerializer):
scm_type = attrs.get('scm_type', u'') or u''
if self.instance and not scm_type:
valid_local_paths.append(self.instance.local_path)
+ if self.instance and scm_type and "local_path" in attrs and self.instance.local_path != attrs['local_path']:
+ errors['local_path'] = _(f'Cannot change local_path for {scm_type}-based projects')
if scm_type:
attrs.pop('local_path', None)
if 'local_path' in attrs and attrs['local_path'] not in valid_local_paths:
diff --git a/awx/api/templates/api/dashboard_jobs_graph_view.md b/awx/api/templates/api/dashboard_jobs_graph_view.md
index 2e510b2a56..baadd4d561 100644
--- a/awx/api/templates/api/dashboard_jobs_graph_view.md
+++ b/awx/api/templates/api/dashboard_jobs_graph_view.md
@@ -8,7 +8,7 @@ The `period` of the data can be adjusted with:
?period=month
-Where `month` can be replaced with `week`, or `day`. `month` is the default.
+Where `month` can be replaced with `week`, `two_weeks`, or `day`. `month` is the default.
The type of job can be filtered with:
diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py
index 2745f87095..636e68e4bd 100644
--- a/awx/api/urls/urls.py
+++ b/awx/api/urls/urls.py
@@ -15,6 +15,7 @@ from awx.api.views import (
ApiV2PingView,
ApiV2ConfigView,
ApiV2SubscriptionView,
+ ApiV2AttachView,
AuthView,
UserMeList,
DashboardView,
@@ -94,6 +95,7 @@ v2_urls = [
url(r'^ping/$', ApiV2PingView.as_view(), name='api_v2_ping_view'),
url(r'^config/$', ApiV2ConfigView.as_view(), name='api_v2_config_view'),
url(r'^config/subscriptions/$', ApiV2SubscriptionView.as_view(), name='api_v2_subscription_view'),
+ url(r'^config/attach/$', ApiV2AttachView.as_view(), name='api_v2_attach_view'),
url(r'^auth/$', AuthView.as_view()),
url(r'^me/$', UserMeList.as_view(), name='user_me_list'),
url(r'^dashboard/$', DashboardView.as_view(), name='dashboard_view'),
diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py
index 4f436c8f0e..87a12a7d51 100644
--- a/awx/api/views/__init__.py
+++ b/awx/api/views/__init__.py
@@ -153,6 +153,7 @@ from awx.api.views.root import ( # noqa
ApiV2PingView,
ApiV2ConfigView,
ApiV2SubscriptionView,
+ ApiV2AttachView,
)
from awx.api.views.webhooks import ( # noqa
WebhookKeyView,
@@ -316,6 +317,9 @@ class DashboardJobsGraphView(APIView):
if period == 'month':
end_date = start_date - dateutil.relativedelta.relativedelta(months=1)
interval = 'days'
+ elif period == 'two_weeks':
+ end_date = start_date - dateutil.relativedelta.relativedelta(weeks=2)
+ interval = 'days'
elif period == 'week':
end_date = start_date - dateutil.relativedelta.relativedelta(weeks=1)
interval = 'days'
@@ -3043,7 +3047,7 @@ class WorkflowJobTemplateNodeCreateApproval(RetrieveAPIView):
approval_template,
context=self.get_serializer_context()
).data
- return Response(data, status=status.HTTP_200_OK)
+ return Response(data, status=status.HTTP_201_CREATED)
def check_permissions(self, request):
obj = self.get_object().workflow_job_template
@@ -4253,7 +4257,9 @@ class NotificationTemplateDetail(RetrieveUpdateDestroyAPIView):
obj = self.get_object()
if not request.user.can_access(self.model, 'delete', obj):
return Response(status=status.HTTP_404_NOT_FOUND)
- if obj.notifications.filter(status='pending').exists():
+
+ hours_old = now() - dateutil.relativedelta.relativedelta(hours=8)
+ if obj.notifications.filter(status='pending', created__gt=hours_old).exists():
return Response({"error": _("Delete not allowed while there are pending notifications")},
status=status.HTTP_405_METHOD_NOT_ALLOWED)
return super(NotificationTemplateDetail, self).delete(request, *args, **kwargs)
diff --git a/awx/api/views/root.py b/awx/api/views/root.py
index aeda19cdeb..0f5e7e6cdd 100644
--- a/awx/api/views/root.py
+++ b/awx/api/views/root.py
@@ -1,9 +1,10 @@
# Copyright (c) 2018 Ansible, Inc.
# All Rights Reserved.
+import base64
+import json
import logging
import operator
-import json
from collections import OrderedDict
from django.conf import settings
@@ -29,8 +30,8 @@ from awx.main.utils import (
get_custom_venv_choices,
to_python_boolean,
)
+from awx.main.utils.licensing import validate_entitlement_manifest
from awx.api.versioning import reverse, drf_reverse
-from awx.conf.license import get_license
from awx.main.constants import PRIVILEGE_ESCALATION_METHODS
from awx.main.models import (
Project,
@@ -178,7 +179,7 @@ class ApiV2PingView(APIView):
class ApiV2SubscriptionView(APIView):
permission_classes = (IsAuthenticated,)
- name = _('Configuration')
+ name = _('Subscriptions')
swagger_topic = 'System Configuration'
def check_permissions(self, request):
@@ -189,18 +190,18 @@ class ApiV2SubscriptionView(APIView):
def post(self, request):
from awx.main.utils.common import get_licenser
data = request.data.copy()
- if data.get('rh_password') == '$encrypted$':
- data['rh_password'] = settings.REDHAT_PASSWORD
+ if data.get('subscriptions_password') == '$encrypted$':
+ data['subscriptions_password'] = settings.SUBSCRIPTIONS_PASSWORD
try:
- user, pw = data.get('rh_username'), data.get('rh_password')
+ user, pw = data.get('subscriptions_username'), data.get('subscriptions_password')
with set_environ(**settings.AWX_TASK_ENV):
validated = get_licenser().validate_rh(user, pw)
if user:
- settings.REDHAT_USERNAME = data['rh_username']
+ settings.SUBSCRIPTIONS_USERNAME = data['subscriptions_username']
if pw:
- settings.REDHAT_PASSWORD = data['rh_password']
+ settings.SUBSCRIPTIONS_PASSWORD = data['subscriptions_password']
except Exception as exc:
- msg = _("Invalid License")
+ msg = _("Invalid Subscription")
if (
isinstance(exc, requests.exceptions.HTTPError) and
getattr(getattr(exc, 'response', None), 'status_code', None) == 401
@@ -213,13 +214,63 @@ class ApiV2SubscriptionView(APIView):
elif isinstance(exc, (ValueError, OSError)) and exc.args:
msg = exc.args[0]
else:
- logger.exception(smart_text(u"Invalid license submitted."),
+ logger.exception(smart_text(u"Invalid subscription submitted."),
extra=dict(actor=request.user.username))
return Response({"error": msg}, status=status.HTTP_400_BAD_REQUEST)
return Response(validated)
+class ApiV2AttachView(APIView):
+
+ permission_classes = (IsAuthenticated,)
+ name = _('Attach Subscription')
+ swagger_topic = 'System Configuration'
+
+ def check_permissions(self, request):
+ super(ApiV2AttachView, self).check_permissions(request)
+ if not request.user.is_superuser and request.method.lower() not in {'options', 'head'}:
+ self.permission_denied(request) # Raises PermissionDenied exception.
+
+ def post(self, request):
+ data = request.data.copy()
+ pool_id = data.get('pool_id', None)
+ if not pool_id:
+ return Response({"error": _("No subscription pool ID provided.")}, status=status.HTTP_400_BAD_REQUEST)
+ user = getattr(settings, 'SUBSCRIPTIONS_USERNAME', None)
+ pw = getattr(settings, 'SUBSCRIPTIONS_PASSWORD', None)
+ if pool_id and user and pw:
+ from awx.main.utils.common import get_licenser
+ data = request.data.copy()
+ try:
+ with set_environ(**settings.AWX_TASK_ENV):
+ validated = get_licenser().validate_rh(user, pw)
+ except Exception as exc:
+ msg = _("Invalid Subscription")
+ if (
+ isinstance(exc, requests.exceptions.HTTPError) and
+ getattr(getattr(exc, 'response', None), 'status_code', None) == 401
+ ):
+ msg = _("The provided credentials are invalid (HTTP 401).")
+ elif isinstance(exc, requests.exceptions.ProxyError):
+ msg = _("Unable to connect to proxy server.")
+ elif isinstance(exc, requests.exceptions.ConnectionError):
+ msg = _("Could not connect to subscription service.")
+ elif isinstance(exc, (ValueError, OSError)) and exc.args:
+ msg = exc.args[0]
+ else:
+ logger.exception(smart_text(u"Invalid subscription submitted."),
+ extra=dict(actor=request.user.username))
+ return Response({"error": msg}, status=status.HTTP_400_BAD_REQUEST)
+ for sub in validated:
+ if sub['pool_id'] == pool_id:
+ sub['valid_key'] = True
+ settings.LICENSE = sub
+ return Response(sub)
+
+ return Response({"error": _("Error processing subscription metadata.")}, status=status.HTTP_400_BAD_REQUEST)
+
+
class ApiV2ConfigView(APIView):
permission_classes = (IsAuthenticated,)
@@ -234,15 +285,11 @@ class ApiV2ConfigView(APIView):
def get(self, request, format=None):
'''Return various sitewide configuration settings'''
- if request.user.is_superuser or request.user.is_system_auditor:
- license_data = get_license(show_key=True)
- else:
- license_data = get_license(show_key=False)
+ from awx.main.utils.common import get_licenser
+ license_data = get_licenser().validate()
+
if not license_data.get('valid_key', False):
license_data = {}
- if license_data and 'features' in license_data and 'activity_streams' in license_data['features']:
- # FIXME: Make the final setting value dependent on the feature?
- license_data['features']['activity_streams'] &= settings.ACTIVITY_STREAM_ENABLED
pendo_state = settings.PENDO_TRACKING_STATE if settings.PENDO_TRACKING_STATE in ('off', 'anonymous', 'detailed') else 'off'
@@ -281,9 +328,10 @@ class ApiV2ConfigView(APIView):
return Response(data)
+
def post(self, request):
if not isinstance(request.data, dict):
- return Response({"error": _("Invalid license data")}, status=status.HTTP_400_BAD_REQUEST)
+ return Response({"error": _("Invalid subscription data")}, status=status.HTTP_400_BAD_REQUEST)
if "eula_accepted" not in request.data:
return Response({"error": _("Missing 'eula_accepted' property")}, status=status.HTTP_400_BAD_REQUEST)
try:
@@ -300,25 +348,47 @@ class ApiV2ConfigView(APIView):
logger.info(smart_text(u"Invalid JSON submitted for license."),
extra=dict(actor=request.user.username))
return Response({"error": _("Invalid JSON")}, status=status.HTTP_400_BAD_REQUEST)
- try:
- from awx.main.utils.common import get_licenser
- license_data = json.loads(data_actual)
- license_data_validated = get_licenser(**license_data).validate()
- except Exception:
- logger.warning(smart_text(u"Invalid license submitted."),
- extra=dict(actor=request.user.username))
- return Response({"error": _("Invalid License")}, status=status.HTTP_400_BAD_REQUEST)
+
+ from awx.main.utils.common import get_licenser
+ license_data = json.loads(data_actual)
+ if 'license_key' in license_data:
+ return Response({"error": _('Legacy license submitted. A subscription manifest is now required.')}, status=status.HTTP_400_BAD_REQUEST)
+ if 'manifest' in license_data:
+ try:
+ json_actual = json.loads(base64.b64decode(license_data['manifest']))
+ if 'license_key' in json_actual:
+ return Response(
+ {"error": _('Legacy license submitted. A subscription manifest is now required.')},
+ status=status.HTTP_400_BAD_REQUEST
+ )
+ except Exception:
+ pass
+ try:
+ license_data = validate_entitlement_manifest(license_data['manifest'])
+ except ValueError as e:
+ return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
+ except Exception:
+ logger.exception('Invalid manifest submitted. {}')
+ return Response({"error": _('Invalid manifest submitted.')}, status=status.HTTP_400_BAD_REQUEST)
+
+ try:
+ license_data_validated = get_licenser().license_from_manifest(license_data)
+ except Exception:
+ logger.warning(smart_text(u"Invalid subscription submitted."),
+ extra=dict(actor=request.user.username))
+ return Response({"error": _("Invalid License")}, status=status.HTTP_400_BAD_REQUEST)
+ else:
+ license_data_validated = get_licenser().validate()
# If the license is valid, write it to the database.
if license_data_validated['valid_key']:
- settings.LICENSE = license_data
if not settings_registry.is_setting_read_only('TOWER_URL_BASE'):
settings.TOWER_URL_BASE = "{}://{}".format(request.scheme, request.get_host())
return Response(license_data_validated)
- logger.warning(smart_text(u"Invalid license submitted."),
+ logger.warning(smart_text(u"Invalid subscription submitted."),
extra=dict(actor=request.user.username))
- return Response({"error": _("Invalid license")}, status=status.HTTP_400_BAD_REQUEST)
+ return Response({"error": _("Invalid subscription")}, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request):
try:
diff --git a/awx/asgi.py b/awx/asgi.py
index 698c5f7533..eb141aabdb 100644
--- a/awx/asgi.py
+++ b/awx/asgi.py
@@ -25,10 +25,12 @@ if MODE == 'production':
try:
fd = open("/var/lib/awx/.tower_version", "r")
if fd.read().strip() != tower_version:
- raise Exception()
- except Exception:
+ raise ValueError()
+ except FileNotFoundError:
+ pass
+ except ValueError as e:
logger.error("Missing or incorrect metadata for Tower version. Ensure Tower was installed using the setup playbook.")
- raise Exception("Missing or incorrect metadata for Tower version. Ensure Tower was installed using the setup playbook.")
+ raise Exception("Missing or incorrect metadata for Tower version. Ensure Tower was installed using the setup playbook.") from e
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "awx.settings")
diff --git a/awx/conf/license.py b/awx/conf/license.py
index 6ad1042f9a..3929c37921 100644
--- a/awx/conf/license.py
+++ b/awx/conf/license.py
@@ -1,18 +1,14 @@
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved.
-
__all__ = ['get_license']
def _get_validated_license_data():
- from awx.main.utils.common import get_licenser
+ from awx.main.utils import get_licenser
return get_licenser().validate()
-def get_license(show_key=False):
+def get_license():
"""Return a dictionary representing the active license on this Tower instance."""
- license_data = _get_validated_license_data()
- if not show_key:
- license_data.pop('license_key', None)
- return license_data
+ return _get_validated_license_data()
diff --git a/awx/conf/migrations/0008_subscriptions.py b/awx/conf/migrations/0008_subscriptions.py
new file mode 100644
index 0000000000..dacd066b4d
--- /dev/null
+++ b/awx/conf/migrations/0008_subscriptions.py
@@ -0,0 +1,26 @@
+# Generated by Django 2.2.11 on 2020-08-04 15:19
+
+import logging
+
+from django.db import migrations
+
+from awx.conf.migrations._subscriptions import clear_old_license, prefill_rh_credentials
+
+logger = logging.getLogger('awx.conf.migrations')
+
+
+def _noop(apps, schema_editor):
+ pass
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('conf', '0007_v380_rename_more_settings'),
+ ]
+
+
+ operations = [
+ migrations.RunPython(clear_old_license, _noop),
+ migrations.RunPython(prefill_rh_credentials, _noop)
+ ]
diff --git a/awx/conf/migrations/_subscriptions.py b/awx/conf/migrations/_subscriptions.py
new file mode 100644
index 0000000000..2b979fb68e
--- /dev/null
+++ b/awx/conf/migrations/_subscriptions.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+import logging
+from django.utils.timezone import now
+from awx.main.utils.encryption import decrypt_field, encrypt_field
+
+logger = logging.getLogger('awx.conf.settings')
+
+__all__ = ['clear_old_license', 'prefill_rh_credentials']
+
+
+def clear_old_license(apps, schema_editor):
+ Setting = apps.get_model('conf', 'Setting')
+ Setting.objects.filter(key='LICENSE').delete()
+
+
+def _migrate_setting(apps, old_key, new_key, encrypted=False):
+ Setting = apps.get_model('conf', 'Setting')
+ if not Setting.objects.filter(key=old_key).exists():
+ return
+ new_setting = Setting.objects.create(key=new_key,
+ created=now(),
+ modified=now()
+ )
+ if encrypted:
+ new_setting.value = decrypt_field(Setting.objects.filter(key=old_key).first(), 'value')
+ new_setting.value = encrypt_field(new_setting, 'value')
+ else:
+ new_setting.value = getattr(Setting.objects.filter(key=old_key).first(), 'value')
+ new_setting.save()
+
+
+def prefill_rh_credentials(apps, schema_editor):
+ _migrate_setting(apps, 'REDHAT_USERNAME', 'SUBSCRIPTIONS_USERNAME', encrypted=False)
+ _migrate_setting(apps, 'REDHAT_PASSWORD', 'SUBSCRIPTIONS_PASSWORD', encrypted=True)
diff --git a/awx/conf/models.py b/awx/conf/models.py
index 2859650f54..fe28fd89a8 100644
--- a/awx/conf/models.py
+++ b/awx/conf/models.py
@@ -78,14 +78,6 @@ class Setting(CreatedModifiedModel):
def get_cache_id_key(self, key):
return '{}_ID'.format(key)
- def display_value(self):
- if self.key == 'LICENSE' and 'license_key' in self.value:
- # don't log the license key in activity stream
- value = self.value.copy()
- value['license_key'] = '********'
- return value
- return self.value
-
import awx.conf.signals # noqa
diff --git a/awx/main/analytics/collectors.py b/awx/main/analytics/collectors.py
index e1dc468d51..0f51ad179a 100644
--- a/awx/main/analytics/collectors.py
+++ b/awx/main/analytics/collectors.py
@@ -33,9 +33,9 @@ data _since_ the last report date - i.e., new data in the last 24 hours)
'''
-@register('config', '1.1', description=_('General platform configuration.'))
+@register('config', '1.2', description=_('General platform configuration.'))
def config(since, **kwargs):
- license_info = get_license(show_key=False)
+ license_info = get_license()
install_type = 'traditional'
if os.environ.get('container') == 'oci':
install_type = 'openshift'
@@ -194,7 +194,6 @@ def instance_info(since, include_hostnames=False, **kwargs):
return info
-@register('job_counts', '1.0', description=_('Counts of jobs by status'))
def job_counts(since, **kwargs):
counts = {}
counts['total_jobs'] = models.UnifiedJob.objects.exclude(launch_type='sync').count()
@@ -204,7 +203,6 @@ def job_counts(since, **kwargs):
return counts
-@register('job_instance_counts', '1.0', description=_('Counts of jobs by execution node'))
def job_instance_counts(since, **kwargs):
counts = {}
job_types = models.UnifiedJob.objects.exclude(launch_type='sync').values_list(
diff --git a/awx/main/analytics/core.py b/awx/main/analytics/core.py
index fe48fb30bf..2c77444929 100644
--- a/awx/main/analytics/core.py
+++ b/awx/main/analytics/core.py
@@ -24,7 +24,7 @@ logger = logging.getLogger('awx.main.analytics')
def _valid_license():
try:
- if get_license(show_key=False).get('license_type', 'UNLICENSED') == 'open':
+ if get_license().get('license_type', 'UNLICENSED') == 'open':
return False
access_registry[Job](None).check_license()
except PermissionDenied:
diff --git a/awx/main/analytics/metrics.py b/awx/main/analytics/metrics.py
index 1dd85eb6a7..9346de0a80 100644
--- a/awx/main/analytics/metrics.py
+++ b/awx/main/analytics/metrics.py
@@ -12,7 +12,7 @@ from prometheus_client import (
from awx.conf.license import get_license
from awx.main.utils import (get_awx_version, get_ansible_version)
from awx.main.analytics.collectors import (
- counts,
+ counts,
instance_info,
job_instance_counts,
job_counts,
@@ -54,7 +54,7 @@ LICENSE_INSTANCE_FREE = Gauge('awx_license_instance_free', 'Number of remaining
def metrics():
- license_info = get_license(show_key=False)
+ license_info = get_license()
SYSTEM_INFO.info({
'install_uuid': settings.INSTALL_UUID,
'insights_analytics': str(settings.INSIGHTS_TRACKING_STATE),
diff --git a/awx/main/conf.py b/awx/main/conf.py
index 3b41c3a19b..6bf86db214 100644
--- a/awx/main/conf.py
+++ b/awx/main/conf.py
@@ -1,7 +1,5 @@
# Python
-import json
import logging
-import os
# Django
from django.utils.translation import ugettext_lazy as _
@@ -13,6 +11,7 @@ from rest_framework.fields import FloatField
# Tower
from awx.conf import fields, register, register_validate
+
logger = logging.getLogger('awx.main.conf')
register(
@@ -92,22 +91,10 @@ register(
)
-def _load_default_license_from_file():
- try:
- license_file = os.environ.get('AWX_LICENSE_FILE', '/etc/tower/license')
- if os.path.exists(license_file):
- license_data = json.load(open(license_file))
- logger.debug('Read license data from "%s".', license_file)
- return license_data
- except Exception:
- logger.warning('Could not read license from "%s".', license_file, exc_info=True)
- return {}
-
-
register(
'LICENSE',
field_class=fields.DictField,
- default=_load_default_license_from_file,
+ default=lambda: {},
label=_('License'),
help_text=_('The license controls which features and functionality are '
'enabled. Use /api/v2/config/ to update or change '
@@ -124,7 +111,7 @@ register(
encrypted=False,
read_only=False,
label=_('Red Hat customer username'),
- help_text=_('This username is used to retrieve license information and to send Automation Analytics'), # noqa
+ help_text=_('This username is used to send data to Automation Analytics'),
category=_('System'),
category_slug='system',
)
@@ -137,7 +124,33 @@ register(
encrypted=True,
read_only=False,
label=_('Red Hat customer password'),
- help_text=_('This password is used to retrieve license information and to send Automation Analytics'), # noqa
+ help_text=_('This password is used to send data to Automation Analytics'),
+ category=_('System'),
+ category_slug='system',
+)
+
+register(
+ 'SUBSCRIPTIONS_USERNAME',
+ field_class=fields.CharField,
+ default='',
+ allow_blank=True,
+ encrypted=False,
+ read_only=False,
+ label=_('Red Hat or Satellite username'),
+ help_text=_('This username is used to retrieve subscription and content information'), # noqa
+ category=_('System'),
+ category_slug='system',
+)
+
+register(
+ 'SUBSCRIPTIONS_PASSWORD',
+ field_class=fields.CharField,
+ default='',
+ allow_blank=True,
+ encrypted=True,
+ read_only=False,
+ label=_('Red Hat or Satellite password'),
+ help_text=_('This password is used to retrieve subscription and content information'), # noqa
category=_('System'),
category_slug='system',
)
diff --git a/awx/main/dispatch/worker/callback.py b/awx/main/dispatch/worker/callback.py
index 79033e329a..fd96a4f04e 100644
--- a/awx/main/dispatch/worker/callback.py
+++ b/awx/main/dispatch/worker/callback.py
@@ -1,10 +1,7 @@
-import cProfile
import json
import logging
import os
-import pstats
import signal
-import tempfile
import time
import traceback
@@ -23,6 +20,7 @@ from awx.main.models import (JobEvent, AdHocCommandEvent, ProjectUpdateEvent,
Job)
from awx.main.tasks import handle_success_and_failure_notifications
from awx.main.models.events import emit_event_detail
+from awx.main.utils.profiling import AWXProfiler
from .base import BaseWorker
@@ -48,6 +46,7 @@ class CallbackBrokerWorker(BaseWorker):
self.buff = {}
self.pid = os.getpid()
self.redis = redis.Redis.from_url(settings.BROKER_URL)
+ self.prof = AWXProfiler("CallbackBrokerWorker")
for key in self.redis.keys('awx_callback_receiver_statistics_*'):
self.redis.delete(key)
@@ -87,19 +86,12 @@ class CallbackBrokerWorker(BaseWorker):
)
def toggle_profiling(self, *args):
- if self.prof:
- self.prof.disable()
- filename = f'callback-{self.pid}.pstats'
- filepath = os.path.join(tempfile.gettempdir(), filename)
- with open(filepath, 'w') as f:
- pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats()
- pstats.Stats(self.prof).dump_stats(filepath + '.raw')
- self.prof = False
- logger.error(f'profiling is disabled, wrote {filepath}')
- else:
- self.prof = cProfile.Profile()
- self.prof.enable()
+ if not self.prof.is_started():
+ self.prof.start()
logger.error('profiling is enabled')
+ else:
+ filepath = self.prof.stop()
+ logger.error(f'profiling is disabled, wrote {filepath}')
def work_loop(self, *args, **kw):
if settings.AWX_CALLBACK_PROFILE:
diff --git a/awx/main/management/commands/check_license.py b/awx/main/management/commands/check_license.py
index 8c0798cc53..356ab42249 100644
--- a/awx/main/management/commands/check_license.py
+++ b/awx/main/management/commands/check_license.py
@@ -18,7 +18,5 @@ class Command(BaseCommand):
super(Command, self).__init__()
license = get_licenser().validate()
if options.get('data'):
- if license.get('license_key', '') != 'UNLICENSED':
- license['license_key'] = '********'
return json.dumps(license)
return license.get('license_type', 'none')
diff --git a/awx/main/management/commands/check_migrations.py b/awx/main/management/commands/check_migrations.py
index 50ea354960..6f9cfc7727 100644
--- a/awx/main/management/commands/check_migrations.py
+++ b/awx/main/management/commands/check_migrations.py
@@ -8,5 +8,7 @@ class Command(MakeMigrations):
def execute(self, *args, **options):
settings = connections['default'].settings_dict.copy()
settings['ENGINE'] = 'sqlite3'
+ if 'application_name' in settings['OPTIONS']:
+ del settings['OPTIONS']['application_name']
connections['default'] = DatabaseWrapper(settings)
return MakeMigrations().execute(*args, **options)
diff --git a/awx/main/management/commands/graph_jobs.py b/awx/main/management/commands/graph_jobs.py
new file mode 100644
index 0000000000..f1c8ad75e1
--- /dev/null
+++ b/awx/main/management/commands/graph_jobs.py
@@ -0,0 +1,117 @@
+# Python
+import asciichartpy as chart
+import collections
+import time
+import sys
+
+# Django
+from django.db.models import Count
+from django.core.management.base import BaseCommand
+
+# AWX
+from awx.main.models import (
+ Job,
+ Instance
+)
+
+
+DEFAULT_WIDTH = 100
+DEFAULT_HEIGHT = 30
+
+
+def chart_color_lookup(color_str):
+ return getattr(chart, color_str)
+
+
+def clear_screen():
+ print(chr(27) + "[2J")
+
+
+class JobStatus():
+ def __init__(self, status, color, width):
+ self.status = status
+ self.color = color
+ self.color_code = chart_color_lookup(color)
+ self.x = collections.deque(maxlen=width)
+ self.y = collections.deque(maxlen=width)
+
+ def tick(self, x, y):
+ self.x.append(x)
+ self.y.append(y)
+
+
+class JobStatusController:
+ RESET = chart_color_lookup('reset')
+
+ def __init__(self, width):
+ self.plots = [
+ JobStatus('pending', 'red', width),
+ JobStatus('waiting', 'blue', width),
+ JobStatus('running', 'green', width)
+ ]
+ self.ts_start = int(time.time())
+
+ def tick(self):
+ ts = int(time.time()) - self.ts_start
+ q = Job.objects.filter(status__in=['pending','waiting','running']).values_list('status').order_by().annotate(Count('status'))
+ status_count = dict(pending=0, waiting=0, running=0)
+ for status, count in q:
+ status_count[status] = count
+
+ for p in self.plots:
+ p.tick(ts, status_count[p.status])
+
+ def series(self):
+ return [list(p.y) for p in self.plots]
+
+ def generate_status(self):
+ line = ""
+ lines = []
+ for p in self.plots:
+ lines.append(f'{p.color_code}{p.status} {p.y[-1]}{self.RESET}')
+
+ line += ", ".join(lines) + '\n'
+
+ width = 5
+ time_running = int(time.time()) - self.ts_start
+ instances = Instance.objects.all().order_by('hostname')
+ line += "Capacity: " + ", ".join([f"{instance.capacity:{width}}" for instance in instances]) + '\n'
+ line += "Remaining: " + ", ".join([f"{instance.remaining_capacity:{width}}" for instance in instances]) + '\n'
+ line += f"Seconds running: {time_running}" + '\n'
+
+ return line
+
+
+class Command(BaseCommand):
+ help = "Plot pending, waiting, running jobs over time on the terminal"
+
+ def add_arguments(self, parser):
+ parser.add_argument('--refresh', dest='refresh', type=float, default=1.0,
+ help='Time between refreshes of the graph and data in seconds (defaults to 1.0)')
+ parser.add_argument('--width', dest='width', type=int, default=DEFAULT_WIDTH,
+ help=f'Width of the graph (defaults to {DEFAULT_WIDTH})')
+ parser.add_argument('--height', dest='height', type=int, default=DEFAULT_HEIGHT,
+ help=f'Height of the graph (defaults to {DEFAULT_HEIGHT})')
+
+ def handle(self, *args, **options):
+ refresh_seconds = options['refresh']
+ width = options['width']
+ height = options['height']
+
+ jctl = JobStatusController(width)
+
+ conf = {
+ 'colors': [chart_color_lookup(p.color) for p in jctl.plots],
+ 'height': height,
+ }
+
+ while True:
+ jctl.tick()
+
+ draw = chart.plot(jctl.series(), conf)
+ status_line = jctl.generate_status()
+ clear_screen()
+ print(draw)
+ sys.stdout.write(status_line)
+ time.sleep(refresh_seconds)
+
diff --git a/awx/main/management/commands/inventory_import.py b/awx/main/management/commands/inventory_import.py
index f4431b2705..c92215560e 100644
--- a/awx/main/management/commands/inventory_import.py
+++ b/awx/main/management/commands/inventory_import.py
@@ -903,7 +903,7 @@ class Command(BaseCommand):
def check_license(self):
license_info = get_licenser().validate()
local_license_type = license_info.get('license_type', 'UNLICENSED')
- if license_info.get('license_key', 'UNLICENSED') == 'UNLICENSED':
+ if local_license_type == 'UNLICENSED':
logger.error(LICENSE_NON_EXISTANT_MESSAGE)
raise CommandError('No license found!')
elif local_license_type == 'open':
diff --git a/awx/main/management/commands/profile_sql.py b/awx/main/management/commands/profile_sql.py
index 5bbc4c80ca..585fb3d706 100644
--- a/awx/main/management/commands/profile_sql.py
+++ b/awx/main/management/commands/profile_sql.py
@@ -19,7 +19,9 @@ class Command(BaseCommand):
profile_sql.delay(
threshold=options['threshold'], minutes=options['minutes']
)
- print(f"Logging initiated with a threshold of {options['threshold']} second(s) and a duration of"
- f" {options['minutes']} minute(s), any queries that meet criteria can"
- f" be found in /var/log/tower/profile/."
- )
+ if options['threshold'] > 0:
+ print(f"SQL profiling initiated with a threshold of {options['threshold']} second(s) and a"
+ f" duration of {options['minutes']} minute(s), any queries that meet criteria can"
+ f" be found in /var/log/tower/profile/.")
+ else:
+ print("SQL profiling disabled.")
diff --git a/awx/main/middleware.py b/awx/main/middleware.py
index 781266e8dd..759c2daa98 100644
--- a/awx/main/middleware.py
+++ b/awx/main/middleware.py
@@ -1,13 +1,9 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
-import uuid
import logging
import threading
import time
-import cProfile
-import pstats
-import os
import urllib.parse
from django.conf import settings
@@ -22,6 +18,7 @@ from django.urls import reverse, resolve
from awx.main.utils.named_url_graph import generate_graph, GraphNode
from awx.conf import fields, register
+from awx.main.utils.profiling import AWXProfiler
logger = logging.getLogger('awx.main.middleware')
@@ -32,11 +29,14 @@ class TimingMiddleware(threading.local, MiddlewareMixin):
dest = '/var/log/tower/profile'
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.prof = AWXProfiler("TimingMiddleware")
+
def process_request(self, request):
self.start_time = time.time()
if settings.AWX_REQUEST_PROFILE:
- self.prof = cProfile.Profile()
- self.prof.enable()
+ self.prof.start()
def process_response(self, request, response):
if not hasattr(self, 'start_time'): # some tools may not invoke process_request
@@ -44,33 +44,10 @@ class TimingMiddleware(threading.local, MiddlewareMixin):
total_time = time.time() - self.start_time
response['X-API-Total-Time'] = '%0.3fs' % total_time
if settings.AWX_REQUEST_PROFILE:
- self.prof.disable()
- cprofile_file = self.save_profile_file(request)
- response['cprofile_file'] = cprofile_file
+ response['X-API-Profile-File'] = self.prof.stop()
perf_logger.info('api response times', extra=dict(python_objects=dict(request=request, response=response)))
return response
- def save_profile_file(self, request):
- if not os.path.isdir(self.dest):
- os.makedirs(self.dest)
- filename = '%.3fs-%s.pstats' % (pstats.Stats(self.prof).total_tt, uuid.uuid4())
- filepath = os.path.join(self.dest, filename)
- with open(filepath, 'w') as f:
- f.write('%s %s\n' % (request.method, request.get_full_path()))
- pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats()
-
- if settings.AWX_REQUEST_PROFILE_WITH_DOT:
- from gprof2dot import main as generate_dot
- raw = os.path.join(self.dest, filename) + '.raw'
- pstats.Stats(self.prof).dump_stats(raw)
- generate_dot([
- '-n', '2.5', '-f', 'pstats', '-o',
- os.path.join( self.dest, filename).replace('.pstats', '.dot'),
- raw
- ])
- os.remove(raw)
- return filepath
-
class SessionTimeoutMiddleware(MiddlewareMixin):
"""
diff --git a/awx/main/migrations/0117_v400_remove_cloudforms_inventory.py b/awx/main/migrations/0117_v400_remove_cloudforms_inventory.py
index 8c33318755..9a94c6b02b 100644
--- a/awx/main/migrations/0117_v400_remove_cloudforms_inventory.py
+++ b/awx/main/migrations/0117_v400_remove_cloudforms_inventory.py
@@ -1,11 +1,7 @@
# Generated by Django 2.2.11 on 2020-05-01 13:25
from django.db import migrations, models
-from awx.main.migrations._inventory_source import create_scm_script_substitute
-
-
-def convert_cloudforms_to_scm(apps, schema_editor):
- create_scm_script_substitute(apps, 'cloudforms')
+from awx.main.migrations._inventory_source import delete_cloudforms_inv_source
class Migration(migrations.Migration):
@@ -15,7 +11,7 @@ class Migration(migrations.Migration):
]
operations = [
- migrations.RunPython(convert_cloudforms_to_scm),
+ migrations.RunPython(delete_cloudforms_inv_source),
migrations.AlterField(
model_name='inventorysource',
name='source',
diff --git a/awx/main/migrations/0122_really_remove_cloudforms_inventory.py b/awx/main/migrations/0122_really_remove_cloudforms_inventory.py
new file mode 100644
index 0000000000..ee44573304
--- /dev/null
+++ b/awx/main/migrations/0122_really_remove_cloudforms_inventory.py
@@ -0,0 +1,13 @@
+from django.db import migrations
+from awx.main.migrations._inventory_source import delete_cloudforms_inv_source
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0121_delete_toweranalyticsstate'),
+ ]
+
+ operations = [
+ migrations.RunPython(delete_cloudforms_inv_source),
+ ]
diff --git a/awx/main/migrations/_inventory_source.py b/awx/main/migrations/_inventory_source.py
index ed79606587..c53a18f035 100644
--- a/awx/main/migrations/_inventory_source.py
+++ b/awx/main/migrations/_inventory_source.py
@@ -5,6 +5,7 @@ from uuid import uuid4
from django.utils.encoding import smart_text
from django.utils.timezone import now
+from awx.main.utils.common import set_current_apps
from awx.main.utils.common import parse_yaml_or_json
logger = logging.getLogger('awx.main.migrations')
@@ -91,43 +92,14 @@ def back_out_new_instance_id(apps, source, new_id):
))
-def create_scm_script_substitute(apps, source):
- """Only applies for cloudforms in practice, but written generally.
- Given a source type, this will replace all inventory sources of that type
- with SCM inventory sources that source the script from Ansible core
- """
- # the revision in the Ansible 2.9 stable branch this project will start out as
- # it can still be updated manually later (but staying within 2.9 branch), if desired
- ansible_rev = '6f83b9aff42331e15c55a171de0a8b001208c18c'
+def delete_cloudforms_inv_source(apps, schema_editor):
+ set_current_apps(apps)
InventorySource = apps.get_model('main', 'InventorySource')
- ContentType = apps.get_model('contenttypes', 'ContentType')
- Project = apps.get_model('main', 'Project')
- if not InventorySource.objects.filter(source=source).exists():
- logger.debug('No sources of type {} to migrate'.format(source))
- return
- proj_name = 'Replacement project for {} type sources - {}'.format(source, uuid4())
- right_now = now()
- project = Project.objects.create(
- name=proj_name,
- created=right_now,
- modified=right_now,
- description='Created by migration',
- polymorphic_ctype=ContentType.objects.get(model='project'),
- # project-specific fields
- scm_type='git',
- scm_url='https://github.com/ansible/ansible.git',
- scm_branch='stable-2.9',
- scm_revision=ansible_rev
- )
- ct = 0
- for inv_src in InventorySource.objects.filter(source=source).iterator():
- inv_src.source = 'scm'
- inv_src.source_project = project
- inv_src.source_path = 'contrib/inventory/{}.py'.format(source)
- inv_src.scm_last_revision = ansible_rev
- inv_src.save(update_fields=['source', 'source_project', 'source_path', 'scm_last_revision'])
- logger.debug('Changed inventory source {} to scm type'.format(inv_src.pk))
- ct += 1
+ InventoryUpdate = apps.get_model('main', 'InventoryUpdate')
+ CredentialType = apps.get_model('main', 'CredentialType')
+ InventoryUpdate.objects.filter(inventory_source__source='cloudforms').delete()
+ InventorySource.objects.filter(source='cloudforms').delete()
+ ct = CredentialType.objects.filter(namespace='cloudforms').first()
if ct:
- logger.info('Changed total of {} inventory sources from {} type to scm'.format(ct, source))
-
+ ct.credentials.all().delete()
+ ct.delete()
diff --git a/awx/main/models/credential/__init__.py b/awx/main/models/credential/__init__.py
index df12177aae..66db962430 100644
--- a/awx/main/models/credential/__init__.py
+++ b/awx/main/models/credential/__init__.py
@@ -881,33 +881,6 @@ ManagedCredentialType(
}
)
-ManagedCredentialType(
- namespace='cloudforms',
- kind='cloud',
- name=ugettext_noop('Red Hat CloudForms'),
- managed_by_tower=True,
- inputs={
- 'fields': [{
- 'id': 'host',
- 'label': ugettext_noop('CloudForms URL'),
- 'type': 'string',
- 'help_text': ugettext_noop('Enter the URL for the virtual machine that '
- 'corresponds to your CloudForms instance. '
- 'For example, https://cloudforms.example.org')
- }, {
- 'id': 'username',
- 'label': ugettext_noop('Username'),
- 'type': 'string'
- }, {
- 'id': 'password',
- 'label': ugettext_noop('Password'),
- 'type': 'string',
- 'secret': True,
- }],
- 'required': ['host', 'username', 'password'],
- }
-)
-
ManagedCredentialType(
namespace='gce',
kind='cloud',
diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py
index fc4e9c022e..5071786653 100644
--- a/awx/main/models/ha.py
+++ b/awx/main/models/ha.py
@@ -261,18 +261,20 @@ class InstanceGroup(HasPolicyEditsMixin, BaseModel, RelatedJobsMixin):
app_label = 'main'
- def fit_task_to_most_remaining_capacity_instance(self, task):
+ @staticmethod
+ def fit_task_to_most_remaining_capacity_instance(task, instances):
instance_most_capacity = None
- for i in self.instances.filter(capacity__gt=0, enabled=True).order_by('hostname'):
+ for i in instances:
if i.remaining_capacity >= task.task_impact and \
(instance_most_capacity is None or
i.remaining_capacity > instance_most_capacity.remaining_capacity):
instance_most_capacity = i
return instance_most_capacity
- def find_largest_idle_instance(self):
+ @staticmethod
+ def find_largest_idle_instance(instances):
largest_instance = None
- for i in self.instances.filter(capacity__gt=0, enabled=True).order_by('hostname'):
+ for i in instances:
if i.jobs_running == 0:
if largest_instance is None:
largest_instance = i
diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py
index 8f42b9d577..2c274e18f6 100644
--- a/awx/main/models/jobs.py
+++ b/awx/main/models/jobs.py
@@ -798,6 +798,10 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana
if self.project:
for name in ('awx', 'tower'):
r['{}_project_revision'.format(name)] = self.project.scm_revision
+ r['{}_project_scm_branch'.format(name)] = self.project.scm_branch
+ if self.scm_branch:
+ for name in ('awx', 'tower'):
+ r['{}_job_scm_branch'.format(name)] = self.scm_branch
if self.job_template:
for name in ('awx', 'tower'):
r['{}_job_template_id'.format(name)] = self.job_template.pk
diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py
index 1abbb29fcb..c50c8668d5 100644
--- a/awx/main/models/unified_jobs.py
+++ b/awx/main/models/unified_jobs.py
@@ -873,7 +873,13 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
# If status changed, update the parent instance.
if self.status != status_before:
- self._update_parent_instance()
+ # Update parent outside of the transaction for Job w/ allow_simultaneous=True
+ # This dodges lock contention at the expense of the foreign key not being
+ # completely correct.
+ if getattr(self, 'allow_simultaneous', False):
+ connection.on_commit(self._update_parent_instance)
+ else:
+ self._update_parent_instance()
# Done.
return result
diff --git a/awx/main/models/workflow.py b/awx/main/models/workflow.py
index d3e9d2d957..dd8bc3e894 100644
--- a/awx/main/models/workflow.py
+++ b/awx/main/models/workflow.py
@@ -674,7 +674,7 @@ class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificatio
return self.status == 'running'
-class WorkflowApprovalTemplate(UnifiedJobTemplate):
+class WorkflowApprovalTemplate(UnifiedJobTemplate, RelatedJobsMixin):
FIELDS_TO_PRESERVE_AT_COPY = ['description', 'timeout',]
@@ -702,6 +702,12 @@ class WorkflowApprovalTemplate(UnifiedJobTemplate):
def workflow_job_template(self):
return self.workflowjobtemplatenodes.first().workflow_job_template
+ '''
+ RelatedJobsMixin
+ '''
+ def _get_related_jobs(self):
+ return UnifiedJob.objects.filter(unified_job_template=self)
+
class WorkflowApproval(UnifiedJob, JobNotificationMixin):
class Meta:
diff --git a/awx/main/notifications/webhook_backend.py b/awx/main/notifications/webhook_backend.py
index a33cf026f8..d67fc11a35 100644
--- a/awx/main/notifications/webhook_backend.py
+++ b/awx/main/notifications/webhook_backend.py
@@ -57,6 +57,7 @@ class WebhookBackend(AWXBaseEmailBackend, CustomNotificationBase):
def send_messages(self, messages):
sent_messages = 0
+ self.headers['Content-Type'] = 'application/json'
if 'User-Agent' not in self.headers:
self.headers['User-Agent'] = "Tower {}".format(get_awx_version())
if self.http_method.lower() not in ['put','post']:
@@ -68,7 +69,7 @@ class WebhookBackend(AWXBaseEmailBackend, CustomNotificationBase):
auth = (self.username, self.password)
r = chosen_method("{}".format(m.recipients()[0]),
auth=auth,
- json=m.body,
+ data=json.dumps(m.body, ensure_ascii=False).encode('utf-8'),
headers=self.headers,
verify=(not self.disable_ssl_verification))
if r.status_code >= 400:
diff --git a/awx/main/scheduler/kubernetes.py b/awx/main/scheduler/kubernetes.py
index 862cfd3f04..529a5e5442 100644
--- a/awx/main/scheduler/kubernetes.py
+++ b/awx/main/scheduler/kubernetes.py
@@ -12,6 +12,24 @@ from awx.main.utils.common import parse_yaml_or_json
logger = logging.getLogger('awx.main.scheduler')
+def deepmerge(a, b):
+ """
+ Merge dict structures and return the result.
+
+ >>> a = {'first': {'all_rows': {'pass': 'dog', 'number': '1'}}}
+ >>> b = {'first': {'all_rows': {'fail': 'cat', 'number': '5'}}}
+ >>> import pprint; pprint.pprint(deepmerge(a, b))
+ {'first': {'all_rows': {'fail': 'cat', 'number': '5', 'pass': 'dog'}}}
+ """
+ if isinstance(a, dict) and isinstance(b, dict):
+ return dict([(k, deepmerge(a.get(k), b.get(k)))
+ for k in set(a.keys()).union(b.keys())])
+ elif b is None:
+ return a
+ else:
+ return b
+
+
class PodManager(object):
def __init__(self, task=None):
@@ -128,11 +146,13 @@ class PodManager(object):
pod_spec = {**default_pod_spec, **pod_spec_override}
if self.task:
- pod_spec['metadata']['name'] = self.pod_name
- pod_spec['metadata']['labels'] = {
- 'ansible-awx': settings.INSTALL_UUID,
- 'ansible-awx-job-id': str(self.task.id)
- }
+ pod_spec['metadata'] = deepmerge(
+ pod_spec.get('metadata', {}),
+ dict(name=self.pod_name,
+ labels={
+ 'ansible-awx': settings.INSTALL_UUID,
+ 'ansible-awx-job-id': str(self.task.id)
+ }))
pod_spec['spec']['containers'][0]['name'] = self.pod_name
return pod_spec
diff --git a/awx/main/scheduler/task_manager.py b/awx/main/scheduler/task_manager.py
index 9f4818bd37..43d43fe64d 100644
--- a/awx/main/scheduler/task_manager.py
+++ b/awx/main/scheduler/task_manager.py
@@ -7,12 +7,14 @@ import logging
import uuid
import json
import random
+from types import SimpleNamespace
# Django
from django.db import transaction, connection
from django.utils.translation import ugettext_lazy as _, gettext_noop
from django.utils.timezone import now as tz_now
from django.conf import settings
+from django.db.models import Q
# AWX
from awx.main.dispatch.reaper import reap_job
@@ -45,6 +47,15 @@ logger = logging.getLogger('awx.main.scheduler')
class TaskManager():
def __init__(self):
+ '''
+ Do NOT put database queries or other potentially expensive operations
+ in the task manager init. The task manager object is created every time a
+ job is created, transitions state, and every 30 seconds on each tower node.
+ More often then not, the object is destroyed quickly because the NOOP case is hit.
+
+ The NOOP case is short-circuit logic. If the task manager realizes that another instance
+ of the task manager is already running, then it short-circuits and decides not to run.
+ '''
self.graph = dict()
# start task limit indicates how many pending jobs can be started on this
# .schedule() run. Starting jobs is expensive, and there is code in place to reap
@@ -52,10 +63,30 @@ class TaskManager():
# 5 minutes to start pending jobs. If this limit is reached, pending jobs
# will no longer be started and will be started on the next task manager cycle.
self.start_task_limit = settings.START_TASK_LIMIT
+
+ def after_lock_init(self):
+ '''
+ Init AFTER we know this instance of the task manager will run because the lock is acquired.
+ '''
+ instances = Instance.objects.filter(~Q(hostname=None), capacity__gt=0, enabled=True)
+ self.real_instances = {i.hostname: i for i in instances}
+
+ instances_partial = [SimpleNamespace(obj=instance,
+ remaining_capacity=instance.remaining_capacity,
+ capacity=instance.capacity,
+ jobs_running=instance.jobs_running,
+ hostname=instance.hostname) for instance in instances]
+
+ instances_by_hostname = {i.hostname: i for i in instances_partial}
+
for rampart_group in InstanceGroup.objects.prefetch_related('instances'):
self.graph[rampart_group.name] = dict(graph=DependencyGraph(rampart_group.name),
capacity_total=rampart_group.capacity,
- consumed_capacity=0)
+ consumed_capacity=0,
+ instances=[])
+ for instance in rampart_group.instances.filter(capacity__gt=0, enabled=True).order_by('hostname'):
+ if instance.hostname in instances_by_hostname:
+ self.graph[rampart_group.name]['instances'].append(instances_by_hostname[instance.hostname])
def is_job_blocked(self, task):
# TODO: I'm not happy with this, I think blocking behavior should be decided outside of the dependency graph
@@ -254,7 +285,7 @@ class TaskManager():
for group in InstanceGroup.objects.all():
if group.is_containerized or group.controller_id:
continue
- match = group.fit_task_to_most_remaining_capacity_instance(task)
+ match = group.fit_task_to_most_remaining_capacity_instance(task, group.instances.all())
if match:
break
task.instance_group = rampart_group
@@ -466,7 +497,6 @@ class TaskManager():
continue
preferred_instance_groups = task.preferred_instance_groups
found_acceptable_queue = False
- idle_instance_that_fits = None
if isinstance(task, WorkflowJob):
if task.unified_job_template_id in running_workflow_templates:
if not task.allow_simultaneous:
@@ -483,24 +513,24 @@ class TaskManager():
found_acceptable_queue = True
break
- if idle_instance_that_fits is None:
- idle_instance_that_fits = rampart_group.find_largest_idle_instance()
remaining_capacity = self.get_remaining_capacity(rampart_group.name)
if not rampart_group.is_containerized and self.get_remaining_capacity(rampart_group.name) <= 0:
logger.debug("Skipping group {}, remaining_capacity {} <= 0".format(
rampart_group.name, remaining_capacity))
continue
- execution_instance = rampart_group.fit_task_to_most_remaining_capacity_instance(task)
- if execution_instance:
- logger.debug("Starting {} in group {} instance {} (remaining_capacity={})".format(
- task.log_format, rampart_group.name, execution_instance.hostname, remaining_capacity))
- elif not execution_instance and idle_instance_that_fits:
+ execution_instance = InstanceGroup.fit_task_to_most_remaining_capacity_instance(task, self.graph[rampart_group.name]['instances']) or \
+ InstanceGroup.find_largest_idle_instance(self.graph[rampart_group.name]['instances'])
+
+ if execution_instance or rampart_group.is_containerized:
if not rampart_group.is_containerized:
- execution_instance = idle_instance_that_fits
+ execution_instance.remaining_capacity = max(0, execution_instance.remaining_capacity - task.task_impact)
+ execution_instance.jobs_running += 1
logger.debug("Starting {} in group {} instance {} (remaining_capacity={})".format(
task.log_format, rampart_group.name, execution_instance.hostname, remaining_capacity))
- if execution_instance or rampart_group.is_containerized:
+
+ if execution_instance:
+ execution_instance = self.real_instances[execution_instance.hostname]
self.graph[rampart_group.name]['graph'].add_job(task)
self.start_task(task, rampart_group, task.get_jobs_fail_chain(), execution_instance)
found_acceptable_queue = True
@@ -572,6 +602,9 @@ class TaskManager():
def _schedule(self):
finished_wfjs = []
all_sorted_tasks = self.get_tasks()
+
+ self.after_lock_init()
+
if len(all_sorted_tasks) > 0:
# TODO: Deal with
# latest_project_updates = self.get_latest_project_update_tasks(all_sorted_tasks)
diff --git a/awx/main/tasks.py b/awx/main/tasks.py
index 0e03055055..2a1c85e23d 100644
--- a/awx/main/tasks.py
+++ b/awx/main/tasks.py
@@ -313,7 +313,7 @@ def delete_project_files(project_path):
@task(queue='tower_broadcast_all')
def profile_sql(threshold=1, minutes=1):
- if threshold == 0:
+ if threshold <= 0:
cache.delete('awx-profile-sql-threshold')
logger.error('SQL PROFILING DISABLED')
else:
@@ -2160,7 +2160,7 @@ class RunProjectUpdate(BaseTask):
'local_path': os.path.basename(project_update.project.local_path),
'project_path': project_update.get_project_path(check_if_exists=False), # deprecated
'insights_url': settings.INSIGHTS_URL_BASE,
- 'awx_license_type': get_license(show_key=False).get('license_type', 'UNLICENSED'),
+ 'awx_license_type': get_license().get('license_type', 'UNLICENSED'),
'awx_version': get_awx_version(),
'scm_url': scm_url,
'scm_branch': scm_branch,
diff --git a/awx/main/tests/functional/analytics/test_projects_by_scm_type.py b/awx/main/tests/functional/analytics/test_projects_by_scm_type.py
deleted file mode 100644
index 1590b5d3bb..0000000000
--- a/awx/main/tests/functional/analytics/test_projects_by_scm_type.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import pytest
-import random
-
-from awx.main.models import Project
-from awx.main.analytics import collectors
-
-
-@pytest.mark.django_db
-def test_empty():
- assert collectors.projects_by_scm_type(None) == {
- 'manual': 0,
- 'git': 0,
- 'svn': 0,
- 'hg': 0,
- 'insights': 0,
- 'archive': 0,
- }
-
-
-@pytest.mark.django_db
-@pytest.mark.parametrize('scm_type', [t[0] for t in Project.SCM_TYPE_CHOICES])
-def test_multiple(scm_type):
- expected = {
- 'manual': 0,
- 'git': 0,
- 'svn': 0,
- 'hg': 0,
- 'insights': 0,
- 'archive': 0,
- }
- for i in range(random.randint(0, 10)):
- Project(scm_type=scm_type).save()
- expected[scm_type or 'manual'] += 1
- assert collectors.projects_by_scm_type(None) == expected
diff --git a/awx/main/tests/functional/api/test_credential.py b/awx/main/tests/functional/api/test_credential.py
index 9a534a8897..e8e7b4b271 100644
--- a/awx/main/tests/functional/api/test_credential.py
+++ b/awx/main/tests/functional/api/test_credential.py
@@ -675,33 +675,6 @@ def test_net_create_ok(post, organization, admin):
assert cred.inputs['authorize'] is True
-#
-# Cloudforms Credentials
-#
-@pytest.mark.django_db
-def test_cloudforms_create_ok(post, organization, admin):
- params = {
- 'credential_type': 1,
- 'name': 'Best credential ever',
- 'inputs': {
- 'host': 'some_host',
- 'username': 'some_username',
- 'password': 'some_password',
- }
- }
- cloudforms = CredentialType.defaults['cloudforms']()
- cloudforms.save()
- params['organization'] = organization.id
- response = post(reverse('api:credential_list'), params, admin)
- assert response.status_code == 201
-
- assert Credential.objects.count() == 1
- cred = Credential.objects.all()[:1].get()
- assert cred.inputs['host'] == 'some_host'
- assert cred.inputs['username'] == 'some_username'
- assert decrypt_field(cred, 'password') == 'some_password'
-
-
#
# GCE Credentials
#
diff --git a/awx/main/tests/functional/api/test_project.py b/awx/main/tests/functional/api/test_project.py
index 09fed17c67..a31eb0804a 100644
--- a/awx/main/tests/functional/api/test_project.py
+++ b/awx/main/tests/functional/api/test_project.py
@@ -99,3 +99,12 @@ def test_changing_overwrite_behavior_okay_if_not_used(post, patch, organization,
expect=200
)
assert Project.objects.get(pk=r1.data['id']).allow_override is False
+
+
+@pytest.mark.django_db
+def test_scm_project_local_path_invalid(get, patch, project, admin):
+ url = reverse('api:project_detail', kwargs={'pk': project.id})
+ resp = patch(url, {'local_path': '/foo/bar'}, user=admin, expect=400)
+ assert resp.data['local_path'] == [
+ 'Cannot change local_path for git-based projects'
+ ]
diff --git a/awx/main/tests/functional/api/test_rbac_displays.py b/awx/main/tests/functional/api/test_rbac_displays.py
index 4180647d44..d0a0cb4f98 100644
--- a/awx/main/tests/functional/api/test_rbac_displays.py
+++ b/awx/main/tests/functional/api/test_rbac_displays.py
@@ -282,10 +282,6 @@ def test_prefetch_ujt_project_capabilities(alice, project, job_template, mocker)
list_serializer.child.to_representation(project)
assert 'capability_map' not in list_serializer.child.context
- # Models for which the prefetch is valid for do
- list_serializer.child.to_representation(job_template)
- assert set(list_serializer.child.context['capability_map'][job_template.id].keys()) == set(('copy', 'edit', 'start'))
-
@pytest.mark.django_db
def test_prefetch_group_capabilities(group, rando):
diff --git a/awx/main/tests/functional/api/test_schedules.py b/awx/main/tests/functional/api/test_schedules.py
index 7b93c2804b..bdaa6aa4a6 100644
--- a/awx/main/tests/functional/api/test_schedules.py
+++ b/awx/main/tests/functional/api/test_schedules.py
@@ -349,7 +349,7 @@ def test_months_with_31_days(post, admin_user):
('MINUTELY', 1, 60),
('MINUTELY', 15, 15 * 60),
('HOURLY', 1, 3600),
- ('HOURLY', 4, 3600 * 4),
+ ('HOURLY', 2, 3600 * 2),
))
def test_really_old_dtstart(post, admin_user, freq, delta, total_seconds):
url = reverse('api:schedule_rrule')
diff --git a/awx/main/tests/functional/api/test_settings.py b/awx/main/tests/functional/api/test_settings.py
index 67c9868649..8a1f50035f 100644
--- a/awx/main/tests/functional/api/test_settings.py
+++ b/awx/main/tests/functional/api/test_settings.py
@@ -4,7 +4,6 @@
# Python
import pytest
-import os
from django.conf import settings
@@ -19,15 +18,6 @@ TEST_PNG_LOGO = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAjCAYAAAAaL
TEST_JPEG_LOGO = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBkRXhpZgAATU0AKgAAAAgAAwEGAAMAAAABAAIAAAESAAMAAAABAAEAAIdpAAQAAAABAAAAMgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAIaADAAQAAAABAAAAIwAAAAD/4QkhaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQuMCI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiLz4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+AP/tADhQaG90b3Nob3AgMy4wADhCSU0EBAAAAAAAADhCSU0EJQAAAAAAENQdjNmPALIE6YAJmOz4Qn7/wAARCAAjACEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9sAQwAGBgYGBgYKBgYKDgoKCg4SDg4ODhIXEhISEhIXHBcXFxcXFxwcHBwcHBwcIiIiIiIiJycnJycsLCwsLCwsLCws/9sAQwEHBwcLCgsTCgoTLh8aHy4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u/90ABAAD/9oADAMBAAIRAxEAPwD6poormvFfivSvB2lHVtWLGMtsRE2hnYKzlVLsi52oxALDdjauWKqQCXQfFXh7xP8Aaf7AvYrz7HL5U3lk/K3YjIGVODtcZVsHBODXQV806bcT+E9L03XbCOS2udMsLQanbB4po72xYMfOQpKYyV2zPEwcNwVK7WAr6WriwWMWIUvdcZRdmnuu33rVFSjYKKKK7ST/0PqmuF8Vv4X8S+HNZ0+e/gIsYJvtEsL+bJZsI3UuyxNvBA3gpxvXchyCRXdV8ta3bW667DoloW1y10tLLTJxZWP2hoLSGYzNHclGZpJC0ESk8IAZcRB8is61T2cHK1/1DrY526h8YXHh691vxCz6dafY5Q0U7yGSeQxSxohNzJLcbUeQ4VnVNxBRCWL19b2eraVqE9xa2F3BcS2jbJ0ikV2ibJG1wpJU5UjBx0PpXzrrniy4k17TrrWrGex022ufMijvd9m11PGH8naXKqsUcgR3MhB5U7MA16x4L8F3vhq2sY9Ru4rg6day2tusEAhCrcOkknmEMRI2Y1AcLGT8xYMzZHjZFGu6cquKjaUnt2XS76vv/SN8RVjOdoKyXY9Cooor3TA//9H6pr4gfxRrMvxJ0/whLJE+maVrcVnZRtBCzwQQ3SIipMU80fKignflgPmJr7fr4A/5rf8A9zJ/7eUAdX8SfGviPwl8TtaPh6eK1eTyN0n2eCSUg28OV8ySNn2/KDtztzzjNfZVhY2umWMGm2KeXb2sSQxJknakYCqMkknAHUnNfBXxt/5Kdq//AG7/APpPFX3/AEAFFFFAH//Z' # NOQA
-@pytest.fixture
-def mock_no_license_file(mocker):
- '''
- Ensures that tests don't pick up dev container license file
- '''
- os.environ['AWX_LICENSE_FILE'] = '/does_not_exist'
- return None
-
-
@pytest.mark.django_db
def test_url_base_defaults_to_request(options, admin):
# If TOWER_URL_BASE is not set, default to the Tower request hostname
diff --git a/awx/main/tests/functional/api/test_workflow_node.py b/awx/main/tests/functional/api/test_workflow_node.py
index ec70716f94..6253548d60 100644
--- a/awx/main/tests/functional/api/test_workflow_node.py
+++ b/awx/main/tests/functional/api/test_workflow_node.py
@@ -89,7 +89,7 @@ class TestApprovalNodes():
url = reverse('api:workflow_job_template_node_create_approval',
kwargs={'pk': approval_node.pk, 'version': 'v2'})
post(url, {'name': 'Test', 'description': 'Approval Node', 'timeout': 0},
- user=admin_user, expect=200)
+ user=admin_user, expect=201)
approval_node = WorkflowJobTemplateNode.objects.get(pk=approval_node.pk)
assert isinstance(approval_node.unified_job_template, WorkflowApprovalTemplate)
@@ -108,9 +108,9 @@ class TestApprovalNodes():
assert {'name': ['This field may not be blank.']} == json.loads(r.content)
@pytest.mark.parametrize("is_admin, is_org_admin, status", [
- [True, False, 200], # if they're a WFJT admin, they get a 200
+ [True, False, 201], # if they're a WFJT admin, they get a 201
[False, False, 403], # if they're not a WFJT *nor* org admin, they get a 403
- [False, True, 200], # if they're an organization admin, they get a 200
+ [False, True, 201], # if they're an organization admin, they get a 201
])
def test_approval_node_creation_rbac(self, post, approval_node, alice, is_admin, is_org_admin, status):
url = reverse('api:workflow_job_template_node_create_approval',
@@ -165,7 +165,7 @@ class TestApprovalNodes():
url = reverse('api:workflow_job_template_node_create_approval',
kwargs={'pk': node.pk, 'version': 'v2'})
post(url, {'name': 'Approve Test', 'description': '', 'timeout': 0},
- user=admin_user, expect=200)
+ user=admin_user, expect=201)
post(reverse('api:workflow_job_template_launch', kwargs={'pk': wfjt.pk}),
user=admin_user, expect=201)
wf_job = WorkflowJob.objects.first()
@@ -195,7 +195,7 @@ class TestApprovalNodes():
url = reverse('api:workflow_job_template_node_create_approval',
kwargs={'pk': node.pk, 'version': 'v2'})
post(url, {'name': 'Deny Test', 'description': '', 'timeout': 0},
- user=admin_user, expect=200)
+ user=admin_user, expect=201)
post(reverse('api:workflow_job_template_launch', kwargs={'pk': wfjt.pk}),
user=admin_user, expect=201)
wf_job = WorkflowJob.objects.first()
diff --git a/awx/main/tests/functional/core/test_licenses.py b/awx/main/tests/functional/core/test_licenses.py
deleted file mode 100644
index f59318502c..0000000000
--- a/awx/main/tests/functional/core/test_licenses.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015 Ansible, Inc.
-# All Rights Reserved.
-
-from awx.main.utils.common import StubLicense
-
-
-def test_stub_license():
- license_actual = StubLicense().validate()
- assert license_actual['license_key'] == 'OPEN'
- assert license_actual['valid_key']
- assert license_actual['compliant']
- assert license_actual['license_type'] == 'open'
-
diff --git a/awx/main/tests/functional/test_credential.py b/awx/main/tests/functional/test_credential.py
index 684f9dd5a7..27f67b96f4 100644
--- a/awx/main/tests/functional/test_credential.py
+++ b/awx/main/tests/functional/test_credential.py
@@ -79,7 +79,6 @@ def test_default_cred_types():
'aws',
'azure_kv',
'azure_rm',
- 'cloudforms',
'conjur',
'galaxy_api_token',
'gce',
diff --git a/awx/main/tests/functional/test_inventory_source_migration.py b/awx/main/tests/functional/test_inventory_source_migration.py
index ecea2f0408..2b1e089392 100644
--- a/awx/main/tests/functional/test_inventory_source_migration.py
+++ b/awx/main/tests/functional/test_inventory_source_migration.py
@@ -5,7 +5,7 @@ from awx.main.migrations import _inventory_source as invsrc
from django.apps import apps
-from awx.main.models import InventorySource
+from awx.main.models import InventorySource, InventoryUpdate, ManagedCredentialType, CredentialType, Credential
@pytest.mark.parametrize('vars,id_var,result', [
@@ -42,16 +42,40 @@ def test_apply_new_instance_id(inventory_source):
@pytest.mark.django_db
-def test_replacement_scm_sources(inventory):
- inv_source = InventorySource.objects.create(
- name='test',
- inventory=inventory,
- organization=inventory.organization,
- source='ec2'
+def test_cloudforms_inventory_removal(inventory):
+ ManagedCredentialType(
+ name='Red Hat CloudForms',
+ namespace='cloudforms',
+ kind='cloud',
+ managed_by_tower=True,
+ inputs={},
)
- invsrc.create_scm_script_substitute(apps, 'ec2')
- inv_source.refresh_from_db()
- assert inv_source.source == 'scm'
- assert inv_source.source_project
- project = inv_source.source_project
- assert 'Replacement project for' in project.name
+ CredentialType.defaults['cloudforms']().save()
+ cloudforms = CredentialType.objects.get(namespace='cloudforms')
+ Credential.objects.create(
+ name='test',
+ credential_type=cloudforms,
+ )
+
+ for source in ('ec2', 'cloudforms'):
+ i = InventorySource.objects.create(
+ name='test',
+ inventory=inventory,
+ organization=inventory.organization,
+ source=source,
+ )
+ InventoryUpdate.objects.create(
+ name='test update',
+ inventory_source=i,
+ source=source,
+ )
+ assert Credential.objects.count() == 1
+ assert InventorySource.objects.count() == 2 # ec2 + cf
+ assert InventoryUpdate.objects.count() == 2 # ec2 + cf
+ invsrc.delete_cloudforms_inv_source(apps, None)
+ assert InventorySource.objects.count() == 1 # ec2
+ assert InventoryUpdate.objects.count() == 1 # ec2
+ assert InventorySource.objects.first().source == 'ec2'
+ assert InventoryUpdate.objects.first().source == 'ec2'
+ assert Credential.objects.count() == 0
+ assert CredentialType.objects.filter(namespace='cloudforms').exists() is False
diff --git a/awx/main/tests/functional/test_licenses.py b/awx/main/tests/functional/test_licenses.py
index 6c34321f8d..757349ee13 100644
--- a/awx/main/tests/functional/test_licenses.py
+++ b/awx/main/tests/functional/test_licenses.py
@@ -1,6 +1,5 @@
import glob
-import json
import os
from django.conf import settings
@@ -30,8 +29,7 @@ def test_python_and_js_licenses():
# Check variations of '-' and '_' in filenames due to python
for fname in [name, name.replace('-','_')]:
if entry.startswith(fname) and entry.endswith('.tar.gz'):
- entry = entry[:-7]
- (n, v) = entry.rsplit('-',1)
+ v = entry.split(name + '-')[1].split('.tar.gz')[0]
return v
return None
@@ -66,28 +64,6 @@ def test_python_and_js_licenses():
ret[name] = { 'name': name, 'version': version}
return ret
-
- def read_ui_requirements(path):
- def json_deps(jsondata):
- ret = {}
- deps = jsondata.get('dependencies',{})
- for key in deps.keys():
- key = key.lower()
- devonly = deps[key].get('dev',False)
- if not devonly:
- if key not in ret.keys():
- depname = key.replace('/','-')
- ret[depname] = {
- 'name': depname,
- 'version': deps[key]['version']
- }
- ret.update(json_deps(deps[key]))
- return ret
-
- with open('%s/package-lock.json' % path) as f:
- jsondata = json.load(f)
- return json_deps(jsondata)
-
def remediate_licenses_and_requirements(licenses, requirements):
errors = []
items = list(licenses.keys())
@@ -114,12 +90,9 @@ def test_python_and_js_licenses():
base_dir = settings.BASE_DIR
api_licenses = index_licenses('%s/../docs/licenses' % base_dir)
- ui_licenses = index_licenses('%s/../docs/licenses/ui' % base_dir)
api_requirements = read_api_requirements('%s/../requirements' % base_dir)
- ui_requirements = read_ui_requirements('%s/ui' % base_dir)
errors = []
- errors += remediate_licenses_and_requirements(ui_licenses, ui_requirements)
errors += remediate_licenses_and_requirements(api_licenses, api_requirements)
if errors:
raise Exception('Included licenses not consistent with requirements:\n%s' %
diff --git a/awx/main/tests/unit/models/test_ha.py b/awx/main/tests/unit/models/test_ha.py
index 0e29caf8aa..2534acfd15 100644
--- a/awx/main/tests/unit/models/test_ha.py
+++ b/awx/main/tests/unit/models/test_ha.py
@@ -45,19 +45,14 @@ class TestInstanceGroup(object):
(T(100), Is([50, 0, 20, 99, 11, 1, 5, 99]), None, "The task don't a fit, you must a quit!"),
])
def test_fit_task_to_most_remaining_capacity_instance(self, task, instances, instance_fit_index, reason):
- with mock.patch.object(InstanceGroup,
- 'instances',
- Mock(spec_set=['filter'],
- filter=lambda *args, **kargs: Mock(spec_set=['order_by'],
- order_by=lambda x: instances))):
- ig = InstanceGroup(id=10)
+ ig = InstanceGroup(id=10)
- if instance_fit_index is None:
- assert ig.fit_task_to_most_remaining_capacity_instance(task) is None, reason
- else:
- assert ig.fit_task_to_most_remaining_capacity_instance(task) == \
- instances[instance_fit_index], reason
+ instance_picked = ig.fit_task_to_most_remaining_capacity_instance(task, instances)
+ if instance_fit_index is None:
+ assert instance_picked is None, reason
+ else:
+ assert instance_picked == instances[instance_fit_index], reason
@pytest.mark.parametrize('instances,instance_fit_index,reason', [
(Is([(0, 100)]), 0, "One idle instance, pick it"),
@@ -70,16 +65,12 @@ class TestInstanceGroup(object):
def filter_offline_instances(*args):
return filter(lambda i: i.capacity > 0, instances)
- with mock.patch.object(InstanceGroup,
- 'instances',
- Mock(spec_set=['filter'],
- filter=lambda *args, **kargs: Mock(spec_set=['order_by'],
- order_by=filter_offline_instances))):
- ig = InstanceGroup(id=10)
+ ig = InstanceGroup(id=10)
+ instances_online_only = filter_offline_instances(instances)
- if instance_fit_index is None:
- assert ig.find_largest_idle_instance() is None, reason
- else:
- assert ig.find_largest_idle_instance() == \
- instances[instance_fit_index], reason
+ if instance_fit_index is None:
+ assert ig.find_largest_idle_instance(instances_online_only) is None, reason
+ else:
+ assert ig.find_largest_idle_instance(instances_online_only) == \
+ instances[instance_fit_index], reason
diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py
index b49af2efd0..0de5dce996 100644
--- a/awx/main/tests/unit/test_tasks.py
+++ b/awx/main/tests/unit/test_tasks.py
@@ -39,6 +39,8 @@ from awx.main import tasks
from awx.main.utils import encrypt_field, encrypt_value
from awx.main.utils.safe_yaml import SafeLoader
+from awx.main.utils.licensing import Licenser
+
class TestJobExecution(object):
EXAMPLE_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\nxyz==\n-----END PRIVATE KEY-----'
@@ -1830,7 +1832,10 @@ class TestProjectUpdateGalaxyCredentials(TestJobExecution):
task = RunProjectUpdate()
env = task.build_env(project_update, private_data_dir)
- task.build_extra_vars_file(project_update, private_data_dir)
+
+ with mock.patch.object(Licenser, 'validate', lambda *args, **kw: {}):
+ task.build_extra_vars_file(project_update, private_data_dir)
+
assert task.__vars__['roles_enabled'] is False
assert task.__vars__['collections_enabled'] is False
for k in env:
@@ -1850,7 +1855,10 @@ class TestProjectUpdateGalaxyCredentials(TestJobExecution):
project_update.project.organization.galaxy_credentials.add(public_galaxy)
task = RunProjectUpdate()
env = task.build_env(project_update, private_data_dir)
- task.build_extra_vars_file(project_update, private_data_dir)
+
+ with mock.patch.object(Licenser, 'validate', lambda *args, **kw: {}):
+ task.build_extra_vars_file(project_update, private_data_dir)
+
assert task.__vars__['roles_enabled'] is True
assert task.__vars__['collections_enabled'] is True
assert sorted([
@@ -1935,7 +1943,9 @@ class TestProjectUpdateCredentials(TestJobExecution):
assert settings.PROJECTS_ROOT in process_isolation['process_isolation_show_paths']
task._write_extra_vars_file = mock.Mock()
- task.build_extra_vars_file(project_update, private_data_dir)
+
+ with mock.patch.object(Licenser, 'validate', lambda *args, **kw: {}):
+ task.build_extra_vars_file(project_update, private_data_dir)
call_args, _ = task._write_extra_vars_file.call_args_list[0]
_, extra_vars = call_args
@@ -2140,10 +2150,6 @@ class TestInventoryUpdateCredentials(TestJobExecution):
return cred
inventory_update.get_cloud_credential = get_cred
inventory_update.get_extra_credentials = mocker.Mock(return_value=[])
- inventory_update.source_vars = {
- 'include_powerstate': 'yes',
- 'group_by_resource_group': 'no'
- }
private_data_files = task.build_private_data_files(inventory_update, private_data_dir)
env = task.build_env(inventory_update, private_data_dir, False, private_data_files)
@@ -2177,11 +2183,6 @@ class TestInventoryUpdateCredentials(TestJobExecution):
return cred
inventory_update.get_cloud_credential = get_cred
inventory_update.get_extra_credentials = mocker.Mock(return_value=[])
- inventory_update.source_vars = {
- 'include_powerstate': 'yes',
- 'group_by_resource_group': 'no',
- 'group_by_security_group': 'no'
- }
private_data_files = task.build_private_data_files(inventory_update, private_data_dir)
env = task.build_env(inventory_update, private_data_dir, False, private_data_files)
@@ -2296,21 +2297,14 @@ class TestInventoryUpdateCredentials(TestJobExecution):
inventory_update.get_cloud_credential = get_cred
inventory_update.get_extra_credentials = mocker.Mock(return_value=[])
- inventory_update.source_vars = {
- 'satellite6_group_patterns': '[a,b,c]',
- 'satellite6_group_prefix': 'hey_',
- 'satellite6_want_hostcollections': True,
- 'satellite6_want_ansible_ssh_host': True,
- 'satellite6_rich_params': True,
- 'satellite6_want_facts': False
- }
-
private_data_files = task.build_private_data_files(inventory_update, private_data_dir)
env = task.build_env(inventory_update, private_data_dir, False, private_data_files)
+ safe_env = build_safe_env(env)
- env["FOREMAN_SERVER"] == "https://example.org",
- env["FOREMAN_USER"] == "bob",
- env["FOREMAN_PASSWORD"] == "secret",
+ assert env["FOREMAN_SERVER"] == "https://example.org"
+ assert env["FOREMAN_USER"] == "bob"
+ assert env["FOREMAN_PASSWORD"] == "secret"
+ assert safe_env["FOREMAN_PASSWORD"] == tasks.HIDDEN_PASSWORD
@pytest.mark.parametrize('verify', [True, False])
def test_tower_source(self, verify, inventory_update, private_data_dir, mocker):
diff --git a/awx/main/utils/common.py b/awx/main/utils/common.py
index a65120c8e8..00fc73c631 100644
--- a/awx/main/utils/common.py
+++ b/awx/main/utils/common.py
@@ -55,8 +55,7 @@ __all__ = [
'model_instance_diff', 'parse_yaml_or_json', 'RequireDebugTrueOrTest',
'has_model_field_prefetched', 'set_environ', 'IllegalArgumentError',
'get_custom_venv_choices', 'get_external_account', 'task_manager_bulk_reschedule',
- 'schedule_task_manager', 'classproperty', 'create_temporary_fifo', 'truncate_stdout',
- 'StubLicense'
+ 'schedule_task_manager', 'classproperty', 'create_temporary_fifo', 'truncate_stdout'
]
@@ -190,7 +189,7 @@ def get_awx_version():
def get_awx_http_client_headers():
- license = get_license(show_key=False).get('license_type', 'UNLICENSED')
+ license = get_license().get('license_type', 'UNLICENSED')
headers = {
'Content-Type': 'application/json',
'User-Agent': '{} {} ({})'.format(
@@ -202,34 +201,15 @@ def get_awx_http_client_headers():
return headers
-class StubLicense(object):
-
- features = {
- 'activity_streams': True,
- 'ha': True,
- 'ldap': True,
- 'multiple_organizations': True,
- 'surveys': True,
- 'system_tracking': True,
- 'rebranding': True,
- 'enterprise_auth': True,
- 'workflows': True,
- }
-
- def validate(self):
- return dict(license_key='OPEN',
- valid_key=True,
- compliant=True,
- features=self.features,
- license_type='open')
-
-
def get_licenser(*args, **kwargs):
+ from awx.main.utils.licensing import Licenser, OpenLicense
try:
- from tower_license import TowerLicense
- return TowerLicense(*args, **kwargs)
- except ImportError:
- return StubLicense(*args, **kwargs)
+ if os.path.exists('/var/lib/awx/.tower_version'):
+ return Licenser(*args, **kwargs)
+ else:
+ return OpenLicense()
+ except Exception as e:
+ raise ValueError(_('Error importing Tower License: %s') % e)
def update_scm_url(scm_type, url, username=True, password=True,
diff --git a/awx/main/utils/licensing.py b/awx/main/utils/licensing.py
new file mode 100644
index 0000000000..efefcf6944
--- /dev/null
+++ b/awx/main/utils/licensing.py
@@ -0,0 +1,393 @@
+# Copyright (c) 2015 Ansible, Inc.
+# All Rights Reserved.
+
+'''
+This is intended to be a lightweight license class for verifying subscriptions, and parsing subscription data
+from entitlement certificates.
+
+The Licenser class can do the following:
+ - Parse an Entitlement cert to generate license
+'''
+
+import base64
+import configparser
+from datetime import datetime
+import collections
+import copy
+import io
+import json
+import logging
+import re
+import requests
+import time
+import zipfile
+
+from dateutil.parser import parse as parse_date
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.asymmetric import padding
+from cryptography import x509
+
+# Django
+from django.conf import settings
+from django.utils.translation import ugettext_lazy as _
+
+# AWX
+from awx.main.models import Host
+
+MAX_INSTANCES = 9999999
+
+logger = logging.getLogger(__name__)
+
+
+def rhsm_config():
+ path = '/etc/rhsm/rhsm.conf'
+ config = configparser.ConfigParser()
+ config.read(path)
+ return config
+
+
+def validate_entitlement_manifest(data):
+ buff = io.BytesIO()
+ buff.write(base64.b64decode(data))
+ try:
+ z = zipfile.ZipFile(buff)
+ except zipfile.BadZipFile as e:
+ raise ValueError(_("Invalid manifest: a subscription manifest zip file is required.")) from e
+ buff = io.BytesIO()
+
+ files = z.namelist()
+ if 'consumer_export.zip' not in files or 'signature' not in files:
+ raise ValueError(_("Invalid manifest: missing required files."))
+ export = z.open('consumer_export.zip').read()
+ sig = z.open('signature').read()
+ with open('/etc/tower/candlepin-redhat-ca.crt', 'rb') as f:
+ cert = x509.load_pem_x509_certificate(f.read(), backend=default_backend())
+ key = cert.public_key()
+ try:
+ key.verify(sig, export, padding=padding.PKCS1v15(), algorithm=hashes.SHA256())
+ except InvalidSignature as e:
+ raise ValueError(_("Invalid manifest: signature verification failed.")) from e
+
+ buff.write(export)
+ z = zipfile.ZipFile(buff)
+ for f in z.filelist:
+ if f.filename.startswith('export/entitlements') and f.filename.endswith('.json'):
+ return json.loads(z.open(f).read())
+ raise ValueError(_("Invalid manifest: manifest contains no subscriptions."))
+
+
+class OpenLicense(object):
+ def validate(self):
+ return dict(
+ license_type='open',
+ valid_key=True,
+ subscription_name='OPEN',
+ product_name="AWX",
+ )
+
+
+class Licenser(object):
+ # warn when there is a month (30 days) left on the subscription
+ SUBSCRIPTION_TIMEOUT = 60 * 60 * 24 * 30
+
+ UNLICENSED_DATA = dict(
+ subscription_name=None,
+ sku=None,
+ support_level=None,
+ instance_count=0,
+ license_date=0,
+ license_type="UNLICENSED",
+ product_name="Red Hat Ansible Automation Platform",
+ valid_key=False
+ )
+
+ def __init__(self, **kwargs):
+ self._attrs = dict(
+ instance_count=0,
+ license_date=0,
+ license_type='UNLICENSED',
+ )
+ self.config = rhsm_config()
+ if not kwargs:
+ license_setting = getattr(settings, 'LICENSE', None)
+ if license_setting is not None:
+ kwargs = license_setting
+
+ if 'company_name' in kwargs:
+ kwargs.pop('company_name')
+ self._attrs.update(kwargs)
+ if 'valid_key' in self._attrs:
+ if not self._attrs['valid_key']:
+ self._unset_attrs()
+ else:
+ self._unset_attrs()
+
+
+ def _unset_attrs(self):
+ self._attrs = self.UNLICENSED_DATA.copy()
+
+
+ def license_from_manifest(self, manifest):
+ # Parse output for subscription metadata to build config
+ license = dict()
+ license['sku'] = manifest['pool']['productId']
+ try:
+ license['instance_count'] = manifest['pool']['exported']
+ except KeyError:
+ license['instance_count'] = manifest['pool']['quantity']
+ license['subscription_name'] = manifest['pool']['productName']
+ license['pool_id'] = manifest['pool']['id']
+ license['license_date'] = parse_date(manifest['endDate']).strftime('%s')
+ license['product_name'] = manifest['pool']['productName']
+ license['valid_key'] = True
+ license['license_type'] = 'enterprise'
+ license['satellite'] = False
+
+ self._attrs.update(license)
+ settings.LICENSE = self._attrs
+ return self._attrs
+
+
+ def update(self, **kwargs):
+ # Update attributes of the current license.
+ if 'instance_count' in kwargs:
+ kwargs['instance_count'] = int(kwargs['instance_count'])
+ if 'license_date' in kwargs:
+ kwargs['license_date'] = int(kwargs['license_date'])
+ self._attrs.update(kwargs)
+
+
+ def validate_rh(self, user, pw):
+ try:
+ host = 'https://' + str(self.config.get("server", "hostname"))
+ except Exception:
+ logger.exception('Cannot access rhsm.conf, make sure subscription manager is installed and configured.')
+ host = None
+ if not host:
+ host = getattr(settings, 'REDHAT_CANDLEPIN_HOST', None)
+
+ if not user:
+ raise ValueError('subscriptions_username is required')
+
+ if not pw:
+ raise ValueError('subscriptions_password is required')
+
+ if host and user and pw:
+ if 'subscription.rhsm.redhat.com' in host:
+ json = self.get_rhsm_subs(host, user, pw)
+ else:
+ json = self.get_satellite_subs(host, user, pw)
+ return self.generate_license_options_from_entitlements(json)
+ return []
+
+
+ def get_rhsm_subs(self, host, user, pw):
+ verify = getattr(settings, 'REDHAT_CANDLEPIN_VERIFY', True)
+ json = []
+ try:
+ subs = requests.get(
+ '/'.join([host, 'subscription/users/{}/owners'.format(user)]),
+ verify=verify,
+ auth=(user, pw)
+ )
+ except requests.exceptions.ConnectionError as error:
+ raise error
+ except OSError as error:
+ raise OSError('Unable to open certificate bundle {}. Check that Ansible Tower is running on Red Hat Enterprise Linux.'.format(verify)) from error # noqa
+ subs.raise_for_status()
+
+ for sub in subs.json():
+ resp = requests.get(
+ '/'.join([
+ host,
+ 'subscription/owners/{}/pools/?match=*tower*'.format(sub['key'])
+ ]),
+ verify=verify,
+ auth=(user, pw)
+ )
+ resp.raise_for_status()
+ json.extend(resp.json())
+ return json
+
+
+ def get_satellite_subs(self, host, user, pw):
+ try:
+ verify = str(self.config.get("rhsm", "repo_ca_cert"))
+ except Exception as e:
+ logger.exception('Unable to read rhsm config to get ca_cert location. {}'.format(str(e)))
+ verify = getattr(settings, 'REDHAT_CANDLEPIN_VERIFY', True)
+ json = []
+ try:
+ orgs = requests.get(
+ '/'.join([host, 'katello/api/organizations']),
+ verify=verify,
+ auth=(user, pw)
+ )
+ except requests.exceptions.ConnectionError as error:
+ raise error
+ except OSError as error:
+ raise OSError('Unable to open certificate bundle {}. Check that Ansible Tower is running on Red Hat Enterprise Linux.'.format(verify)) from error # noqa
+ orgs.raise_for_status()
+
+ for org in orgs.json()['results']:
+ resp = requests.get(
+ '/'.join([
+ host,
+ '/katello/api/organizations/{}/subscriptions/?search=Red Hat Ansible Automation'.format(org['id'])
+ ]),
+ verify=verify,
+ auth=(user, pw)
+ )
+ resp.raise_for_status()
+ results = resp.json()['results']
+ if results != []:
+ for sub in results:
+ # Parse output for subscription metadata to build config
+ license = dict()
+ license['productId'] = sub['product_id']
+ license['quantity'] = int(sub['quantity'])
+ license['support_level'] = sub['support_level']
+ license['subscription_name'] = sub['name']
+ license['id'] = sub['upstream_pool_id']
+ license['endDate'] = sub['end_date']
+ license['productName'] = "Red Hat Ansible Automation"
+ license['valid_key'] = True
+ license['license_type'] = 'enterprise'
+ license['satellite'] = True
+ json.append(license)
+ return json
+
+
+ def is_appropriate_sat_sub(self, sub):
+ if 'Red Hat Ansible Automation' not in sub['subscription_name']:
+ return False
+ return True
+
+
+ def is_appropriate_sub(self, sub):
+ if sub['activeSubscription'] is False:
+ return False
+ # Products that contain Ansible Tower
+ products = sub.get('providedProducts', [])
+ if any(map(lambda product: product.get('productId', None) == "480", products)):
+ return True
+ return False
+
+
+ def generate_license_options_from_entitlements(self, json):
+ from dateutil.parser import parse
+ ValidSub = collections.namedtuple('ValidSub', 'sku name support_level end_date trial quantity pool_id satellite')
+ valid_subs = []
+ for sub in json:
+ satellite = sub.get('satellite')
+ if satellite:
+ is_valid = self.is_appropriate_sat_sub(sub)
+ else:
+ is_valid = self.is_appropriate_sub(sub)
+ if is_valid:
+ try:
+ end_date = parse(sub.get('endDate'))
+ except Exception:
+ continue
+ now = datetime.utcnow()
+ now = now.replace(tzinfo=end_date.tzinfo)
+ if end_date < now:
+ # If the sub has a past end date, skip it
+ continue
+ try:
+ quantity = int(sub['quantity'])
+ if quantity == -1:
+ # effectively, unlimited
+ quantity = MAX_INSTANCES
+ except Exception:
+ continue
+
+ sku = sub['productId']
+ trial = sku.startswith('S') # i.e.,, SER/SVC
+ support_level = ''
+ pool_id = sub['id']
+ if satellite:
+ support_level = sub['support_level']
+ else:
+ for attr in sub.get('productAttributes', []):
+ if attr.get('name') == 'support_level':
+ support_level = attr.get('value')
+
+ valid_subs.append(ValidSub(
+ sku, sub['productName'], support_level, end_date, trial, quantity, pool_id, satellite
+ ))
+
+ if valid_subs:
+ licenses = []
+ for sub in valid_subs:
+ license = self.__class__(subscription_name='Red Hat Ansible Automation Platform')
+ license._attrs['instance_count'] = int(sub.quantity)
+ license._attrs['sku'] = sub.sku
+ license._attrs['support_level'] = sub.support_level
+ license._attrs['license_type'] = 'enterprise'
+ if sub.trial:
+ license._attrs['trial'] = True
+ license._attrs['license_type'] = 'trial'
+ license._attrs['instance_count'] = min(
+ MAX_INSTANCES, license._attrs['instance_count']
+ )
+ human_instances = license._attrs['instance_count']
+ if human_instances == MAX_INSTANCES:
+ human_instances = 'Unlimited'
+ subscription_name = re.sub(
+ r' \([\d]+ Managed Nodes',
+ ' ({} Managed Nodes'.format(human_instances),
+ sub.name
+ )
+ license._attrs['subscription_name'] = subscription_name
+ license._attrs['satellite'] = satellite
+ license._attrs['valid_key'] = True
+ license.update(
+ license_date=int(sub.end_date.strftime('%s'))
+ )
+ license.update(
+ pool_id=sub.pool_id
+ )
+ licenses.append(license._attrs.copy())
+ return licenses
+
+ raise ValueError(
+ 'No valid Red Hat Ansible Automation subscription could be found for this account.' # noqa
+ )
+
+
+ def validate(self):
+ # Return license attributes with additional validation info.
+ attrs = copy.deepcopy(self._attrs)
+ type = attrs.get('license_type', 'none')
+
+ if (type == 'UNLICENSED' or False):
+ attrs.update(dict(valid_key=False, compliant=False))
+ return attrs
+ attrs['valid_key'] = True
+
+ if Host:
+ current_instances = Host.objects.active_count()
+ else:
+ current_instances = 0
+ available_instances = int(attrs.get('instance_count', None) or 0)
+ attrs['current_instances'] = current_instances
+ attrs['available_instances'] = available_instances
+ free_instances = (available_instances - current_instances)
+ attrs['free_instances'] = max(0, free_instances)
+
+ license_date = int(attrs.get('license_date', 0) or 0)
+ current_date = int(time.time())
+ time_remaining = license_date - current_date
+ attrs['time_remaining'] = time_remaining
+ if attrs.setdefault('trial', False):
+ attrs['grace_period_remaining'] = time_remaining
+ else:
+ attrs['grace_period_remaining'] = (license_date + 2592000) - current_date
+ attrs['compliant'] = bool(time_remaining > 0 and free_instances >= 0)
+ attrs['date_warning'] = bool(time_remaining < self.SUBSCRIPTION_TIMEOUT)
+ attrs['date_expired'] = bool(time_remaining <= 0)
+ return attrs
diff --git a/awx/main/utils/profiling.py b/awx/main/utils/profiling.py
new file mode 100644
index 0000000000..c550175d7b
--- /dev/null
+++ b/awx/main/utils/profiling.py
@@ -0,0 +1,151 @@
+import cProfile
+import functools
+import pstats
+import os
+import uuid
+import datetime
+import json
+import sys
+
+
+class AWXProfileBase:
+ def __init__(self, name, dest):
+ self.name = name
+ self.dest = dest
+ self.results = {}
+
+ def generate_results(self):
+ raise RuntimeError("define me")
+
+ def output_results(self, fname=None):
+ if not os.path.isdir(self.dest):
+ os.makedirs(self.dest)
+
+ if fname:
+ fpath = os.path.join(self.dest, fname)
+ with open(fpath, 'w') as f:
+ f.write(json.dumps(self.results, indent=2))
+
+
+class AWXTiming(AWXProfileBase):
+ def __init__(self, name, dest='/var/log/tower/timing'):
+ super().__init__(name, dest)
+
+ self.time_start = None
+ self.time_end = None
+
+ def start(self):
+ self.time_start = datetime.datetime.now()
+
+ def stop(self):
+ self.time_end = datetime.datetime.now()
+
+ self.generate_results()
+ self.output_results()
+
+ def generate_results(self):
+ diff = (self.time_end - self.time_start).total_seconds()
+ self.results = {
+ 'name': self.name,
+ 'diff': f'{diff}-seconds',
+ }
+
+ def output_results(self):
+ fname = f"{self.results['diff']}-{self.name}-{uuid.uuid4()}.time"
+ super().output_results(fname)
+
+
+def timing(name, *init_args, **init_kwargs):
+ def decorator_profile(func):
+ @functools.wraps(func)
+ def wrapper_profile(*args, **kwargs):
+ timing = AWXTiming(name, *init_args, **init_kwargs)
+ timing.start()
+ res = func(*args, **kwargs)
+ timing.stop()
+ return res
+ return wrapper_profile
+ return decorator_profile
+
+
+class AWXProfiler(AWXProfileBase):
+ def __init__(self, name, dest='/var/log/tower/profile', dot_enabled=True):
+ '''
+ Try to do as little as possible in init. Instead, do the init
+ only when the profiling is started.
+ '''
+ super().__init__(name, dest)
+ self.started = False
+ self.dot_enabled = dot_enabled
+ self.results = {
+ 'total_time_seconds': 0,
+ }
+
+ def generate_results(self):
+ self.results['total_time_seconds'] = pstats.Stats(self.prof).total_tt
+
+ def output_results(self):
+ super().output_results()
+
+ filename_base = '%.3fs-%s-%s-%s' % (self.results['total_time_seconds'], self.name, self.pid, uuid.uuid4())
+ pstats_filepath = os.path.join(self.dest, f"{filename_base}.pstats")
+ extra_data = ""
+
+ if self.dot_enabled:
+ try:
+ from gprof2dot import main as generate_dot
+ except ImportError:
+ extra_data = 'Dot graph generation failed due to package "gprof2dot" being unavailable.'
+ else:
+ raw_filepath = os.path.join(self.dest, f"{filename_base}.raw")
+ dot_filepath = os.path.join(self.dest, f"{filename_base}.dot")
+
+ pstats.Stats(self.prof).dump_stats(raw_filepath)
+ generate_dot([
+ '-n', '2.5', '-f', 'pstats', '-o',
+ dot_filepath,
+ raw_filepath
+ ])
+ os.remove(raw_filepath)
+
+ with open(pstats_filepath, 'w') as f:
+ print(f"{self.name}, {extra_data}", file=f)
+ pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats()
+ return pstats_filepath
+
+
+ def start(self):
+ self.prof = cProfile.Profile()
+ self.pid = os.getpid()
+
+ self.prof.enable()
+ self.started = True
+
+ def is_started(self):
+ return self.started
+
+ def stop(self):
+ if self.started:
+ self.prof.disable()
+
+ self.generate_results()
+ res = self.output_results()
+ self.started = False
+ return res
+ else:
+ print("AWXProfiler::stop() called without calling start() first", file=sys.stderr)
+ return None
+
+
+def profile(name, *init_args, **init_kwargs):
+ def decorator_profile(func):
+ @functools.wraps(func)
+ def wrapper_profile(*args, **kwargs):
+ prof = AWXProfiler(name, *init_args, **init_kwargs)
+ prof.start()
+ res = func(*args, **kwargs)
+ prof.stop()
+ return res
+ return wrapper_profile
+ return decorator_profile
+
diff --git a/awx/playbooks/project_update.yml b/awx/playbooks/project_update.yml
index 169273d628..74e55e7ada 100644
--- a/awx/playbooks/project_update.yml
+++ b/awx/playbooks/project_update.yml
@@ -159,23 +159,29 @@
gather_facts: false
connection: local
name: Install content with ansible-galaxy command if necessary
+ vars:
+ yaml_exts:
+ - {ext: .yml}
+ - {ext: .yaml}
tasks:
- block:
- - name: detect requirements.yml
+ - name: detect roles/requirements.(yml/yaml)
stat:
- path: '{{project_path|quote}}/roles/requirements.yml'
+ path: "{{project_path|quote}}/roles/requirements{{ item.ext }}"
+ with_items: "{{ yaml_exts }}"
register: doesRequirementsExist
- - name: fetch galaxy roles from requirements.yml
+ - name: fetch galaxy roles from requirements.(yml/yaml)
command: >
- ansible-galaxy role install -r roles/requirements.yml
+ ansible-galaxy role install -r {{ item.stat.path }}
--roles-path {{projects_root}}/.__awx_cache/{{local_path}}/stage/requirements_roles
{{ ' -' + 'v' * ansible_verbosity if ansible_verbosity else '' }}
args:
chdir: "{{project_path|quote}}"
register: galaxy_result
- when: doesRequirementsExist.stat.exists
+ with_items: "{{ doesRequirementsExist.results }}"
+ when: item.stat.exists
changed_when: "'was installed successfully' in galaxy_result.stdout"
environment:
ANSIBLE_FORCE_COLOR: false
@@ -186,20 +192,22 @@
- install_roles
- block:
- - name: detect collections/requirements.yml
+ - name: detect collections/requirements.(yml/yaml)
stat:
- path: '{{project_path|quote}}/collections/requirements.yml'
+ path: "{{project_path|quote}}/collections/requirements{{ item.ext }}"
+ with_items: "{{ yaml_exts }}"
register: doesCollectionRequirementsExist
- - name: fetch galaxy collections from collections/requirements.yml
+ - name: fetch galaxy collections from collections/requirements.(yml/yaml)
command: >
- ansible-galaxy collection install -r collections/requirements.yml
+ ansible-galaxy collection install -r {{ item.stat.path }}
--collections-path {{projects_root}}/.__awx_cache/{{local_path}}/stage/requirements_collections
{{ ' -' + 'v' * ansible_verbosity if ansible_verbosity else '' }}
args:
chdir: "{{project_path|quote}}"
register: galaxy_collection_result
- when: doesCollectionRequirementsExist.stat.exists
+ with_items: "{{ doesCollectionRequirementsExist.results }}"
+ when: item.stat.exists
changed_when: "'Installing ' in galaxy_collection_result.stdout"
environment:
ANSIBLE_FORCE_COLOR: false
diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py
index 618f5282a4..6204486456 100644
--- a/awx/settings/defaults.py
+++ b/awx/settings/defaults.py
@@ -91,7 +91,6 @@ USE_L10N = True
USE_TZ = True
STATICFILES_DIRS = (
- os.path.join(BASE_DIR, 'ui', 'static'),
os.path.join(BASE_DIR, 'ui_next', 'build', 'static'),
os.path.join(BASE_DIR, 'static'),
)
@@ -249,8 +248,6 @@ TEMPLATES = [
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
- 'awx.ui.context_processors.settings',
- 'awx.ui.context_processors.version',
'social_django.context_processors.backends',
'social_django.context_processors.login_redirect',
],
diff --git a/awx/settings/development.py b/awx/settings/development.py
index 3a4e008488..108767b98c 100644
--- a/awx/settings/development.py
+++ b/awx/settings/development.py
@@ -184,3 +184,6 @@ else:
pass
AWX_CALLBACK_PROFILE = True
+
+if 'sqlite3' not in DATABASES['default']['ENGINE']: # noqa
+ DATABASES['default'].setdefault('OPTIONS', dict()).setdefault('application_name', f'{CLUSTER_HOST_ID}-{os.getpid()}-{" ".join(sys.argv)}'[:63]) # noqa
diff --git a/awx/settings/production.py b/awx/settings/production.py
index c2cde28c0f..fb24b7087f 100644
--- a/awx/settings/production.py
+++ b/awx/settings/production.py
@@ -102,6 +102,7 @@ except IOError:
else:
raise
+# The below runs AFTER all of the custom settings are imported.
CELERYBEAT_SCHEDULE.update({ # noqa
'isolated_heartbeat': {
@@ -110,3 +111,5 @@ CELERYBEAT_SCHEDULE.update({ # noqa
'options': {'expires': AWX_ISOLATED_PERIODIC_CHECK * 2}, # noqa
}
})
+
+DATABASES['default'].setdefault('OPTIONS', dict()).setdefault('application_name', f'{CLUSTER_HOST_ID}-{os.getpid()}-{" ".join(sys.argv)}'[:63]) # noqa
diff --git a/awx/ui/.eslintignore b/awx/ui/.eslintignore
deleted file mode 100644
index f1daf7c9ab..0000000000
--- a/awx/ui/.eslintignore
+++ /dev/null
@@ -1,19 +0,0 @@
-Gruntfile.js
-karma.*.js
-webpack.*.js
-nightwatch.*.js
-
-etc
-coverage
-grunt-tasks
-node_modules
-po
-static
-templates
-
-client/src/**/*.js
-client/assets/**/*.js
-test/spec/**/*.js
-
-!client/src/app.start.js
-!client/src/vendor.js
diff --git a/awx/ui/.eslintrc.js b/awx/ui/.eslintrc.js
deleted file mode 100644
index 27759bf2b9..0000000000
--- a/awx/ui/.eslintrc.js
+++ /dev/null
@@ -1,72 +0,0 @@
-const path = require('path');
-
-module.exports = {
- root: true,
- extends: [
- 'airbnb-base'
- ],
- plugins: [
- 'import',
- 'disable'
- ],
- settings: {
- 'import/resolver': {
- webpack: {
- config: path.join(__dirname, 'build/webpack.development.js')
- }
- },
- 'eslint-plugin-disable': {
- paths: {
- import: ['**/build/*.js']
- }
- }
- },
- env: {
- browser: true,
- node: true
- },
- globals: {
- angular: true,
- d3: true,
- $: true,
- _: true,
- codemirror: true,
- jsyaml: true,
- crypto: true
- },
- rules: {
- 'arrow-parens': 'off',
- 'comma-dangle': 'off',
- indent: ['error', 4, {
- SwitchCase: 1
- }],
- 'max-len': ['error', {
- code: 100,
- ignoreStrings: true,
- ignoreTemplateLiterals: true,
- }],
- 'no-continue': 'off',
- 'no-debugger': 'off',
- 'no-mixed-operators': 'off',
- 'no-param-reassign': 'off',
- 'no-plusplus': 'off',
- 'no-underscore-dangle': 'off',
- 'no-use-before-define': 'off',
- 'no-multiple-empty-lines': ['error', { max: 1 }],
- 'object-curly-newline': 'off',
- 'space-before-function-paren': ['error', 'always'],
- 'no-trailing-spaces': ['error'],
- 'prefer-destructuring': ['error', {
- 'VariableDeclarator': {
- 'array': false,
- 'object': true
- },
- 'AssignmentExpression': {
- 'array': false,
- 'object': true
- }
- }, {
- 'enforceForRenamedProperties': false
- }]
- }
-};
diff --git a/awx/ui/.jshintrc b/awx/ui/.jshintrc
deleted file mode 100644
index 363d2e5ba8..0000000000
--- a/awx/ui/.jshintrc
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "browser": true,
- "node": true,
- "jquery": true,
- "esnext": true,
- "globalstrict": true,
- "curly": true,
- "immed": true,
- "latedef": "nofunc",
- "noarg": true,
- "nonew": true,
- "maxerr": 10000,
- "notypeof": true,
- "globals": {
- "$ENV": true,
- "require": true,
- "global": true,
- "beforeEach": false,
- "inject": false,
- "module": false,
- "angular":false,
- "alert":false,
- "$AnsibleConfig":true,
- "$basePath":true,
- "jsyaml":false,
- "_":false,
- "d3":false,
- "Donut3D":false,
- "nv":false,
- "it": false,
- "xit": false,
- "expect": false,
- "context": false,
- "describe": false,
- "moment": false,
- "spyOn": false,
- "jasmine": false,
- "dagre": false,
- "crypto": false
- },
- "strict": false,
- "quotmark": false,
- "trailing": true,
- "undef": true,
- "unused": true,
- "eqeqeq": true,
- "indent": 4,
- "newcap": false
-}
diff --git a/awx/ui/.npmrc b/awx/ui/.npmrc
deleted file mode 100644
index d883e4fa13..0000000000
--- a/awx/ui/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-progress=false
diff --git a/awx/ui/Gruntfile.js b/awx/ui/Gruntfile.js
deleted file mode 100644
index f688925708..0000000000
--- a/awx/ui/Gruntfile.js
+++ /dev/null
@@ -1,20 +0,0 @@
-module.exports = function(grunt) {
- // Load grunt tasks & configurations automatically from dir grunt/
- require('load-grunt-tasks')(grunt);
- // display task timings
- require('time-grunt')(grunt);
-
- var options = {
- config: {
- src: './grunt-tasks/*.js'
- },
- pkg: grunt.file.readJSON('package.json')
- };
-
- var configs = require('load-grunt-configs')(grunt, options);
-
- // Project configuration.
- grunt.initConfig(configs);
- grunt.loadNpmTasks('grunt-newer');
- grunt.loadNpmTasks('grunt-angular-gettext');
-};
diff --git a/awx/ui/README.md b/awx/ui/README.md
deleted file mode 100644
index 4627012162..0000000000
--- a/awx/ui/README.md
+++ /dev/null
@@ -1,103 +0,0 @@
-# AWX UI
-
-## Requirements
-- node.js 10.x LTS
-- npm >=6.x
-- bzip2, gcc-c++, git, make
-
-## Development
-The API development server will need to be running. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
-
-```shell
-# Build ui for the devel environment - reachable at https://localhost:8043
-make ui-devel
-
-# Alternatively, start the ui development server. While running, the ui will be reachable
-# at https://localhost:3000 and updated automatically when code changes.
-make ui-docker
-
-# When using docker machine, use this command to start the ui development server instead.
-DOCKER_MACHINE_NAME=default make ui-docker-machine
-```
-
-## Development with an external server
-If you normally run awx on an external host/server (in this example, `awx.local`),
-you'll need to reconfigure the webpack proxy slightly for `make ui-docker` to
-work:
-
-```javascript
-/awx/settings/development.py
-+
-+CSRF_TRUSTED_ORIGINS = ['awx.local:8043']
-
-awx/ui/build/webpack.watch.js
-- host: '127.0.0.1',
-+ host: '0.0.0.0',
-+ disableHostCheck: true,
-
-/awx/ui/package.json
-@@ -7,7 +7,7 @@
- "config": {
- ...
-+ "django_host": "awx.local"
- },
-```
-
-## Testing
-```shell
-# run linters
-make jshint
-
-# run unit tests
-make ui-test-ci
-
-# run e2e tests - see awx/ui/test/e2e for more information
-npm --prefix awx/ui run e2e
-```
-**Note**: Unit tests are run on your host machine and not in the development containers.
-
-## Adding dependencies
-```shell
-# add an exact development or build dependency
-npm install --prefix awx/ui --save-dev --save-exact dev-package@1.2.3
-
-# add an exact production dependency
-npm install --prefix awx/ui --save --save-exact prod-package@1.23
-
-# add the updated package.json and package-lock.json files to scm
-git add awx/ui/package.json awx/ui/package-lock.json
-```
-
-## Removing dependencies
-```shell
-# remove a development or build dependency
-npm uninstall --prefix awx/ui --save-dev dev-package
-
-# remove a production dependency
-npm uninstall --prefix awx/ui --save prod-package
-```
-
-## Building for Production
-```shell
-# built files are placed in awx/ui/static
-make ui-release
-```
-
-## Internationalization
-Application strings marked for translation are extracted and used to generate `.pot` files using the following command:
-```shell
-# extract strings and generate .pot files
-make pot
-```
-To include the translations in the development environment, we compile them prior to building the ui:
-```shell
-# remove any prior ui builds
-make clean-ui
-
-# compile the .pot files to javascript files usable by the application
-make languages
-
-# build the ui with translations included
-make ui-devel
-```
-**Note**: Python 3.6 is required to compile the `.pot` files.
diff --git a/awx/ui/__init__.py b/awx/ui/__init__.py
index ac6a554356..bfb3e776cd 100644
--- a/awx/ui/__init__.py
+++ b/awx/ui/__init__.py
@@ -2,3 +2,4 @@
# All Rights Reserved.
default_app_config = 'awx.ui.apps.UIConfig'
+
diff --git a/awx/ui/apps.py b/awx/ui/apps.py
index 40943c6f53..5b8e5083c1 100644
--- a/awx/ui/apps.py
+++ b/awx/ui/apps.py
@@ -7,3 +7,4 @@ class UIConfig(AppConfig):
name = 'awx.ui'
verbose_name = _('UI')
+
diff --git a/awx/ui/build/webpack.base.js b/awx/ui/build/webpack.base.js
deleted file mode 100644
index f1e5ac8e0b..0000000000
--- a/awx/ui/build/webpack.base.js
+++ /dev/null
@@ -1,235 +0,0 @@
-const path = require('path');
-
-const webpack = require('webpack');
-const CleanWebpackPlugin = require('clean-webpack-plugin');
-const CopyWebpackPlugin = require('copy-webpack-plugin');
-const HtmlWebpackPlugin = require('html-webpack-plugin');
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
-
-const CLIENT_PATH = path.resolve(__dirname, '../client');
-const LIB_PATH = path.join(CLIENT_PATH, 'lib');
-const UI_PATH = path.resolve(__dirname, '..');
-
-const ASSETS_PATH = path.join(CLIENT_PATH, 'assets');
-const COMPONENTS_PATH = path.join(LIB_PATH, 'components');
-const COVERAGE_PATH = path.join(UI_PATH, 'coverage');
-const FEATURES_PATH = path.join(CLIENT_PATH, 'features');
-const LANGUAGES_PATH = path.join(CLIENT_PATH, 'languages');
-const MODELS_PATH = path.join(LIB_PATH, 'models');
-const NODE_MODULES_PATH = path.join(UI_PATH, 'node_modules');
-const SERVICES_PATH = path.join(LIB_PATH, 'services');
-const SRC_PATH = path.join(CLIENT_PATH, 'src');
-const STATIC_PATH = path.join(UI_PATH, 'static');
-const TEST_PATH = path.join(UI_PATH, 'test');
-const THEME_PATH = path.join(LIB_PATH, 'theme');
-
-const APP_ENTRY = path.join(SRC_PATH, 'app.js');
-const VENDOR_ENTRY = path.join(SRC_PATH, 'vendor.js');
-const INDEX_ENTRY = path.join(CLIENT_PATH, 'index.template.ejs');
-const INDEX_OUTPUT = path.join(UI_PATH, 'templates/ui/index.html');
-const INSTALL_RUNNING_ENTRY = path.join(CLIENT_PATH, 'installing.template.ejs');
-const INSTALL_RUNNING_OUTPUT = path.join(UI_PATH, 'templates/ui/installing.html');
-const THEME_ENTRY = path.join(LIB_PATH, 'theme', 'index.less');
-const OUTPUT = 'js/[name].[chunkhash].js';
-const CHUNKS = ['vendor', 'app'];
-
-const VENDOR = VENDOR_ENTRY;
-const APP = [THEME_ENTRY, APP_ENTRY];
-
-const base = {
- entry: {
- vendor: VENDOR,
- app: APP
- },
- output: {
- path: STATIC_PATH,
- publicPath: '',
- filename: OUTPUT
- },
- stats: {
- children: false,
- modules: false,
- chunks: false,
- excludeAssets: name => {
- const chunkNames = `(${CHUNKS.join('|')})`;
- const outputPattern = new RegExp(`${chunkNames}.[a-f0-9]+.(js|css)(|.map)$`, 'i');
-
- return !outputPattern.test(name);
- }
- },
- module: {
- rules: [
- {
- test: /\.js$/,
- use: {
- loader: 'istanbul-instrumenter-loader',
- options: { esModules: true }
- },
- enforce: 'pre',
- include: [
- /src\/network-ui\//
- ]
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/,
- options: {
- presets: [
- ['env', {
- targets: {
- browsers: ['last 2 versions']
- }
- }]
- ]
- }
- },
- {
- test: /\.css$/,
- use: ExtractTextPlugin.extract({
- use: {
- loader: 'css-loader',
- options: {
- url: false
- }
- }
- })
- },
- {
- test: /lib\/theme\/index.less$/,
- use: ExtractTextPlugin.extract({
- use: ['css-loader', 'less-loader']
- })
- },
- {
- test: /\.html$/,
- use: ['ngtemplate-loader', 'html-loader'],
- include: [
- /lib\/components\//,
- /features\//,
- /src\//
- ]
- },
- {
- test: /\.svg$/,
- use: ['ngtemplate-loader', 'html-loader'],
- include: [
- /lib\/components\//,
- /features\//,
- /src\//
- ]
- },
- {
- test: /\.json$/,
- loader: 'json-loader',
- exclude: /node_modules/
- }
- ]
- },
- plugins: [
- new webpack.ProvidePlugin({
- jsyaml: 'js-yaml',
- CodeMirror: 'codemirror',
- jsonlint: 'codemirror.jsonlint'
- }),
- new ExtractTextPlugin('css/[name].[chunkhash].css'),
- new CleanWebpackPlugin([STATIC_PATH, COVERAGE_PATH], {
- root: UI_PATH,
- verbose: false
- }),
- new CopyWebpackPlugin([
- {
- from: path.join(ASSETS_PATH, 'fontcustom/**/*'),
- to: path.join(STATIC_PATH, 'fonts/'),
- flatten: true
- },
- {
- from: path.join(NODE_MODULES_PATH, 'components-font-awesome/fonts/*'),
- to: path.join(STATIC_PATH, 'fonts/'),
- flatten: true
- },
- {
- from: path.join(ASSETS_PATH, 'custom-theme/images.new/*'),
- to: path.join(STATIC_PATH, 'images/'),
- flatten: true
- },
- {
- from: path.join(LANGUAGES_PATH, '*'),
- to: path.join(STATIC_PATH, 'languages'),
- flatten: true
- },
- {
- from: ASSETS_PATH,
- to: path.join(STATIC_PATH, 'assets')
- },
- {
- from: path.join(NODE_MODULES_PATH, 'angular-scheduler/lib/*.html'),
- to: path.join(STATIC_PATH, 'lib'),
- context: NODE_MODULES_PATH
- },
- {
- from: path.join(NODE_MODULES_PATH, 'angular-tz-extensions/tz/data/*'),
- to: path.join(STATIC_PATH, 'lib/'),
- context: NODE_MODULES_PATH
- },
- {
- from: path.join(SRC_PATH, '**/*.partial.html'),
- to: path.join(STATIC_PATH, 'partials/'),
- context: SRC_PATH
- },
- {
- from: path.join(SRC_PATH, 'partials', '*.html'),
- to: STATIC_PATH,
- context: SRC_PATH
- },
- {
- from: path.join(SRC_PATH, '*config.js'),
- to: STATIC_PATH,
- flatten: true
- }
- ]),
- new HtmlWebpackPlugin({
- alwaysWriteToDisk: true,
- template: INDEX_ENTRY,
- filename: INDEX_OUTPUT,
- inject: false,
- chunks: CHUNKS,
- chunksSortMode: chunk => (chunk.names[0] === 'vendor' ? -1 : 1)
- }),
- new HtmlWebpackPlugin({
- alwaysWriteToDisk: true,
- template: INSTALL_RUNNING_ENTRY,
- filename: INSTALL_RUNNING_OUTPUT,
- inject: false,
- chunks: CHUNKS,
- chunksSortMode: chunk => (chunk.names[0] === 'vendor' ? -1 : 1)
- }),
- ],
- resolve: {
- alias: {
- '~assets': ASSETS_PATH,
- '~components': COMPONENTS_PATH,
- '~features': FEATURES_PATH,
- '~models': MODELS_PATH,
- '~node_modules': NODE_MODULES_PATH,
- '~services': SERVICES_PATH,
- '~src': SRC_PATH,
- '~test': TEST_PATH,
- '~theme': THEME_PATH,
- '~ui': UI_PATH,
- d3$: '~node_modules/d3/d3.min.js',
- 'codemirror.jsonlint$': '~node_modules/codemirror/addon/lint/json-lint.js',
- jquery: '~node_modules/jquery/dist/jquery.js',
- 'jquery-resize$': '~node_modules/javascript-detect-element-resize/jquery.resize.js',
- select2$: '~node_modules/select2/dist/js/select2.full.min.js',
- 'js-yaml$': '~node_modules/js-yaml/dist/js-yaml.min.js',
- 'lr-infinite-scroll$': '~node_modules/lr-infinite-scroll/lrInfiniteScroll.js',
- 'angular-tz-extensions$': '~node_modules/angular-tz-extensions/lib/angular-tz-extensions.js',
- 'ng-toast-provider$': '~node_modules/ng-toast/src/scripts/provider.js',
- 'ng-toast-directives$': '~node_modules/ng-toast/src/scripts/directives.js',
- 'ng-toast$': '~node_modules/ng-toast/src/scripts/module.js'
- }
- }
-};
-
-module.exports = base;
diff --git a/awx/ui/build/webpack.development.js b/awx/ui/build/webpack.development.js
deleted file mode 100644
index 56e2d90b51..0000000000
--- a/awx/ui/build/webpack.development.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const merge = require('webpack-merge');
-
-const base = require('./webpack.base');
-
-const development = {
- devtool: 'source-map'
-};
-
-module.exports = merge(base, development);
diff --git a/awx/ui/build/webpack.production.js b/awx/ui/build/webpack.production.js
deleted file mode 100644
index 4f57e23cc3..0000000000
--- a/awx/ui/build/webpack.production.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const path = require('path');
-
-const merge = require('webpack-merge');
-const webpack = require('webpack');
-const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
-const HtmlWebpackPlugin = require('html-webpack-plugin');
-
-const base = require('./webpack.base');
-
-const CLIENT_PATH = path.resolve(__dirname, '../client');
-const UI_PATH = path.resolve(__dirname, '..');
-const CHUNKS = ['vendor', 'app'];
-
-const production = {
- plugins: [
- new UglifyJSPlugin({
- compress: true,
- mangle: false
- }),
- new webpack.DefinePlugin({
- 'process.env': {
- NODE_ENV: JSON.stringify('production')
- }
- })
- ]
-};
-
-module.exports = merge(base, production);
diff --git a/awx/ui/build/webpack.test.js b/awx/ui/build/webpack.test.js
deleted file mode 100644
index 8fb4e4e1c7..0000000000
--- a/awx/ui/build/webpack.test.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const _ = require('lodash');
-const webpack = require('webpack');
-
-const STATIC_URL = '/static/';
-
-const development = require('./webpack.base');
-
-const test = {
- devtool: 'cheap-source-map',
- plugins: [
- new webpack.DefinePlugin({
- $basePath: STATIC_URL
- })
- ]
-};
-
-test.plugins = development.plugins.concat(test.plugins);
-
-module.exports = _.merge(development, test);
-
diff --git a/awx/ui/build/webpack.watch.js b/awx/ui/build/webpack.watch.js
deleted file mode 100644
index 143058077a..0000000000
--- a/awx/ui/build/webpack.watch.js
+++ /dev/null
@@ -1,84 +0,0 @@
-const path = require('path');
-
-const _ = require('lodash');
-const webpack = require('webpack');
-const merge = require('webpack-merge');
-const nodeObjectHash = require('node-object-hash');
-const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
-const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
-
-const TARGET_PORT = _.get(process.env, 'npm_package_config_django_port', 8043);
-const TARGET_HOST = _.get(process.env, 'npm_package_config_django_host', 'https://localhost');
-const TARGET = `https://${TARGET_HOST}:${TARGET_PORT}`;
-const OUTPUT = 'js/[name].js';
-
-const development = require('./webpack.development');
-
-const watch = {
- cache: true,
- devtool: 'cheap-source-map',
- output: {
- filename: OUTPUT
- },
- module: {
- rules: [
- {
- test: /\.js$/,
- enforce: 'pre',
- exclude: /node_modules/,
- loader: 'eslint-loader'
- }
- ]
- },
- plugins: [
- new HtmlWebpackHarddiskPlugin(),
- new HardSourceWebpackPlugin({
- cacheDirectory: 'node_modules/.cache/hard-source/[confighash]',
- recordsPath: 'node_modules/.cache/hard-source/[confighash]/records.json',
- configHash: config => nodeObjectHash({ sort: false }).hash(config),
- environmentHash: {
- root: process.cwd(),
- directories: ['node_modules'],
- files: ['package.json']
- }
- }),
- new webpack.HotModuleReplacementPlugin()
- ],
- devServer: {
- hot: true,
- inline: true,
- contentBase: path.resolve(__dirname, '..', 'static'),
- stats: 'minimal',
- publicPath: '/static/',
- host: '127.0.0.1',
- https: true,
- port: 3000,
- clientLogLevel: 'none',
- proxy: [{
- context: (pathname, req) => !(pathname === '/api/login/' && req.method === 'POST'),
- target: TARGET,
- secure: false,
- ws: false,
- bypass: req => req.originalUrl.includes('hot-update.json')
- },
- {
- context: '/api/login/',
- target: TARGET,
- secure: false,
- ws: false,
- headers: {
- Host: `localhost:${TARGET_PORT}`,
- Origin: TARGET,
- Referer: `${TARGET}/`
- }
- },
- {
- context: '/websocket',
- target: TARGET,
- secure: false,
- ws: true
- }]
- }
-};
-
-module.exports = merge(development, watch);
diff --git a/awx/ui/build/zuul_download_chromium.sh b/awx/ui/build/zuul_download_chromium.sh
deleted file mode 100755
index 23311d2131..0000000000
--- a/awx/ui/build/zuul_download_chromium.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-REVISION=588429
-CHROMIUM_URL="https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/${REVISION}/chrome-linux.zip"
-
-wget ${CHROMIUM_URL} -w 30 -t 6 -O /tmp/chrome-linux.zip
-unzip -o -d /tmp /tmp/chrome-linux.zip
diff --git a/awx/ui/client/assets/LICENSE.txt b/awx/ui/client/assets/LICENSE.txt
deleted file mode 100644
index d645695673..0000000000
--- a/awx/ui/client/assets/LICENSE.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/awx/ui/client/assets/OpenSans-Bold.ttf b/awx/ui/client/assets/OpenSans-Bold.ttf
deleted file mode 100644
index fd79d43bea..0000000000
Binary files a/awx/ui/client/assets/OpenSans-Bold.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-BoldItalic.ttf b/awx/ui/client/assets/OpenSans-BoldItalic.ttf
deleted file mode 100644
index 9bc800958a..0000000000
Binary files a/awx/ui/client/assets/OpenSans-BoldItalic.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-ExtraBold.ttf b/awx/ui/client/assets/OpenSans-ExtraBold.ttf
deleted file mode 100644
index 21f6f84a07..0000000000
Binary files a/awx/ui/client/assets/OpenSans-ExtraBold.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-ExtraBoldItalic.ttf b/awx/ui/client/assets/OpenSans-ExtraBoldItalic.ttf
deleted file mode 100644
index 31cb688340..0000000000
Binary files a/awx/ui/client/assets/OpenSans-ExtraBoldItalic.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-Italic.ttf b/awx/ui/client/assets/OpenSans-Italic.ttf
deleted file mode 100644
index c90da48ff3..0000000000
Binary files a/awx/ui/client/assets/OpenSans-Italic.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-Light.ttf b/awx/ui/client/assets/OpenSans-Light.ttf
deleted file mode 100644
index 0d381897da..0000000000
Binary files a/awx/ui/client/assets/OpenSans-Light.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-LightItalic.ttf b/awx/ui/client/assets/OpenSans-LightItalic.ttf
deleted file mode 100644
index 68299c4bc6..0000000000
Binary files a/awx/ui/client/assets/OpenSans-LightItalic.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-Regular.ttf b/awx/ui/client/assets/OpenSans-Regular.ttf
deleted file mode 100644
index db433349b7..0000000000
Binary files a/awx/ui/client/assets/OpenSans-Regular.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-Semibold.ttf b/awx/ui/client/assets/OpenSans-Semibold.ttf
deleted file mode 100644
index 1a7679e394..0000000000
Binary files a/awx/ui/client/assets/OpenSans-Semibold.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/OpenSans-SemiboldItalic.ttf b/awx/ui/client/assets/OpenSans-SemiboldItalic.ttf
deleted file mode 100644
index 59b6d16b06..0000000000
Binary files a/awx/ui/client/assets/OpenSans-SemiboldItalic.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/animated-overlay.gif b/awx/ui/client/assets/custom-theme/images.new/animated-overlay.gif
deleted file mode 100644
index d441f75ebf..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/animated-overlay.gif and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_0_aaaaaa_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_0_aaaaaa_40x100.png
deleted file mode 100644
index e1a114b4e2..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_3276b1_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_3276b1_40x100.png
deleted file mode 100644
index 3199c1d479..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_3276b1_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_428bca_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_428bca_40x100.png
deleted file mode 100644
index 38940fe30d..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_428bca_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_ffffff_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_ffffff_40x100.png
deleted file mode 100644
index 708e95ddc0..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_100_ffffff_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_50_ffffff_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_50_ffffff_40x100.png
deleted file mode 100644
index cfaa03e8dd..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_50_ffffff_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_55_fbec88_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_55_fbec88_40x100.png
deleted file mode 100644
index cb1dbf2936..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_55_fbec88_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_75_e5e3e3_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_75_e5e3e3_40x100.png
deleted file mode 100644
index 9d8b67a2e2..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_75_e5e3e3_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_75_ffffff_40x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_75_ffffff_40x100.png
deleted file mode 100644
index 399d1ba7dd..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_flat_75_ffffff_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_55_fbf9ee_1x400.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_55_fbf9ee_1x400.png
deleted file mode 100644
index 9267153440..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_55_fbf9ee_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_75_d4d0d0_1x400.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_75_d4d0d0_1x400.png
deleted file mode 100644
index f456416e01..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_75_d4d0d0_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_85_f5f5f5_1x400.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_85_f5f5f5_1x400.png
deleted file mode 100644
index d69f282bee..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_85_f5f5f5_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_95_fef1ec_1x400.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_95_fef1ec_1x400.png
deleted file mode 100644
index be40bcf3c3..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_gloss-wave_50_f5f5f5_500x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_gloss-wave_50_f5f5f5_500x100.png
deleted file mode 100644
index e73bbb88df..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_gloss-wave_50_f5f5f5_500x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glow-ball_100_fff_600x600.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_glow-ball_100_fff_600x600.png
deleted file mode 100644
index b170873d1f..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_glow-ball_100_fff_600x600.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_inset-hard_100_f5f5f5_1x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_inset-hard_100_f5f5f5_1x100.png
deleted file mode 100644
index 2ffa648549..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_inset-hard_100_f5f5f5_1x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-bg_inset-hard_100_fcfdfd_1x100.png b/awx/ui/client/assets/custom-theme/images.new/ui-bg_inset-hard_100_fcfdfd_1x100.png
deleted file mode 100644
index 534a864605..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-bg_inset-hard_100_fcfdfd_1x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_0088cc_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_0088cc_256x240.png
deleted file mode 100644
index 5018f318bc..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_0088cc_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_1778c3_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_1778c3_256x240.png
deleted file mode 100644
index cbf7bc13a3..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_1778c3_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_217bc0_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_217bc0_256x240.png
deleted file mode 100644
index 8d2b7e5704..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_217bc0_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_2e83ff_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_2e83ff_256x240.png
deleted file mode 100644
index 84b601bf0f..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_2e83ff_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_36454F_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_36454F_256x240.png
deleted file mode 100644
index 28a8127a65..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_36454F_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_469bdd_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_469bdd_256x240.png
deleted file mode 100644
index 5dff3f962c..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_469bdd_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_6da8d5_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_6da8d5_256x240.png
deleted file mode 100644
index f7809f8566..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_6da8d5_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_cd0a0a_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_cd0a0a_256x240.png
deleted file mode 100644
index ed5b6b0930..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_cd0a0a_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_d8e7f3_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_d8e7f3_256x240.png
deleted file mode 100644
index 9b46228fb1..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_d8e7f3_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images.new/ui-icons_fff_256x240.png b/awx/ui/client/assets/custom-theme/images.new/ui-icons_fff_256x240.png
deleted file mode 100644
index 4f624bb2b1..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images.new/ui-icons_fff_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/animated-overlay.gif b/awx/ui/client/assets/custom-theme/images/animated-overlay.gif
deleted file mode 100644
index d441f75ebf..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/animated-overlay.gif and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png
deleted file mode 100644
index 8b3239ca8f..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_100_ffffff_40x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_flat_100_ffffff_40x100.png
deleted file mode 100644
index 708e95ddc0..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_100_ffffff_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_50_ffffff_40x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_flat_50_ffffff_40x100.png
deleted file mode 100644
index cfaa03e8dd..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_50_ffffff_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_55_fbec88_40x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_flat_55_fbec88_40x100.png
deleted file mode 100644
index cb1dbf2936..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_55_fbec88_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_75_e5e3e3_40x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_flat_75_e5e3e3_40x100.png
deleted file mode 100644
index 9d8b67a2e2..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_flat_75_e5e3e3_40x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_glass_75_d4d0d0_1x400.png b/awx/ui/client/assets/custom-theme/images/ui-bg_glass_75_d4d0d0_1x400.png
deleted file mode 100644
index f456416e01..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_glass_75_d4d0d0_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_glass_85_f5f5f5_1x400.png b/awx/ui/client/assets/custom-theme/images/ui-bg_glass_85_f5f5f5_1x400.png
deleted file mode 100644
index d69f282bee..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_glass_85_f5f5f5_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_glass_95_fef1ec_1x400.png b/awx/ui/client/assets/custom-theme/images/ui-bg_glass_95_fef1ec_1x400.png
deleted file mode 100644
index fa5b93c019..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_gloss-wave_50_f5f5f5_500x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_gloss-wave_50_f5f5f5_500x100.png
deleted file mode 100644
index e73bbb88df..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_gloss-wave_50_f5f5f5_500x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_inset-hard_100_f5f5f5_1x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_inset-hard_100_f5f5f5_1x100.png
deleted file mode 100644
index 2ffa648549..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_inset-hard_100_f5f5f5_1x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/awx/ui/client/assets/custom-theme/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
deleted file mode 100644
index 534a864605..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-bg_inset-hard_100_fcfdfd_1x100.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_0088cc_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_0088cc_256x240.png
deleted file mode 100644
index 5018f318bc..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_0088cc_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_217bc0_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_217bc0_256x240.png
deleted file mode 100644
index 8d2b7e5704..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_217bc0_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_2e83ff_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_2e83ff_256x240.png
deleted file mode 100644
index 84b601bf0f..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_2e83ff_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_36454F_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_36454F_256x240.png
deleted file mode 100644
index 28a8127a65..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_36454F_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_469bdd_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_469bdd_256x240.png
deleted file mode 100644
index 5dff3f962c..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_469bdd_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_6da8d5_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_6da8d5_256x240.png
deleted file mode 100644
index f7809f8566..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_6da8d5_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_cd0a0a_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_cd0a0a_256x240.png
deleted file mode 100644
index ed5b6b0930..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_cd0a0a_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/images/ui-icons_d8e7f3_256x240.png b/awx/ui/client/assets/custom-theme/images/ui-icons_d8e7f3_256x240.png
deleted file mode 100644
index 9b46228fb1..0000000000
Binary files a/awx/ui/client/assets/custom-theme/images/ui-icons_d8e7f3_256x240.png and /dev/null differ
diff --git a/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.css b/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.css
deleted file mode 100644
index 31f7a97f99..0000000000
--- a/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.css
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*! jQuery UI - v1.10.3 - 2013-06-26
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=normal&fsDefault=14px&cornerRadius=5px&bgColorHeader=%23ffffff&bgTextureHeader=flat&bgImgOpacityHeader=50&borderColorHeader=%23a6c9e2&fcHeader=%2336454F&iconColorHeader=%2336454F&bgColorContent=%23fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=%23a6c9e2&fcContent=%23222222&iconColorContent=%23469bdd&bgColorDefault=%23ffffff&bgTextureDefault=flat&bgImgOpacityDefault=100&borderColorDefault=%23a6c9e2&fcDefault=%230088cc&iconColorDefault=%230088cc&bgColorHover=%23e5e3e3&bgTextureHover=flat&bgImgOpacityHover=75&borderColorHover=%23e3e3e3&fcHover=%23005580&iconColorHover=%23217bc0&bgColorActive=%23f5f5f5&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=%23e3e3e3&fcActive=%2336454F&iconColorActive=%2336454F&bgColorHighlight=%23fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=%23fad42e&fcHighlight=%23363636&iconColorHighlight=%232e83ff&bgColorError=%23fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=%23cd0a0a&fcError=%23cd0a0a&iconColorError=%23cd0a0a&bgColorOverlay=%23aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=%23aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden {
- display: none;
-}
-.ui-helper-hidden-accessible {
- border: 0;
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-.ui-helper-reset {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- line-height: 1.3;
- text-decoration: none;
- font-size: 100%;
- list-style: none;
-}
-.ui-helper-clearfix:before,
-.ui-helper-clearfix:after {
- content: "";
- display: table;
- border-collapse: collapse;
-}
-.ui-helper-clearfix:after {
- clear: both;
-}
-.ui-helper-clearfix {
- min-height: 0; /* support: IE7 */
-}
-.ui-helper-zfix {
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
- position: absolute;
- opacity: 0;
- filter:Alpha(Opacity=0);
-}
-
-.ui-front {
- z-index: 100;
-}
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled {
- cursor: default !important;
-}
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- display: block;
- text-indent: -99999px;
- overflow: hidden;
- background-repeat: no-repeat;
-}
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-.ui-resizable {
- position: relative;
-}
-.ui-resizable-handle {
- position: absolute;
- font-size: 0.1px;
- display: block;
-}
-.ui-resizable-disabled .ui-resizable-handle,
-.ui-resizable-autohide .ui-resizable-handle {
- display: none;
-}
-.ui-resizable-n {
- cursor: n-resize;
- height: 7px;
- width: 100%;
- top: -5px;
- left: 0;
-}
-.ui-resizable-s {
- cursor: s-resize;
- height: 7px;
- width: 100%;
- bottom: -5px;
- left: 0;
-}
-.ui-resizable-e {
- cursor: e-resize;
- width: 7px;
- right: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-w {
- cursor: w-resize;
- width: 7px;
- left: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-se {
- cursor: se-resize;
- width: 12px;
- height: 12px;
- right: 1px;
- bottom: 1px;
-}
-.ui-resizable-sw {
- cursor: sw-resize;
- width: 9px;
- height: 9px;
- left: -5px;
- bottom: -5px;
-}
-.ui-resizable-nw {
- cursor: nw-resize;
- width: 9px;
- height: 9px;
- left: -5px;
- top: -5px;
-}
-.ui-resizable-ne {
- cursor: ne-resize;
- width: 9px;
- height: 9px;
- right: -5px;
- top: -5px;
-}
-.ui-selectable-helper {
- position: absolute;
- z-index: 100;
- border: 1px dotted black;
-}
-.ui-accordion .ui-accordion-header {
- display: block;
- cursor: pointer;
- position: relative;
- margin-top: 2px;
- padding: .5em .5em .5em .7em;
- min-height: 0; /* support: IE7 */
-}
-
-.ui-accordion-header {
- font-weight: bold;
-}
-
-.ui-accordion .ui-accordion-icons {
- padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-noicons {
- padding-left: .7em;
-}
-.ui-accordion .ui-accordion-icons .ui-accordion-icons {
- padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
- position: absolute;
- left: .5em;
- top: 50%;
- margin-top: -8px;
-}
-.ui-accordion .ui-accordion-content {
- padding: 1em 2.2em;
- border-top: 0;
- overflow: auto;
-}
-.ui-autocomplete {
- position: absolute;
- top: 0;
- left: 0;
- cursor: default;
-}
-.ui-button {
- display: inline-block;
- position: relative;
- padding: 0;
- line-height: normal;
- margin-right: .1em;
- cursor: pointer;
- vertical-align: middle;
- text-align: center;
- overflow: visible; /* removes extra width in IE */
-}
-.ui-button,
-.ui-button:link,
-.ui-button:visited,
-.ui-button:hover,
-.ui-button:active {
- text-decoration: none;
-}
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
- width: 2.2em;
-}
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
- width: 2.4em;
-}
-.ui-button-icons-only {
- width: 3.4em;
-}
-button.ui-button-icons-only {
- width: 3.7em;
-}
-
-/* button text element */
-.ui-button .ui-button-text {
- display: block;
- line-height: normal;
-}
-.ui-button-text-only .ui-button-text {
- padding: .4em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
- padding: .4em;
- text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 1em .4em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 2.1em .4em 1em;
-}
-.ui-button-text-icons .ui-button-text {
- padding-left: 2.1em;
- padding-right: 2.1em;
-}
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
- padding: .4em 1em;
-}
-
-/* button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
- position: absolute;
- top: 50%;
- margin-top: -8px;
-}
-.ui-button-icon-only .ui-icon {
- left: 50%;
- margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
- left: .5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
- right: .5em;
-}
-
-/* button sets */
-.ui-buttonset {
- margin-right: 7px;
-}
-.ui-buttonset .ui-button {
- margin-left: 0;
- margin-right: -.3em;
-}
-
-/* workarounds */
-/* reset extra padding in Firefox, see h5bp.com/l */
-input.ui-button::-moz-focus-inner,
-button.ui-button::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-.ui-datepicker {
- width: 17em;
- padding: .2em .2em 0;
- display: none;
-}
-.ui-datepicker .ui-datepicker-header {
- position: relative;
- padding: .2em 0;
-}
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
- position: absolute;
- top: 2px;
- width: 1.8em;
- height: 1.8em;
-}
-.ui-datepicker .ui-datepicker-prev-hover,
-.ui-datepicker .ui-datepicker-next-hover {
- top: 1px;
-}
-.ui-datepicker .ui-datepicker-prev {
- left: 2px;
-}
-.ui-datepicker .ui-datepicker-next {
- right: 2px;
-}
-.ui-datepicker .ui-datepicker-prev-hover {
- left: 1px;
-}
-.ui-datepicker .ui-datepicker-next-hover {
- right: 1px;
-}
-.ui-datepicker .ui-datepicker-prev span,
-.ui-datepicker .ui-datepicker-next span {
- display: block;
- position: absolute;
- left: 50%;
- margin-left: -8px;
- top: 50%;
- margin-top: -8px;
-}
-.ui-datepicker .ui-datepicker-title {
- margin: 0 2.3em;
- line-height: 1.8em;
- text-align: center;
-}
-.ui-datepicker .ui-datepicker-title select {
- font-size: 1em;
- margin: 1px 0;
-}
-.ui-datepicker select.ui-datepicker-month-year {
- width: 100%;
-}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
- width: 49%;
-}
-.ui-datepicker table {
- width: 100%;
- font-size: .9em;
- border-collapse: collapse;
- margin: 0 0 .4em;
-}
-.ui-datepicker th {
- padding: .7em .3em;
- text-align: center;
- font-weight: bold;
- border: 0;
-}
-.ui-datepicker td {
- border: 0;
- padding: 1px;
-}
-.ui-datepicker td span,
-.ui-datepicker td a {
- display: block;
- padding: .2em;
- text-align: right;
- text-decoration: none;
-}
-.ui-datepicker .ui-datepicker-buttonpane {
- background-image: none;
- margin: .7em 0 0 0;
- padding: 0 .2em;
- border-left: 0;
- border-right: 0;
- border-bottom: 0;
-}
-.ui-datepicker .ui-datepicker-buttonpane button {
- float: right;
- margin: .5em .2em .4em;
- cursor: pointer;
- padding: .2em .6em .3em .6em;
- width: auto;
- overflow: visible;
-}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
- float: left;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
- width: auto;
-}
-.ui-datepicker-multi .ui-datepicker-group {
- float: left;
-}
-.ui-datepicker-multi .ui-datepicker-group table {
- width: 95%;
- margin: 0 auto .4em;
-}
-.ui-datepicker-multi-2 .ui-datepicker-group {
- width: 50%;
-}
-.ui-datepicker-multi-3 .ui-datepicker-group {
- width: 33.3%;
-}
-.ui-datepicker-multi-4 .ui-datepicker-group {
- width: 25%;
-}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
- border-left-width: 0;
-}
-.ui-datepicker-multi .ui-datepicker-buttonpane {
- clear: left;
-}
-.ui-datepicker-row-break {
- clear: both;
- width: 100%;
- font-size: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
- direction: rtl;
-}
-.ui-datepicker-rtl .ui-datepicker-prev {
- right: 2px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next {
- left: 2px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
- right: 1px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next:hover {
- left: 1px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
- clear: right;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
- float: left;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
- float: right;
-}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
- border-right-width: 0;
- border-left-width: 1px;
-}
-.ui-dialog {
- position: absolute;
- top: 0;
- left: 0;
- padding: .2em;
- outline: 0;
-}
-.ui-dialog .ui-dialog-titlebar {
- padding: .4em 1em;
- position: relative;
-}
-.ui-dialog .ui-dialog-title {
- float: left;
- margin: .1em 0;
- white-space: nowrap;
- width: 90%;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.ui-dialog .ui-dialog-titlebar-close {
- position: absolute;
- right: .3em;
- top: 50%;
- width: 21px;
- margin: -10px 0 0 0;
- padding: 1px;
- height: 20px;
-}
-.ui-dialog .ui-dialog-content {
- position: relative;
- border: 0;
- padding: .5em 1em;
- background: none;
- overflow: auto;
-}
-.ui-dialog .ui-dialog-buttonpane {
- text-align: left;
- border-width: 1px 0 0 0;
- background-image: none;
- margin-top: .5em;
- padding: .3em 1em .5em .4em;
-}
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
- float: right;
-}
-.ui-dialog .ui-dialog-buttonpane button {
- margin: .5em .4em .5em 0;
- cursor: pointer;
-}
-.ui-dialog .ui-resizable-se {
- width: 12px;
- height: 12px;
- right: -5px;
- bottom: -5px;
- background-position: 16px 16px;
-}
-.ui-draggable .ui-dialog-titlebar {
- cursor: move;
-}
-.ui-menu {
- list-style: none;
- padding: 2px;
- margin: 0;
- display: block;
- outline: none;
-}
-.ui-menu .ui-menu {
- margin-top: -3px;
- position: absolute;
-}
-.ui-menu .ui-menu-item {
- margin: 0;
- padding: 0;
- width: 100%;
- /* support: IE10, see #8844 */
- list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
-}
-.ui-menu .ui-menu-divider {
- margin: 5px -2px 5px -2px;
- height: 0;
- font-size: 0;
- line-height: 0;
- border-width: 1px 0 0 0;
-}
-.ui-menu .ui-menu-item a {
- text-decoration: none;
- display: block;
- padding: 2px .4em;
- line-height: 1.5;
- min-height: 0; /* support: IE7 */
- font-weight: normal;
-}
-.ui-menu .ui-menu-item a.ui-state-focus,
-.ui-menu .ui-menu-item a.ui-state-active {
- font-weight: normal;
- margin: -1px;
-}
-
-.ui-menu .ui-state-disabled {
- font-weight: normal;
- margin: .4em 0 .2em;
- line-height: 1.5;
-}
-.ui-menu .ui-state-disabled a {
- cursor: default;
-}
-
-/* icon support */
-.ui-menu-icons {
- position: relative;
-}
-.ui-menu-icons .ui-menu-item a {
- position: relative;
- padding-left: 2em;
-}
-
-/* left-aligned */
-.ui-menu .ui-icon {
- position: absolute;
- top: .2em;
- left: .2em;
-}
-
-/* right-aligned */
-.ui-menu .ui-menu-icon {
- position: static;
- float: right;
-}
-.ui-progressbar {
- height: 2em;
- text-align: left;
- overflow: hidden;
-}
-.ui-progressbar .ui-progressbar-value {
- margin: -1px;
- height: 100%;
-}
-.ui-progressbar .ui-progressbar-overlay {
- background: url("/static/images/animated-overlay.gif");
- height: 100%;
- filter: alpha(opacity=25);
- opacity: 0.25;
-}
-.ui-progressbar-indeterminate .ui-progressbar-value {
- background-image: none;
-}
-.ui-slider {
- position: relative;
- text-align: left;
-}
-.ui-slider .ui-slider-handle {
- position: absolute;
- z-index: 2;
- width: 1.2em;
- height: 1.2em;
- cursor: default;
-}
-.ui-slider .ui-slider-range {
- position: absolute;
- z-index: 1;
- font-size: .7em;
- display: block;
- border: 0;
- background-position: 0 0;
-}
-
-/* For IE8 - See #6727 */
-.ui-slider.ui-state-disabled .ui-slider-handle,
-.ui-slider.ui-state-disabled .ui-slider-range {
- filter: inherit;
-}
-
-.ui-slider-horizontal {
- height: .8em;
-}
-.ui-slider-horizontal .ui-slider-handle {
- top: -.3em;
- margin-left: -.6em;
-}
-.ui-slider-horizontal .ui-slider-range {
- top: 0;
- height: 100%;
-}
-.ui-slider-horizontal .ui-slider-range-min {
- left: 0;
-}
-.ui-slider-horizontal .ui-slider-range-max {
- right: 0;
-}
-
-.ui-slider-vertical {
- width: .8em;
- height: 100px;
-}
-.ui-slider-vertical .ui-slider-handle {
- left: -.3em;
- margin-left: 0;
- margin-bottom: -.6em;
-}
-.ui-slider-vertical .ui-slider-range {
- left: 0;
- width: 100%;
-}
-.ui-slider-vertical .ui-slider-range-min {
- bottom: 0;
-}
-.ui-slider-vertical .ui-slider-range-max {
- top: 0;
-}
-.ui-spinner {
- position: relative;
- display: inline-block;
- overflow: hidden;
- padding: 0;
- vertical-align: middle;
-}
-.ui-spinner-input {
- border: none;
- background: none;
- color: inherit;
- padding: 0;
- margin: .2em 0;
- vertical-align: middle;
- margin-left: .4em;
- margin-right: 22px;
-}
-.ui-spinner-button {
- width: 16px;
- height: 50%;
- font-size: .5em;
- padding: 0;
- margin: 0;
- text-align: center;
- position: absolute;
- cursor: default;
- display: block;
- overflow: hidden;
- right: 0;
-}
-/* more specificity required here to overide default borders */
-.ui-spinner a.ui-spinner-button {
- border-top: none;
- border-bottom: none;
- border-right: none;
-}
-/* vertical centre icon */
-.ui-spinner .ui-icon {
- position: absolute;
- margin-top: -8px;
- top: 50%;
- left: 0;
-}
-.ui-spinner-up {
- top: 0;
-}
-.ui-spinner-down {
- bottom: 0;
-}
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
- /* need to fix icons sprite */
- background-position: -65px -16px;
-}
-.ui-tabs {
- position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
- padding: .2em;
-}
-.ui-tabs .ui-tabs-nav {
- margin: 0;
- padding: .2em .2em 0;
-}
-.ui-tabs .ui-tabs-nav li {
- list-style: none;
- float: left;
- position: relative;
- top: 0;
- margin: 1px .2em 0 0;
- border-bottom-width: 0;
- padding: 0;
- white-space: nowrap;
-}
-.ui-tabs .ui-tabs-nav li a {
- float: left;
- padding: .5em 1em;
- text-decoration: none;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active {
- margin-bottom: -1px;
- padding-bottom: 1px;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active a,
-.ui-tabs .ui-tabs-nav li.ui-state-disabled a,
-.ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
- cursor: text;
-}
-.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
- cursor: pointer;
-}
-.ui-tabs .ui-tabs-panel {
- display: block;
- border-width: 0;
- padding: 1em 1.4em;
- background: none;
-}
-.ui-tooltip {
- padding: 8px;
- position: absolute;
- z-index: 9999;
- max-width: 300px;
- -webkit-box-shadow: 0 0 5px #aaa;
- box-shadow: 0 0 5px #aaa;
-}
-body .ui-tooltip {
- border-width: 2px;
-}
-
-/* Component containers
-----------------------------------*/
-.ui-widget {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
-}
-.ui-widget .ui-widget {
- font-size: 1em;
-}
-.ui-widget input,
-.ui-widget select,
-.ui-widget textarea,
-.ui-widget button {
- /*font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
- font-size: 1em;*/
-}
-.ui-widget-content {
- border: 1px solid #a6c9e2;
- background: #fcfdfd url(/static/images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;
- color: #36454F;
- font-weight: normal;
-}
-.ui-widget-content a {
- color: #0088cc;
-}
-.ui-widget-header {
- border: 1px solid #a6c9e2;
- background: #ffffff url(/static/images/ui-bg_flat_50_ffffff_40x100.png) 50% 50% repeat-x;
- color: #36454F;
- font-weight: bold;
-}
-.ui-widget-header a {
- color: #36454F;
-}
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default,
-.ui-widget-content .ui-state-default,
-.ui-widget-header .ui-state-default {
- border: 1px solid #a6c9e2;
- background: #ffffff url(/static/images/ui-bg_flat_100_ffffff_40x100.png) 50% 50% repeat-x;
- font-weight: bold;
- color: #0088cc;
-}
-.ui-state-default a,
-.ui-state-default a:link,
-.ui-state-default a:visited {
- color: #0088cc;
- text-decoration: none;
-}
-.ui-state-hover,
-.ui-widget-content .ui-state-hover,
-.ui-widget-header .ui-state-hover,
-.ui-state-focus,
-.ui-widget-content .ui-state-focus,
-.ui-widget-header .ui-state-focus {
- border: 1px solid #e3e3e3;
- background: #e5e3e3 url(/static/images/ui-bg_flat_75_e5e3e3_40x100.png) 50% 50% repeat-x;
- font-weight: bold;
- color: #005580;
-}
-.ui-state-hover a,
-.ui-state-hover a:hover,
-.ui-state-hover a:link,
-.ui-state-hover a:visited {
- color: #005580;
- text-decoration: none;
-}
-.ui-state-active,
-.ui-widget-content .ui-state-active,
-.ui-widget-header .ui-state-active {
- border: 1px solid #e3e3e3;
- background: #f5f5f5 url(/static/images/ui-bg_inset-hard_100_f5f5f5_1x100.png) 50% 50% repeat-x;
- font-weight: bold;
- color: #36454F;
-}
-.ui-state-active a,
-.ui-state-active a:link,
-.ui-state-active a:visited {
- color: #36454F;
- text-decoration: none;
-}
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight,
-.ui-widget-content .ui-state-highlight,
-.ui-widget-header .ui-state-highlight {
- border: 1px solid #fad42e;
- background: #fbec88 url(/static/images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;
- color: #363636;
-}
-.ui-state-highlight a,
-.ui-widget-content .ui-state-highlight a,
-.ui-widget-header .ui-state-highlight a {
- color: #363636;
-}
-.ui-state-error,
-.ui-widget-content .ui-state-error,
-.ui-widget-header .ui-state-error {
- border: 1px solid #cd0a0a;
- background: #fef1ec url(/static/images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;
- color: #cd0a0a;
-}
-.ui-state-error a,
-.ui-widget-content .ui-state-error a,
-.ui-widget-header .ui-state-error a {
- color: #cd0a0a;
-}
-.ui-state-error-text,
-.ui-widget-content .ui-state-error-text,
-.ui-widget-header .ui-state-error-text {
- color: #cd0a0a;
-}
-.ui-priority-primary,
-.ui-widget-content .ui-priority-primary,
-.ui-widget-header .ui-priority-primary {
- font-weight: normal;
-}
-.ui-priority-secondary,
-.ui-widget-content .ui-priority-secondary,
-.ui-widget-header .ui-priority-secondary {
- opacity: .7;
- filter:Alpha(Opacity=70);
- font-weight: bold;
-}
-.ui-state-disabled,
-.ui-widget-content .ui-state-disabled,
-.ui-widget-header .ui-state-disabled {
- opacity: .35;
- filter:Alpha(Opacity=35);
- background-image: none;
-}
-.ui-state-disabled .ui-icon {
- filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
-}
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- width: 16px;
- height: 16px;
-}
-.ui-icon,
-.ui-widget-content .ui-icon {
- background-image: url(/static/images/ui-icons_469bdd_256x240.png);
-}
-.ui-widget-header .ui-icon {
- background-image: url(/static/images/ui-icons_36454F_256x240.png);
-}
-.ui-state-default .ui-icon {
- background-image: url(/static/images/ui-icons_0088cc_256x240.png);
-}
-.ui-state-hover .ui-icon,
-.ui-state-focus .ui-icon {
- background-image: url(/static/images/ui-icons_217bc0_256x240.png);
-}
-.ui-state-active .ui-icon {
- background-image: url(/static/images/ui-icons_36454F_256x240.png);
-}
-.ui-state-highlight .ui-icon {
- background-image: url(/static/images/ui-icons_2e83ff_256x240.png);
-}
-.ui-state-error .ui-icon,
-.ui-state-error-text .ui-icon {
- background-image: url(/static/images/ui-icons_cd0a0a_256x240.png);
-}
-
-/* positioning */
-.ui-icon-blank { background-position: 16px 16px; }
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-on { background-position: -96px -144px; }
-.ui-icon-radio-off { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-left,
-.ui-corner-tl {
- border-top-left-radius: 5px;
-}
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-right,
-.ui-corner-tr {
- border-top-right-radius: 5px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-left,
-.ui-corner-bl {
- border-bottom-left-radius: 5px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-right,
-.ui-corner-br {
- border-bottom-right-radius: 5px;
-}
-
-/* Overlays */
-.ui-widget-overlay {
- background: #aaaaaa url(/static/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
- opacity: .3;
- filter: Alpha(Opacity=30);
-}
-.ui-widget-shadow {
- margin: -8px 0 0 -8px;
- padding: 8px;
- background: #aaaaaa url(/static/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
- opacity: .3;
- filter: Alpha(Opacity=30);
- border-radius: 8px;
-}
diff --git a/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.min.css b/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.min.css
deleted file mode 100644
index d8794ea158..0000000000
--- a/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.min.css
+++ /dev/null
@@ -1,358 +0,0 @@
-.ui-helper-hidden{display:none;}
-.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;}
-.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none;}
-.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse;}
-.ui-helper-clearfix:after{clear:both;}
-.ui-helper-clearfix{min-height:0;}
-.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:alpha(opacity=0);}
-.ui-front{z-index:100;}
-.ui-state-disabled{cursor:default !important;}
-.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;}
-.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%;}
-.ui-resizable{position:relative;}
-.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;}
-.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none;}
-.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0;}
-.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0;}
-.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%;}
-.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%;}
-.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px;}
-.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px;}
-.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px;}
-.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px;}
-.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black;}
-.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0;}
-.ui-accordion-header{font-weight:bold;}
-.ui-accordion .ui-accordion-icons{padding-left:2.2em;}
-.ui-accordion .ui-accordion-noicons{padding-left:.7em;}
-.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em;}
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px;}
-.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto;}
-.ui-autocomplete{position:absolute;top:0;left:0;cursor:default;}
-.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible;}
-.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none;}
-.ui-button-icon-only{width:2.2em;}
-button.ui-button-icon-only{width:2.4em;}
-.ui-button-icons-only{width:3.4em;}
-button.ui-button-icons-only{width:3.7em;}
-.ui-button .ui-button-text{display:block;line-height:normal;}
-.ui-button-text-only .ui-button-text{padding:.4em 1em;}
-.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px;}
-.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em;}
-.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em;}
-.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em;}
-input.ui-button{padding:.4em 1em;}
-.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px;}
-.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px;}
-.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em;}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em;}
-.ui-buttonset{margin-right:7px;}
-.ui-buttonset .ui-button{margin-left:0;margin-right:-0.3em;}
-input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0;}
-.ui-datepicker{width:17em;padding:.2em .2em 0;display:none;}
-.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0;}
-.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em;}
-.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px;}
-.ui-datepicker .ui-datepicker-prev{left:2px;}
-.ui-datepicker .ui-datepicker-next{right:2px;}
-.ui-datepicker .ui-datepicker-prev-hover{left:1px;}
-.ui-datepicker .ui-datepicker-next-hover{right:1px;}
-.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px;}
-.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center;}
-.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0;}
-.ui-datepicker select.ui-datepicker-month-year{width:100%;}
-.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%;}
-.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em;}
-.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0;}
-.ui-datepicker td{border:0;padding:1px;}
-.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none;}
-.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0;}
-.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible;}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left;}
-.ui-datepicker.ui-datepicker-multi{width:auto;}
-.ui-datepicker-multi .ui-datepicker-group{float:left;}
-.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em;}
-.ui-datepicker-multi-2 .ui-datepicker-group{width:50%;}
-.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%;}
-.ui-datepicker-multi-4 .ui-datepicker-group{width:25%;}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0;}
-.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left;}
-.ui-datepicker-row-break{clear:both;width:100%;font-size:0;}
-.ui-datepicker-rtl{direction:rtl;}
-.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto;}
-.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto;}
-.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto;}
-.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto;}
-.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right;}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left;}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right;}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px;}
-.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0;}
-.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative;}
-.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis;}
-.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px;}
-.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;}
-.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em;}
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right;}
-.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer;}
-.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px;}
-.ui-draggable .ui-dialog-titlebar{cursor:move;}
-.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none;}
-.ui-menu .ui-menu{margin-top:-3px;position:absolute;}
-.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);}
-.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0;}
-.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal;}
-.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px;}
-.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5;}
-.ui-menu .ui-state-disabled a{cursor:default;}
-.ui-menu-icons{position:relative;}
-.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em;}
-.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em;}
-.ui-menu .ui-menu-icon{position:static;float:right;}
-.ui-progressbar{height:2em;text-align:left;overflow:hidden;}
-.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%;}
-.ui-progressbar .ui-progressbar-overlay{background:url("/static/images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25;}
-.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none;}
-.ui-slider{position:relative;text-align:left;}
-.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;}
-.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0;}
-.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit;}
-.ui-slider-horizontal{height:.8em;}
-.ui-slider-horizontal .ui-slider-handle{top:-0.3em;margin-left:-0.6em;}
-.ui-slider-horizontal .ui-slider-range{top:0;height:100%;}
-.ui-slider-horizontal .ui-slider-range-min{left:0;}
-.ui-slider-horizontal .ui-slider-range-max{right:0;}
-.ui-slider-vertical{width:.8em;height:100px;}
-.ui-slider-vertical .ui-slider-handle{left:-0.3em;margin-left:0;margin-bottom:-0.6em;}
-.ui-slider-vertical .ui-slider-range{left:0;width:100%;}
-.ui-slider-vertical .ui-slider-range-min{bottom:0;}
-.ui-slider-vertical .ui-slider-range-max{top:0;}
-.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle;}
-.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px;}
-.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0;}
-.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none;}
-.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0;}
-.ui-spinner-up{top:0;}
-.ui-spinner-down{bottom:0;}
-.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px;}
-.ui-tabs{position:relative;padding:.2em;}
-.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0;}
-.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap;}
-.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none;}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px;}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text;}
-.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer;}
-.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none;}
-.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa;}
-body .ui-tooltip{border-width:2px;}
-.ui-widget{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;}
-.ui-widget .ui-widget{font-size:1em;}
-.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{}
-.ui-widget-content{border:1px solid #a6c9e2;background:#fcfdfd url(/static/images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;color:#36454F;font-weight:normal;}
-.ui-widget-content a{color:#0088cc;}
-.ui-widget-header{border:1px solid #a6c9e2;background:#ffffff url(/static/images/ui-bg_flat_50_ffffff_40x100.png) 50% 50% repeat-x;color:#36454F;font-weight:bold;}
-.ui-widget-header a{color:#36454F;}
-.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #a6c9e2;background:#ffffff url(/static/images/ui-bg_flat_100_ffffff_40x100.png) 50% 50% repeat-x;font-weight:bold;color:#0088cc;}
-.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#0088cc;text-decoration:none;}
-.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #e3e3e3;background:#e5e3e3 url(/static/images/ui-bg_flat_75_e5e3e3_40x100.png) 50% 50% repeat-x;font-weight:bold;color:#005580;}
-.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#005580;text-decoration:none;}
-.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #e3e3e3;background:#f5f5f5 url(/static/images/ui-bg_inset-hard_100_f5f5f5_1x100.png) 50% 50% repeat-x;font-weight:bold;color:#36454F;}
-.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#36454F;text-decoration:none;}
-.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fad42e;background:#fbec88 url(/static/images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;color:#363636;}
-.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636;}
-.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(/static/images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a;}
-.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a;}
-.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a;}
-.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:normal;}
-.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:alpha(opacity=70);font-weight:bold;}
-.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:alpha(opacity=35);background-image:none;}
-.ui-state-disabled .ui-icon{filter:alpha(opacity=35);}
-.ui-icon{width:16px;height:16px;}
-.ui-icon,.ui-widget-content .ui-icon{background-image:url(/static/images/ui-icons_469bdd_256x240.png);}
-.ui-widget-header .ui-icon{background-image:url(/static/images/ui-icons_36454F_256x240.png);}
-.ui-state-default .ui-icon{background-image:url(/static/images/ui-icons_0088cc_256x240.png);}
-.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(/static/images/ui-icons_217bc0_256x240.png);}
-.ui-state-active .ui-icon{background-image:url(/static/images/ui-icons_36454F_256x240.png);}
-.ui-state-highlight .ui-icon{background-image:url(/static/images/ui-icons_2e83ff_256x240.png);}
-.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(/static/images/ui-icons_cd0a0a_256x240.png);}
-.ui-icon-blank{background-position:16px 16px;}
-.ui-icon-carat-1-n{background-position:0 0;}
-.ui-icon-carat-1-ne{background-position:-16px 0;}
-.ui-icon-carat-1-e{background-position:-32px 0;}
-.ui-icon-carat-1-se{background-position:-48px 0;}
-.ui-icon-carat-1-s{background-position:-64px 0;}
-.ui-icon-carat-1-sw{background-position:-80px 0;}
-.ui-icon-carat-1-w{background-position:-96px 0;}
-.ui-icon-carat-1-nw{background-position:-112px 0;}
-.ui-icon-carat-2-n-s{background-position:-128px 0;}
-.ui-icon-carat-2-e-w{background-position:-144px 0;}
-.ui-icon-triangle-1-n{background-position:0 -16px;}
-.ui-icon-triangle-1-ne{background-position:-16px -16px;}
-.ui-icon-triangle-1-e{background-position:-32px -16px;}
-.ui-icon-triangle-1-se{background-position:-48px -16px;}
-.ui-icon-triangle-1-s{background-position:-64px -16px;}
-.ui-icon-triangle-1-sw{background-position:-80px -16px;}
-.ui-icon-triangle-1-w{background-position:-96px -16px;}
-.ui-icon-triangle-1-nw{background-position:-112px -16px;}
-.ui-icon-triangle-2-n-s{background-position:-128px -16px;}
-.ui-icon-triangle-2-e-w{background-position:-144px -16px;}
-.ui-icon-arrow-1-n{background-position:0 -32px;}
-.ui-icon-arrow-1-ne{background-position:-16px -32px;}
-.ui-icon-arrow-1-e{background-position:-32px -32px;}
-.ui-icon-arrow-1-se{background-position:-48px -32px;}
-.ui-icon-arrow-1-s{background-position:-64px -32px;}
-.ui-icon-arrow-1-sw{background-position:-80px -32px;}
-.ui-icon-arrow-1-w{background-position:-96px -32px;}
-.ui-icon-arrow-1-nw{background-position:-112px -32px;}
-.ui-icon-arrow-2-n-s{background-position:-128px -32px;}
-.ui-icon-arrow-2-ne-sw{background-position:-144px -32px;}
-.ui-icon-arrow-2-e-w{background-position:-160px -32px;}
-.ui-icon-arrow-2-se-nw{background-position:-176px -32px;}
-.ui-icon-arrowstop-1-n{background-position:-192px -32px;}
-.ui-icon-arrowstop-1-e{background-position:-208px -32px;}
-.ui-icon-arrowstop-1-s{background-position:-224px -32px;}
-.ui-icon-arrowstop-1-w{background-position:-240px -32px;}
-.ui-icon-arrowthick-1-n{background-position:0 -48px;}
-.ui-icon-arrowthick-1-ne{background-position:-16px -48px;}
-.ui-icon-arrowthick-1-e{background-position:-32px -48px;}
-.ui-icon-arrowthick-1-se{background-position:-48px -48px;}
-.ui-icon-arrowthick-1-s{background-position:-64px -48px;}
-.ui-icon-arrowthick-1-sw{background-position:-80px -48px;}
-.ui-icon-arrowthick-1-w{background-position:-96px -48px;}
-.ui-icon-arrowthick-1-nw{background-position:-112px -48px;}
-.ui-icon-arrowthick-2-n-s{background-position:-128px -48px;}
-.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px;}
-.ui-icon-arrowthick-2-e-w{background-position:-160px -48px;}
-.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px;}
-.ui-icon-arrowthickstop-1-n{background-position:-192px -48px;}
-.ui-icon-arrowthickstop-1-e{background-position:-208px -48px;}
-.ui-icon-arrowthickstop-1-s{background-position:-224px -48px;}
-.ui-icon-arrowthickstop-1-w{background-position:-240px -48px;}
-.ui-icon-arrowreturnthick-1-w{background-position:0 -64px;}
-.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px;}
-.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px;}
-.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px;}
-.ui-icon-arrowreturn-1-w{background-position:-64px -64px;}
-.ui-icon-arrowreturn-1-n{background-position:-80px -64px;}
-.ui-icon-arrowreturn-1-e{background-position:-96px -64px;}
-.ui-icon-arrowreturn-1-s{background-position:-112px -64px;}
-.ui-icon-arrowrefresh-1-w{background-position:-128px -64px;}
-.ui-icon-arrowrefresh-1-n{background-position:-144px -64px;}
-.ui-icon-arrowrefresh-1-e{background-position:-160px -64px;}
-.ui-icon-arrowrefresh-1-s{background-position:-176px -64px;}
-.ui-icon-arrow-4{background-position:0 -80px;}
-.ui-icon-arrow-4-diag{background-position:-16px -80px;}
-.ui-icon-extlink{background-position:-32px -80px;}
-.ui-icon-newwin{background-position:-48px -80px;}
-.ui-icon-refresh{background-position:-64px -80px;}
-.ui-icon-shuffle{background-position:-80px -80px;}
-.ui-icon-transfer-e-w{background-position:-96px -80px;}
-.ui-icon-transferthick-e-w{background-position:-112px -80px;}
-.ui-icon-folder-collapsed{background-position:0 -96px;}
-.ui-icon-folder-open{background-position:-16px -96px;}
-.ui-icon-document{background-position:-32px -96px;}
-.ui-icon-document-b{background-position:-48px -96px;}
-.ui-icon-note{background-position:-64px -96px;}
-.ui-icon-mail-closed{background-position:-80px -96px;}
-.ui-icon-mail-open{background-position:-96px -96px;}
-.ui-icon-suitcase{background-position:-112px -96px;}
-.ui-icon-comment{background-position:-128px -96px;}
-.ui-icon-person{background-position:-144px -96px;}
-.ui-icon-print{background-position:-160px -96px;}
-.ui-icon-trash{background-position:-176px -96px;}
-.ui-icon-locked{background-position:-192px -96px;}
-.ui-icon-unlocked{background-position:-208px -96px;}
-.ui-icon-bookmark{background-position:-224px -96px;}
-.ui-icon-tag{background-position:-240px -96px;}
-.ui-icon-home{background-position:0 -112px;}
-.ui-icon-flag{background-position:-16px -112px;}
-.ui-icon-calendar{background-position:-32px -112px;}
-.ui-icon-cart{background-position:-48px -112px;}
-.ui-icon-pencil{background-position:-64px -112px;}
-.ui-icon-clock{background-position:-80px -112px;}
-.ui-icon-disk{background-position:-96px -112px;}
-.ui-icon-calculator{background-position:-112px -112px;}
-.ui-icon-zoomin{background-position:-128px -112px;}
-.ui-icon-zoomout{background-position:-144px -112px;}
-.ui-icon-search{background-position:-160px -112px;}
-.ui-icon-wrench{background-position:-176px -112px;}
-.ui-icon-gear{background-position:-192px -112px;}
-.ui-icon-heart{background-position:-208px -112px;}
-.ui-icon-star{background-position:-224px -112px;}
-.ui-icon-link{background-position:-240px -112px;}
-.ui-icon-cancel{background-position:0 -128px;}
-.ui-icon-plus{background-position:-16px -128px;}
-.ui-icon-plusthick{background-position:-32px -128px;}
-.ui-icon-minus{background-position:-48px -128px;}
-.ui-icon-minusthick{background-position:-64px -128px;}
-.ui-icon-close{background-position:-80px -128px;}
-.ui-icon-closethick{background-position:-96px -128px;}
-.ui-icon-key{background-position:-112px -128px;}
-.ui-icon-lightbulb{background-position:-128px -128px;}
-.ui-icon-scissors{background-position:-144px -128px;}
-.ui-icon-clipboard{background-position:-160px -128px;}
-.ui-icon-copy{background-position:-176px -128px;}
-.ui-icon-contact{background-position:-192px -128px;}
-.ui-icon-image{background-position:-208px -128px;}
-.ui-icon-video{background-position:-224px -128px;}
-.ui-icon-script{background-position:-240px -128px;}
-.ui-icon-alert{background-position:0 -144px;}
-.ui-icon-info{background-position:-16px -144px;}
-.ui-icon-notice{background-position:-32px -144px;}
-.ui-icon-help{background-position:-48px -144px;}
-.ui-icon-check{background-position:-64px -144px;}
-.ui-icon-bullet{background-position:-80px -144px;}
-.ui-icon-radio-on{background-position:-96px -144px;}
-.ui-icon-radio-off{background-position:-112px -144px;}
-.ui-icon-pin-w{background-position:-128px -144px;}
-.ui-icon-pin-s{background-position:-144px -144px;}
-.ui-icon-play{background-position:0 -160px;}
-.ui-icon-pause{background-position:-16px -160px;}
-.ui-icon-seek-next{background-position:-32px -160px;}
-.ui-icon-seek-prev{background-position:-48px -160px;}
-.ui-icon-seek-end{background-position:-64px -160px;}
-.ui-icon-seek-start{background-position:-80px -160px;}
-.ui-icon-seek-first{background-position:-80px -160px;}
-.ui-icon-stop{background-position:-96px -160px;}
-.ui-icon-eject{background-position:-112px -160px;}
-.ui-icon-volume-off{background-position:-128px -160px;}
-.ui-icon-volume-on{background-position:-144px -160px;}
-.ui-icon-power{background-position:0 -176px;}
-.ui-icon-signal-diag{background-position:-16px -176px;}
-.ui-icon-signal{background-position:-32px -176px;}
-.ui-icon-battery-0{background-position:-48px -176px;}
-.ui-icon-battery-1{background-position:-64px -176px;}
-.ui-icon-battery-2{background-position:-80px -176px;}
-.ui-icon-battery-3{background-position:-96px -176px;}
-.ui-icon-circle-plus{background-position:0 -192px;}
-.ui-icon-circle-minus{background-position:-16px -192px;}
-.ui-icon-circle-close{background-position:-32px -192px;}
-.ui-icon-circle-triangle-e{background-position:-48px -192px;}
-.ui-icon-circle-triangle-s{background-position:-64px -192px;}
-.ui-icon-circle-triangle-w{background-position:-80px -192px;}
-.ui-icon-circle-triangle-n{background-position:-96px -192px;}
-.ui-icon-circle-arrow-e{background-position:-112px -192px;}
-.ui-icon-circle-arrow-s{background-position:-128px -192px;}
-.ui-icon-circle-arrow-w{background-position:-144px -192px;}
-.ui-icon-circle-arrow-n{background-position:-160px -192px;}
-.ui-icon-circle-zoomin{background-position:-176px -192px;}
-.ui-icon-circle-zoomout{background-position:-192px -192px;}
-.ui-icon-circle-check{background-position:-208px -192px;}
-.ui-icon-circlesmall-plus{background-position:0 -208px;}
-.ui-icon-circlesmall-minus{background-position:-16px -208px;}
-.ui-icon-circlesmall-close{background-position:-32px -208px;}
-.ui-icon-squaresmall-plus{background-position:-48px -208px;}
-.ui-icon-squaresmall-minus{background-position:-64px -208px;}
-.ui-icon-squaresmall-close{background-position:-80px -208px;}
-.ui-icon-grip-dotted-vertical{background-position:0 -224px;}
-.ui-icon-grip-dotted-horizontal{background-position:-16px -224px;}
-.ui-icon-grip-solid-vertical{background-position:-32px -224px;}
-.ui-icon-grip-solid-horizontal{background-position:-48px -224px;}
-.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px;}
-.ui-icon-grip-diagonal-se{background-position:-80px -224px;}
-.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:5px;}
-.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:5px;}
-.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:5px;}
-.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:5px;}
-.ui-widget-overlay{background:#aaaaaa url(/static/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:alpha(opacity=30);}
-.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaaaaa url(/static/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:alpha(opacity=30);border-radius:8px;}
diff --git a/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.min.css.old b/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.min.css.old
deleted file mode 100644
index 73cc2d3547..0000000000
--- a/awx/ui/client/assets/custom-theme/jquery-ui-1.10.3.custom.min.css.old
+++ /dev/null
@@ -1,5 +0,0 @@
-/*! jQuery UI - v1.10.3 - 2013-06-26
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=normal&fsDefault=14px&cornerRadius=5px&bgColorHeader=%23ffffff&bgTextureHeader=flat&bgImgOpacityHeader=50&borderColorHeader=%23a6c9e2&fcHeader=%2336454F&iconColorHeader=%2336454F&bgColorContent=%23fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=%23a6c9e2&fcContent=%23222222&iconColorContent=%23469bdd&bgColorDefault=%23ffffff&bgTextureDefault=flat&bgImgOpacityDefault=100&borderColorDefault=%23a6c9e2&fcDefault=%230088cc&iconColorDefault=%230088cc&bgColorHover=%23e5e3e3&bgTextureHover=flat&bgImgOpacityHover=75&borderColorHover=%23e3e3e3&fcHover=%23005580&iconColorHover=%23217bc0&bgColorActive=%23f5f5f5&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=%23e3e3e3&fcActive=%2336454F&iconColorActive=%2336454F&bgColorHighlight=%23fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=%23fad42e&fcHighlight=%23363636&iconColorHighlight=%232e83ff&bgColorError=%23fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=%23cd0a0a&fcError=%23cd0a0a&iconColorError=%23cd0a0a&bgColorOverlay=%23aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=%23aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted #000}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:0;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:0}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:400}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:400;margin:-1px}.ui-menu .ui-state-disabled{font-weight:400;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url(images/animated-overlay.gif);height:100%;filter:alpha(opacity=25);opacity:.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:0;background:0;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:0;border-bottom:0;border-right:0}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:14px}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #a6c9e2;background:#fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #a6c9e2;background:#fff url(images/ui-bg_flat_50_ffffff_40x100.png) 50% 50% repeat-x;color:#36454F;font-weight:bold}.ui-widget-header a{color:#36454F}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #a6c9e2;background:#fff url(images/ui-bg_flat_100_ffffff_40x100.png) 50% 50% repeat-x;font-weight:normal;color:#08c}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#08c;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #e3e3e3;background:#e5e3e3 url(images/ui-bg_flat_75_e5e3e3_40x100.png) 50% 50% repeat-x;font-weight:normal;color:#005580}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#005580;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #e3e3e3;background:#f5f5f5 url(images/ui-bg_inset-hard_100_f5f5f5_1x100.png) 50% 50% repeat-x;font-weight:normal;color:#36454F}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#36454F;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fad42e;background:#fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_469bdd_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_36454F_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_0088cc_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_217bc0_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_36454F_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:5px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:5px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
\ No newline at end of file
diff --git a/awx/ui/client/assets/favicon.ico b/awx/ui/client/assets/favicon.ico
deleted file mode 100644
index 2f009cfad0..0000000000
Binary files a/awx/ui/client/assets/favicon.ico and /dev/null differ
diff --git a/awx/ui/client/assets/fontcustom/.fontcustom-manifest.json b/awx/ui/client/assets/fontcustom/.fontcustom-manifest.json
deleted file mode 100644
index c50d13abe3..0000000000
--- a/awx/ui/client/assets/fontcustom/.fontcustom-manifest.json
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "checksum": {
- "previous": "3dfbafd778b214fc5df2a64fe14fbfb30ba40e33282eedf0d98b5a613786db88",
- "current": "3dfbafd778b214fc5df2a64fe14fbfb30ba40e33282eedf0d98b5a613786db88"
- },
- "fonts": [
- "./fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.ttf",
- "./fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.svg",
- "./fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.woff",
- "./fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.eot"
- ],
- "glyphs": {
- "activity-stream": {
- "codepoint": 61697,
- "source": "new_icons/activity-stream.svg"
- },
- "google": {
- "codepoint": 61698,
- "source": "new_icons/google.svg"
- },
- "launch": {
- "codepoint": 61699,
- "source": "new_icons/launch.svg"
- },
- "microsoft": {
- "codepoint": 61700,
- "source": "new_icons/microsoft.svg"
- },
- "saml-02": {
- "codepoint": 61701,
- "source": "new_icons/saml-02.svg"
- },
- "user": {
- "codepoint": 61702,
- "source": "new_icons/user.svg"
- }
- },
- "options": {
- "autowidth": false,
- "config": false,
- "css_selector": ".icon-{{glyph}}",
- "debug": false,
- "font_ascent": 448,
- "font_descent": 64,
- "font_design_size": 16,
- "font_em": 512,
- "font_name": "fontcustom",
- "force": false,
- "input": {
- "templates": "new_icons/",
- "vectors": "new_icons/"
- },
- "no_hash": false,
- "output": {
- "css": ".",
- "fonts": ".",
- "preview": "."
- },
- "preprocessor_path": null,
- "quiet": false,
- "templates": [
- "css",
- "preview"
- ]
- },
- "templates": [
- "./fontcustom.css",
- "./fontcustom-preview.html"
- ]
-}
\ No newline at end of file
diff --git a/awx/ui/client/assets/fontcustom/fontcustom-preview.html b/awx/ui/client/assets/fontcustom/fontcustom-preview.html
deleted file mode 100644
index bda47533ba..0000000000
--- a/awx/ui/client/assets/fontcustom/fontcustom-preview.html
+++ /dev/null
@@ -1,293 +0,0 @@
-
-
-
- fontcustom glyphs preview
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Pp Pp Pp Pp Pp Pp Pp Pp Pp Pp
-
-
- 12 14 16 18 21 24 36 48 60 72
-
-
-
-
-
-
-
-
-
- Pp Pp Pp Pp Pp Pp Pp Pp Pp Pp
-
-
- 12 14 16 18 21 24 36 48 60 72
-
-
-
-
-
-
-
-
-
- Pp Pp Pp Pp Pp Pp Pp Pp Pp Pp
-
-
- 12 14 16 18 21 24 36 48 60 72
-
-
-
-
-
-
-
-
-
- Pp Pp Pp Pp Pp Pp Pp Pp Pp Pp
-
-
- 12 14 16 18 21 24 36 48 60 72
-
-
-
-
-
-
-
-
-
- Pp Pp Pp Pp Pp Pp Pp Pp Pp Pp
-
-
- 12 14 16 18 21 24 36 48 60 72
-
-
-
-
-
-
-
-
-
- Pp Pp Pp Pp Pp Pp Pp Pp Pp Pp
-
-
- 12 14 16 18 21 24 36 48 60 72
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/fontcustom.css b/awx/ui/client/assets/fontcustom/fontcustom.css
deleted file mode 100644
index 839abf9c98..0000000000
--- a/awx/ui/client/assets/fontcustom/fontcustom.css
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- Icon Font: fontcustom
-*/
-
-@font-face {
- font-family: "fontcustom";
- src: url("/static/fonts/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.eot");
- src: url("/static/fonts/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.eot?#iefix") format("embedded-opentype"),
- url("/static/fonts/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.woff") format("woff"),
- url("/static/fonts/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.ttf") format("truetype"),
- url("/static/fonts/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.svg#fontcustom") format("svg");
- font-weight: normal;
- font-style: normal;
-}
-
-@media screen and (-webkit-min-device-pixel-ratio:0) {
- @font-face {
- font-family: "fontcustom";
- src: url("/static/fonts/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.svg#fontcustom") format("svg");
- }
-}
-
-[data-icon]:before { content: attr(data-icon); }
-
-[data-icon]:before,
-.icon-activity-stream:before,
-.icon-google:before,
-.icon-launch:before,
-.icon-microsoft:before,
-.icon-saml-02:before,
-.icon-user:before {
- display: inline-block;
- font-family: "fontcustom";
- font-style: normal;
- font-weight: normal;
- font-variant: normal;
- line-height: 1;
- text-decoration: inherit;
- text-rendering: optimizeLegibility;
- text-transform: none;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: antialiased;
- font-smoothing: antialiased;
-}
-
-.icon-activity-stream:before { content: "\f101"; }
-.icon-google:before { content: "\f102"; }
-.icon-launch:before { content: "\f103"; }
-.icon-microsoft:before { content: "\f104"; }
-.icon-saml-02:before { content: "\f105"; }
-.icon-user:before { content: "\f106"; }
diff --git a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.eot b/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.eot
deleted file mode 100644
index 7d890d22c2..0000000000
Binary files a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.eot and /dev/null differ
diff --git a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.svg b/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.svg
deleted file mode 100644
index 20e687b626..0000000000
--- a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.svg
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-Created by FontForge 20120731 at Mon Nov 28 21:58:48 2016
- By Chris Church
-Created by Chris Church with FontForge 2.0 (http://fontforge.sf.net)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.ttf b/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.ttf
deleted file mode 100644
index b5bb62ffce..0000000000
Binary files a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.ttf and /dev/null differ
diff --git a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.woff b/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.woff
deleted file mode 100644
index 8fcaf0235f..0000000000
Binary files a/awx/ui/client/assets/fontcustom/fontcustom_3dfbafd778b214fc5df2a64fe14fbfb3.woff and /dev/null differ
diff --git a/awx/ui/client/assets/fontcustom/new_icons/.fontcustom-manifest.json b/awx/ui/client/assets/fontcustom/new_icons/.fontcustom-manifest.json
deleted file mode 100644
index 3177b52034..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/.fontcustom-manifest.json
+++ /dev/null
@@ -1,78 +0,0 @@
-{
- "checksum": {
- "previous": "d77a9996ed04d45b02f5c06874cd36db7f5daa9833b1a6c36bef7029a767a34f",
- "current": "d77a9996ed04d45b02f5c06874cd36db7f5daa9833b1a6c36bef7029a767a34f"
- },
- "fonts": [
- "..//fontcustom_d77a9996ed04d45b02f5c06874cd36db.ttf",
- "..//fontcustom_d77a9996ed04d45b02f5c06874cd36db.svg",
- "..//fontcustom_d77a9996ed04d45b02f5c06874cd36db.woff",
- "..//fontcustom_d77a9996ed04d45b02f5c06874cd36db.eot"
- ],
- "glyphs": {
- "activity-stream": {
- "codepoint": 61698,
- "source": "./activity-stream.svg"
- },
- "google": {
- "codepoint": 61696,
- "source": "./google.svg"
- },
- "launch": {
- "codepoint": 61699,
- "source": "./launch.svg"
- },
- "launch-circle": {
- "codepoint": 61701,
- "source": "./launch-circle.svg"
- },
- "launch-new": {
- "codepoint": 61703,
- "source": "./launch-new.svg"
- },
- "launch2": {
- "codepoint": 61702,
- "source": "./launch2.svg"
- },
- "saml-02": {
- "codepoint": 61697,
- "source": "./saml-02.svg"
- },
- "user": {
- "codepoint": 61700,
- "source": "./user.svg"
- }
- },
- "options": {
- "autowidth": false,
- "config": false,
- "css_selector": ".icon-{{glyph}}",
- "debug": false,
- "font_ascent": 448,
- "font_descent": 64,
- "font_design_size": 16,
- "font_em": 512,
- "font_name": "fontcustom",
- "force": true,
- "input": {
- "templates": ".",
- "vectors": "."
- },
- "no_hash": false,
- "output": {
- "css": "../",
- "fonts": "../",
- "preview": "../"
- },
- "preprocessor_path": null,
- "quiet": false,
- "templates": [
- "css",
- "preview"
- ]
- },
- "templates": [
- "../fontcustom.css",
- "../fontcustom-preview.html"
- ]
-}
\ No newline at end of file
diff --git a/awx/ui/client/assets/fontcustom/new_icons/activity-stream.svg b/awx/ui/client/assets/fontcustom/new_icons/activity-stream.svg
deleted file mode 100644
index 2915f904da..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/activity-stream.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/new_icons/google.svg b/awx/ui/client/assets/fontcustom/new_icons/google.svg
deleted file mode 100644
index 530a136d6c..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/google.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/new_icons/launch.svg b/awx/ui/client/assets/fontcustom/new_icons/launch.svg
deleted file mode 100644
index 22eec6bab0..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/launch.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/new_icons/microsoft.svg b/awx/ui/client/assets/fontcustom/new_icons/microsoft.svg
deleted file mode 100644
index 934eb2b4b9..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/microsoft.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/new_icons/saml-02.svg b/awx/ui/client/assets/fontcustom/new_icons/saml-02.svg
deleted file mode 100644
index 1f33a6c8fc..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/saml-02.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
diff --git a/awx/ui/client/assets/fontcustom/new_icons/user.svg b/awx/ui/client/assets/fontcustom/new_icons/user.svg
deleted file mode 100644
index 7b38db83e6..0000000000
--- a/awx/ui/client/assets/fontcustom/new_icons/user.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/awx/ui/client/assets/help/add_exception.png b/awx/ui/client/assets/help/add_exception.png
deleted file mode 100644
index 4ba7bac86f..0000000000
Binary files a/awx/ui/client/assets/help/add_exception.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/confirm_exception.png b/awx/ui/client/assets/help/confirm_exception.png
deleted file mode 100644
index 93b1fef7fe..0000000000
Binary files a/awx/ui/client/assets/help/confirm_exception.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups001.png b/awx/ui/client/assets/help/groups001.png
deleted file mode 100644
index 6a1c6f63aa..0000000000
Binary files a/awx/ui/client/assets/help/groups001.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups002.png b/awx/ui/client/assets/help/groups002.png
deleted file mode 100644
index 7476db1903..0000000000
Binary files a/awx/ui/client/assets/help/groups002.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups003.png b/awx/ui/client/assets/help/groups003.png
deleted file mode 100644
index c29bc66d37..0000000000
Binary files a/awx/ui/client/assets/help/groups003.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups004.png b/awx/ui/client/assets/help/groups004.png
deleted file mode 100644
index bbadb619b6..0000000000
Binary files a/awx/ui/client/assets/help/groups004.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups005.png b/awx/ui/client/assets/help/groups005.png
deleted file mode 100644
index 805881f84b..0000000000
Binary files a/awx/ui/client/assets/help/groups005.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups006.png b/awx/ui/client/assets/help/groups006.png
deleted file mode 100644
index b4dcac65d5..0000000000
Binary files a/awx/ui/client/assets/help/groups006.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups007.png b/awx/ui/client/assets/help/groups007.png
deleted file mode 100644
index 3fbc3f799d..0000000000
Binary files a/awx/ui/client/assets/help/groups007.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups008.png b/awx/ui/client/assets/help/groups008.png
deleted file mode 100644
index fb7fef8c24..0000000000
Binary files a/awx/ui/client/assets/help/groups008.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups009.png b/awx/ui/client/assets/help/groups009.png
deleted file mode 100644
index bbf962ac33..0000000000
Binary files a/awx/ui/client/assets/help/groups009.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/groups010.png b/awx/ui/client/assets/help/groups010.png
deleted file mode 100644
index 3ff39ef2da..0000000000
Binary files a/awx/ui/client/assets/help/groups010.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/refresh_firefox.png b/awx/ui/client/assets/help/refresh_firefox.png
deleted file mode 100644
index 47c4016165..0000000000
Binary files a/awx/ui/client/assets/help/refresh_firefox.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/socket_indicator.png b/awx/ui/client/assets/help/socket_indicator.png
deleted file mode 100644
index eb37a6bf8c..0000000000
Binary files a/awx/ui/client/assets/help/socket_indicator.png and /dev/null differ
diff --git a/awx/ui/client/assets/help/understand_the_risk.png b/awx/ui/client/assets/help/understand_the_risk.png
deleted file mode 100644
index d668b2b99e..0000000000
Binary files a/awx/ui/client/assets/help/understand_the_risk.png and /dev/null differ
diff --git a/awx/ui/client/assets/i_severity_critical.svg b/awx/ui/client/assets/i_severity_critical.svg
deleted file mode 100644
index 996df323a1..0000000000
--- a/awx/ui/client/assets/i_severity_critical.svg
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-image/svg+xml
diff --git a/awx/ui/client/assets/i_severity_high.svg b/awx/ui/client/assets/i_severity_high.svg
deleted file mode 100644
index 7bd2ba55c8..0000000000
--- a/awx/ui/client/assets/i_severity_high.svg
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-image/svg+xml
diff --git a/awx/ui/client/assets/i_severity_low.svg b/awx/ui/client/assets/i_severity_low.svg
deleted file mode 100644
index 539664987d..0000000000
--- a/awx/ui/client/assets/i_severity_low.svg
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-image/svg+xml
diff --git a/awx/ui/client/assets/i_severity_med.svg b/awx/ui/client/assets/i_severity_med.svg
deleted file mode 100644
index 33e3c19c30..0000000000
--- a/awx/ui/client/assets/i_severity_med.svg
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-image/svg+xml
diff --git a/awx/ui/client/assets/merriweather-bold-webfont.woff b/awx/ui/client/assets/merriweather-bold-webfont.woff
deleted file mode 100644
index a1b95b5c1f..0000000000
Binary files a/awx/ui/client/assets/merriweather-bold-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-bold-webfont.woff2 b/awx/ui/client/assets/merriweather-bold-webfont.woff2
deleted file mode 100644
index d9bf97ef75..0000000000
Binary files a/awx/ui/client/assets/merriweather-bold-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-bolditalic-webfont.woff b/awx/ui/client/assets/merriweather-bolditalic-webfont.woff
deleted file mode 100644
index 1696f92a04..0000000000
Binary files a/awx/ui/client/assets/merriweather-bolditalic-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-bolditalic-webfont.woff2 b/awx/ui/client/assets/merriweather-bolditalic-webfont.woff2
deleted file mode 100644
index 1f7a7ae204..0000000000
Binary files a/awx/ui/client/assets/merriweather-bolditalic-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-heavyitalic-webfont.woff b/awx/ui/client/assets/merriweather-heavyitalic-webfont.woff
deleted file mode 100644
index 6b3baeb97b..0000000000
Binary files a/awx/ui/client/assets/merriweather-heavyitalic-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-heavyitalic-webfont.woff2 b/awx/ui/client/assets/merriweather-heavyitalic-webfont.woff2
deleted file mode 100644
index cbce14b28a..0000000000
Binary files a/awx/ui/client/assets/merriweather-heavyitalic-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-italic-webfont.woff b/awx/ui/client/assets/merriweather-italic-webfont.woff
deleted file mode 100644
index 987146da8b..0000000000
Binary files a/awx/ui/client/assets/merriweather-italic-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-italic-webfont.woff2 b/awx/ui/client/assets/merriweather-italic-webfont.woff2
deleted file mode 100644
index 6a17eaa263..0000000000
Binary files a/awx/ui/client/assets/merriweather-italic-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-lightitalic-webfont.woff b/awx/ui/client/assets/merriweather-lightitalic-webfont.woff
deleted file mode 100644
index 75146e6523..0000000000
Binary files a/awx/ui/client/assets/merriweather-lightitalic-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-lightitalic-webfont.woff2 b/awx/ui/client/assets/merriweather-lightitalic-webfont.woff2
deleted file mode 100644
index 5f42282de1..0000000000
Binary files a/awx/ui/client/assets/merriweather-lightitalic-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-regular-webfont.woff b/awx/ui/client/assets/merriweather-regular-webfont.woff
deleted file mode 100644
index 4ca3dc6672..0000000000
Binary files a/awx/ui/client/assets/merriweather-regular-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather-regular-webfont.woff2 b/awx/ui/client/assets/merriweather-regular-webfont.woff2
deleted file mode 100644
index 92a537d069..0000000000
Binary files a/awx/ui/client/assets/merriweather-regular-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather_light-webfont.woff b/awx/ui/client/assets/merriweather_light-webfont.woff
deleted file mode 100644
index c171be2053..0000000000
Binary files a/awx/ui/client/assets/merriweather_light-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather_light-webfont.woff2 b/awx/ui/client/assets/merriweather_light-webfont.woff2
deleted file mode 100644
index 1a200b5582..0000000000
Binary files a/awx/ui/client/assets/merriweather_light-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather_ultrabold-webfont.woff b/awx/ui/client/assets/merriweather_ultrabold-webfont.woff
deleted file mode 100644
index 7a2b768928..0000000000
Binary files a/awx/ui/client/assets/merriweather_ultrabold-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/merriweather_ultrabold-webfont.woff2 b/awx/ui/client/assets/merriweather_ultrabold-webfont.woff2
deleted file mode 100644
index c2008e7b7f..0000000000
Binary files a/awx/ui/client/assets/merriweather_ultrabold-webfont.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/ubuntu-r-webfont.woff b/awx/ui/client/assets/ubuntu-r-webfont.woff
deleted file mode 100644
index 96cc74f9b2..0000000000
Binary files a/awx/ui/client/assets/ubuntu-r-webfont.woff and /dev/null differ
diff --git a/awx/ui/client/assets/ubuntu.woff2 b/awx/ui/client/assets/ubuntu.woff2
deleted file mode 100644
index 2701e3f6cc..0000000000
Binary files a/awx/ui/client/assets/ubuntu.woff2 and /dev/null differ
diff --git a/awx/ui/client/assets/variables.less b/awx/ui/client/assets/variables.less
deleted file mode 100644
index 3d8f8af957..0000000000
--- a/awx/ui/client/assets/variables.less
+++ /dev/null
@@ -1,21 +0,0 @@
-// Default styles for AWX branding
-
-// Login modal icon
-@login-max-width: 150px;
-@login-margin: -35px 0px -10px -20px;
-
-// Main nav bar logo
-@main-menu-width: 100px;
-@main-menu-margin: 0px 0px 0px 0px;
-@main-menu-max-width: initial;
-@main-menu-max-height: initial;
-@main-menu-height: initial;
-@main-menu-margin-top-breakpoint: -20px;
-
-
-// About modal logo
-@about-modal-float: left;
-@about-modal-width: 150px;
-@about-modal-padding-top: initial;
-@about-modal-margin-top: -40px;
-@about-modal-margin-left: -20px;
diff --git a/awx/ui/client/features/_index.less b/awx/ui/client/features/_index.less
deleted file mode 100644
index 2769b29de7..0000000000
--- a/awx/ui/client/features/_index.less
+++ /dev/null
@@ -1,17 +0,0 @@
-@import 'portalMode/_index';
-@import 'output/_index';
-@import 'credentials/_index';
-
-/** @define Popup Modal after create new token and applicaiton and save form */
-.PopupModal {
- display: flex;
-}
-
-.PopupModal-label {
- font-weight: bold;
- width: 130px;
-}
-
-.PopupModal-value {
- width: 70%;
-}
\ No newline at end of file
diff --git a/awx/ui/client/features/applications/add-applications.controller.js b/awx/ui/client/features/applications/add-applications.controller.js
deleted file mode 100644
index d19c853009..0000000000
--- a/awx/ui/client/features/applications/add-applications.controller.js
+++ /dev/null
@@ -1,118 +0,0 @@
-function AddApplicationsController (models, $state, strings, $scope, Alert, $filter, i18n) {
- const vm = this || {};
-
- const { application, me, organization } = models;
- const omit = [
- 'client_id',
- 'client_secret',
- 'created',
- 'modified',
- 'related',
- 'skip_authorization',
- 'summary_fields',
- 'type',
- 'url',
- 'user'
- ];
-
- vm.mode = 'add';
- vm.strings = strings;
- vm.panelTitle = strings.get('add.PANEL_TITLE');
-
- vm.tab = {
- details: { _active: true },
- users: { _disabled: true }
- };
-
- vm.form = application.createFormSchema('post', { omit });
-
- vm.form.organization = {
- type: 'field',
- label: i18n._('Organization'),
- id: 'organization'
- };
- vm.form.description = {
- type: 'String',
- label: i18n._('Description'),
- id: 'description'
- };
-
- vm.form.disabled = !application.isCreatable();
-
- vm.form.organization._resource = 'organization';
- vm.form.organization._route = 'applications.add.organization';
- vm.form.organization._model = organization;
- vm.form.organization._placeholder = strings.get('inputs.ORGANIZATION_PLACEHOLDER');
-
- vm.form.name.required = true;
- vm.form.organization.required = true;
-
- delete vm.form.name.help_text;
-
- vm.form.save = data => {
- const hiddenData = {
- user: me.get('id')
- };
-
- const payload = _.merge(data, hiddenData);
-
- return application.request('post', { data: payload });
- };
-
- vm.form.onSaveSuccess = res => {
- if (res.data && res.data.client_id) {
- const name = res.data.name ?
- `` : '';
- const clientId = res.data.client_id ?
- `` : '';
- const clientSecret = res.data.client_secret ?
- `` : '';
-
- Alert(strings.get('add.MODAL_HEADER'), `
- ${name}
- ${clientId}
- ${clientSecret}
- `, null, null, null, null, null, true);
- }
- $state.go('applications.edit', { application_id: res.data.id }, { reload: true });
- };
-
- $scope.$watch('organization', () => {
- if ($scope.organization) {
- vm.form.organization._idFromModal = $scope.organization;
- }
- });
-}
-
-AddApplicationsController.$inject = [
- 'resolvedModels',
- '$state',
- 'ApplicationsStrings',
- '$scope',
- 'Alert',
- '$filter',
- 'i18n'
-];
-
-export default AddApplicationsController;
diff --git a/awx/ui/client/features/applications/add-edit-applications.view.html b/awx/ui/client/features/applications/add-edit-applications.view.html
deleted file mode 100644
index 8593e537dc..0000000000
--- a/awx/ui/client/features/applications/add-edit-applications.view.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.USERS') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/applications/applications.strings.js b/awx/ui/client/features/applications/applications.strings.js
deleted file mode 100644
index 27a05fb0ed..0000000000
--- a/awx/ui/client/features/applications/applications.strings.js
+++ /dev/null
@@ -1,42 +0,0 @@
-function ApplicationsStrings (BaseString) {
- BaseString.call(this, 'applications');
-
- const { t } = this;
- const ns = this.applications;
-
- ns.state = {
- LIST_BREADCRUMB_LABEL: t.s('APPLICATIONS'),
- ADD_BREADCRUMB_LABEL: t.s('CREATE APPLICATION'),
- EDIT_BREADCRUMB_LABEL: t.s('EDIT APPLICATION'),
- USER_LIST_BREADCRUMB_LABEL: t.s('TOKENS')
- };
-
- ns.tab = {
- DETAILS: t.s('Details'),
- USERS: t.s('Tokens')
- };
-
- ns.add = {
- PANEL_TITLE: t.s('NEW APPLICATION'),
- CLIENT_ID_LABEL: t.s('CLIENT ID'),
- CLIENT_SECRECT_LABEL: t.s('CLIENT SECRET'),
- MODAL_HEADER: t.s('APPLICATION INFORMATION'),
- NAME_LABEL: t.s('NAME'),
- };
-
- ns.list = {
- PANEL_TITLE: t.s('APPLICATIONS'),
- ROW_ITEM_LABEL_EXPIRED: t.s('EXPIRATION'),
- ROW_ITEM_LABEL_ORGANIZATION: t.s('ORG'),
- ROW_ITEM_LABEL_MODIFIED: t.s('LAST MODIFIED'),
- ADD: t.s('Create a new Application')
- };
-
- ns.inputs = {
- ORGANIZATION_PLACEHOLDER: t.s('SELECT AN ORGANIZATION')
- };
-}
-
-ApplicationsStrings.$inject = ['BaseStringService'];
-
-export default ApplicationsStrings;
diff --git a/awx/ui/client/features/applications/edit-applications.controller.js b/awx/ui/client/features/applications/edit-applications.controller.js
deleted file mode 100644
index cf53a1abc3..0000000000
--- a/awx/ui/client/features/applications/edit-applications.controller.js
+++ /dev/null
@@ -1,104 +0,0 @@
-function EditApplicationsController (models, $state, strings, $scope) {
- const vm = this || {};
-
- const { me, application, organization } = models;
-
- const omit = [
- 'client_id',
- 'client_secret',
- 'created',
- 'modified',
- 'related',
- 'skip_authorization',
- 'summary_fields',
- 'type',
- 'url',
- 'user'
- ];
- const isEditable = application.isEditable();
-
- vm.mode = 'edit';
- vm.strings = strings;
- vm.panelTitle = application.get('name');
-
- vm.tab = {
- details: {
- _active: true,
- _go: 'applications.edit',
- _params: { application_id: application.get('id') }
- },
- users: {
- _go: 'applications.edit.users',
- _params: { application_id: application.get('id') }
- }
- };
-
- $scope.$watch('$state.current.name', (value) => {
- if (/applications.edit.users/.test(value)) {
- vm.tab.details._active = false;
- vm.tab.users._active = true;
- } else {
- vm.tab.details._active = true;
- vm.tab.users._active = false;
- }
- });
-
- $scope.$watch('organization', () => {
- if ($scope.organization) {
- vm.form.organization._idFromModal = $scope.organization;
- }
- });
-
- if (isEditable) {
- vm.form = application.createFormSchema('put', { omit });
- } else {
- vm.form = application.createFormSchema({ omit });
- vm.form.disabled = !isEditable;
- }
-
- vm.form.disabled = !isEditable;
-
- vm.form.name.required = true;
-
- const isOrgAdmin = _.some(me.get('related.admin_of_organizations.results'), (org) => org.id === organization.get('id'));
- const isSuperuser = me.get('is_superuser');
- const isCurrentAuthor = Boolean(application.get('summary_fields.created_by.id') === me.get('id'));
- vm.form.organization._disabled = true;
-
- if (isSuperuser || isOrgAdmin || (application.get('organization') === null && isCurrentAuthor)) {
- vm.form.organization._disabled = false;
- }
-
- vm.form.organization._resource = 'organization';
- vm.form.organization._model = organization;
- vm.form.organization._route = 'applications.edit.organization';
- vm.form.organization._value = application.get('summary_fields.organization.id');
- vm.form.organization._displayValue = application.get('summary_fields.organization.name');
- vm.form.organization._placeholder = strings.get('inputs.ORGANIZATION_PLACEHOLDER');
- vm.form.organization.required = true;
-
- delete vm.form.name.help_text;
-
- vm.form.save = data => {
- const hiddenData = {
- user: me.get('id')
- };
-
- const payload = _.merge(data, hiddenData);
-
- return application.request('put', { data: payload });
- };
-
- vm.form.onSaveSuccess = () => {
- $state.go('applications.edit', { application_id: application.get('id') }, { reload: true });
- };
-}
-
-EditApplicationsController.$inject = [
- 'resolvedModels',
- '$state',
- 'ApplicationsStrings',
- '$scope'
-];
-
-export default EditApplicationsController;
diff --git a/awx/ui/client/features/applications/index.js b/awx/ui/client/features/applications/index.js
deleted file mode 100644
index 9c12d2a3a2..0000000000
--- a/awx/ui/client/features/applications/index.js
+++ /dev/null
@@ -1,347 +0,0 @@
-
-import AddController from './add-applications.controller';
-import EditController from './edit-applications.controller';
-import ListController from './list-applications.controller';
-import UserListController from './list-applications-users.controller';
-import ApplicationsStrings from './applications.strings';
-
-const MODULE_NAME = 'at.features.applications';
-
-const addEditTemplate = require('~features/applications/add-edit-applications.view.html');
-const listTemplate = require('~features/applications/list-applications.view.html');
-const indexTemplate = require('~features/applications/index.view.html');
-const userListTemplate = require('~features/applications/list-applications-users.view.html');
-
-function ApplicationsDetailResolve (
- $q,
- $stateParams,
- Me,
- Application,
- Organization,
- ProcessErrors,
- strings
-) {
- const id = $stateParams.application_id;
-
- const promises = {
- me: new Me('get').then((me) => me.extend('get', 'admin_of_organizations'))
- };
-
- if (!id) {
- promises.application = new Application('options');
- promises.organization = new Organization();
-
- return $q.all(promises);
- }
-
- promises.application = new Application(['get', 'options'], [id, id]);
-
- return $q.all(promises)
- .then(models => {
- const orgId = models.application.get('organization');
-
- const dependents = {
- organization: new Organization('get', orgId)
- };
-
- return $q.all(dependents)
- .then(related => {
- models.organization = related.organization;
-
- return models;
- });
- })
- .catch(({ data, status, config }) => {
- ProcessErrors(null, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- return $q.reject();
- });
-}
-
-ApplicationsDetailResolve.$inject = [
- '$q',
- '$stateParams',
- 'MeModel',
- 'ApplicationModel',
- 'OrganizationModel',
- 'ProcessErrors',
- 'ApplicationsStrings'
-];
-
-function ApplicationsRun ($stateExtender, strings) {
- $stateExtender.addState({
- name: 'applications',
- route: '/applications',
- ncyBreadcrumb: {
- label: strings.get('state.LIST_BREADCRUMB_LABEL')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'o_auth2_application'
- },
- views: {
- '@': {
- templateUrl: indexTemplate,
- },
- 'list@applications': {
- templateUrl: listTemplate,
- controller: ListController,
- controllerAs: 'vm'
- }
- },
- searchPrefix: 'application',
- params: {
- application_search: {
- value: {
- page_size: 10,
- order_by: 'name'
- }
- }
- },
- resolve: {
- resolvedModels: [
- 'ApplicationModel',
- (Application) => {
- const app = new Application(['options']);
- return app;
- }
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.application_search;
- const searchPath = GetBasePath('applications');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => {
- Wait('stop');
- });
- }
- ],
- }
- });
-
- $stateExtender.addState({
- name: 'applications.add',
- route: '/add',
- ncyBreadcrumb: {
- label: strings.get('state.ADD_BREADCRUMB_LABEL')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'o_auth2_application'
- },
- views: {
- 'add@applications': {
- templateUrl: addEditTemplate,
- controller: AddController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: ApplicationsDetailResolve
- }
- });
-
- $stateExtender.addState({
- name: 'applications.edit',
- route: '/:application_id',
- ncyBreadcrumb: {
- label: strings.get('state.EDIT_BREADCRUMB_LABEL')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'o_auth2_application',
- activityStreamId: 'application_id'
- },
- views: {
- 'edit@applications': {
- templateUrl: addEditTemplate,
- controller: EditController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: ApplicationsDetailResolve
- }
- });
-
- $stateExtender.addState({
- name: 'applications.add.organization',
- url: '/organization?selected',
- searchPrefix: 'organization',
- params: {
- organization_search: {
- value: {
- page_size: 5,
- order_by: 'name',
- role_level: 'admin_role'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'organizations',
- formChildState: true
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'organization@applications.add': {
- templateProvider: (ListDefinition, generateList) => {
- const html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
-
- return `${html} `;
- }
- }
- },
- resolve: {
- ListDefinition: ['OrganizationList', list => list],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => qs.search(
- GetBasePath('organizations'),
- $stateParams[`${list.iterator}_search`]
- )
- ]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- });
-
- $stateExtender.addState({
- name: 'applications.edit.organization',
- url: '/organization?selected',
- searchPrefix: 'organization',
- params: {
- organization_search: {
- value: {
- page_size: 5,
- order_by: 'name',
- role_level: 'admin_role'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'organizations',
- formChildState: true
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'organization@applications.edit': {
- templateProvider: (ListDefinition, generateList) => {
- const html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
-
- return `${html} `;
- }
- }
- },
- resolve: {
- ListDefinition: ['OrganizationList', list => list],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => qs.search(
- GetBasePath('organizations'),
- $stateParams[`${list.iterator}_search`]
- )
- ]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- });
-
- $stateExtender.addState({
- name: 'applications.edit.users',
- route: '/users',
- ncyBreadcrumb: {
- label: strings.get('state.USER_LIST_BREADCRUMB_LABEL'),
- parent: 'applications.edit'
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'o_auth2_application'
- },
- views: {
- 'userList@applications.edit': {
- templateUrl: userListTemplate,
- controller: UserListController,
- controllerAs: 'vm'
- }
- },
- params: {
- user_search: {
- value: {
- order_by: 'user__username',
- page_size: 10
- },
- dynamic: true
- }
- },
- searchPrefix: 'user',
- resolve: {
- resolvedModels: [
- 'ApplicationModel',
- (Application) => {
- const app = new Application(['options']);
- return app;
- }
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.user_search;
- const searchPath = `${GetBasePath('applications')}${$stateParams.application_id}/tokens`;
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => {
- Wait('stop');
- });
- }
- ],
- }
- });
-}
-
-ApplicationsRun.$inject = [
- '$stateExtender',
- 'ApplicationsStrings'
-];
-
-angular
- .module(MODULE_NAME, [])
- .service('ApplicationsStrings', ApplicationsStrings)
- .run(ApplicationsRun);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/applications/index.view.html b/awx/ui/client/features/applications/index.view.html
deleted file mode 100644
index b4135fb791..0000000000
--- a/awx/ui/client/features/applications/index.view.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/awx/ui/client/features/applications/list-applications-users.controller.js b/awx/ui/client/features/applications/list-applications-users.controller.js
deleted file mode 100644
index bb7dc70edd..0000000000
--- a/awx/ui/client/features/applications/list-applications-users.controller.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/** ***********************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- ************************************************ */
-function ListApplicationsUsersController (
- $filter,
- $scope,
- Dataset,
- strings,
- $state,
- GetBasePath
-) {
- const vm = this || {};
- vm.strings = strings;
-
- // smart-search
- const name = 'users';
- const iterator = 'user';
- let paginateQuerySet = {};
-
- vm.user_dataset = Dataset.data;
- vm.users = Dataset.data.results;
- vm.list = { iterator, name, basePath: 'applications' };
- vm.basePath = `${GetBasePath('applications')}${$state.params.application_id}/tokens`;
-
- $scope.$on('updateDataset', (e, dataset, queryset) => {
- vm.user_dataset = dataset;
- vm.users = dataset.results;
- paginateQuerySet = queryset;
- });
-
- $scope.$watchCollection('$state.params', () => {
- setToolbarSort();
- });
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.USERNAME_ASCENDING')}`,
- value: 'user__username'
- };
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.USERNAME_DESCENDING')}`, value: '-user__username' },
- { label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
- { label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
- { label: `${strings.get('sort.EXPIRES_ASCENDING')}`, value: 'expires' },
- { label: `${strings.get('sort.EXPIRES_DESCENDING')}`, value: '-expires' }
- ];
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'user_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
- const queryParams = Object.assign(
- {},
- $state.params.user_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update URL with params
- $state.go('.', {
- user_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- vm.getLastUsed = user => {
- const lastUsed = _.get(user, 'last_used');
-
- if (!lastUsed) {
- return undefined;
- }
-
- let html = $filter('longDate')(lastUsed);
-
- const { username, id } = _.get(user, 'summary_fields.last_used', {});
-
- if (username && id) {
- html += ` by ${$filter('sanitize')(username)} `;
- }
-
- return html;
- };
-}
-
-ListApplicationsUsersController.$inject = [
- '$filter',
- '$scope',
- 'Dataset',
- 'ApplicationsStrings',
- '$state',
- 'GetBasePath'
-];
-
-export default ListApplicationsUsersController;
diff --git a/awx/ui/client/features/applications/list-applications-users.view.html b/awx/ui/client/features/applications/list-applications-users.view.html
deleted file mode 100644
index 2ad4b85ce4..0000000000
--- a/awx/ui/client/features/applications/list-applications-users.view.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/applications/list-applications.controller.js b/awx/ui/client/features/applications/list-applications.controller.js
deleted file mode 100644
index 5ac065163c..0000000000
--- a/awx/ui/client/features/applications/list-applications.controller.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/** ***********************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- ************************************************ */
-function ListApplicationsController (
- $filter,
- $scope,
- $state,
- Dataset,
- ProcessErrors,
- Prompt,
- resolvedModels,
- strings,
- Wait
-) {
- const vm = this || {};
- const application = resolvedModels;
- let paginateQuerySet = {};
-
- vm.strings = strings;
- vm.activeId = $state.params.application_id;
-
- $scope.canAdd = application.options('actions.POST');
-
- // smart-search
- const name = 'applications';
- const iterator = 'application';
- const key = 'application_dataset';
-
- $scope.list = { iterator, name, basePath: 'applications' };
- $scope.collection = { iterator };
- $scope[key] = Dataset.data;
- vm.applicationsCount = Dataset.data.count;
- $scope[name] = Dataset.data.results;
-
- $scope.$on('updateDataset', (e, dataset, queryset) => {
- $scope[key] = dataset;
- $scope[name] = dataset.results;
- vm.applicationsCount = dataset.count;
- // Remove paginateQuerySet once the page and page_size params
- // are represented in the url.
- paginateQuerySet = queryset;
- });
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'name'
- };
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
- { label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
- { label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' }
- ];
-
- vm.toolbarSortValue = toolbarSortDefault;
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'application_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- $scope.$watch('$state.params', () => {
- setToolbarSort();
- }, true);
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.application_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update URL with params
- $state.go('.', {
- application_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- vm.getModified = app => {
- const modified = _.get(app, 'modified');
-
- if (!modified) {
- return undefined;
- }
-
- let html = $filter('longDate')(modified);
-
- const { username, id } = _.get(app, 'summary_fields.modified_by', {});
-
- if (username && id) {
- html += ` by ${$filter('sanitize')(username)} `;
- }
-
- return html;
- };
-
- vm.deleteApplication = (app) => {
- const action = () => {
- $('#prompt-modal').modal('hide');
- Wait('start');
- application.request('delete', app.id)
- .then(() => {
- let reloadListStateParams = null;
-
- if ($scope.applications.length === 1 && $state.params.application_search &&
- !_.isEmpty($state.params.application_search.page) &&
- $state.params.application_search.page !== '1') {
- const page = `${(parseInt(reloadListStateParams
- .application_search.page, 10) - 1)}`;
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.application_search.page = page;
- }
-
- if (parseInt($state.params.application_id, 10) === app.id) {
- $state.go('applications', reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, { reload: true });
- }
- })
- .catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${application.path}${app.id}`, status })
- });
- })
- .finally(() => {
- Wait('stop');
- });
- };
-
- const deleteModalBody = `${strings.get('deleteResource.CONFIRM', 'application')}
`;
-
- Prompt({
- hdr: strings.get('deleteResource.HEADER'),
- resourceName: $filter('sanitize')(app.name),
- body: deleteModalBody,
- action,
- actionText: strings.get('DELETE')
- });
- };
-}
-
-ListApplicationsController.$inject = [
- '$filter',
- '$scope',
- '$state',
- 'Dataset',
- 'ProcessErrors',
- 'Prompt',
- 'resolvedModels',
- 'ApplicationsStrings',
- 'Wait'
-];
-
-export default ListApplicationsController;
diff --git a/awx/ui/client/features/applications/list-applications.view.html b/awx/ui/client/features/applications/list-applications.view.html
deleted file mode 100644
index be08782f53..0000000000
--- a/awx/ui/client/features/applications/list-applications.view.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/credentials/_index.less b/awx/ui/client/features/credentials/_index.less
deleted file mode 100644
index f968043d3c..0000000000
--- a/awx/ui/client/features/credentials/_index.less
+++ /dev/null
@@ -1,20 +0,0 @@
-.InputSourceLookup-selectedItem {
- display: flex;
- flex: 0 0 100%;
- align-items: center;
- min-height: 50px;
- margin-top: 16px;
- border-radius: 5px;
- background-color: @default-no-items-bord;
- border: 1px solid @default-border;
-}
-
-.InputSourceLookup-selectedItemLabel {
- color: @default-interface-txt;
- text-transform: uppercase;
- margin: 0 @at-space-2x;
-}
-
-.InputSourceLookup-selectedItemText {
- font-style: italic;
-}
diff --git a/awx/ui/client/features/credentials/add-edit-credentials.controller.js b/awx/ui/client/features/credentials/add-edit-credentials.controller.js
deleted file mode 100644
index 57c8eed1dd..0000000000
--- a/awx/ui/client/features/credentials/add-edit-credentials.controller.js
+++ /dev/null
@@ -1,666 +0,0 @@
-/* eslint camelcase: 0 */
-/* eslint arrow-body-style: 0 */
-function AddEditCredentialsController (
- models,
- $state,
- $scope,
- strings,
- componentsStrings,
- ConfigService,
- ngToast,
- Wait,
- $filter,
- CredentialType,
- GetBasePath,
- Rest,
-) {
- const vm = this || {};
- const {
- me,
- credential,
- credentialType,
- organization,
- isOrgEditableByUser,
- sourceCredentials,
- } = models;
-
- const omit = ['user', 'team', 'inputs'];
- const isEditable = credential.isEditable();
- const isExternal = credentialType.get('kind') === 'external';
- const mode = $state.current.name.startsWith('credentials.add') ? 'add' : 'edit';
-
- vm.mode = mode;
- vm.strings = strings;
-
- if (mode === 'edit') {
- vm.panelTitle = credential.get('name');
- vm.tab = {
- details: {
- _active: true,
- _go: 'credentials.edit',
- _params: { credential_id: credential.get('id') }
- },
- permissions: {
- _go: 'credentials.edit.permissions',
- _params: { credential_id: credential.get('id') }
- }
- };
-
- if (isEditable) {
- vm.form = credential.createFormSchema('put', { omit });
- } else {
- vm.form = credential.createFormSchema({ omit });
- vm.form.disabled = !isEditable;
- }
-
- vm.form._organization._disabled = !isOrgEditableByUser;
- // Only exists for permissions compatibility
- $scope.credential_obj = credential.get();
-
- // Custom credentials can have input fields named 'name', 'organization',
- // 'description', etc. Underscore these variables to make collisions
- // less likely to occur.
- vm.form._organization._resource = 'organization';
- vm.form._organization._model = organization;
- vm.form._organization._route = 'credentials.edit.organization';
- vm.form._organization._value = credential.get('summary_fields.organization.id');
- vm.form._organization._displayValue = credential.get('summary_fields.organization.name');
- vm.form._organization._placeholder = strings.get('inputs.ORGANIZATION_PLACEHOLDER');
-
- vm.form.credential_type._resource = 'credential_type';
- vm.form.credential_type._model = credentialType;
- vm.form.credential_type._route = 'credentials.edit.credentialType';
- vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER');
- vm.form.credential_type._value = credentialType.get('id');
- vm.form.credential_type._displayValue = credentialType.get('name');
- vm.isTestable = (isEditable && credentialType.get('kind') === 'external');
-
- if (credential.get('related.input_sources.results').length > 0) {
- vm.form.credential_type._disabled = true;
- }
-
- $scope.$watch('$state.current.name', (value) => {
- if (/credentials.edit($|\.organization$|\.credentialType$)/.test(value)) {
- vm.tab.details._active = true;
- vm.tab.permissions._active = false;
- } else {
- vm.tab.permissions._active = true;
- vm.tab.details._active = false;
- }
- });
- } else if (mode === 'add') {
- vm.panelTitle = strings.get('add.PANEL_TITLE');
- vm.tab = {
- details: { _active: true },
- permissions: { _disabled: true }
- };
- vm.form = credential.createFormSchema('post', {
- omit: ['user', 'team', 'inputs']
- });
-
- vm.form._formName = 'credential';
- vm.form.disabled = !credential.isCreatable();
-
- vm.form._organization._resource = 'organization';
- vm.form._organization._route = 'credentials.add.organization';
- vm.form._organization._model = organization;
- vm.form._organization._placeholder = strings.get('inputs.ORGANIZATION_PLACEHOLDER');
-
- vm.form.credential_type._resource = 'credential_type';
- vm.form.credential_type._route = 'credentials.add.credentialType';
- vm.form.credential_type._model = credentialType;
- vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER');
- vm.isTestable = credentialType.get('kind') === 'external';
- }
-
- $scope.$watch('organization', () => {
- if ($scope.organization) {
- vm.form._organization._idFromModal = $scope.organization;
- }
- });
-
- $scope.$watch('credential_type', () => {
- if ($scope.credential_type) {
- vm.form.credential_type._idFromModal = $scope.credential_type;
- }
- });
-
- const gceFileInputSchema = {
- id: 'gce_service_account_key',
- type: 'file',
- label: strings.get('inputs.GCE_FILE_INPUT_LABEL'),
- help_text: strings.get('inputs.GCE_FILE_INPUT_HELP_TEXT'),
- };
-
- let gceFileInputPreEditValues;
-
- vm.form.inputs = {
- _get ({ getSubmitData, check }) {
- const apiConfig = ConfigService.get();
-
- credentialType.mergeInputProperties();
- const fields = credential.assignInputGroupValues(
- apiConfig,
- credentialType,
- sourceCredentials
- );
-
- if (credentialType.get('name') === 'Google Compute Engine') {
- fields.splice(2, 0, gceFileInputSchema);
- $scope.$watch(`vm.form.${gceFileInputSchema.id}._value`, gceOnFileInputChanged);
- if (mode === 'edit') {
- $scope.$watch('vm.form.ssh_key_data._isBeingReplaced', gceOnReplaceKeyChanged);
- }
- }
-
- vm.inputSources.initialItems = credential.get('related.input_sources.results');
- vm.inputSources.items = [];
- vm.inputSources.changedInputFields = [];
- if (credential.get('credential_type') === credentialType.get('id')) {
- vm.inputSources.items = credential.get('related.input_sources.results');
- }
-
- if (mode === 'add') {
- vm.isTestable = (models.me.get('is_superuser') && credentialType.get('kind') === 'external');
- } else {
- vm.isTestable = (isEditable && credentialType.get('kind') === 'external');
- }
-
- vm.getSubmitData = getSubmitData;
- vm.checkForm = check;
-
- return fields;
- },
- _onRemoveTag ({ id }) {
- vm.onInputSourceClear(id);
- },
- _onInputLookup ({ id }) {
- vm.onInputSourceOpen(id);
- },
- _source: vm.form.credential_type,
- _reference: 'vm.form.inputs',
- _key: 'inputs',
- border: true,
- title: true,
- };
-
- vm.externalTest = {
- form: {
- inputs: {
- _get: () => vm.externalTest.metadataInputs,
- _reference: 'vm.form.inputs',
- _key: 'inputs',
- _source: { _value: {} },
- },
- },
- metadataInputs: null,
- };
- vm.inputSources = {
- tabs: {
- credential: {
- _active: true,
- _disabled: false,
- },
- metadata: {
- _active: false,
- _disabled: false,
- }
- },
- form: {
- inputs: {
- _get: () => vm.inputSources.metadataInputs,
- _reference: 'vm.form.inputs',
- _key: 'inputs',
- _source: { _value: {} },
- },
- },
- field: null,
- credentialTypeId: null,
- credentialTypeName: null,
- credentialId: null,
- credentialName: null,
- metadataInputs: null,
- changedInputFields: [],
- initialItems: credential.get('related.input_sources.results'),
- items: credential.get('related.input_sources.results'),
- };
-
- function setInputSourceTab (name) {
- const metaIsActive = name === 'metadata';
- vm.inputSources.tabs.credential._active = !metaIsActive;
- vm.inputSources.tabs.credential._disabled = false;
- vm.inputSources.tabs.metadata._active = metaIsActive;
- vm.inputSources.tabs.metadata._disabled = false;
- }
-
- function unsetInputSourceTabs () {
- vm.inputSources.tabs.credential._active = false;
- vm.inputSources.tabs.credential._disabled = false;
- vm.inputSources.tabs.metadata._active = false;
- vm.inputSources.tabs.metadata._disabled = false;
- }
-
- vm.onInputSourceClear = (field) => {
- vm.form[field].tagMode = true;
- vm.form[field].asTag = false;
- vm.form[field]._value = '';
- vm.form[field]._tagValue = '';
- vm.form[field]._isValid = true;
- vm.form[field]._rejected = false;
- vm.inputSources.items = vm.inputSources.items
- .filter(({ input_field_name }) => input_field_name !== field);
- vm.inputSources.changedInputFields.push(field);
- };
-
- vm.onInputSourceOpen = (field) => {
- // We get here when the input source lookup modal for a field is opened. If source
- // credential and metadata values for this field already exist in the initial API data
- // or from it being set during a prior visit to the lookup, we initialize the lookup with
- // these values here before opening it.
- const sourceItem = vm.inputSources.items
- .find(({ input_field_name }) => input_field_name === field);
- if (sourceItem) {
- const { source_credential, summary_fields } = sourceItem;
- const { source_credential: { credential_type_id, name } } = summary_fields;
- vm.inputSources.credentialId = source_credential;
- vm.inputSources.credentialName = name;
- vm.inputSources.credentialTypeId = credential_type_id;
- vm.inputSources._value = credential_type_id;
- } else {
- vm.inputSources.credentialId = null;
- vm.inputSources.credentialName = null;
- vm.inputSources.credentialTypeId = null;
- vm.inputSources._value = null;
- }
-
- setInputSourceTab('credential');
- vm.inputSources.field = field;
- };
-
- vm.onInputSourceClose = () => {
- // We get here if the lookup was closed or canceled so we clear the state for the lookup
- // and metadata form without storing any changes.
- vm.inputSources.field = null;
- vm.inputSources.credentialId = null;
- vm.inputSources.credentialName = null;
- vm.inputSources.metadataInputs = null;
- unsetInputSourceTabs();
- };
-
- /**
- * Extract the current set of input values from the metadata form and reshape them to a
- * metadata object that can be sent to the api later or reloaded when re-opening the form.
- */
- function getMetadataFormSubmitData ({ inputs }) {
- return inputs._group.reduce((metadata, { id, _value }) => {
- if (_value !== undefined) {
- metadata[id] = _value;
- }
- return metadata;
- }, {});
- }
-
- vm.onInputSourceNext = () => {
- const { field, credentialId, credentialTypeId } = vm.inputSources;
- Wait('start');
- new CredentialType('get', credentialTypeId)
- .then(model => {
- model.mergeInputProperties('metadata');
- vm.inputSources.metadataInputs = model.get('inputs.metadata');
- vm.inputSources.credentialTypeName = model.get('name');
- // Pre-populate the input values for the metadata form if state for this specific
- // field_name->source_credential link already exists. This occurs one of two ways:
- //
- // 1. This field->source_credential link already exists in the API and so we're
- // showing the current state as it exists on the backend.
- // 2. The metadata form for this specific field->source_credential combination was
- // set during a prior visit to this lookup and so we're reflecting the most
- // recent set of (unsaved) metadata values provided by the user for this field.
- //
- // Note: Prior state for a given credential input field is only set for one source
- // credential at a time. Linking a field to a source credential will remove all
- // other prior input state for that field.
- const [metavals] = vm.inputSources.items
- .filter(({ input_field_name }) => input_field_name === field)
- .filter(({ source_credential }) => source_credential === credentialId)
- .map(({ metadata }) => metadata);
- Object.keys(metavals || {}).forEach(key => {
- const obj = vm.inputSources.metadataInputs.find(o => o.id === key);
- if (obj) obj._value = metavals[key];
- });
- setInputSourceTab('metadata');
- })
- .finally(() => Wait('stop'));
- };
-
- vm.onInputSourceSelect = () => {
- const { field, credentialId, credentialName, credentialTypeId } = vm.inputSources;
- const metadata = getMetadataFormSubmitData(vm.inputSources.form);
- // Remove any input source objects already stored for this field then store the metadata
- // and currently selected source credential as a credential input source object that
- // can be sent to the api later or reloaded into the form if it is reopened.
- vm.inputSources.items = vm.inputSources.items
- .filter(({ input_field_name }) => input_field_name !== field)
- .concat([{
- metadata,
- input_field_name: field,
- source_credential: credentialId,
- target_credential: credential.get('id'),
- summary_fields: {
- source_credential: {
- name: credentialName,
- credential_type_id: credentialTypeId
- }
- },
- }]);
- // Record that this field was changed
- vm.inputSources.changedInputFields.push(field);
- // Now that we've extracted and stored the selected source credential and metadata values
- // for this field, we clear the state for the source credential lookup and metadata form.
- vm.inputSources.field = null;
- vm.inputSources.metadataInputs = null;
- unsetInputSourceTabs();
- // We've linked this field to a credential, so display value as a credential tag
- vm.form[field]._value = '';
- vm.form[field]._tagValue = credentialName;
- vm.form[field]._isValid = true;
- vm.form[field].asTag = true;
- vm.checkForm();
- };
-
- vm.onInputSourceTabSelect = (name) => {
- if (name === 'metadata') {
- // Clicking on the metadata tab should have identical behavior to clicking the 'next'
- // button, so we pass-through to the same handler here.
- vm.onInputSourceNext();
- } else {
- setInputSourceTab('credential');
- }
- };
-
- vm.onInputSourceItemSelect = ({ id, credential_type, name }) => {
- vm.inputSources.credentialId = id;
- vm.inputSources.credentialName = name;
- vm.inputSources.credentialTypeId = credential_type;
- vm.inputSources._value = credential_type;
- };
-
- vm.onInputSourceTest = () => {
- // We get here if the test button on the metadata form for the field of a non-external
- // credential was used. All input values for the external credential are already stored
- // on the backend, so we are only testing how it works with a set of metadata before
- // linking it.
- const metadata = getMetadataFormSubmitData(vm.inputSources.form);
- const name = $filter('sanitize')(vm.inputSources.credentialTypeName);
- const endpoint = `${vm.inputSources.credentialId}/test/`;
- return runTest({ name, model: credential, endpoint, data: { metadata } });
- };
-
- function onExternalTestOpen () {
- // We get here if test button on the top-level form for an external credential type was
- // used. We load the metadata schema for this particular external credential type and
- // use it to generate and open a form for submitting test values.
- credentialType.mergeInputProperties('metadata');
- vm.externalTest.metadataInputs = credentialType.get('inputs.metadata');
- }
- vm.form.secondary = onExternalTestOpen;
-
- vm.onExternalTestClose = () => {
- // We get here if the metadata test form for an external credential type was canceled or
- // closed so we clear the form state and close without submitting any data to the test api,
- vm.externalTest.metadataInputs = null;
- };
-
- vm.onExternalTest = () => {
- const name = $filter('sanitize')(credentialType.get('name'));
- const { inputs } = vm.getSubmitData();
- const metadata = getMetadataFormSubmitData(vm.externalTest.form);
- // We get here if the test button on the top-level form for an external credential type was
- // used. We need to see if the currently selected credential type is the one loaded from
- // the api when we initialized the view or if its type was changed on the form and hasn't
- // been saved. If the credential type hasn't been changed, it means some of the input
- // values for the credential may be stored in the backend and not in the form, so we need
- // to use the test endpoint for the credential. If the credential type has been changed,
- // the user must provide a complete set of input values for the credential to save their
- // changes, so we use the generic test endpoint for the credental type as if we were
- // testing a completely new and unsaved credential.
- let model;
- if (credential.get('credential_type') !== credentialType.get('id')) {
- model = credentialType;
- } else {
- model = credential;
- }
-
- const endpoint = `${model.get('id')}/test/`;
- return runTest({ name, model, endpoint, data: { inputs, metadata } });
- };
-
- vm.filterInputSourceCredentialResults = (data) => {
- // If an external credential is changed to have a non-external `credential_type` while
- // editing, we avoid showing a self-reference in the list of selectable external
- // credentials for input fields by filtering it out here.
- if (isExternal) {
- data.results = data.results.filter(({ id }) => id !== credential.get('id'));
- }
-
- // only show credentials we can use
- data.results = data.results
- .filter(({ summary_fields }) => summary_fields.user_capabilities.use);
-
- return data;
- };
-
- function runTest ({ name, model, endpoint, data: { inputs, metadata } }) {
- return model.http.post({ url: endpoint, data: { inputs, metadata }, replace: false })
- .then(() => {
- const icon = 'fa-check-circle';
- const msg = strings.get('edit.TEST_PASSED');
- const content = buildTestNotificationContent({ name, icon, msg });
- ngToast.success({
- content,
- dismissButton: false,
- dismissOnTimeout: true
- });
- })
- .catch(({ data }) => {
- const icon = 'fa-exclamation-triangle';
- const msg = data.inputs || strings.get('edit.TEST_FAILED');
- const content = buildTestNotificationContent({ name, icon, msg });
- ngToast.danger({
- content,
- dismissButton: false,
- dismissOnTimeout: true
- });
- });
- }
-
- function buildTestNotificationContent ({ name, msg, icon }) {
- const sanitize = $filter('sanitize');
- const content = `
-
-
-
-
- ${sanitize(name)}: ${sanitize(msg)}
-
-
`;
- return content;
- }
-
- function deleteInputSource ({ id }) {
- Rest.setUrl(`${GetBasePath('credential_input_sources')}${id}/`);
- return Rest.destroy();
- }
-
- function createInputSource (data) {
- Rest.setUrl(GetBasePath('credential_input_sources'));
- return Rest.post(data);
- }
-
- function create (data) {
- // can send only one of org, user, team
- if (!data.organization && !data.team) {
- data.user = me.get('id');
- }
-
- if (_.get(data.inputs, gceFileInputSchema.id)) {
- delete data.inputs[gceFileInputSchema.id];
- }
-
- const updatedLinkedFieldNames = vm.inputSources.items
- .map(({ input_field_name }) => input_field_name);
- const sourcesToAssociate = [...vm.inputSources.items];
-
- // remove inputs with empty string values
- let filteredInputs = _.omit(data.inputs, (value) => value === '');
- // remove inputs that are to be linked to an external credential
- filteredInputs = _.omit(filteredInputs, updatedLinkedFieldNames);
- data.inputs = filteredInputs;
-
- return credential.request('post', { data })
- .then(() => {
- sourcesToAssociate.forEach(obj => { obj.target_credential = credential.get('id'); });
- return Promise.all(sourcesToAssociate.map(createInputSource));
- });
- }
-
- /**
- * If a credential's `credential_type` is changed while editing, the inputs associated with
- * the old type need to be cleared before saving the inputs associated with the new type.
- * Otherwise inputs are merged together making the request invalid.
- */
- function update (data) {
- // can send only one of org, user, team
- if (!data.organization && !data.team) {
- data.user = me.get('id');
- }
-
- credential.unset('inputs');
-
- if (_.get(data.inputs, gceFileInputSchema.id)) {
- delete data.inputs[gceFileInputSchema.id];
- }
-
- const initialLinkedFieldNames = vm.inputSources.initialItems
- .map(({ input_field_name }) => input_field_name);
- const updatedLinkedFieldNames = vm.inputSources.items
- .map(({ input_field_name }) => input_field_name);
-
- const fieldsToDisassociate = initialLinkedFieldNames
- .filter(name => !updatedLinkedFieldNames.includes(name))
- .concat(updatedLinkedFieldNames)
- .filter(name => vm.inputSources.changedInputFields.includes(name));
- const fieldsToAssociate = updatedLinkedFieldNames
- .filter(name => vm.inputSources.changedInputFields.includes(name));
-
- const sourcesToDisassociate = fieldsToDisassociate
- .map(name => vm.inputSources.initialItems
- .find(({ input_field_name }) => input_field_name === name))
- .filter(source => source !== undefined);
- const sourcesToAssociate = fieldsToAssociate
- .map(name => vm.inputSources.items
- .find(({ input_field_name }) => input_field_name === name))
- .filter(source => source !== undefined);
-
- // remove inputs with empty string values
- let filteredInputs = _.omit(data.inputs, (value) => value === '');
- // remove inputs that are to be linked to an external credential
- filteredInputs = _.omit(filteredInputs, updatedLinkedFieldNames);
- data.inputs = filteredInputs;
-
- return credential.request('put', { data })
- .then(() => Promise.all(sourcesToDisassociate.map(deleteInputSource)))
- .then(() => Promise.all(sourcesToAssociate.map(createInputSource)));
- }
-
- vm.form.save = data => {
- if (mode === 'edit') {
- return update(data);
- }
- return create(data);
- };
-
- vm.form.onSaveSuccess = () => {
- $state.go('credentials.edit', { credential_id: credential.get('id') }, { reload: true });
- };
-
- function gceOnReplaceKeyChanged (value) {
- vm.form[gceFileInputSchema.id]._disabled = !value;
- }
-
- function gceOnFileInputChanged (value, oldValue) {
- if (value === oldValue) return;
-
- const gceFileIsLoaded = !!value;
- const gceFileInputState = vm.form[gceFileInputSchema.id];
- const { obj, error } = gceParseFileInput(value);
-
- gceFileInputState._isValid = !error;
- gceFileInputState._message = error ? componentsStrings.get('message.INVALID_INPUT') : '';
-
- vm.form.project._disabled = gceFileIsLoaded;
- vm.form.username._disabled = gceFileIsLoaded;
- vm.form.ssh_key_data._disabled = gceFileIsLoaded;
- vm.form.ssh_key_data._displayHint = !vm.form.ssh_key_data._disabled;
-
- if (gceFileIsLoaded) {
- gceFileInputPreEditValues = Object.assign({}, {
- project: vm.form.project._value,
- ssh_key_data: vm.form.ssh_key_data._value,
- username: vm.form.username._value
- });
-
- vm.form.project.asTag = false;
- vm.form.project._value = _.get(obj, 'project_id', '');
- vm.inputSources.changedInputFields.push('project');
- vm.inputSources.items = vm.inputSources.items
- .filter(({ input_field_name }) => input_field_name !== 'project');
-
- vm.form.ssh_key_data.asTag = false;
- vm.form.ssh_key_data._value = _.get(obj, 'private_key', '');
- vm.inputSources.changedInputFields.push('ssh_key_data');
- vm.inputSources.items = vm.inputSources.items
- .filter(({ input_field_name }) => input_field_name !== 'ssh_key_data');
-
- vm.form.username.asTag = false;
- vm.form.username._value = _.get(obj, 'client_email', '');
- vm.inputSources.changedInputFields.push('username');
- vm.inputSources.items = vm.inputSources.items
- .filter(({ input_field_name }) => input_field_name !== 'username');
- } else {
- vm.form.project._value = gceFileInputPreEditValues.project;
- vm.form.ssh_key_data._value = gceFileInputPreEditValues.ssh_key_data;
- vm.form.username._value = gceFileInputPreEditValues.username;
- }
- }
-
- function gceParseFileInput (value) {
- let obj;
- let error;
-
- try {
- obj = angular.fromJson(value);
- } catch (err) {
- error = err;
- }
-
- return { obj, error };
- }
-}
-
-AddEditCredentialsController.$inject = [
- 'resolvedModels',
- '$state',
- '$scope',
- 'CredentialsStrings',
- 'ComponentsStrings',
- 'ConfigService',
- 'ngToast',
- 'Wait',
- '$filter',
- 'CredentialTypeModel',
- 'GetBasePath',
- 'Rest',
-];
-
-export default AddEditCredentialsController;
diff --git a/awx/ui/client/features/credentials/add-edit-credentials.view.html b/awx/ui/client/features/credentials/add-edit-credentials.view.html
deleted file mode 100644
index aa3e581b6d..0000000000
--- a/awx/ui/client/features/credentials/add-edit-credentials.view.html
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.PERMISSIONS') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('inputs.GROUP_TITLE') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.PERMISSIONS') }}
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/credentials/credentials.strings.js b/awx/ui/client/features/credentials/credentials.strings.js
deleted file mode 100644
index 55e19ca152..0000000000
--- a/awx/ui/client/features/credentials/credentials.strings.js
+++ /dev/null
@@ -1,55 +0,0 @@
-function CredentialsStrings (BaseString) {
- BaseString.call(this, 'credentials');
-
- const { t } = this;
- const ns = this.credentials;
-
- ns.state = {
- ADD_BREADCRUMB_LABEL: t.s('CREATE CREDENTIAL'),
- EDIT_BREADCRUMB_LABEL: t.s('EDIT CREDENTIAL')
- };
-
- ns.tab = {
- DETAILS: t.s('Details'),
- PERMISSIONS: t.s('Permissions'),
- };
-
- ns.inputs = {
- GROUP_TITLE: t.s('Type Details'),
- ORGANIZATION_PLACEHOLDER: t.s('SELECT AN ORGANIZATION'),
- CREDENTIAL_TYPE_PLACEHOLDER: t.s('SELECT A CREDENTIAL TYPE'),
- GCE_FILE_INPUT_LABEL: t.s('Service Account JSON File'),
- GCE_FILE_INPUT_HELP_TEXT: t.s('Provide account information using Google Compute Engine JSON credentials file.')
- };
-
- ns.externalTest = {
- TITLE: t.s('Test External Credential')
- };
-
- ns.inputSources = {
- TITLE: t.s('Set Input Source'),
- CREDENTIAL: t.s('CREDENTIAL'),
- METADATA: t.s('METADATA'),
- NO_MATCH: t.s('No records matched your search.'),
- NO_RECORDS: t.s('No external credentials available.'),
- SELECTED: t.s('selected'),
- NONE_SELECTED: t.s('No credential selected'),
- };
-
- ns.add = {
- PANEL_TITLE: t.s('NEW CREDENTIAL')
- };
-
- ns.edit = {
- TEST_PASSED: t.s('Test passed.'),
- TEST_FAILED: t.s('Test failed.')
- };
-
- ns.permissions = {
- TITLE: t.s('CREDENTIALS PERMISSIONS')
- };
-}
-
-CredentialsStrings.$inject = ['BaseStringService'];
-
-export default CredentialsStrings;
diff --git a/awx/ui/client/features/credentials/external-test-modal.component.js b/awx/ui/client/features/credentials/external-test-modal.component.js
deleted file mode 100644
index 7b8ac82685..0000000000
--- a/awx/ui/client/features/credentials/external-test-modal.component.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const templateUrl = require('~features/credentials/external-test-modal.partial.html');
-
-function ExternalTestModalController (strings) {
- const vm = this || {};
-
- vm.strings = strings;
- vm.title = strings.get('externalTest.TITLE');
-
- vm.$onInit = () => {
- vm.form.save = () => vm.onSubmit();
- };
-}
-
-ExternalTestModalController.$inject = [
- 'CredentialsStrings',
-];
-
-export default {
- templateUrl,
- controller: ExternalTestModalController,
- controllerAs: 'vm',
- bindings: {
- onClose: '=',
- onSubmit: '=',
- form: '=',
- },
-};
diff --git a/awx/ui/client/features/credentials/external-test-modal.partial.html b/awx/ui/client/features/credentials/external-test-modal.partial.html
deleted file mode 100644
index 5f35774655..0000000000
--- a/awx/ui/client/features/credentials/external-test-modal.partial.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
- {{::vm.strings.get('CLOSE')}}
-
-
- {{::vm.strings.get('RUN')}}
-
-
-
-
diff --git a/awx/ui/client/features/credentials/index.js b/awx/ui/client/features/credentials/index.js
deleted file mode 100644
index c0f28f5dc2..0000000000
--- a/awx/ui/client/features/credentials/index.js
+++ /dev/null
@@ -1,167 +0,0 @@
-import LegacyCredentials from './legacy.credentials';
-import AddEditController from './add-edit-credentials.controller';
-import CredentialsStrings from './credentials.strings';
-import InputSourceLookupComponent from './input-source-lookup.component';
-import ExternalTestModalComponent from './external-test-modal.component';
-
-const MODULE_NAME = 'at.features.credentials';
-
-const addEditTemplate = require('~features/credentials/add-edit-credentials.view.html');
-
-function CredentialsResolve (
- $q,
- $stateParams,
- Me,
- Credential,
- CredentialType,
- Organization,
- ProcessErrors,
- strings,
- Rest,
- GetBasePath,
-) {
- const id = $stateParams.credential_id;
-
- const promises = {
- me: new Me('get').then((me) => me.extend('get', 'admin_of_organizations'))
- };
-
- if (!id) {
- promises.credential = new Credential('options');
- promises.credentialType = new CredentialType();
- promises.organization = new Organization();
- promises.sourceCredentials = $q.resolve({ data: { count: 0, results: [] } });
-
- return $q.all(promises);
- }
-
- promises.credential = new Credential(['get', 'options'], [id, id]);
-
- return $q.all(promises)
- .then(models => {
- const typeId = models.credential.get('credential_type');
-
- Rest.setUrl(GetBasePath('credentials'));
- const params = { target_input_sources__target_credential: id };
- const sourceCredentialsPromise = Rest.get({ params });
-
- const dependents = {
- credentialType: new CredentialType('get', typeId),
- organization: new Organization('get', {
- resource: models.credential.get('summary_fields.organization')
- }),
- credentialInputSources: models.credential.extend('GET', 'input_sources'),
- sourceCredentials: sourceCredentialsPromise
- };
-
- dependents.isOrgCredAdmin = dependents.organization.then((org) => org.search({ role_level: 'credential_admin_role' }));
-
- return $q.all(dependents)
- .then(related => {
- models.credentialType = related.credentialType;
- models.organization = related.organization;
- models.sourceCredentials = related.sourceCredentials;
-
- const isOrgAdmin = _.some(models.me.get('related.admin_of_organizations.results'), (org) => org.id === models.organization.get('id'));
- const isSuperuser = models.me.get('is_superuser');
- const isCurrentAuthor = Boolean(models.credential.get('summary_fields.created_by.id') === models.me.get('id'));
-
- models.isOrgEditableByUser = (isSuperuser || isOrgAdmin
- || related.isOrgCredAdmin
- || (models.credential.get('organization') === null && isCurrentAuthor));
-
- return models;
- });
- }).catch(({ data, status, config }) => {
- ProcessErrors(null, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- return $q.reject();
- });
-}
-
-CredentialsResolve.$inject = [
- '$q',
- '$stateParams',
- 'MeModel',
- 'CredentialModel',
- 'CredentialTypeModel',
- 'OrganizationModel',
- 'ProcessErrors',
- 'CredentialsStrings',
- 'Rest',
- 'GetBasePath',
-];
-
-function CredentialsRun ($stateExtender, legacy, strings) {
- $stateExtender.addState({
- name: 'credentials.add',
- route: '/add',
- ncyBreadcrumb: {
- label: strings.get('state.ADD_BREADCRUMB_LABEL')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'credential'
- },
- views: {
- 'add@credentials': {
- templateUrl: addEditTemplate,
- controller: AddEditController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: CredentialsResolve
- }
- });
-
- $stateExtender.addState({
- name: 'credentials.edit',
- route: '/:credential_id',
- ncyBreadcrumb: {
- label: strings.get('state.EDIT_BREADCRUMB_LABEL')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'credential',
- activityStreamId: 'credential_id'
- },
- views: {
- 'edit@credentials': {
- templateUrl: addEditTemplate,
- controller: AddEditController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: CredentialsResolve
- }
- });
-
- $stateExtender.addState(legacy.getStateConfiguration('list'));
- $stateExtender.addState(legacy.getStateConfiguration('edit-permissions'));
- $stateExtender.addState(legacy.getStateConfiguration('add-permissions'));
- $stateExtender.addState(legacy.getStateConfiguration('add-organization'));
- $stateExtender.addState(legacy.getStateConfiguration('edit-organization'));
- $stateExtender.addState(legacy.getStateConfiguration('add-credential-type'));
- $stateExtender.addState(legacy.getStateConfiguration('edit-credential-type'));
-}
-
-CredentialsRun.$inject = [
- '$stateExtender',
- 'LegacyCredentialsService',
- 'CredentialsStrings'
-];
-
-angular
- .module(MODULE_NAME, [])
- .controller('AddEditController', AddEditController)
- .service('LegacyCredentialsService', LegacyCredentials)
- .service('CredentialsStrings', CredentialsStrings)
- .component('atInputSourceLookup', InputSourceLookupComponent)
- .component('atExternalCredentialTest', ExternalTestModalComponent)
- .run(CredentialsRun);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/credentials/index.view.html b/awx/ui/client/features/credentials/index.view.html
deleted file mode 100644
index 964941c53d..0000000000
--- a/awx/ui/client/features/credentials/index.view.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
diff --git a/awx/ui/client/features/credentials/input-source-lookup.component.js b/awx/ui/client/features/credentials/input-source-lookup.component.js
deleted file mode 100644
index b76baf043b..0000000000
--- a/awx/ui/client/features/credentials/input-source-lookup.component.js
+++ /dev/null
@@ -1,42 +0,0 @@
-const templateUrl = require('~features/credentials/input-source-lookup.partial.html');
-
-function InputSourceLookupController (strings, wait) {
- const vm = this || {};
-
- vm.strings = strings;
- vm.title = strings.get('inputSources.TITLE');
-
- vm.$onInit = () => {
- wait('start');
- vm.form.save = () => vm.onTest();
- };
-
- vm.onReady = () => {
- vm.isReady = true;
- wait('stop');
- };
-}
-
-InputSourceLookupController.$inject = [
- 'CredentialsStrings',
- 'Wait',
-];
-
-export default {
- templateUrl,
- controller: InputSourceLookupController,
- controllerAs: 'vm',
- bindings: {
- tabs: '=',
- onClose: '=',
- onNext: '=',
- onSelect: '=',
- onTabSelect: '=',
- onItemSelect: '=',
- onTest: '=',
- selectedId: '=',
- selectedName: '=',
- form: '=',
- resultsFilter: '=',
- },
-};
diff --git a/awx/ui/client/features/credentials/input-source-lookup.partial.html b/awx/ui/client/features/credentials/input-source-lookup.partial.html
deleted file mode 100644
index dc9461ba31..0000000000
--- a/awx/ui/client/features/credentials/input-source-lookup.partial.html
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
- {{::vm.strings.get('inputSources.CREDENTIAL')}}
-
-
- {{::vm.strings.get('inputSources.METADATA')}}
-
-
-
-
-
-
-
-
-
-
- {{::vm.strings.get('TEST')}}
-
-
- {{::vm.strings.get('CANCEL')}}
-
-
- {{::vm.strings.get('NEXT')}}
-
-
- {{::vm.strings.get('OK')}}
-
-
-
-
diff --git a/awx/ui/client/features/credentials/legacy.credentials.js b/awx/ui/client/features/credentials/legacy.credentials.js
deleted file mode 100644
index 6707272201..0000000000
--- a/awx/ui/client/features/credentials/legacy.credentials.js
+++ /dev/null
@@ -1,355 +0,0 @@
-import ListController from '../../src/credentials/list/credentials-list.controller';
-import { N_ } from '../../src/i18n';
-
-const indexTemplate = require('~features/credentials/index.view.html');
-
-function LegacyCredentialsService () {
- this.list = {
- name: 'credentials',
- route: '/credentials',
- ncyBreadcrumb: {
- label: N_('CREDENTIALS')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'credential'
- },
- views: {
- '@': {
- templateUrl: indexTemplate
- },
- 'list@credentials': {
- templateProvider (CredentialList, generateList) {
- const html = generateList.build({
- list: CredentialList,
- mode: 'edit'
- });
-
- return html;
- },
- controller: ListController
- }
- },
- searchPrefix: 'credential',
- resolve: {
- Dataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => {
- const path = GetBasePath(list.basePath) || GetBasePath(list.name);
-
- return qs.search(path, $stateParams[`${list.iterator}_search`]);
- }
- ],
- credentialType: ['CredentialTypeModel', CredentialType => new CredentialType('get')]
- }
- };
-
- this.editPermissions = {
- name: 'credentials.edit.permissions',
- url: '/permissions?{permission_search:queryset}',
- resolve: {
- ListDefinition: () => ({
- name: 'permissions',
- disabled: 'organization === undefined',
- ngClick: 'organization === undefined || $state.go(\'credentials.edit.permissions\')',
- awToolTip: '{{permissionsTooltip}}',
- dataTipWatch: 'permissionsTooltip',
- awToolTipTabEnabledInEditMode: true,
- dataPlacement: 'right',
- basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/',
- search: {
- order_by: 'username'
- },
- type: 'collection',
- title: N_('Permissions'),
- iterator: 'permission',
- index: false,
- open: false,
- actions: {
- add: {
- ngClick: '$state.go(\'.add\')',
- label: N_('Add'),
- awToolTip: N_('Add a permission'),
- actionClass: 'at-Button--add',
- actionId: 'button-add--permission',
- ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- }
- },
- fields: {
- username: {
- key: true,
- label: N_('User'),
- linkBase: 'users',
- columnClass: 'col-lg-3 col-md-3 col-sm-3 col-xs-4'
- },
- role: {
- label: N_('Role'),
- type: 'role',
- nosort: true,
- columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
- },
- team_roles: {
- label: N_('Team Roles'),
- type: 'team_roles',
- nosort: true,
- columnClass: 'col-lg-5 col-md-5 col-sm-5 col-xs-4'
- }
- }
- }),
- Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => {
- const id = $stateParams.credential_id;
- const path = `api/v2/credentials/${id}/access_list/`;
-
- return qs.search(path, $stateParams.permission_search);
- }]
- },
- params: {
- permission_search: {
- value: {
- page_size: '20',
- order_by: 'username'
- },
- dynamic: true,
- squash: ''
- }
- },
- ncyBreadcrumb: {
- parent: 'credentials.edit',
- label: N_('PERMISSIONS')
- },
- views: {
- related: {
- templateProvider (CredentialForm, GenerateForm) {
- const html = GenerateForm.buildCollection({
- mode: 'edit',
- related: 'permissions',
- form: typeof (CredentialForm) === 'function' ?
- CredentialForm() : CredentialForm
- });
- return html;
- },
- controller: 'PermissionsList'
- }
- }
- };
-
- this.addPermissions = {
- name: 'credentials.edit.permissions.add',
- url: '/add-permissions',
- resolve: {
- usersDataset: [
- 'addPermissionsUsersList',
- 'QuerySet',
- '$stateParams',
- 'GetBasePath',
- 'resourceData',
- (list, qs, $stateParams, GetBasePath, resourceData) => {
- let path;
-
- if (resourceData.data.organization) {
- path = `${GetBasePath('organizations')}${resourceData.data.organization}/users`;
- } else {
- path = list.basePath || GetBasePath(list.name);
- }
-
- return qs.search(path, $stateParams.user_search);
- }
- ],
- teamsDataset: [
- 'addPermissionsTeamsList',
- 'QuerySet',
- '$stateParams',
- 'GetBasePath',
- 'resourceData',
- (list, qs, $stateParams, GetBasePath, resourceData) => {
- const path = GetBasePath(list.basePath) || GetBasePath(list.name);
- const org = resourceData.data.organization;
-
- if (!org) {
- return null;
- }
-
- $stateParams[`${list.iterator}_search`].organization = org;
-
- return qs.search(path, $stateParams.team_search);
- }
- ],
- resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) =>
- new Credential('get', $stateParams.credential_id)
- .then(credential => ({ data: credential.get() }))
- ]
- },
- params: {
- user_search: {
- value: {
- order_by: 'username',
- page_size: 5,
- is_superuser: false
- },
- dynamic: true
- },
- team_search: {
- value: {
- order_by: 'name',
- page_size: 5
- },
- dynamic: true
- }
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'modal@credentials.edit': {
- template: `
-
- `
- }
- },
- onExit: $state => {
- if ($state.transition) {
- $('#add-permissions-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- };
-
- this.lookupTemplateProvider = (ListDefinition, generateList) => {
- const html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
-
- return `${html} `;
- };
-
- this.organization = {
- url: '/organization?selected',
- searchPrefix: 'organization',
- params: {
- organization_search: {
- value: {
- page_size: 5,
- order_by: 'name',
- role_level: 'credential_admin_role'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'organizations',
- formChildState: true
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {},
- resolve: {
- ListDefinition: ['OrganizationList', list => list],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => qs.search(
- GetBasePath('organizations'),
- $stateParams[`${list.iterator}_search`]
- )
- ]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- };
-
- this.credentialType = {
- url: '/credential_type?selected',
- searchPrefix: 'credential_type',
- params: {
- credential_type_search: {
- value: {
- page_size: 5,
- order_by: 'name'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'credential_types',
- formChildState: true
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {},
- resolve: {
- ListDefinition: ['CredentialTypesList', list => list],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => qs.search(
- GetBasePath('credential_types'),
- $stateParams[`${list.iterator}_search`]
- )
- ]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- };
-
- this.getStateConfiguration = (name) => {
- switch (name) {
- case 'list':
- return this.list;
- case 'edit-permissions':
- return this.editPermissions;
- case 'add-permissions':
- return this.addPermissions;
- case 'add-organization':
- this.organization.name = 'credentials.add.organization';
- this.organization.views['organization@credentials.add'] = {
- templateProvider: this.lookupTemplateProvider
- };
-
- return this.organization;
- case 'edit-organization':
- this.organization.name = 'credentials.edit.organization';
- this.organization.views['organization@credentials.edit'] = {
- templateProvider: this.lookupTemplateProvider
- };
-
- return this.organization;
- case 'add-credential-type':
- this.credentialType.name = 'credentials.add.credentialType';
- this.credentialType.views['credential_type@credentials.add'] = {
- templateProvider: this.lookupTemplateProvider
- };
-
- return this.credentialType;
- case 'edit-credential-type':
- this.credentialType.name = 'credentials.edit.credentialType';
- this.credentialType.views['credential_type@credentials.edit'] = {
- templateProvider: this.lookupTemplateProvider
- };
-
- return this.credentialType;
-
- default:
- throw new Error(N_(`Legacy state configuration for ${name} does not exist`));
- }
- };
-}
-
-export default LegacyCredentialsService;
diff --git a/awx/ui/client/features/index.js b/awx/ui/client/features/index.js
deleted file mode 100644
index b816d2c65d..0000000000
--- a/awx/ui/client/features/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import atLibServices from '~services';
-import atLibComponents from '~components';
-import atLibModels from '~models';
-
-import atFeaturesApplications from '~features/applications';
-import atFeaturesCredentials from '~features/credentials';
-import atFeaturesOutput from '~features/output';
-import atFeaturesTemplates from '~features/templates';
-import atFeaturesUsers from '~features/users';
-import atFeaturesJobs from '~features/jobs';
-import atFeaturesPortalMode from '~features/portalMode';
-import atFeaturesProjects from '~features/projects';
-
-const MODULE_NAME = 'at.features';
-
-angular.module(MODULE_NAME, [
- atLibServices,
- atLibComponents,
- atLibModels,
- atFeaturesApplications,
- atFeaturesCredentials,
- atFeaturesTemplates,
- atFeaturesUsers,
- atFeaturesJobs,
- atFeaturesOutput,
- atFeaturesTemplates,
- atFeaturesPortalMode,
- atFeaturesProjects
-]);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/jobs/index.controller.js b/awx/ui/client/features/jobs/index.controller.js
deleted file mode 100644
index f0ab4e2315..0000000000
--- a/awx/ui/client/features/jobs/index.controller.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function IndexJobsController ($scope, strings, dataset) {
- const vm = this;
- vm.strings = strings;
- vm.count = dataset.data.count;
-
- $scope.$on('updateCount', (e, count) => {
- if (typeof count === 'number') {
- vm.count = count;
- }
- });
-}
-
-IndexJobsController.$inject = [
- '$scope',
- 'JobsStrings',
- 'Dataset'
-];
-
-export default IndexJobsController;
diff --git a/awx/ui/client/features/jobs/index.js b/awx/ui/client/features/jobs/index.js
deleted file mode 100644
index 99d91515d5..0000000000
--- a/awx/ui/client/features/jobs/index.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import JobsStrings from './jobs.strings';
-import jobsRoute from './routes/jobs.route';
-import { jobsSchedulesRoute, jobsSchedulesEditRoute } from '../../src/scheduler/schedules.route';
-import jobsListController from './jobsList.controller';
-
-const MODULE_NAME = 'at.features.jobs';
-
-angular
- .module(MODULE_NAME, [])
- .service('JobsStrings', JobsStrings)
- .controller('jobsListController', jobsListController)
- .run(['$stateExtender', ($stateExtender) => {
- $stateExtender.addState(jobsRoute);
- $stateExtender.addState(jobsSchedulesRoute);
- $stateExtender.addState(jobsSchedulesEditRoute);
- }]);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/jobs/index.view.html b/awx/ui/client/features/jobs/index.view.html
deleted file mode 100644
index a1fa58df9e..0000000000
--- a/awx/ui/client/features/jobs/index.view.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
diff --git a/awx/ui/client/features/jobs/jobs.strings.js b/awx/ui/client/features/jobs/jobs.strings.js
deleted file mode 100644
index dbdfa0c69c..0000000000
--- a/awx/ui/client/features/jobs/jobs.strings.js
+++ /dev/null
@@ -1,35 +0,0 @@
-function JobsStrings (BaseString) {
- BaseString.call(this, 'jobs');
-
- const { t } = this;
- const ns = this.jobs;
-
- ns.list = {
- PANEL_TITLE: t.s('JOBS'),
- ROW_ITEM_LABEL_STARTED: t.s('Started'),
- ROW_ITEM_LABEL_FINISHED: t.s('Finished'),
- ROW_ITEM_LABEL_WORKFLOW_JOB: t.s('Workflow Job'),
- ROW_ITEM_LABEL_LAUNCHED_BY: t.s('Launched By'),
- ROW_ITEM_LABEL_JOB_TEMPLATE: t.s('Job Template'),
- ROW_ITEM_LABEL_INVENTORY: t.s('Inventory'),
- ROW_ITEM_LABEL_PROJECT: t.s('Project'),
- ROW_ITEM_LABEL_CREDENTIALS: t.s('Credentials'),
- ROW_ITEM_LABEL_WEBHOOK: t.s('Webhook'),
- NO_RUNNING: t.s('There are no running jobs.'),
- JOB: t.s('Job'),
- STATUS_TOOLTIP: status => t.s('Job {{status}}. Click for details.', { status }),
- SLICE_JOB: t.s('Slice Job'),
- NEW: t.s('new'),
- PENDING: t.s('pending'),
- WAITING: t.s('waiting'),
- RUNNING: t.s('running'),
- SUCCESSFUL: t.s('successful'),
- FAILED: t.s('failed'),
- ERROR: t.s('error'),
- CANCELED: t.s('canceled')
- };
-}
-
-JobsStrings.$inject = ['BaseStringService'];
-
-export default JobsStrings;
diff --git a/awx/ui/client/features/jobs/jobsList.controller.js b/awx/ui/client/features/jobs/jobsList.controller.js
deleted file mode 100644
index 5720a53b80..0000000000
--- a/awx/ui/client/features/jobs/jobsList.controller.js
+++ /dev/null
@@ -1,393 +0,0 @@
-/** ***********************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- ************************************************ */
-const mapChoices = choices => Object.assign(...choices.map(([k, v]) => ({ [k]: v })));
-
-function ListJobsController (
- $scope,
- $state,
- Dataset,
- resolvedModels,
- strings,
- qs,
- Prompt,
- $filter,
- ProcessErrors,
- Wait,
- Rest,
- SearchBasePath,
- $timeout
-) {
- const vm = this || {};
- const [unifiedJob] = resolvedModels;
-
- vm.strings = strings;
-
- let newJobs = [];
-
- // smart-search
- const name = 'jobs';
- const iterator = 'job';
- let paginateQuerySet = {};
-
- let launchModalOpen = false;
- let newJobsTimerRunning = false;
-
- vm.searchBasePath = SearchBasePath;
-
- vm.list = { iterator, name };
- vm.job_dataset = Dataset.data;
- vm.jobs = Dataset.data.results;
-
- $scope.$watch('$state.params', () => {
- setToolbarSort();
- }, true);
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.FINISH_TIME_DESCENDING')}`,
- value: '-finished'
- };
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'job_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- vm.toolbarSortOptions = [
- { label: `${strings.get('sort.NAME_ASCENDING')}`, value: 'name' },
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
- { label: `${strings.get('sort.FINISH_TIME_ASCENDING')}`, value: 'finished' },
- toolbarSortDefault,
- { label: `${strings.get('sort.START_TIME_ASCENDING')}`, value: 'started' },
- { label: `${strings.get('sort.START_TIME_DESCENDING')}`, value: '-started' },
- { label: `${strings.get('sort.LAUNCHED_BY_ASCENDING')}`, value: 'created_by__id' },
- { label: `${strings.get('sort.LAUNCHED_BY_DESCENDING')}`, value: '-created_by__id' },
- { label: `${strings.get('sort.PROJECT_ASCENDING')}`, value: 'unified_job_template__project__id' },
- { label: `${strings.get('sort.PROJECT_DESCENDING')}`, value: '-unified_job_template__project__id' }
- ];
-
- vm.toolbarSortValue = toolbarSortDefault;
-
- // Temporary hack to retrieve $scope.querySet from the paginate directive.
- // Remove this event listener once the page and page_size params
- // are represented in the url.
- $scope.$on('updateDataset', (event, dataset, queryset) => {
- paginateQuerySet = queryset;
- vm.jobs = dataset.results;
- vm.job_dataset = dataset;
- });
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.job_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update URL with params
- $state.go('.', {
- job_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- $scope.$watch('vm.job_dataset.count', () => {
- $scope.$emit('updateCount', vm.job_dataset.count, 'jobs');
- });
-
- const canAddRowsDynamically = () => {
- const orderByValue = _.get($state.params, 'job_search.order_by');
- const pageValue = _.get($state.params, 'job_search.page');
- const idInValue = _.get($state.params, 'job_search.id__in');
-
- return (!idInValue && (!pageValue || pageValue === '1')
- && (orderByValue === '-finished' || orderByValue === '-started'));
- };
-
- const updateJobRow = (msg) => {
- // Loop across the jobs currently shown and update the row
- // if it exists
- for (let i = 0; i < vm.jobs.length; i++) {
- if (vm.jobs[i].id === msg.unified_job_id) {
- // Update the job status.
- vm.jobs[i].status = msg.status;
- if (msg.finished) {
- vm.jobs[i].finished = msg.finished;
- const orderByValue = _.get($state.params, 'job_search.order_by');
- if (orderByValue === '-finished') {
- // Attempt to sort the rows in the list by their finish
- // timestamp in descending order
- vm.jobs.sort((a, b) =>
- (!b.finished) - (!a.finished)
- || new Date(b.finished) - new Date(a.finished));
- }
- }
- break;
- }
- }
- };
-
- $scope.$on('ws-jobs', (e, msg) => {
- if (msg.status === 'pending' && canAddRowsDynamically()) {
- newJobs.push(msg.unified_job_id);
- if (!launchModalOpen && !newJobsTimerRunning) {
- fetchNewJobs();
- }
- } else if (!newJobs.includes(msg.unified_job_id)) {
- updateJobRow(msg);
- }
- });
-
- $scope.$on('launchModalOpen', (evt, isOpen) => {
- evt.stopPropagation();
- if (!isOpen && newJobs.length > 0) {
- fetchNewJobs();
- }
- launchModalOpen = isOpen;
- });
-
- if ($state.includes('instanceGroups')) {
- vm.emptyListReason = strings.get('list.NO_RUNNING');
- }
-
- vm.isPortalMode = $state.includes('portalMode');
-
- vm.jobTypes = mapChoices(unifiedJob.options('actions.GET.type.choices'));
-
- vm.buildCredentialTags = (credentials) =>
- credentials.map(credential => {
- const icon = `${credential.kind}`;
- const link = `/#/credentials/${credential.id}`;
- const value = $filter('sanitize')(credential.name);
-
- return { icon, link, value };
- });
-
- vm.getSecondaryTagLabel = (job) => {
- if (job.job_slice_number && job.job_slice_count && job.job_slice_count > 1) {
- return `${strings.get('list.SLICE_JOB')} ${job.job_slice_number}/${job.job_slice_count}`;
- }
- if (job.launch_type === 'webhook') {
- return strings.get('list.ROW_ITEM_LABEL_WEBHOOK');
- }
- return null;
- };
-
- vm.getTranslatedStatusString = (status) => {
- switch (status) {
- case 'new':
- return strings.get('list.NEW');
- case 'pending':
- return strings.get('list.PENDING');
- case 'waiting':
- return strings.get('list.WAITING');
- case 'running':
- return strings.get('list.RUNNING');
- case 'successful':
- return strings.get('list.SUCCESSFUL');
- case 'failed':
- return strings.get('list.FAILED');
- case 'error':
- return strings.get('list.ERROR');
- case 'canceled':
- return strings.get('list.CANCELED');
- default:
- return status;
- }
- };
-
- vm.getSref = ({ type, id }) => {
- let sref;
-
- switch (type) {
- case 'job':
- sref = `output({type: 'playbook', id: ${id}})`;
- break;
- case 'ad_hoc_command':
- sref = `output({type: 'command', id: ${id}})`;
- break;
- case 'system_job':
- sref = `output({type: 'system', id: ${id}})`;
- break;
- case 'project_update':
- sref = `output({type: 'project', id: ${id}})`;
- break;
- case 'inventory_update':
- sref = `output({type: 'inventory', id: ${id}})`;
- break;
- case 'workflow_job':
- sref = `workflowResults({id: ${id}})`;
- break;
- default:
- sref = '';
- break;
- }
-
- return sref;
- };
-
- vm.deleteJob = (job) => {
- const action = () => {
- $('#prompt-modal').modal('hide');
- Wait('start');
- Rest.setUrl(job.url);
- Rest.destroy()
- .then(() => {
- let reloadListStateParams = null;
-
- if (vm.jobs.length === 1 && $state.params.job_search &&
- _.has($state, 'params.job_search.page') &&
- $state.params.job_search.page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.job_search.page =
- (parseInt(reloadListStateParams.job_search.page, 10) - 1).toString();
- }
-
- $state.go('.', reloadListStateParams, { reload: true });
- })
- .catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${job.url}`, status })
- });
- })
- .finally(() => {
- Wait('stop');
- });
- };
-
- const deleteModalBody = `${strings.get('deleteResource.CONFIRM', 'job')}
`;
-
- Prompt({
- hdr: strings.get('deleteResource.HEADER'),
- resourceName: $filter('sanitize')(job.name),
- body: deleteModalBody,
- action,
- actionText: strings.get('DELETE'),
- });
- };
-
- vm.cancelJob = (job) => {
- const action = () => {
- $('#prompt-modal').modal('hide');
- Wait('start');
- Rest.setUrl(job.related.cancel);
- Rest.post()
- .then(() => {
- let reloadListStateParams = null;
-
- if (vm.jobs.length === 1 && $state.params.job_search &&
- !_.isEmpty($state.params.job_search.page) &&
- $state.params.job_search.page !== '1') {
- const page = `${(parseInt(reloadListStateParams
- .job_search.page, 10) - 1)}`;
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.job_search.page = page;
- }
-
- $state.go('.', reloadListStateParams, { reload: true });
- })
- .catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${job.url}`, status })
- });
- })
- .finally(() => {
- Wait('stop');
- });
- };
-
- const deleteModalBody = `${strings.get('cancelJob.SUBMIT_REQUEST')}
`;
-
- Prompt({
- hdr: strings.get('cancelJob.HEADER'),
- resourceName: $filter('sanitize')(job.name),
- body: deleteModalBody,
- action,
- actionText: strings.get('cancelJob.CANCEL_JOB'),
- cancelText: strings.get('cancelJob.RETURN')
- });
- };
-
- const fetchNewJobs = () => {
- newJobsTimerRunning = true;
- const newJobIdsFilter = newJobs.join(',');
- newJobs = [];
- const newJobsSearchParams = Object.assign({}, $state.params.job_search);
- newJobsSearchParams.count_disabled = 1;
- newJobsSearchParams.id__in = newJobIdsFilter;
- delete newJobsSearchParams.page_size;
- const stringifiedSearchParams = qs.encodeQueryset(newJobsSearchParams, false);
- Rest.setUrl(`${vm.searchBasePath}${stringifiedSearchParams}`);
- Rest.get()
- .then(({ data }) => {
- vm.job_dataset.count += data.results.length;
- const pageSize = parseInt($state.params.job_search.page_size, 10) || 20;
- const joinedJobs = data.results.concat(vm.jobs);
- vm.jobs = joinedJobs.length > pageSize
- ? joinedJobs.slice(0, pageSize)
- : joinedJobs;
- $timeout(() => {
- if (canAddRowsDynamically()) {
- if (newJobs.length > 0 && !launchModalOpen) {
- fetchNewJobs();
- } else {
- newJobsTimerRunning = false;
- }
- } else {
- // Bail out - one of [order_by, page, id__in] params has changed since we
- // received these new job messages
- newJobs = [];
- newJobsTimerRunning = false;
- }
- }, 5000);
- })
- .catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', {
- path: `${vm.searchBasePath}${stringifiedSearchParams}`,
- status
- })
- });
- });
- };
-
- vm.isCollapsed = true;
-
- vm.onCollapse = () => {
- vm.isCollapsed = true;
- };
-
- vm.onExpand = () => {
- vm.isCollapsed = false;
- };
-}
-
-ListJobsController.$inject = [
- '$scope',
- '$state',
- 'Dataset',
- 'resolvedModels',
- 'JobsStrings',
- 'QuerySet',
- 'Prompt',
- '$filter',
- 'ProcessErrors',
- 'Wait',
- 'Rest',
- 'SearchBasePath',
- '$timeout'
-];
-
-export default ListJobsController;
diff --git a/awx/ui/client/features/jobs/jobsList.view.html b/awx/ui/client/features/jobs/jobsList.view.html
deleted file mode 100644
index 50b25c1aff..0000000000
--- a/awx/ui/client/features/jobs/jobsList.view.html
+++ /dev/null
@@ -1,113 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/jobs/routes/hostCompletedJobs.route.js b/awx/ui/client/features/jobs/routes/hostCompletedJobs.route.js
deleted file mode 100644
index 6d4034aa28..0000000000
--- a/awx/ui/client/features/jobs/routes/hostCompletedJobs.route.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import jobsListController from '../jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- url: '/completed_jobs',
- params: {
- job_search: {
- value: {
- page_size: '20',
- job__hosts: '',
- order_by: '-id'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- ncyBreadcrumb: {
- label: N_('COMPLETED JOBS')
- },
- views: {
- related: {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const hostId = $stateParams.host_id;
-
- const searchParam = _.assign($stateParams
- .job_search, { job__hosts: hostId });
-
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- }
-};
diff --git a/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js b/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js
deleted file mode 100644
index 91de83b254..0000000000
--- a/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import listContainerController from '~src/instance-groups/jobs/instanceGroupsJobsListContainer.controller';
-import { N_ } from '../../../src/i18n';
-import jobsListController from '../jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-const listContainerTemplate = require('~src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html');
-
-const instanceGroupJobsRoute = {
- name: 'instanceGroups.jobs',
- url: '/:instance_group_id/jobs',
- ncyBreadcrumb: {
- parent: 'instanceGroups.edit',
- label: N_('JOBS')
- },
- params: {
- job_search: {
- value: {
- page_size: '10',
- order_by: '-finished'
- },
- dynamic: true
- }
- },
- views: {
- 'instanceGroupsJobsContainer@instanceGroups': {
- templateUrl: listContainerTemplate,
- controller: listContainerController,
- controllerAs: 'vm'
- },
- 'jobsList@instanceGroups.jobs': {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- },
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const groupId = $stateParams.instance_group_id;
-
- const searchParam = $stateParams.job_search;
-
- const searchPath = `api/v2/instance_groups/${groupId}/jobs`;
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- '$stateParams',
- ($stateParams) => `api/v2/instance_groups/${$stateParams.instance_group_id}/jobs`
- ],
- }
-};
-
-const containerGroupJobsRoute = {
- name: 'instanceGroups.containerGroupJobs',
- url: '/container_groups/:instance_group_id/jobs',
- ncyBreadcrumb: {
- parent: 'instanceGroups.editContainerGroup',
- label: N_('JOBS')
- },
- params: {
- job_search: {
- value: {
- page_size: '10',
- order_by: '-finished'
- },
- dynamic: true
- }
- },
- views: {
- 'containerGroupJobs@instanceGroups': {
- templateUrl: listContainerTemplate,
- controller: listContainerController,
- controllerAs: 'vm'
- },
- 'jobsList@instanceGroups.containerGroupJobs': {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- },
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'QuerySet',
- ($stateParams, Wait, qs) => {
- const groupId = $stateParams.instance_group_id;
-
- const searchParam = $stateParams.job_search;
-
- const searchPath = `api/v2/instance_groups/${groupId}/jobs`;
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- '$stateParams',
- ($stateParams) => `api/v2/instance_groups/${$stateParams.instance_group_id}/jobs`
- ],
- }
-};
-
-export { instanceGroupJobsRoute, containerGroupJobsRoute };
diff --git a/awx/ui/client/features/jobs/routes/instanceJobs.route.js b/awx/ui/client/features/jobs/routes/instanceJobs.route.js
deleted file mode 100644
index b88bbb4cd8..0000000000
--- a/awx/ui/client/features/jobs/routes/instanceJobs.route.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import listContainerController from '~src/instance-groups/jobs/instanceJobsListContainer.controller';
-import { N_ } from '../../../src/i18n';
-import jobsListController from '../jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-const listContainerTemplate = require('~src/instance-groups/jobs/instanceJobsListContainer.partial.html');
-
-export default {
- name: 'instanceGroups.instanceJobs',
- url: '/:instance_group_id/instances/:instance_id/jobs',
- ncyBreadcrumb: {
- parent: 'instanceGroups.instances',
- label: N_('JOBS')
- },
- views: {
- 'instanceJobsContainer@instanceGroups': {
- templateUrl: listContainerTemplate,
- controller: listContainerController,
- controllerAs: 'vm'
- },
- 'jobsList@instanceGroups.instanceJobs': {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- },
- },
- params: {
- job_search: {
- value: {
- page_size: '10',
- order_by: '-finished'
- },
- dynamic: true
- },
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const instanceId = $stateParams.instance_id;
-
- const searchParam = $stateParams.job_search;
-
- const searchPath = `api/v2/instances/${instanceId}/jobs`;
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- '$stateParams',
- ($stateParams) => `api/v2/instances/${$stateParams.instance_id}/jobs`
- ]
- }
-};
diff --git a/awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js b/awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js
deleted file mode 100644
index 531e663909..0000000000
--- a/awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import jobsListController from '../jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- url: '/completed_jobs',
- params: {
- job_search: {
- value: {
- page_size: '20',
- or__job__inventory: '',
- or__adhoccommand__inventory: '',
- or__inventoryupdate__inventory_source__inventory: '',
- order_by: '-id'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- ncyBreadcrumb: {
- label: N_('JOBS')
- },
- views: {
- related: {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const inventoryId = $stateParams.inventory_id ?
- $stateParams.inventory_id : $stateParams.smartinventory_id;
-
- const searchParam = _.assign($stateParams.job_search, {
- or__job__inventory: inventoryId,
- or__adhoccommand__inventory: inventoryId,
- or__inventoryupdate__inventory_source__inventory: inventoryId,
- or__workflowjob__inventory: inventoryId,
- });
-
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- }
-};
diff --git a/awx/ui/client/features/jobs/routes/jobs.route.js b/awx/ui/client/features/jobs/routes/jobs.route.js
deleted file mode 100644
index 427d7d165d..0000000000
--- a/awx/ui/client/features/jobs/routes/jobs.route.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import indexController from '../index.controller';
-
-const indexTemplate = require('~features/jobs/index.view.html');
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- searchPrefix: 'job',
- name: 'jobs',
- url: '/jobs',
- ncyBreadcrumb: {
- label: N_('JOBS')
- },
- params: {
- job_search: {
- value: {
- not__launch_type: 'sync',
- order_by: '-finished'
- },
- dynamic: true,
- squash: false
- }
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'job',
- socket: {
- groups: {
- jobs: ['status_changed'],
- schedules: ['changed']
- }
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.job_search;
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- },
- views: {
- '@': {
- templateUrl: indexTemplate,
- controller: indexController,
- controllerAs: 'vm'
- },
- 'jobsList@jobs': {
- templateUrl: jobsListTemplate,
- controller: 'jobsListController',
- controllerAs: 'vm'
- }
- }
-};
diff --git a/awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js b/awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js
deleted file mode 100644
index e1323714cc..0000000000
--- a/awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import jobsListController from '../jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- url: '/completed_jobs',
- name: 'templates.editJobTemplate.completed_jobs',
- params: {
- job_search: {
- value: {
- page_size: '20',
- job__job_template: '',
- order_by: '-id'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- ncyBreadcrumb: {
- label: N_('COMPLETED JOBS')
- },
- views: {
- related: {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const templateId = $stateParams.job_template_id ?
- $stateParams.job_template_id : $stateParams.job_template_id;
-
- const searchParam = _.assign($stateParams
- .job_search, { job__job_template: templateId });
-
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- }
-};
diff --git a/awx/ui/client/features/jobs/routes/workflowJobTemplateCompletedJobs.route.js b/awx/ui/client/features/jobs/routes/workflowJobTemplateCompletedJobs.route.js
deleted file mode 100644
index 258cf325d4..0000000000
--- a/awx/ui/client/features/jobs/routes/workflowJobTemplateCompletedJobs.route.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import jobsListController from '../jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- url: '/completed_jobs',
- name: 'templates.editWorkflowJobTemplate.completed_jobs',
- params: {
- job_search: {
- value: {
- page_size: '20',
- workflow_job__workflow_job_template: '',
- order_by: '-id'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- ncyBreadcrumb: {
- label: N_('COMPLETED JOBS')
- },
- views: {
- related: {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const templateId = $stateParams.workflow_job_template_id;
-
- const searchParam = _.assign($stateParams
- .job_search, { workflow_job__workflow_job_template: templateId });
-
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- }
-};
diff --git a/awx/ui/client/features/output/_index.less b/awx/ui/client/features/output/_index.less
deleted file mode 100644
index a4bef87569..0000000000
--- a/awx/ui/client/features/output/_index.less
+++ /dev/null
@@ -1,474 +0,0 @@
-@import 'host-event/_index';
-.at-Stdout {
- &-menuTop {
- color: @at-gray-646972;
- border: 1px solid @at-gray-b7;
- border-top-left-radius: 4px;
- border-top-right-radius: 4px;
- border-bottom: none;
- margin-top: 15px;
-
- & > div {
- user-select: none;
- }
- }
-
- &-menuIconGroup {
- & > p {
- margin: 0;
- }
-
- & > p:first-child {
- font-size: 20px;
- margin-right: 8px;
- }
-
- & > p:last-child {
- margin-top: 9px;
- }
- }
-
- &-menuIcon {
- font-size: 12px;
- padding: 10px;
- cursor: pointer;
-
- &:hover {
- color: @at-blue;
- }
- }
-
- &-menuIcon--md {
- font-size: 14px;
- padding: 10px;
- cursor: pointer;
-
- &:hover {
- color: @at-blue;
- }
- }
-
- &-menuIcon--lg {
- font-size: 22px;
- line-height: 12px;
- font-weight: bold;
- padding: 10px;
- cursor: pointer;
-
- &:hover {
- color: @at-blue;
- }
- }
-
- &-menuIcon--active {
- font-size: 22px;
- line-height: 12px;
- font-weight: bold;
- padding: 10px;
- cursor: pointer;
- color: @at-blue;
- }
-
- &-row {
- display: flex;
-
- &:hover {
- background-color: white;
- }
-
- &:hover div {
- background-color: white;
- }
-
- &--hidden {
- display: none;
- }
- }
-
- &-row--clickable {
- cursor: pointer;
- }
-
- &-toggle {
- background-color: @at-gray-eb;
- color: @at-gray-646972;
- display: flex;
- flex: 0 0 30px;
- font-size: 18px;
- justify-content: center;
- line-height: 12px;
-
- & > i {
- cursor: pointer;
- }
-
- user-select: none;
- }
-
- &-line {
- color: @at-gray-161b1f;
- background-color: @at-gray-eb;
- flex: 0 0 45px;
- text-align: right;
- vertical-align: top;
- padding-right: 5px;
- border-right: 1px solid @at-gray-b7;
- user-select: none;
- }
-
- &-line--clickable {
- cursor: pointer;
- }
-
- &-event {
- .at-mixin-event();
- }
-
- &-time {
- padding-right: 2ch;
- font-size: 12px;
- text-align: right;
- user-select: none;
- width: 11ch;
-
- & > span {
- background-color: white;
- border-radius: 4px;
- padding: 1px 2px;
- }
- }
-
- &-wrapper {
- display: flex;
- flex-flow: column nowrap;
- height: 100%;
- }
-
- &-container {
- background-color: @at-gray-f2;
- border-radius: 0 0 4px 4px;
- border: 1px solid @at-gray-b7;
- color: @at-gray-161b1f;
- display: flex;
- flex-direction: column;
- flex: 1;
- font-family: monospace;
- font-size: 15px;
- height: 100%;
- margin: 0;
- overflow-y: scroll;
- padding: 0;
-
- @media screen and (max-width: @breakpoint-md) {
- max-height: calc(100vh - 30px);
- }
- }
-
- &-borderHeader {
- .at-mixin-stdoutBorder();
- height: 10px;
- }
-
- &-borderFooter {
- .at-mixin-stdoutBorder();
- flex: 1;
- }
-
- &--fullscreen {
- grid-column-start: 1;
- grid-column-end: 3;
- }
-
- /* The ng-transclude tag that gets injected as a part of at-Panel was throwing off the height
- of the panel after Bootstrap's move to display: flex. This seemed like the most concise fix*/
- ng-transclude {
- display: flex;
- flex-flow: column nowrap;
- height: 100%;
- }
-}
-
-.at-mixin-event() {
- padding: 0 10px;
- white-space: pre-wrap;
- word-break: break-all;
- word-wrap: break-word;
-}
-
-.at-mixin-stdoutBorder() {
- background-color: @at-gray-eb;
- border-right: 1px solid @at-gray-b7;
- width: 75px;
-}
-
-// Search ---------------------------------------------------------------------------------
-@at-jobz-top-search-key: @at-space-2x;
-@at-jobz-bottom-search-key: @at-space-3x;
-
-.jobz-searchKeyPaneContainer {
- margin-top: @at-jobz-top-search-key;
- margin-bottom: @at-jobz-bottom-search-key;
-}
-
-.jobz-searchKeyPane {
- // background-color: @at-gray-f6;
- background-color: @login-notice-bg;
- color: @login-notice-text;
- border-radius: @at-border-radius;
- border: 1px solid @at-gray-b7;
- // color: @at-gray-646972;
- padding: 6px @at-padding-input 6px @at-padding-input;
-}
-
-.jobz-searchClearAllContainer {
- .at-mixin-VerticallyCenter();
-}
-
-.jobz-searchClearAll {
- font-size: 10px;
-}
-
-.jobz-Button-searchKey {
- .at-mixin-Button();
-
- background-color: @at-blue;
- border-color: at-color-button-border-default;
- color: @at-white;
-
- &:hover, &:active {
- color: @at-white;
- background-color: @at-blue-hover;
- box-shadow: none;
- }
-
- &:focus {
- color: @at-white;
- }
-}
-
-.jobz-tagz {
- margin-top: @at-space;
- display: flex;
- width: 100%;
- flex-wrap: wrap;
- margin-left: -5px;
-}
-
-// Status Bar -----------------------------------------------------------------------------
-.HostStatusBar {
- display: flex;
- flex: 0 0 auto;
- width: 100%;
- margin-bottom: 15px;
-}
-
-.HostStatusBar-ok,
-.HostStatusBar-changed,
-.HostStatusBar-dark,
-.HostStatusBar-failures,
-.HostStatusBar-skipped,
-.HostStatusBar-noData {
- height: 15px;
- border-top: 5px solid @default-bg;
- border-bottom: 5px solid @default-bg;
-}
-
-.HostStatusBar-ok {
- background-color: @default-succ;
- display: flex;
- flex: 0 0 auto;
-}
-
-.HostStatusBar-changed {
- background-color: @default-warning;
- flex: 0 0 auto;
-}
-
-.HostStatusBar-dark {
- background-color: @default-unreachable;
- flex: 0 0 auto;
-}
-
-.HostStatusBar-failures {
- background-color: @default-err;
- flex: 0 0 auto;
-}
-
-.HostStatusBar-skipped {
- background-color: @default-link;
- flex: 0 0 auto;
-}
-
-.HostStatusBar-noData {
- background-color: @default-icon-hov;
- flex: 1 0 auto;
-}
-
-.HostStatusBar-tooltipLabel {
- text-transform: uppercase;
- margin-right: 15px;
-}
-
-.HostStatusBar-tooltipBadge {
- border-radius: 5px;
- border: 1px solid @default-bg;
-}
-
-.HostStatusBar-tooltipBadge--ok {
- background-color: @default-succ;
-}
-
-.HostStatusBar-tooltipBadge--dark {
- background-color: @default-unreachable;
-}
-
-.HostStatusBar-tooltipBadge--skipped {
- background-color: @default-link;
-}
-
-.HostStatusBar-tooltipBadge--changed {
- background-color: @default-warning;
-}
-
-.HostStatusBar-tooltipBadge--failures {
- background-color: @default-err;
-
-}
-
-.HostStatusBar-tooltip.top {
- margin-top: 4px;
-}
-
-// Job Details ---------------------------------------------------------------------------------
-
-@breakpoint-md: 1200px;
-
-.JobResults-container {
- display: grid;
- grid-gap: 20px;
- grid-template-columns: minmax(400px, 1fr) minmax(500px, 2fr);
- grid-template-rows: minmax(500px, ~"calc(100vh - 130px)");
-
- .at-Panel {
- min-width: 0;
- overflow-y: auto;
- }
-}
-
-.JobResults-detailsPanel {
- display: flex;
- flex-direction: column;
-}
-
-.JobResults-panelHeader {
- display: flex;
- height: 30px;
-}
-
-.JobResults-panelHeaderText {
- color: @default-interface-txt;
- flex: 1 0 auto;
- font-size: 14px;
- font-weight: bold;
- margin-right: 10px;
- text-transform: uppercase;
-}
-
-.JobResults-panelHeaderButtonActions {
- display: flex;
-}
-
-.JobResults-resultRow {
- width: 100%;
- display: flex;
- padding-bottom: 10px;
- flex-wrap: wrap;
-}
-
-.JobResults-resultRow div[id$='variables-container'] {
- width: 100%;
-}
-
-.JobResults-resultRowLabel {
- text-transform: uppercase;
- color: @default-interface-txt;
- font-size: 12px;
- font-weight: normal!important;
- width: 30%;
- margin-right: 20px;
-
- @media screen and (max-width: @breakpoint-md) {
- flex: 2.5 0 auto;
- }
-}
-
-.JobResults-resultRowLabel--fullWidth {
- width: 100%;
- margin-right: 0px;
-}
-
-.JobResults-resultRowText {
- display: flex;
- flex-flow: row wrap;
- width: ~"calc(70% - 20px)";
- flex: 1 0 auto;
- text-transform: none;
- word-wrap: break-word;
-}
-
-.JobResults-resultRowText--fullWidth {
- width: 100%;
-}
-
-.JobResults-expandArrow {
- color: #D7D7D7;
- font-size: 14px;
- font-weight: bold;
- margin-right: 10px;
- text-transform: uppercase;
- margin-left: 10px;
-}
-
-.JobResults-resultRowText--instanceGroup {
- display: flex;
-}
-
-.JobResults-isolatedBadge {
- align-items: center;
- background-color: @default-list-header-bg;
- border-radius: 5px;
- color: @default-stdout-txt;
- display: flex;
- font-size: 10px;
- height: 16px;
- margin: 3px 0 0 10px;
- padding: 0 10px;
- text-transform: uppercase;
-}
-
-.JobResults-statusResultIcon {
- padding-left: 0px;
- padding-right: 10px;
-}
-
-.StandardOut-panelHeader {
- flex: initial;
-}
-
-.JobResults-seeMoreLess {
- color: #337AB7;
- margin: 4px 0px;
- text-transform: uppercase;
- padding: 2px 0px;
- cursor: pointer;
- border-radius: 5px;
- font-size: 11px;
-}
-
-@media screen and (max-width: @breakpoint-md) {
- .JobResults-container {
- display: flex;
- flex-direction: column;
- min-width: 400px;
- }
-}
diff --git a/awx/ui/client/features/output/api.events.service.js b/awx/ui/client/features/output/api.events.service.js
deleted file mode 100644
index 9da4f34ba8..0000000000
--- a/awx/ui/client/features/output/api.events.service.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import {
- API_MAX_PAGE_SIZE,
- OUTPUT_ORDER_BY,
- OUTPUT_PAGE_SIZE,
-} from './constants';
-
-const BASE_PARAMS = {
- page_size: OUTPUT_PAGE_SIZE,
- order_by: OUTPUT_ORDER_BY,
-};
-
-const merge = (...objs) => _.merge({}, ...objs);
-
-function JobEventsApiService ($http, $q) {
- this.init = (endpoint, params) => {
- this.endpoint = endpoint;
- this.params = merge(BASE_PARAMS, params);
-
- this.state = { count: 0, maxCounter: 0 };
- this.cache = {};
- };
-
- this.fetch = () => this.getLast()
- .then(results => {
- this.cache.last = results;
-
- return this;
- });
-
- this.clearCache = () => {
- Object.keys(this.cache).forEach(key => {
- delete this.cache[key];
- });
- };
-
- this.pushMaxCounter = events => {
- const maxCounter = Math.max(...events.map(({ counter }) => counter));
-
- if (maxCounter > this.state.maxCounter) {
- this.state.maxCounter = maxCounter;
- }
-
- return maxCounter;
- };
-
- this.getFirst = () => {
- const params = merge(this.params, { page: 1 });
-
- return $http.get(this.endpoint, { params })
- .then(({ data }) => {
- const { results, count } = data;
-
- this.state.count = count;
- this.pushMaxCounter(results);
-
- return results;
- });
- };
-
- this.getPage = number => {
- if (number < 1 || number > this.getLastPageNumber()) {
- return $q.resolve([]);
- }
-
- const params = merge(this.params, { page: number });
-
- return $http.get(this.endpoint, { params })
- .then(({ data }) => {
- const { results, count } = data;
-
- this.state.count = count;
- this.pushMaxCounter(results);
-
- return results;
- });
- };
-
- this.getLast = () => {
- if (this.cache.last) {
- return $q.resolve(this.cache.last);
- }
-
- const params = merge(this.params, { page: 1, order_by: `-${OUTPUT_ORDER_BY}` });
-
- return $http.get(this.endpoint, { params })
- .then(({ data }) => {
- const { results, count } = data;
-
- let rotated = results;
-
- if (count > OUTPUT_PAGE_SIZE) {
- rotated = results.splice(count % OUTPUT_PAGE_SIZE);
-
- if (results.length > 0) {
- rotated = results;
- }
- }
-
- this.state.count = count;
- this.pushMaxCounter(results);
-
- return rotated;
- });
- };
-
- this.getRange = range => {
- if (!range) {
- return $q.resolve([]);
- }
-
- const [low, high] = range;
-
- if (low > high) {
- return $q.resolve([]);
- }
-
- const params = merge(this.params, { counter__gte: [low], counter__lte: [high] });
-
- params.page_size = API_MAX_PAGE_SIZE;
-
- return $http.get(this.endpoint, { params })
- .then(({ data }) => {
- const { results } = data;
-
- this.pushMaxCounter(results);
-
- return results;
- });
- };
-
- this.getLastPageNumber = () => Math.ceil(this.state.count / OUTPUT_PAGE_SIZE);
- this.getMaxCounter = () => this.state.maxCounter;
-}
-
-JobEventsApiService.$inject = ['$http', '$q'];
-
-export default JobEventsApiService;
diff --git a/awx/ui/client/features/output/constants.js b/awx/ui/client/features/output/constants.js
deleted file mode 100644
index d82bafd17c..0000000000
--- a/awx/ui/client/features/output/constants.js
+++ /dev/null
@@ -1,51 +0,0 @@
-export const API_MAX_PAGE_SIZE = 200;
-export const API_ROOT = '/api/v2/';
-
-export const EVENT_START_TASK = 'playbook_on_task_start';
-export const EVENT_START_PLAY = 'playbook_on_play_start';
-export const EVENT_START_PLAYBOOK = 'playbook_on_start';
-export const EVENT_STATS_PLAY = 'playbook_on_stats';
-
-export const HOST_STATUS_KEYS = ['dark', 'failures', 'changed', 'ok', 'skipped'];
-
-export const JOB_STATUS_COMPLETE = ['successful', 'failed', 'unknown'];
-export const JOB_STATUS_INCOMPLETE = ['canceled', 'error'];
-export const JOB_STATUS_UNSUCCESSFUL = ['failed'].concat(JOB_STATUS_INCOMPLETE);
-export const JOB_STATUS_FINISHED = JOB_STATUS_COMPLETE.concat(JOB_STATUS_INCOMPLETE);
-
-export const OUTPUT_ANSI_COLORMAP = {
- 0: '#000',
- 1: '#A00',
- 2: '#080',
- 3: '#F0AD4E',
- 4: '#00A',
- 5: '#A0A',
- 6: '#0AA',
- 7: '#AAA',
- 8: '#555',
- 9: '#F55',
- 10: '#5F5',
- 11: '#FF5',
- 12: '#55F',
- 13: '#F5F',
- 14: '#5FF',
- 15: '#FFF'
-};
-export const OUTPUT_ELEMENT_CONTAINER = '.at-Stdout-container';
-export const OUTPUT_ELEMENT_TBODY = '#atStdoutResultTable';
-export const OUTPUT_ELEMENT_LAST = '#atStdoutMenuLast';
-export const OUTPUT_MAX_BUFFER_LENGTH = 1000;
-export const OUTPUT_MAX_LAG = 120;
-export const OUTPUT_NO_COUNT_JOB_TYPES = ['ad_hoc_command', 'system_job', 'inventory_update'];
-export const OUTPUT_ORDER_BY = 'start_line';
-export const OUTPUT_PAGE_CACHE = true;
-export const OUTPUT_PAGE_LIMIT = 5;
-export const OUTPUT_PAGE_SIZE = 50;
-export const OUTPUT_SCROLL_DELAY = 100;
-export const OUTPUT_SCROLL_THRESHOLD = 0.1;
-export const OUTPUT_SEARCH_DOCLINK = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/search_sort.html';
-export const OUTPUT_SEARCH_FIELDS = ['changed', 'created', 'failed', 'host_name', 'stdout', 'task', 'role', 'playbook', 'play', 'start_line', 'end_line'];
-export const OUTPUT_SEARCH_KEY_EXAMPLES = ['host_name:localhost', 'task:set', 'created:>=2000-01-01', 'start_line:>=9000'];
-export const OUTPUT_EVENT_LIMIT = OUTPUT_PAGE_LIMIT * OUTPUT_PAGE_SIZE;
-
-export const WS_PREFIX = 'ws';
diff --git a/awx/ui/client/features/output/details.component.js b/awx/ui/client/features/output/details.component.js
deleted file mode 100644
index 8f1c8ef361..0000000000
--- a/awx/ui/client/features/output/details.component.js
+++ /dev/null
@@ -1,935 +0,0 @@
-const templateUrl = require('~features/output/details.partial.html');
-
-let $http;
-let $filter;
-let $state;
-
-let error;
-let parse;
-let prompt;
-let resource;
-let strings;
-let wait;
-
-let vm;
-
-function mapChoices (choices) {
- if (!choices) return {};
- return Object.assign(...choices.map(([k, v]) => ({ [k]: v })));
-}
-
-function getStatusDetails (jobStatus) {
- const unmapped = jobStatus || resource.model.get('status');
-
- if (!unmapped) {
- return null;
- }
-
- const choices = mapChoices(resource.model.options('actions.GET.status.choices'));
- const label = strings.get('labels.STATUS');
-
- let icon;
- let value;
-
- if (unmapped === 'unknown') {
- icon = 'fa icon-job-pending';
- value = strings.get('details.UNKNOWN');
- } else {
- icon = `fa icon-job-${unmapped}`;
- value = choices[unmapped];
- }
-
- return { unmapped, label, icon, value };
-}
-
-function getStartDetails (started) {
- const unfiltered = started || resource.model.get('started');
- const label = strings.get('labels.STARTED');
-
- let value;
-
- if (unfiltered) {
- value = $filter('longDate')(unfiltered);
- } else {
- value = strings.get('details.NOT_STARTED');
- }
-
- return { label, value };
-}
-
-function getFinishDetails (finished) {
- const unfiltered = finished || resource.model.get('finished');
- const label = strings.get('labels.FINISHED');
-
- let value;
-
- if (unfiltered) {
- value = $filter('longDate')(unfiltered);
- } else {
- value = strings.get('details.NOT_FINISHED');
- }
-
- return { label, value };
-}
-
-function getModuleArgDetails () {
- const value = resource.model.get('module_args');
- const label = strings.get('labels.MODULE_ARGS');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getJobTypeDetails () {
- const unmapped = resource.model.get('job_type');
-
- if (!unmapped) {
- return null;
- }
-
- const choices = mapChoices(resource.model.options('actions.GET.job_type.choices'));
-
- const label = strings.get('labels.JOB_TYPE');
- const value = choices[unmapped];
-
- return { label, value };
-}
-
-function getVerbosityDetails () {
- const verbosity = resource.model.get('verbosity');
-
- if (!verbosity) {
- return null;
- }
-
- const choices = mapChoices(resource.model.options('actions.GET.verbosity.choices'));
-
- const label = strings.get('labels.VERBOSITY');
- const value = choices[verbosity];
-
- return { label, value };
-}
-
-function getEnvironmentDetails (virtualenv) {
- const customVirtualenv = virtualenv || resource.model.get('custom_virtualenv');
-
- if (!customVirtualenv || customVirtualenv === '') {
- return null;
- }
-
- const label = strings.get('labels.ENVIRONMENT');
- const value = $filter('sanitize')(customVirtualenv);
-
- return { label, value };
-}
-
-function getSourceWorkflowJobDetails () {
- const sourceWorkflowJob = resource.model.get('summary_fields.source_workflow_job');
-
- if (!sourceWorkflowJob) {
- return null;
- }
-
- const label = strings.get('labels.SOURCE_WORKFLOW_JOB');
- const value = sourceWorkflowJob.name;
- const link = `/#/workflows/${sourceWorkflowJob.id}`;
- const tooltip = strings.get('tooltips.SOURCE_WORKFLOW_JOB');
-
- return { label, value, link, tooltip };
-}
-
-function getSliceJobDetails () {
- const count = resource.model.get('job_slice_count');
-
- if (!count) {
- return null;
- }
-
- if (count === 1) {
- return null;
- }
-
- const number = resource.model.get('job_slice_number');
-
- if (!number) {
- return null;
- }
-
- const label = strings.get('labels.SLICE_JOB');
- const offset = `${number}/${count}`;
- const tooltip = strings.get('tooltips.SLICE_JOB_DETAILS');
-
- if (label && offset && tooltip) {
- return { label, offset, tooltip };
- }
- return null;
-}
-
-function getJobTemplateDetails () {
- const jobTemplate = resource.model.get('summary_fields.job_template');
-
- if (!jobTemplate) {
- return null;
- }
-
- const label = strings.get('labels.JOB_TEMPLATE');
- const link = `/#/templates/job_template/${jobTemplate.id}`;
- const value = $filter('sanitize')(jobTemplate.name);
- const tooltip = strings.get('tooltips.JOB_TEMPLATE');
-
- return { label, link, value, tooltip };
-}
-
-function getInventorySourceDetails () {
- if (!resource.model.has('summary_fields.inventory_source.source')) {
- return null;
- }
-
- if (resource.model.get('summary_fields.inventory_source.source') === 'scm') {
- // we already show a SOURCE PROJECT item for scm inventory updates, so we
- // skip the display of the standard source details item.
- return null;
- }
-
- const { source } = resource.model.get('summary_fields.inventory_source');
- const choices = mapChoices(resource.model.options('actions.GET.source.choices'));
-
- const label = strings.get('labels.SOURCE');
- const value = choices[source];
-
- return { label, value };
-}
-
-function getOverwriteDetails () {
- if (!resource.model.has('overwrite')) {
- return null;
- }
-
- const label = strings.get('labels.OVERWRITE');
- const value = resource.model.get('overwrite');
-
- return { label, value };
-}
-
-function getOverwriteVarsDetails () {
- if (!resource.model.has('overwrite_vars')) {
- return null;
- }
-
- const label = strings.get('labels.OVERWRITE_VARS');
- const value = resource.model.get('overwrite_vars');
-
- return { label, value };
-}
-
-function getLicenseErrorDetails () {
- if (!resource.model.has('license_error')) {
- return null;
- }
-
- const label = strings.get('labels.LICENSE_ERROR');
- const value = resource.model.get('license_error');
-
- return { label, value };
-}
-
-function getHostLimitErrorDetails () {
- if (!resource.model.has('org_host_limit_error')) {
- return null;
- }
-
- const label = strings.get('labels.HOST_LIMIT_ERROR');
- const tooltip = strings.get('tooltips.HOST_LIMIT');
- const value = resource.model.get('org_host_limit_error');
-
- return { tooltip, label, value };
-}
-
-function getLaunchedByDetails () {
- const createdBy = resource.model.get('summary_fields.created_by');
- const jobTemplate = resource.model.get('summary_fields.job_template');
- const workflowJobTemplate = resource.model.get('summary_fields.workflow_job_template');
- const relatedSchedule = resource.model.get('related.schedule');
- const schedule = resource.model.get('summary_fields.schedule');
- const launchType = resource.model.get('launch_type');
-
- if (!createdBy && !schedule && !launchType) {
- return null;
- }
-
- const label = strings.get('labels.LAUNCHED_BY');
-
- let link;
- let tooltip;
- let value;
-
- if (launchType === 'webhook' && jobTemplate) {
- tooltip = strings.get('tooltips.WEBHOOK_JOB_TEMPLATE');
- link = `/#/templates/job_template/${jobTemplate.id}`;
- value = strings.get('details.WEBHOOK');
- } else if (launchType === 'webhook' && workflowJobTemplate) {
- tooltip = strings.get('tooltips.WEBHOOK_WORKFLOW_JOB_TEMPLATE');
- link = `/#/templates/workflow_job_template/${workflowJobTemplate.id}`;
- value = strings.get('details.WEBHOOK');
- } else if (createdBy) {
- tooltip = strings.get('tooltips.USER');
- link = `/#/users/${createdBy.id}`;
- value = $filter('sanitize')(createdBy.username);
- } else if (relatedSchedule && jobTemplate) {
- tooltip = strings.get('tooltips.SCHEDULE');
- link = `/#/templates/job_template/${jobTemplate.id}/schedules/${schedule.id}`;
- value = $filter('sanitize')(schedule.name);
- } else if (schedule) {
- tooltip = null;
- link = null;
- value = $filter('sanitize')(schedule.name);
- } else {
- return null;
- }
-
- return { label, link, tooltip, value };
-}
-
-function getInventoryDetails () {
- const inventory = resource.model.get('summary_fields.inventory');
-
- if (!inventory) {
- return null;
- }
-
- const label = strings.get('labels.INVENTORY');
- const tooltip = strings.get('tooltips.INVENTORY');
- const value = $filter('sanitize')(inventory.name);
-
- let link;
-
- if (inventory.kind === 'smart') {
- link = `/#/inventories/smart/${inventory.id}`;
- } else {
- link = `/#/inventories/inventory/${inventory.id}`;
- }
-
- return { label, link, tooltip, value };
-}
-
-function getProjectDetails () {
- const project = resource.model.get('summary_fields.project');
-
- if (!project) {
- return null;
- }
-
- const label = strings.get('labels.PROJECT');
- const link = `/#/projects/${project.id}`;
- const value = project.name;
- const tooltip = strings.get('tooltips.PROJECT');
-
- return { label, link, value, tooltip };
-}
-
-function getProjectStatusDetails (projectStatus) {
- const project = resource.model.get('summary_fields.project');
- const jobStatus = projectStatus || resource.model.get('summary_fields.project_update.status');
-
- if (!project) {
- return null;
- }
-
- return jobStatus;
-}
-
-function getProjectUpdateDetails (updateId) {
- const project = resource.model.get('summary_fields.project');
- const jobId = updateId || resource.model.get('summary_fields.project_update.id');
-
- if (!project) {
- return null;
- }
-
- const link = `/#/jobs/project/${jobId}`;
- const tooltip = strings.get('tooltips.PROJECT_UPDATE');
-
- return { link, tooltip };
-}
-
-function getSCMBranchDetails (scmBranch) {
- const label = strings.get('labels.SCM_BRANCH');
- const value = scmBranch || resource.model.get('scm_branch');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getSCMRefspecDetails (scmRefspec) {
- const label = strings.get('labels.SCM_REFSPEC');
- const value = scmRefspec || resource.model.get('scm_refspec');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getInventoryScmDetails (updateId, updateStatus) {
- const projectId = resource.model.get('summary_fields.source_project.id');
- const projectName = resource.model.get('summary_fields.source_project.name');
- const jobId = updateId || resource.model.get('source_project_update');
- const status = updateStatus || resource.model.get('summary_fields.inventory_source.status');
-
- if (!projectId || !projectName) {
- return null;
- }
-
- const label = strings.get('labels.INVENTORY_SCM');
- const jobLink = `/#/jobs/project/${jobId}`;
- const link = `/#/projects/${projectId}`;
- const jobTooltip = strings.get('tooltips.INVENTORY_SCM_JOB');
- const tooltip = strings.get('tooltips.INVENTORY_SCM');
- const value = $filter('sanitize')(projectName);
-
- let icon;
-
- if (status === 'unknown') {
- icon = 'fa icon-job-pending';
- } else {
- icon = `fa icon-job-${status}`;
- }
-
- return { label, link, icon, jobLink, jobTooltip, tooltip, value };
-}
-
-function getSCMRevisionDetails () {
- const label = strings.get('labels.SCM_REVISION');
- const value = resource.model.get('scm_revision');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getPlaybookDetails () {
- const label = strings.get('labels.PLAYBOOK');
- const value = resource.model.get('playbook');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getJobExplanationDetails () {
- const explanation = resource.model.get('job_explanation');
-
- if (!explanation) {
- return null;
- }
-
- const limit = 150;
- const label = strings.get('labels.JOB_EXPLANATION');
-
- let more = explanation;
-
- if (explanation.split(':')[0] === 'Previous Task Failed') {
- const taskStringIndex = explanation.split(':')[0].length + 1;
- const task = JSON.parse(explanation.substring(taskStringIndex));
-
- more = `${task.job_type} failed for ${task.job_name} with ID ${task.job_id}`;
- }
-
- const less = $filter('limitTo')(more, limit);
-
- const showMore = false;
- const hasMoreToShow = more.length > limit;
-
- return { label, less, more, showMore, hasMoreToShow };
-}
-
-function getResultTracebackDetails (resultTraceback) {
- const traceback = resultTraceback || resource.model.get('result_traceback');
-
- if (!traceback) {
- return null;
- }
-
- const limit = 150;
- const label = strings.get('labels.RESULT_TRACEBACK');
-
- const more = traceback;
- const less = $filter('limitTo')(more, limit);
-
- const showMore = false;
- const hasMoreToShow = more.length > limit;
-
- return { label, less, more, showMore, hasMoreToShow };
-}
-
-function getCredentialDetails () {
- let credentials = [];
- let credentialTags = [];
-
- if (resource.model.get('type') === 'job') {
- credentials = resource.model.get('summary_fields.credentials');
- } else {
- const credential = resource.model.get('summary_fields.credential');
- if (credential) {
- credentials.push(credential);
- }
- }
-
- if (!credentials || credentials.length < 1) {
- return null;
- }
-
- credentialTags = credentials.map((cred) => buildCredentialDetails(cred));
-
- const label = strings.get('labels.CREDENTIAL');
- const value = credentialTags;
-
- return { label, value };
-}
-
-function buildCredentialDetails (credential) {
- let icon;
- if (credential.cloud) {
- icon = 'cloud';
- } else {
- icon = `${credential.kind}`;
- }
-
- const link = `/#/credentials/${credential.id}`;
- const tooltip = strings.get('tooltips.CREDENTIAL');
- const value = $filter('sanitize')(credential.name);
-
- return { icon, link, tooltip, value };
-}
-
-function getForkDetails () {
- const label = strings.get('labels.FORKS');
- const value = resource.model.get('forks');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getLimitDetails () {
- const label = strings.get('labels.LIMIT');
- const value = resource.model.get('limit');
-
- if (!value) {
- return null;
- }
-
- return { label, value };
-}
-
-function getExecutionNodeDetails (node) {
- const executionNode = node || resource.model.get('execution_node');
-
- if (!executionNode) {
- return null;
- }
-
- const label = strings.get('labels.EXECUTION_NODE');
- const value = $filter('sanitize')(executionNode);
-
- return { label, value };
-}
-
-function getInstanceGroupDetails () {
- const instanceGroup = resource.model.get('summary_fields.instance_group');
-
- if (!instanceGroup) {
- return null;
- }
-
- const value = $filter('sanitize')(instanceGroup.name);
-
- let label = strings.get('labels.INSTANCE_GROUP');
- let link = `/#/instance_groups/${instanceGroup.id}`;
- if (instanceGroup.is_containerized) {
- label = strings.get('labels.CONTAINER_GROUP');
- link = `/#/instance_groups/container_group/${instanceGroup.id}`;
- }
-
- let isolated = null;
- if (instanceGroup.controller_id) {
- isolated = strings.get('details.ISOLATED');
- }
-
- return { label, value, isolated, link };
-}
-
-function getJobTagDetails () {
- const tagString = resource.model.get('job_tags');
-
- let jobTags;
-
- if (tagString) {
- jobTags = tagString.split(',').filter(tag => tag !== '');
- } else {
- jobTags = [];
- }
-
- if (jobTags.length < 1) {
- return null;
- }
-
- const label = strings.get('labels.JOB_TAGS');
- const more = false;
-
- const value = jobTags.map($filter('sanitize'));
-
- return { label, more, value };
-}
-
-function getSkipTagDetails () {
- const tagString = resource.model.get('skip_tags');
-
- let skipTags;
-
- if (tagString) {
- skipTags = tagString.split(',').filter(tag => tag !== '');
- } else {
- skipTags = [];
- }
-
- if (skipTags.length < 1) {
- return null;
- }
-
- const more = false;
- const label = strings.get('labels.SKIP_TAGS');
- const value = skipTags.map($filter('sanitize'));
-
- return { label, more, value };
-}
-
-function getExtraVarsDetails () {
- const extraVars = resource.model.get('extra_vars');
-
- if (!extraVars) {
- return null;
- }
-
- const label = strings.get('labels.EXTRA_VARS');
- const tooltip = strings.get('tooltips.EXTRA_VARS');
- const value = parse(extraVars);
- const disabled = true;
- const name = 'extra_vars';
-
- return { label, tooltip, value, disabled, name };
-}
-
-function getArtifactsDetails (val) {
- const artifacts = val || resource.model.get('artifacts');
- if (!artifacts || (Object.entries(artifacts).length === 0 &&
- artifacts.constructor === Object)) {
- return null;
- }
-
- const label = strings.get('labels.ARTIFACTS');
- const tooltip = strings.get('tooltips.ARTIFACTS');
- const value = parse(artifacts);
- const disabled = true;
- const name = 'artifacts';
-
- return { label, tooltip, value, disabled, name };
-}
-
-function getLabelDetails () {
- const jobLabels = _.get(resource.model.get('summary_fields.labels'), 'results', []);
-
- if (jobLabels.length < 1) {
- return null;
- }
-
- const label = strings.get('labels.LABELS');
- const more = false;
- const value = jobLabels.map(({ name }) => name).map($filter('sanitize'));
- const truncate = true;
- const truncateLength = 5;
- const hasMoreToShow = jobLabels.length > truncateLength;
-
- return { label, more, hasMoreToShow, value, truncate, truncateLength };
-}
-
-function createErrorHandler (path, action) {
- return res => {
- const hdr = strings.get('error.HEADER');
- const msg = strings.get('error.CALL', { path, action, status: res.status });
-
- error(null, res.data, res.status, null, { hdr, msg });
- };
-}
-
-const ELEMENT_LABELS = '#job-results-labels';
-const ELEMENT_JOB_TAGS = '#job-results-job-tags';
-const ELEMENT_SKIP_TAGS = '#job-results-skip-tags';
-const ELEMENT_PROMPT_MODAL = '#prompt-modal';
-const TAGS_SLIDE_DISTANCE = 200;
-
-function showLabels () {
- this.labels.truncate = !this.labels.truncate;
-
- const jobLabelsCount = _.get(resource.model.get('summary_fields.labels'), 'count');
- const maxCount = 50;
-
- if (this.labels.value.length === jobLabelsCount || this.labels.value.length >= maxCount) {
- return;
- }
-
- const config = {
- params: {
- page_size: maxCount
- }
- };
-
- wait('start');
- resource.model.extend('get', 'labels', config)
- .then((model) => {
- const jobLabels = _.get(model.get('related.labels'), 'results', []);
- this.labels.value = jobLabels.map(({ name }) => name).map($filter('sanitize'));
- })
- .catch(createErrorHandler('get labels', 'GET'))
- .finally(() => wait('stop'));
-}
-
-function toggleLabels () {
- if (!this.labels.more) {
- $(ELEMENT_LABELS).slideUp(TAGS_SLIDE_DISTANCE);
- this.labels.more = true;
- } else {
- $(ELEMENT_LABELS).slideDown(TAGS_SLIDE_DISTANCE);
- this.labels.more = false;
- }
-}
-
-function toggleJobTags () {
- if (!this.jobTags.more) {
- $(ELEMENT_JOB_TAGS).slideUp(TAGS_SLIDE_DISTANCE);
- this.jobTags.more = true;
- } else {
- $(ELEMENT_JOB_TAGS).slideDown(TAGS_SLIDE_DISTANCE);
- this.jobTags.more = false;
- }
-}
-
-function toggleSkipTags () {
- if (!this.skipTags.more) {
- $(ELEMENT_SKIP_TAGS).slideUp(TAGS_SLIDE_DISTANCE);
- this.skipTags.more = true;
- } else {
- $(ELEMENT_SKIP_TAGS).slideDown(TAGS_SLIDE_DISTANCE);
- this.skipTags.more = false;
- }
-}
-
-function cancelJob () {
- const actionText = strings.get('cancelJob.CANCEL_JOB');
- const hdr = strings.get('cancelJob.HEADER');
- const warning = strings.get('cancelJob.SUBMIT_REQUEST');
- const cancelText = strings.get('cancelJob.RETURN');
-
- const id = resource.model.get('id');
- const name = $filter('sanitize')(resource.model.get('name'));
-
- const body = `${warning}
`;
- const resourceName = `#${id} ${name}`;
-
- const method = 'POST';
- const url = `${resource.model.path}${id}/cancel/`;
-
- const errorHandler = createErrorHandler('cancel job', method);
-
- const action = () => {
- wait('start');
- $http({ method, url })
- .catch(errorHandler)
- .finally(() => {
- $(ELEMENT_PROMPT_MODAL).modal('hide');
- wait('stop');
- });
- };
-
- prompt({ hdr, resourceName, body, actionText, action, cancelText });
-}
-
-function deleteJob () {
- const actionText = strings.get('DELETE');
- const hdr = strings.get('deleteResource.HEADER');
- const warning = strings.get('deleteResource.CONFIRM', 'job');
-
- const id = resource.model.get('id');
- const name = $filter('sanitize')(resource.model.get('name'));
-
- const body = `${warning}
`;
- const resourceName = `#${id} ${name}`;
-
- const method = 'DELETE';
- const url = `${resource.model.path}${id}/`;
-
- const errorHandler = createErrorHandler('delete job', method);
-
- const action = () => {
- wait('start');
- $http({ method, url })
- .then(() => $state.go('jobs'))
- .catch(errorHandler)
- .finally(() => {
- $(ELEMENT_PROMPT_MODAL).modal('hide');
- wait('stop');
- });
- };
-
- prompt({ hdr, resourceName, body, actionText, action });
-}
-
-function JobDetailsController (
- _$http_,
- _$filter_,
- _$state_,
- _error_,
- _prompt_,
- _strings_,
- _wait_,
- _parse_,
- { subscribe },
-) {
- vm = this || {};
-
- $http = _$http_;
- $filter = _$filter_;
- $state = _$state_;
- error = _error_;
-
- parse = _parse_;
- prompt = _prompt_;
- strings = _strings_;
- wait = _wait_;
-
- let unsubscribe;
-
- vm.$onInit = () => {
- resource = this.resource; // eslint-disable-line prefer-destructuring
- vm.strings = strings;
-
- vm.status = getStatusDetails();
- vm.started = getStartDetails();
- vm.finished = getFinishDetails();
- vm.moduleArgs = getModuleArgDetails();
- vm.jobType = getJobTypeDetails();
- vm.jobTemplate = getJobTemplateDetails();
- vm.sourceWorkflowJob = getSourceWorkflowJobDetails();
- vm.sliceJobDetails = getSliceJobDetails();
- vm.inventory = getInventoryDetails();
- vm.project = getProjectDetails();
- vm.projectUpdate = getProjectUpdateDetails();
- vm.projectStatus = getProjectStatusDetails();
- vm.scmBranch = getSCMBranchDetails();
- vm.scmRefspec = getSCMRefspecDetails();
- vm.scmRevision = getSCMRevisionDetails();
- vm.inventoryScm = getInventoryScmDetails();
- vm.playbook = getPlaybookDetails();
- vm.resultTraceback = getResultTracebackDetails();
- vm.launchedBy = getLaunchedByDetails();
- vm.jobExplanation = getJobExplanationDetails();
- vm.verbosity = getVerbosityDetails();
- vm.environment = getEnvironmentDetails();
- vm.credentials = getCredentialDetails();
- vm.forks = getForkDetails();
- vm.limit = getLimitDetails();
- vm.executionNode = getExecutionNodeDetails();
- vm.instanceGroup = getInstanceGroupDetails();
- vm.jobTags = getJobTagDetails();
- vm.skipTags = getSkipTagDetails();
- vm.extraVars = getExtraVarsDetails();
- vm.artifacts = getArtifactsDetails();
- vm.labels = getLabelDetails();
- vm.inventorySource = getInventorySourceDetails();
- vm.overwrite = getOverwriteDetails();
- vm.overwriteVars = getOverwriteVarsDetails();
- vm.licenseError = getLicenseErrorDetails();
- vm.hostLimitError = getHostLimitErrorDetails();
-
- // Relaunch and Delete Components
- vm.job = angular.copy(_.get(resource.model, 'model.GET', {}));
- vm.canDelete = resource.model.get('summary_fields.user_capabilities.delete');
-
- vm.cancelJob = cancelJob;
- vm.deleteJob = deleteJob;
- vm.toggleJobTags = toggleJobTags;
- vm.toggleSkipTags = toggleSkipTags;
- vm.toggleLabels = toggleLabels;
- vm.showLabels = showLabels;
-
- unsubscribe = subscribe(({
- status,
- started,
- finished,
- scm,
- scmBranch,
- scmRefspec,
- inventoryScm,
- scmRevision,
- instanceGroup,
- environment,
- artifacts,
- executionNode,
- resultTraceback
- }) => {
- vm.started = getStartDetails(started);
- vm.finished = getFinishDetails(finished);
- vm.projectUpdate = getProjectUpdateDetails(scm.id);
- vm.projectStatus = getProjectStatusDetails(scm.status);
- vm.scmBranch = getSCMBranchDetails(scmBranch);
- vm.scmRefspec = getSCMRefspecDetails(scmRefspec);
- vm.environment = getEnvironmentDetails(environment);
- vm.artifacts = getArtifactsDetails(artifacts);
- vm.executionNode = getExecutionNodeDetails(executionNode);
- vm.inventoryScm = getInventoryScmDetails(inventoryScm.id, inventoryScm.status);
- vm.resultTraceback = getResultTracebackDetails(resultTraceback);
- vm.scmRevision = getSCMRevisionDetails(scmRevision);
- vm.instanceGroup = getInstanceGroupDetails(instanceGroup);
- vm.status = getStatusDetails(status);
- vm.job.status = status;
- });
- };
-
- vm.$onDestroy = () => {
- unsubscribe();
- };
-}
-
-JobDetailsController.$inject = [
- '$http',
- '$filter',
- '$state',
- 'ProcessErrors',
- 'Prompt',
- 'OutputStrings',
- 'Wait',
- 'ParseVariableString',
- 'OutputStatusService',
-];
-
-export default {
- templateUrl,
- controller: JobDetailsController,
- controllerAs: 'vm',
- bindings: {
- resource: '<'
- },
-};
diff --git a/awx/ui/client/features/output/details.partial.html b/awx/ui/client/features/output/details.partial.html
deleted file mode 100644
index abcb281298..0000000000
--- a/awx/ui/client/features/output/details.partial.html
+++ /dev/null
@@ -1,479 +0,0 @@
-
-
-
-
-
-
-
-
{{ vm.status.label }}
-
-
- {{ vm.status.value }}
-
-
-
-
-
-
{{ vm.jobExplanation.label }}
-
- {{ vm.jobExplanation.less }}
- ...
-
- {{:: vm.strings.get('details.SHOW_MORE') }}
-
-
-
- {{ vm.jobExplanation.more }}
-
- {{:: vm.strings.get('details.SHOW_LESS') }}
-
-
-
-
-
-
-
{{ vm.licenseError.label }}
-
- {{ vm.licenseError.value }}
-
-
-
-
-
-
- {{ vm.hostLimitError.label }}
-
-
-
-
-
- {{ vm.hostLimitError.value }}
-
-
-
-
-
-
{{ vm.started.label }}
-
- {{ vm.started.value }}
-
-
-
-
-
-
{{ vm.finished.label }}
-
- {{ vm.finished.value }}
-
-
-
-
-
-
{{ vm.moduleArgs.label }}
-
{{ vm.moduleArgs.value }}
-
-
-
-
-
{{ vm.resultTraceback.label }}
-
- {{ vm.resultTraceback.less }}
- ...
-
- {{:: vm.strings.get('details.SHOW_MORE') }}
-
-
-
- {{ vm.resultTraceback.more }}
-
- {{:: vm.strings.get('details.SHOW_LESS') }}
-
-
-
-
-
-
-
{{ vm.jobTemplate.label }}
-
-
-
-
-
-
{{ vm.jobType.label }}
-
{{ vm.jobType.value }}
-
-
-
-
-
{{ vm.sliceJobDetails.label }}
-
{{ vm.sliceJobDetails.offset }}
-
-
-
-
-
{{ vm.launchedBy.label }}
-
-
- {{ vm.launchedBy.value }}
-
-
-
-
-
-
{{ vm.inventory.label }}
-
-
-
-
-
-
{{ vm.project.label }}
-
-
-
-
-
-
{{ vm.scmBranch.label }}
-
{{ vm.scmBranch.value }}
-
-
-
-
-
{{ vm.scmRefspec.label }}
-
{{ vm.scmRefspec.value }}
-
-
-
-
-
{{ vm.inventoryScm.label }}
-
-
-
-
-
-
{{ vm.scmRevision.label }}
-
-
-
-
-
-
{{ vm.playbook.label }}
-
{{ vm.playbook.value }}
-
-
-
-
-
{{ vm.credentials.label }}
-
-
-
-
-
-
{{ vm.inventorySource.label }}
-
- {{ vm.inventorySource.value }}
-
-
-
-
-
-
{{ vm.overwrite.label }}
-
- {{ vm.overwrite.value }}
-
-
-
-
-
-
{{ vm.overwriteVars.label }}
-
- {{ vm.overwriteVars.value }}
-
-
-
-
-
-
{{ vm.forks.label }}
-
{{ vm.forks.value }}
-
-
-
-
-
{{ vm.limit.label }}
-
{{ vm.limit.value }}
-
-
-
-
-
{{ vm.verbosity.label }}
-
{{ vm.verbosity.value }}
-
-
-
-
-
{{ vm.environment.label }}
-
{{ vm.environment.value }}
-
-
-
-
-
{{ vm.executionNode.label }}
-
{{ vm.executionNode.value }}
-
-
-
-
-
-
-
-
{{ vm.sourceWorkflowJob.label }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('details.SHOW_MORE') }}
-
-
-
-
-
- {{:: vm.strings.get('details.SHOW_LESS') }}
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/output/host-event/_index.less b/awx/ui/client/features/output/host-event/_index.less
deleted file mode 100644
index f93f80a56d..0000000000
--- a/awx/ui/client/features/output/host-event/_index.less
+++ /dev/null
@@ -1,193 +0,0 @@
-.noselect {
- -webkit-touch-callout: none; /* iOS Safari */
- -webkit-user-select: none; /* Chrome/Safari/Opera */
- -khtml-user-select: none; /* Konqueror */
- -moz-user-select: none; /* Firefox */
- -ms-user-select: none; /* Internet Explorer/Edge */
- user-select: none; /* Non-prefixed version, currently
- not supported by any browser */
-}
-
-@media screen and (min-width: 768px){
- .HostEvent .modal-dialog{
- width: 700px;
- }
-}
-.HostEvent .CodeMirror{
- overflow-x: hidden;
- max-height: none!important;
-}
-
-.HostEvent-close:hover{
- color: @btn-txt;
- background-color: @btn-bg-hov;
-}
-
-.HostEvent-body{
- margin-bottom: 20px;
-}
-.HostEvent-tab {
- color: @btn-txt;
- background-color: @btn-bg;
- font-size: 12px;
- border: 1px solid @btn-bord;
- height: 30px;
- border-radius: 5px;
- margin-right: 20px;
- padding-left: 10px;
- padding-right: 10px;
- padding-bottom: 5px;
- padding-top: 5px;
- transition: background-color 0.2s;
- text-transform: uppercase;
- text-align: center;
- white-space: nowrap;
- .noselect;
-}
-.HostEvent-tab:hover {
- color: @btn-txt;
- background-color: @btn-bg-hov;
- cursor: pointer;
-}
-.HostEvent-tab--selected{
- color: @btn-txt-sel!important;
- background-color: @default-icon!important;
- border-color: @default-icon!important;
-}
-.HostEvent-view--container{
- width: 100%;
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- justify-content: space-between;
-}
-.HostEvent .modal-footer{
- border: 0;
- margin-top: 0px;
- padding-top: 5px;
-}
-.HostEvent-controls{
- float: right;
- button {
- margin-left: 10px;
- }
-}
-.HostEvent-status--ok{
- color: @green;
-}
-.HostEvent-status--unreachable{
- color: @unreachable;
-}
-.HostEvent-status--changed{
- color: @changed;
-}
-.HostEvent-status--failed{
- color: @default-err;
-}
-.HostEvent-status--skipped{
- color: @skipped;
-}
-.HostEvent-header{
- padding-bottom: 15px;
-}
-.HostEvent-title{
- color: @default-interface-txt;
- font-weight: 600;
- margin-bottom: 8px;
-}
-.HostEvent .modal-body{
- padding: 0px!important;
- overflow-y: auto;
-}
-.HostEvent-nav{
- padding-top: 12px;
- padding-bottom: 20px;
-}
-.HostEvent-field{
- margin-bottom: 8px;
- flex: 0 1 12em;
-}
-.HostEvent-field--label{
- text-transform: uppercase;
- flex: 0 1 80px;
- max-width: 80px;
- min-width: 80px;
- font-size: 12px;
- word-wrap: break-word;
-}
-.HostEvent-field{
- .OnePlusTwo-left--detailsRow;
-}
-.HostEvent-field--content{
- word-wrap: break-word;
-}
-.HostEvent-field--monospaceContent{
- font-family: monospace;
-}
-.HostEvent-button:disabled {
- pointer-events: all!important;
-}
-
-.HostEvent-stdout{
- height:200px;
- width:100%
-}
-
-.HostEvent-stdoutContainer {
- height:200px;
- overflow-y: scroll;
- overflow-x: hidden;
- border-radius: 5px;
- border: 1px solid #ccc;
- font-style: normal;
- background-color: @default-no-items-bord;
- font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
-}
-
-.HostEvent-numberColumnPreload {
- background-color: @default-list-header-bg;
- height: 198px;
- border-right: 1px solid #ccc;
- width: 30px;
- position: fixed;
-}
-
-.HostEvent-numberColumn {
- background-color: @default-list-header-bg;
- border-right: 1px solid #ccc;
- border-bottom-left-radius: 5px;
- color: #999;
- font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
- position: fixed;
- padding: 4px 3px 0 5px;
- text-align: right;
- white-space: nowrap;
- width: 30px;
-}
-
-.HostEvent-numberColumn--second{
- padding-top:0px;
-}
-
-.HostEvent-stdoutColumn{
- overflow-y: hidden;
- overflow-x: auto;
- margin-left: 46px;
- padding-top: 4px;
- white-space: pre-wrap;
- word-break: break-all;
- word-wrap: break-word;
-}
-
-.HostEvent-noJson{
- align-items: center;
- background-color: @default-no-items-bord;
- border: 1px solid @default-icon-hov;
- border-radius: 5px;
- color: @b7grey;
- display: flex;
- height: 200px;
- justify-content: center;
- text-transform: uppercase;
- width: 100%;
-}
diff --git a/awx/ui/client/features/output/host-event/host-event-codemirror.partial.html b/awx/ui/client/features/output/host-event/host-event-codemirror.partial.html
deleted file mode 100644
index e766c768a5..0000000000
--- a/awx/ui/client/features/output/host-event/host-event-codemirror.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-No JSON data returned by the module
diff --git a/awx/ui/client/features/output/host-event/host-event-modal.partial.html b/awx/ui/client/features/output/host-event/host-event-modal.partial.html
deleted file mode 100644
index 1557334d04..0000000000
--- a/awx/ui/client/features/output/host-event/host-event-modal.partial.html
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
-
-
-
-
-
- {{strings.get('host_event_modal.CREATED')}}
- {{(event.created | longDate) || "No result found"}}
-
-
- {{strings.get('host_event_modal.ID')}}
- {{event.id || "No result found"}}
-
-
- {{strings.get('host_event_modal.PLAY')}}
- {{event.play || "No result found"}}
-
-
- {{strings.get('host_event_modal.TASK')}}
- {{event.task || "No result found"}}
-
-
- {{strings.get('host_event_modal.MODULE')}}
- {{module_name}}
-
-
-
-
-
-
-
- JSON
-
-
- {{strings.get('host_event_modal.STANDARD_OUT')}}
-
-
- {{strings.get('host_event_modal.STANDARD_ERROR')}}
-
-
-
-
-
-
-
- {{strings.get('CLOSE')}}
-
-
-
-
-
diff --git a/awx/ui/client/features/output/host-event/host-event-stderr.partial.html b/awx/ui/client/features/output/host-event/host-event-stderr.partial.html
deleted file mode 100644
index e775d17681..0000000000
--- a/awx/ui/client/features/output/host-event/host-event-stderr.partial.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
diff --git a/awx/ui/client/features/output/host-event/host-event-stdout.partial.html b/awx/ui/client/features/output/host-event/host-event-stdout.partial.html
deleted file mode 100644
index 96df87b163..0000000000
--- a/awx/ui/client/features/output/host-event/host-event-stdout.partial.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
diff --git a/awx/ui/client/features/output/host-event/host-event.controller.js b/awx/ui/client/features/output/host-event/host-event.controller.js
deleted file mode 100644
index 87f698db9d..0000000000
--- a/awx/ui/client/features/output/host-event/host-event.controller.js
+++ /dev/null
@@ -1,177 +0,0 @@
-function HostEventsController (
- $scope,
- $state,
- $filter,
- HostEventService,
- hostEvent,
- OutputStrings
-) {
- $scope.processEventStatus = HostEventService.processEventStatus;
- $scope.processResults = processResults;
- $scope.isActiveState = isActiveState;
- $scope.getActiveHostIndex = getActiveHostIndex;
- $scope.closeHostEvent = closeHostEvent;
- $scope.strings = OutputStrings;
-
- const sanitize = $filter('sanitize');
-
- function init () {
- hostEvent.event_name = hostEvent.event;
- $scope.event = _.cloneDeep(hostEvent);
-
- // grab standard out & standard error if present from the host
- // event's 'res' object, for things like Ansible modules. Small
- // wrinkle in this implementation is that the stdout/stderr tabs
- // should be shown if the `res` object has stdout/stderr keys, even
- // if they're a blank string. The presence of these keys is
- // potentially significant to a user.
- if (_.has(hostEvent.event_data, 'task_action')) {
- $scope.module_name = hostEvent.event_data.task_action;
- } else if (!_.has(hostEvent.event_data, 'task_action')) {
- $scope.module_name = 'No result found';
- }
-
- if (_.has(hostEvent.event_data, 'res.stdout')) {
- if (hostEvent.event_data.res.stdout === '') {
- $scope.stdout = ' ';
- } else {
- $scope.stdout = sanitize(hostEvent.event_data.res.stdout);
- }
- }
-
- if (_.has(hostEvent.event_data, 'res.stderr')) {
- if (hostEvent.event_data.res.stderr === '') {
- $scope.stderr = ' ';
- } else {
- $scope.stderr = sanitize(hostEvent.event_data.res.stderr);
- }
- }
-
- if (_.has(hostEvent.event_data, 'res')) {
- $scope.json = hostEvent.event_data.res;
- }
-
- if ($scope.module_name === 'debug' &&
- _.has(hostEvent.event_data, 'res.result.stdout')) {
- $scope.stdout = sanitize(hostEvent.event_data.res.result.stdout);
- }
- if ($scope.module_name === 'yum' &&
- _.has(hostEvent.event_data, 'res.results') &&
- _.isArray(hostEvent.event_data.res.results)) {
- const event = hostEvent.event_data.res.results;
- $scope.stdout = sanitize(event[0]);// eslint-disable-line prefer-destructuring
- }
- // instantiate Codemirror
- if ($state.current.name === 'output.host-event.json') {
- try {
- if (_.has(hostEvent.event_data, 'res')) {
- initCodeMirror(
- 'HostEvent-codemirror',
- JSON.stringify($scope.json, null, 4),
- { name: 'javascript', json: true }
- );
- resize();
- } else {
- $scope.no_json = true;
- }
- } catch (err) {
- // element with id HostEvent-codemirror is not the view
- // controlled by this instance of HostEventController
- }
- } else if ($state.current.name === 'output.host-event.stdout') {
- try {
- resize();
- } catch (err) {
- // element with id HostEvent-codemirror is not the view
- // controlled by this instance of HostEventController
- }
- } else if ($state.current.name === 'output.host-event.stderr') {
- try {
- resize();
- } catch (err) {
- // element with id HostEvent-codemirror is not the view
- // controlled by this instance of HostEventController
- }
- }
- $('#HostEvent').modal('show');
- $('.modal-content').resizable({
- minHeight: 523,
- minWidth: 600
- });
- $('.modal-dialog').draggable({
- cancel: '.HostEvent-view--container'
- });
-
- function resize () {
- if ($state.current.name === 'output.host-event.json') {
- const editor = $('.CodeMirror')[0].CodeMirror;
- const height = $('.modal-dialog').height() - $('.HostEvent-header').height() - $('.HostEvent-details').height() - $('.HostEvent-nav').height() - $('.HostEvent-controls').height() - 120;
- editor.setSize('100%', height);
- } else if ($state.current.name === 'output.host-event.stdout' || $state.current.name === 'output.host-event.stderr') {
- const height = $('.modal-dialog').height() - $('.HostEvent-header').height() - $('.HostEvent-details').height() - $('.HostEvent-nav').height() - $('.HostEvent-controls').height() - 120;
- $('.HostEvent-stdout').width('100%');
- $('.HostEvent-stdout').height(height);
- $('.HostEvent-stdoutContainer').height(height);
- $('.HostEvent-numberColumnPreload').height(height);
- }
- }
-
- $('.modal-dialog').on('resize', resize);
-
- $('#HostEvent').on('hidden.bs.modal', $scope.closeHostEvent);
- }
-
- function processResults (value) {
- if (typeof value === 'object') {
- return false;
- }
- return true;
- }
-
- function initCodeMirror (el, data, mode) {
- const container = document.getElementById(el);
- const options = {};
- options.lineNumbers = true;
- options.mode = mode;
- options.readOnly = true;
- options.scrollbarStyle = null;
- const editor = CodeMirror.fromTextArea(// eslint-disable-line no-undef
- container,
- options
- );
- editor.setSize('100%', 200);
- editor.getDoc().setValue(data);
- }
-
- function isActiveState (name) {
- return $state.current.name === name;
- }
-
- function getActiveHostIndex () {
- function hostResultfilter (obj) {
- return obj.id === $scope.event.id;
- }
- const result = $scope.hostResults.filter(hostResultfilter);
- return $scope.hostResults.indexOf(result[0]);
- }
-
- function closeHostEvent () {
- // Unbind the listener so it doesn't fire when we close the modal via navigation
- $('#HostEvent').off('hidden.bs.modal');
- $('#HostEvent').modal('hide');
- $state.go('output');
- }
- $scope.init = init;
- $scope.init();
-}
-
-HostEventsController.$inject = [
- '$scope',
- '$state',
- '$filter',
- 'HostEventService',
- 'hostEvent',
- 'OutputStrings'
-];
-
-module.exports = HostEventsController;
diff --git a/awx/ui/client/features/output/host-event/host-event.route.js b/awx/ui/client/features/output/host-event/host-event.route.js
deleted file mode 100644
index aba9273327..0000000000
--- a/awx/ui/client/features/output/host-event/host-event.route.js
+++ /dev/null
@@ -1,72 +0,0 @@
-const HostEventModalTemplate = require('~features/output/host-event/host-event-modal.partial.html');
-const HostEventCodeMirrorTemplate = require('~features/output/host-event/host-event-codemirror.partial.html');
-const HostEventStdoutTemplate = require('~features/output/host-event/host-event-stdout.partial.html');
-const HostEventStderrTemplate = require('~features/output/host-event/host-event-stderr.partial.html');
-
-function exit () {
- // close the modal
- // using an onExit event to handle cases where the user navs away
- // using the url bar / back and not modal "X"
- $('#HostEvent').modal('hide');
- // hacky way to handle user browsing away via URL bar
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
-}
-
-function HostEventResolve (HostEventService, $stateParams) {
- return HostEventService.getRelatedJobEvents($stateParams.id, $stateParams.type, {
- id: $stateParams.eventId
- }).then((response) => response.data.results[0]);
-}
-
-HostEventResolve.$inject = [
- 'HostEventService',
- '$stateParams',
-];
-
-const hostEventModal = {
- name: 'output.host-event',
- url: '/host-event/:eventId',
- controller: 'HostEventsController',
- templateUrl: HostEventModalTemplate,
- abstract: false,
- ncyBreadcrumb: {
- skip: true
- },
- resolve: {
- hostEvent: HostEventResolve
- },
- onExit: exit
-};
-
-const hostEventJson = {
- name: 'output.host-event.json',
- url: '/json',
- controller: 'HostEventsController',
- templateUrl: HostEventCodeMirrorTemplate,
- ncyBreadcrumb: {
- skip: true
- },
-};
-
-const hostEventStdout = {
- name: 'output.host-event.stdout',
- url: '/stdout',
- controller: 'HostEventsController',
- templateUrl: HostEventStdoutTemplate,
- ncyBreadcrumb: {
- skip: true
- },
-};
-
-const hostEventStderr = {
- name: 'output.host-event.stderr',
- url: '/stderr',
- controller: 'HostEventsController',
- templateUrl: HostEventStderrTemplate,
- ncyBreadcrumb: {
- skip: true
- },
-};
-
-export { hostEventJson, hostEventModal, hostEventStdout, hostEventStderr };
diff --git a/awx/ui/client/features/output/host-event/host-event.service.js b/awx/ui/client/features/output/host-event/host-event.service.js
deleted file mode 100644
index 4709c1055f..0000000000
--- a/awx/ui/client/features/output/host-event/host-event.service.js
+++ /dev/null
@@ -1,92 +0,0 @@
-function HostEventService (
- Rest,
- ProcessErrors,
- GetBasePath,
- $rootScope
-) {
- this.getUrl = (id, type, params) => {
- const queryString = this.stringifyParams(params);
-
- let baseUrl;
- let related;
-
- if (type === 'playbook') {
- baseUrl = GetBasePath('jobs');
- related = 'job_events';
- }
-
- if (type === 'command') {
- baseUrl = GetBasePath('ad_hoc_commands');
- related = 'events';
- }
-
- if (type === 'project') {
- baseUrl = GetBasePath('project_updates');
- related = 'events';
- }
-
- return `${baseUrl}${id}/${related}/?${queryString}`;
- };
-
- // GET events related to a job run
- // e.g.
- // ?event=playbook_on_stats
- // ?parent=206&event__startswith=runner&page_size=200&order=host_name,counter
- this.getRelatedJobEvents = (id, type, params) => {
- const url = this.getUrl(id, type, params);
- Rest.setUrl(url);
- return Rest.get()
- .then(response => response)
- .catch(({ data, status }) => {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: `Call to ${url}. GET returned: ${status}` });
- });
- };
-
- this.stringifyParams = params => {
- function reduceFunction (result, value, key) {
- return `${result}${key}=${value}&`;
- }
- return _.reduce(params, reduceFunction, '');
- };
-
- // Generate a helper class for job_event statuses
- // the stack for which status to display is
- // unreachable > failed > changed > ok
- // uses the API's runner events and convenience properties .failed .changed to determine status.
- // see: job_event_callback.py for more filters to support
- this.processEventStatus = event => {
- const obj = {};
- if (event.event === 'runner_on_unreachable') {
- obj.class = 'HostEvent-status--unreachable';
- obj.status = 'unreachable';
- }
- // equiv to 'runner_on_error' && 'runner on failed'
- if (event.failed) {
- obj.class = 'HostEvent-status--failed';
- obj.status = 'failed';
- }
- if (event.event === 'runner_on_ok' || event.event === 'runner_on_async_ok') {
- obj.class = 'HostEvent-status--ok';
- obj.status = 'ok';
- }
- // if both 'changed' and 'ok' are true, show 'changed' status
- if (event.changed) {
- obj.class = 'HostEvent-status--changed';
- obj.status = 'changed';
- }
- if (event.event === 'runner_on_skipped') {
- obj.class = 'HostEvent-status--skipped';
- obj.status = 'skipped';
- }
- return obj;
- };
-}
-
-HostEventService.$inject = [
- 'Rest',
- 'ProcessErrors',
- 'GetBasePath',
- '$rootScope'
-];
-export default HostEventService;
diff --git a/awx/ui/client/features/output/host-event/index.js b/awx/ui/client/features/output/host-event/index.js
deleted file mode 100644
index f00b0b36b4..0000000000
--- a/awx/ui/client/features/output/host-event/index.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import {
- hostEventModal,
- hostEventJson,
- hostEventStdout,
- hostEventStderr
-} from './host-event.route';
-import controller from './host-event.controller';
-import service from './host-event.service';
-
-const MODULE_NAME = 'hostEvents';
-
-function hostEventRun ($stateExtender) {
- $stateExtender.addState(hostEventModal);
- $stateExtender.addState(hostEventJson);
- $stateExtender.addState(hostEventStdout);
- $stateExtender.addState(hostEventStderr);
-}
-hostEventRun.$inject = [
- '$stateExtender'
-];
-
-angular.module(MODULE_NAME, [])
- .controller('HostEventsController', controller)
- .service('HostEventService', service)
- .run(hostEventRun);
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/output/index.controller.js b/awx/ui/client/features/output/index.controller.js
deleted file mode 100644
index 7f171f728a..0000000000
--- a/awx/ui/client/features/output/index.controller.js
+++ /dev/null
@@ -1,881 +0,0 @@
-/* eslint camelcase: 0 */
-import {
- EVENT_START_PLAY,
- EVENT_START_TASK,
- OUTPUT_ELEMENT_LAST,
- OUTPUT_PAGE_SIZE,
-} from './constants';
-
-let $q;
-let $scope;
-let $state;
-
-let resource;
-let render;
-let scroll;
-let status;
-let slide;
-let stream;
-let page;
-
-let vm;
-const listeners = [];
-let lockFrames = false;
-
-function onFrames (events) {
- events = slide.pushFrames(events);
-
- if (lockFrames) {
- return $q.resolve();
- }
-
- const popCount = events.length - render.getCapacity();
-
- if (!vm.isFollowing && canStartFollowing()) {
- startFollowing();
- }
-
- if (!vm.isFollowing && popCount > 0) {
- return $q.resolve();
- }
-
- scroll.pause();
-
- if (vm.isFollowing) {
- scroll.scrollToBottom();
- }
-
- return render.popBack(popCount)
- .then(() => {
- if (vm.isFollowing) {
- scroll.scrollToBottom();
- }
-
- return render.pushFront(events);
- })
- .then(() => {
- if (vm.isFollowing) {
- scroll.scrollToBottom();
- }
-
- scroll.resume();
-
- return $q.resolve();
- });
-}
-
-//
-// Menu Controls (Running)
-//
-
-function firstRange () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- stopFollowing();
- lockFollow = true;
-
- if (slide.isOnFirstPage()) {
- scroll.resetScrollPosition();
-
- return $q.resolve();
- }
-
- scroll.pause();
- lockFrames = true;
-
- return render.clear()
- .then(() => slide.getFirst())
- .then(results => render.pushFront(results))
- .then(() => slide.getNext())
- .then(results => {
- const popCount = results.length - render.getCapacity();
-
- return render.popBack(popCount)
- .then(() => render.pushFront(results));
- })
- .finally(() => {
- render.compile();
- scroll.resume();
- lockFollow = false;
- });
-}
-
-function nextRange () {
- if (vm.isFollowing) {
- scroll.scrollToBottom();
-
- return $q.resolve();
- }
-
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
- lockFrames = true;
-
- return slide.getNext()
- .then(results => {
- const popCount = results.length - render.getCapacity();
-
- return render.popBack(popCount)
- .then(() => render.pushFront(results));
- })
- .finally(() => {
- render.compile();
- scroll.resume();
- lockFrames = false;
-
- return $q.resolve();
- });
-}
-
-function previousRange () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
- stopFollowing();
- lockFrames = true;
-
- let initialPosition;
- let popHeight;
-
- return slide.getPrevious()
- .then(results => {
- const popCount = results.length - render.getCapacity();
- initialPosition = scroll.getScrollPosition();
-
- return render.popFront(popCount)
- .then(() => {
- popHeight = scroll.getScrollHeight();
-
- return render.pushBack(results);
- });
- })
- .then(() => {
- const currentHeight = scroll.getScrollHeight();
- scroll.setScrollPosition(currentHeight - popHeight + initialPosition);
-
- return $q.resolve();
- })
- .finally(() => {
- render.compile();
- scroll.resume();
- lockFrames = false;
-
- return $q.resolve();
- });
-}
-
-function lastRange () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
- lockFrames = true;
-
- return render.clear()
- .then(() => slide.getLast())
- .then(results => render.pushFront(results))
- .then(() => {
- stream.setMissingCounterThreshold(slide.getTailCounter() + 1);
-
- scroll.scrollToBottom();
- lockFrames = false;
-
- return $q.resolve();
- })
- .finally(() => {
- render.compile();
- scroll.resume();
-
- return $q.resolve();
- });
-}
-
-function menuLastRange () {
- if (vm.isFollowing) {
- lockFollow = true;
- stopFollowing();
-
- return $q.resolve();
- }
-
- lockFollow = false;
-
- return lastRange()
- .then(() => {
- startFollowing();
-
- return $q.resolve();
- });
-}
-
-let followOnce;
-let lockFollow;
-function canStartFollowing () {
- if (lockFollow) {
- return false;
- }
-
- if (slide.isOnLastPage() && scroll.isBeyondLowerThreshold()) {
- followOnce = false;
-
- return true;
- }
-
- if (followOnce && // one-time activation from top of first page
- scroll.isBeyondUpperThreshold()) {
- followOnce = false;
-
- return true;
- }
-
- return false;
-}
-
-function startFollowing () {
- if (vm.isFollowing) {
- return;
- }
-
- vm.isFollowing = true;
- vm.followTooltip = vm.strings.get('tooltips.MENU_FOLLOWING');
-}
-
-function stopFollowing () {
- if (!vm.isFollowing) {
- return;
- }
-
- scroll.unlock();
- scroll.unhide();
-
- vm.isFollowing = false;
- vm.followTooltip = vm.strings.get('tooltips.MENU_LAST');
-}
-
-//
-// Menu Controls (Page Mode)
-//
-
-function firstPage () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
-
- return render.clear()
- .then(() => page.getFirst())
- .then(results => render.pushFront(results))
- .then(() => page.getNext())
- .then(results => {
- const popCount = page.trimHead();
-
- return render.popBack(popCount)
- .then(() => render.pushFront(results));
- })
- .finally(() => {
- render.compile();
- scroll.resume();
-
- return $q.resolve();
- });
-}
-
-function lastPage () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
-
- return render.clear()
- .then(() => page.getLast())
- .then(results => render.pushBack(results))
- .then(() => page.getPrevious())
- .then(results => {
- const popCount = page.trimTail();
-
- return render.popFront(popCount)
- .then(() => render.pushBack(results));
- })
- .then(() => {
- scroll.scrollToBottom();
-
- return $q.resolve();
- })
- .finally(() => {
- render.compile();
- scroll.resume();
-
- return $q.resolve();
- });
-}
-
-function nextPage () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
-
- return page.getNext()
- .then(results => {
- const popCount = page.trimHead();
-
- return render.popBack(popCount)
- .then(() => render.pushFront(results));
- })
- .finally(() => {
- render.compile();
- scroll.resume();
- });
-}
-
-function previousPage () {
- if (scroll.isPaused()) {
- return $q.resolve();
- }
-
- scroll.pause();
-
- let initialPosition;
- let popHeight;
-
- return page.getPrevious()
- .then(results => {
- const popCount = page.trimTail();
- initialPosition = scroll.getScrollPosition();
-
- return render.popFront(popCount)
- .then(() => {
- popHeight = scroll.getScrollHeight();
-
- return render.pushBack(results);
- });
- })
- .then(() => {
- const currentHeight = scroll.getScrollHeight();
- scroll.setScrollPosition(currentHeight - popHeight + initialPosition);
-
- return $q.resolve();
- })
- .finally(() => {
- render.compile();
- scroll.resume();
-
- return $q.resolve();
- });
-}
-
-//
-// Menu Controls
-//
-
-function first () {
- if (vm.isProcessingFinished) {
- return firstPage();
- }
-
- return firstRange();
-}
-
-function last () {
- if (vm.isProcessingFinished) {
- return lastPage();
- }
-
- return lastRange()
- .then(() => previousRange());
-}
-
-function next () {
- if (vm.isProcessingFinished) {
- return nextPage();
- }
-
- return nextRange();
-}
-
-function previous () {
- if (vm.isProcessingFinished) {
- return previousPage();
- }
-
- return previousRange();
-}
-
-function menuLast () {
- if (vm.isProcessingFinished) {
- return lastPage();
- }
-
- return menuLastRange();
-}
-
-function down () {
- scroll.moveDown();
-
- if (scroll.isBeyondLowerThreshold()) {
- next();
- }
-}
-
-function up () {
- scroll.moveUp();
-
- if (scroll.isBeyondUpperThreshold()) {
- previous();
- }
-}
-
-function togglePanelExpand () {
- vm.isPanelExpanded = !vm.isPanelExpanded;
-}
-
-//
-// Line Interaction
-//
-
-const iconCollapsed = 'fa-angle-right';
-const iconExpanded = 'fa-angle-down';
-const iconSelector = '.at-Stdout-toggle > i';
-const lineCollapsed = 'at-Stdout-row--hidden';
-
-function toggleCollapseAll () {
- if (scroll.isPaused()) return;
-
- const records = Object.keys(render.records).map(key => render.records[key]);
- const plays = records.filter(({ name }) => name === EVENT_START_PLAY);
- const tasks = records.filter(({ name }) => name === EVENT_START_TASK);
-
- const orphanLines = records
- .filter(({ level }) => level === 3)
- .filter(({ parents }) => !records[parents[0]]);
-
- const orphanLineParents = orphanLines
- .map(({ parents }) => ({ uuid: parents[0] }));
-
- plays.concat(tasks).forEach(({ uuid }) => {
- const icon = $(`#${uuid} ${iconSelector}`);
-
- if (vm.isMenuCollapsed) {
- icon.removeClass(iconCollapsed);
- icon.addClass(iconExpanded);
- } else {
- icon.removeClass(iconExpanded);
- icon.addClass(iconCollapsed);
- }
- });
-
- tasks.concat(orphanLineParents).forEach(({ uuid }) => {
- const lines = $(`.child-of-${uuid}`);
-
- if (vm.isMenuCollapsed) {
- lines.removeClass(lineCollapsed);
- } else {
- lines.addClass(lineCollapsed);
- }
- });
-
- vm.isMenuCollapsed = !vm.isMenuCollapsed;
- render.setCollapseAll(vm.isMenuCollapsed);
-}
-
-function toggleCollapse (uuid) {
- if (scroll.isPaused()) return;
-
- const record = render.records[uuid];
-
- if (record.name === EVENT_START_PLAY) {
- togglePlayCollapse(uuid);
- }
-
- if (record.name === EVENT_START_TASK) {
- toggleTaskCollapse(uuid);
- }
-}
-
-function togglePlayCollapse (uuid) {
- const record = render.records[uuid];
- const descendants = record.children || [];
-
- const icon = $(`#${uuid} ${iconSelector}`);
- const lines = $(`.child-of-${uuid}`);
- const taskIcons = $(`#${descendants.join(', #')}`).find(iconSelector);
-
- const isCollapsed = icon.hasClass(iconCollapsed);
-
- if (isCollapsed) {
- icon.removeClass(iconCollapsed);
- icon.addClass(iconExpanded);
-
- taskIcons.removeClass(iconExpanded);
- taskIcons.addClass(iconCollapsed);
- lines.removeClass(lineCollapsed);
-
- descendants
- .map(item => $(`.child-of-${item}`))
- .forEach(line => line.addClass(lineCollapsed));
- } else {
- icon.removeClass(iconExpanded);
- icon.addClass(iconCollapsed);
-
- taskIcons.removeClass(iconExpanded);
- taskIcons.addClass(iconCollapsed);
-
- lines.addClass(lineCollapsed);
-
- descendants
- .map(item => $(`.child-of-${item}`))
- .forEach(line => line.addClass(lineCollapsed));
- }
-
- descendants
- .map(item => render.records[item])
- .filter((descRecord) => descRecord && descRecord.name === EVENT_START_TASK)
- .forEach(rec => { render.records[rec.uuid].isCollapsed = true; });
-
- render.records[uuid].isCollapsed = !isCollapsed;
-}
-
-function toggleTaskCollapse (uuid) {
- const icon = $(`#${uuid} ${iconSelector}`);
- const lines = $(`.child-of-${uuid}`);
-
- const isCollapsed = icon.hasClass(iconCollapsed);
-
- if (isCollapsed) {
- icon.removeClass(iconCollapsed);
- icon.addClass(iconExpanded);
- lines.removeClass(lineCollapsed);
- } else {
- icon.removeClass(iconExpanded);
- icon.addClass(iconCollapsed);
- lines.addClass(lineCollapsed);
- }
-
- render.records[uuid].isCollapsed = !isCollapsed;
-}
-
-function showHostDetails (id, uuid) {
- $state.go('output.host-event.json', { eventId: id, taskUuid: uuid });
-}
-
-function showMissingEvents (uuid) {
- const record = render.records[uuid];
-
- const min = Math.min(...record.counters);
- const max = Math.min(Math.max(...record.counters), min + OUTPUT_PAGE_SIZE);
-
- const selector = `#${uuid}`;
- const clicked = $(selector);
-
- return resource.events.getRange([min, max])
- .then(results => {
- const counters = results.map(({ counter }) => counter);
-
- for (let i = min; i <= max; i++) {
- if (counters.indexOf(i) < 0) {
- results = results.filter(({ counter }) => counter < i);
- break;
- }
- }
-
- let lines = 0;
- let untrusted = '';
-
- for (let i = 0; i <= results.length - 1; i++) {
- const { html, count } = render.transformEvent(results[i]);
-
- lines += count;
- untrusted += html;
-
- const shifted = render.records[uuid].counters.shift();
- delete render.uuids[shifted];
- }
-
- const trusted = render.trustHtml(untrusted);
- const elements = angular.element(trusted);
-
- return render
- .requestAnimationFrame(() => {
- elements.insertBefore(clicked);
-
- if (render.records[uuid].counters.length === 0) {
- clicked.remove();
- delete render.records[uuid];
- }
- })
- .then(() => render.compile())
- .then(() => lines);
- });
-}
-
-//
-// Event Handling
-//
-
-let streaming;
-function stopListening () {
- streaming = null;
-
- listeners.forEach(deregister => deregister());
- listeners.length = 0;
-}
-
-function startListening () {
- stopListening();
-
- listeners.push($scope.$on(resource.ws.events, (scope, data) => handleJobEvent(data)));
- listeners.push($scope.$on(resource.ws.status, (scope, data) => handleStatusEvent(data)));
-
- if (resource.model.get('type') === 'job') return;
- if (resource.model.get('type') === 'project_update') return;
-
- listeners.push($scope.$on(resource.ws.summary, (scope, data) => handleSummaryEvent(data)));
-}
-
-function handleJobEvent (data) {
- streaming = streaming || resource.events
- .getRange([Math.max(1, data.counter - 50), data.counter + 50])
- .then(results => {
- results.push(data);
-
- const counters = results.map(({ counter }) => counter);
- const min = Math.min(...counters);
- const max = Math.max(...counters);
-
- const missing = [];
- for (let i = min; i <= max; i++) {
- if (counters.indexOf(i) < 0) {
- missing.push(i);
- }
- }
-
- if (missing.length > 0) {
- const maxMissing = Math.max(...missing);
- results = results.filter(({ counter }) => counter > maxMissing);
- }
-
- results.forEach(item => {
- stream.pushJobEvent(item);
- status.pushJobEvent(item);
- });
-
- stream.setMissingCounterThreshold(min);
-
- return $q.resolve();
- });
-
- streaming
- .then(() => {
- stream.pushJobEvent(data);
- status.pushJobEvent(data);
- });
-}
-
-function handleStatusEvent (data) {
- status.pushStatusEvent(data);
-}
-
-function handleSummaryEvent (data) {
- if (resource.model.get('id') !== data.unified_job_id) return;
- if (!data.final_counter) return;
-
- stream.setFinalCounter(data.final_counter);
-}
-
-//
-// Search
-//
-
-function reloadState (params) {
- params.isPanelExpanded = vm.isPanelExpanded;
-
- return $state.transitionTo($state.current, params, { inherit: false, location: 'replace' });
-}
-
-//
-// Debug Mode
-//
-
-function clear () {
- stopListening();
- render.clear();
-
- followOnce = true;
- lockFollow = false;
- lockFrames = false;
-
- stream.bufferInit();
- status.init(resource);
- slide.init(resource.events, render);
- status.subscribe(data => { vm.status = data.status; });
-
- startListening();
-}
-
-function OutputIndexController (
- _$q_,
- _$scope_,
- _$state_,
- _resource_,
- _scroll_,
- _page_,
- _render_,
- _status_,
- _slide_,
- _stream_,
- $filter,
- strings,
- $stateParams,
-) {
- const { isPanelExpanded, _debug } = $stateParams;
- const isProcessingFinished = !_debug && _resource_.model.get('event_processing_finished');
-
- $q = _$q_;
- $scope = _$scope_;
- $state = _$state_;
-
- resource = _resource_;
- scroll = _scroll_;
- render = _render_;
- status = _status_;
- stream = _stream_;
- slide = _slide_;
- page = _page_;
-
- vm = this || {};
-
- // Panel
- vm.title = $filter('sanitize')(resource.model.get('name'));
- vm.status = resource.model.get('status');
- vm.strings = strings;
- vm.resource = resource;
- vm.reloadState = reloadState;
- vm.isPanelExpanded = isPanelExpanded;
- vm.isProcessingFinished = isProcessingFinished;
- vm.togglePanelExpand = togglePanelExpand;
-
- // Stdout Navigation
- vm.menu = { last: menuLast, first, down, up, clear };
- vm.isMenuCollapsed = false;
- vm.isFollowing = false;
- vm.toggleCollapseAll = toggleCollapseAll;
- vm.toggleCollapse = toggleCollapse;
- vm.showHostDetails = showHostDetails;
- vm.showMissingEvents = showMissingEvents;
- vm.toggleLineEnabled = resource.model.get('type') === 'job';
- vm.followTooltip = vm.strings.get('tooltips.MENU_LAST');
- vm.debug = _debug;
-
- render.requestAnimationFrame(() => {
- render.init($scope, { toggles: vm.toggleLineEnabled });
-
- status.init(resource);
- page.init(resource.events);
- slide.init(resource.events, render);
-
- scroll.init({
- next,
- previous,
- onThresholdLeave () {
- followOnce = false;
- lockFollow = false;
- stopFollowing();
-
- return $q.resolve();
- },
- });
-
- let showFollowTip = true;
- const rates = [];
- stream.init({
- onFrames,
- onFrameRate (rate) {
- rates.push(rate);
- rates.splice(0, rates.length - 5);
-
- if (rates.every(value => value === 1)) {
- scroll.unlock();
- scroll.unhide();
- }
-
- if (rate > 1 && vm.isFollowing) {
- scroll.lock();
- scroll.hide();
-
- if (showFollowTip) {
- showFollowTip = false;
- $(OUTPUT_ELEMENT_LAST).trigger('mouseenter');
- }
- }
- },
- onStop () {
- lockFollow = true;
- stopFollowing();
- status.updateStats();
- status.dispatch();
- status.sync();
- scroll.unlock();
- scroll.unhide();
- render.compile();
- }
- });
-
- if (isProcessingFinished) {
- followOnce = false;
- lockFollow = true;
- lockFrames = true;
- stopListening();
- } else {
- followOnce = true;
- lockFollow = false;
- lockFrames = false;
- resource.events.clearCache();
- status.subscribe(data => { vm.status = data.status; });
- startListening();
- }
-
- if (_debug) {
- return render.clear();
- }
-
- return last();
- });
-
- $scope.$on('$destroy', () => {
- stopListening();
-
- render.clear();
- render.el.remove();
- slide.clear();
- stream.bufferInit();
- });
-}
-
-OutputIndexController.$inject = [
- '$q',
- '$scope',
- '$state',
- 'resource',
- 'OutputScrollService',
- 'OutputPageService',
- 'OutputRenderService',
- 'OutputStatusService',
- 'OutputSlideService',
- 'OutputStreamService',
- '$filter',
- 'OutputStrings',
- '$stateParams',
-];
-
-module.exports = OutputIndexController;
diff --git a/awx/ui/client/features/output/index.js b/awx/ui/client/features/output/index.js
deleted file mode 100644
index 0109877d9b..0000000000
--- a/awx/ui/client/features/output/index.js
+++ /dev/null
@@ -1,249 +0,0 @@
-/* eslint camelcase: 0 */
-import atLibModels from '~models';
-import atLibComponents from '~components';
-
-import Strings from '~features/output/output.strings';
-import Controller from '~features/output/index.controller';
-import RenderService from '~features/output/render.service';
-import ScrollService from '~features/output/scroll.service';
-import StreamService from '~features/output/stream.service';
-import StatusService from '~features/output/status.service';
-import MessageService from '~features/output/message.service';
-import EventsApiService from '~features/output/api.events.service';
-import PageService from '~features/output/page.service';
-import SlideService from '~features/output/slide.service';
-import LegacyRedirect from '~features/output/legacy.route';
-
-import DetailsComponent from '~features/output/details.component';
-import SearchComponent from '~features/output/search.component';
-import StatsComponent from '~features/output/stats.component';
-import HostEvent from './host-event/index';
-
-import {
- API_ROOT,
- OUTPUT_ORDER_BY,
- OUTPUT_PAGE_SIZE,
- WS_PREFIX,
-} from './constants';
-
-const MODULE_NAME = 'at.features.output';
-const Template = require('~features/output/index.view.html');
-
-function resolveResource (
- $state,
- $stateParams,
- Job,
- ProjectUpdate,
- AdHocCommand,
- SystemJob,
- WorkflowJob,
- InventoryUpdate,
- qs,
- Wait,
- Events,
-) {
- const { id, type, handleErrors, job_event_search } = $stateParams;
- const { name, key } = getWebSocketResource(type);
-
- let Resource;
- let related;
-
- switch (type) {
- case 'project':
- Resource = ProjectUpdate;
- related = `project_updates/${id}/events/`;
- break;
- case 'playbook':
- Resource = Job;
- related = `jobs/${id}/job_events/`;
- break;
- case 'command':
- Resource = AdHocCommand;
- related = `ad_hoc_commands/${id}/events/`;
- break;
- case 'system':
- Resource = SystemJob;
- related = `system_jobs/${id}/events/`;
- break;
- case 'inventory':
- Resource = InventoryUpdate;
- related = `inventory_updates/${id}/events/`;
- break;
- // case 'workflow':
- // todo: integrate workflow chart components into this view
- // break;
- default:
- // Redirect
- return null;
- }
-
- const params = {
- page_size: OUTPUT_PAGE_SIZE,
- order_by: OUTPUT_ORDER_BY,
- };
-
- if (job_event_search) {
- const query = qs.encodeQuerysetObject(qs.decodeArr(job_event_search));
- Object.assign(params, query);
- }
-
- Events.init(`${API_ROOT}${related}`, params);
-
- Wait('start');
- const promise = Promise.all([new Resource(['get', 'options'], [id, id]), Events.fetch()])
- .then(([model, events]) => ({
- id,
- type,
- model,
- events,
- ws: {
- events: `${WS_PREFIX}-${key}-${id}`,
- status: `${WS_PREFIX}-${name}`,
- summary: `${WS_PREFIX}-${name}-summary`,
- },
- }));
-
- if (!handleErrors) {
- return promise
- .finally(() => Wait('stop'));
- }
-
- return promise
- .catch(({ data, status }) => {
- qs.error(data, status);
-
- return $state.go($state.current, $state.params, { reload: true });
- })
- .finally(() => Wait('stop'));
-}
-
-function resolveWebSocketConnection ($stateParams, SocketService) {
- const { type, id } = $stateParams;
- const { name, key } = getWebSocketResource(type);
-
- const state = {
- data: {
- socket: {
- groups: {
- [name]: ['status_changed', 'summary'],
- [key]: []
- }
- }
- }
- };
-
- SocketService.addStateResolve(state, id);
-}
-
-function getWebSocketResource (type) {
- let name;
- let key;
-
- switch (type) {
- case 'system':
- name = 'jobs';
- key = 'system_job_events';
- break;
- case 'project':
- name = 'jobs';
- key = 'project_update_events';
- break;
- case 'command':
- name = 'jobs';
- key = 'ad_hoc_command_events';
- break;
- case 'inventory':
- name = 'jobs';
- key = 'inventory_update_events';
- break;
- case 'playbook':
- name = 'jobs';
- key = 'job_events';
- break;
- default:
- throw new Error('Unsupported WebSocket type');
- }
-
- return { name, key };
-}
-
-function JobsRun ($stateRegistry, $filter, strings) {
- const parent = 'jobs';
- const ncyBreadcrumb = { parent, label: strings.get('state.BREADCRUMB_DEFAULT') };
- const sanitize = $filter('sanitize');
-
- const state = {
- url: '/:type/:id?job_event_search?_debug',
- name: 'output',
- parent,
- ncyBreadcrumb,
- params: {
- handleErrors: true,
- isPanelExpanded: false,
- },
- data: {
- activityStream: false,
- },
- views: {
- '@': {
- templateUrl: Template,
- controller: Controller,
- controllerAs: 'vm'
- },
- },
- resolve: {
- webSocketConnection: [
- '$stateParams',
- 'SocketService',
- resolveWebSocketConnection
- ],
- resource: [
- '$state',
- '$stateParams',
- 'JobModel',
- 'ProjectUpdateModel',
- 'AdHocCommandModel',
- 'SystemJobModel',
- 'WorkflowJobModel',
- 'InventoryUpdateModel',
- 'QuerySet',
- 'Wait',
- 'JobEventsApiService',
- resolveResource
- ],
- breadcrumbLabel: [
- 'resource',
- ({ model }) => {
- ncyBreadcrumb.label = `${model.get('id')} - ${sanitize(model.get('name'))}`;
- }
- ],
- },
- };
-
- $stateRegistry.register(state);
-}
-
-JobsRun.$inject = ['$stateRegistry', '$filter', 'OutputStrings'];
-
-angular
- .module(MODULE_NAME, [
- atLibModels,
- atLibComponents,
- HostEvent
- ])
- .service('OutputStrings', Strings)
- .service('OutputScrollService', ScrollService)
- .service('OutputRenderService', RenderService)
- .service('OutputStreamService', StreamService)
- .service('OutputStatusService', StatusService)
- .service('OutputMessageService', MessageService)
- .service('JobEventsApiService', EventsApiService)
- .service('OutputPageService', PageService)
- .service('OutputSlideService', SlideService)
- .component('atJobSearch', SearchComponent)
- .component('atJobStats', StatsComponent)
- .component('atJobDetails', DetailsComponent)
- .run(JobsRun)
- .run(LegacyRedirect);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/output/index.view.html b/awx/ui/client/features/output/index.view.html
deleted file mode 100644
index ea6c31c2fc..0000000000
--- a/awx/ui/client/features/output/index.view.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- {{ vm.title }}
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/output/legacy.route.js b/awx/ui/client/features/output/legacy.route.js
deleted file mode 100644
index 838cc5c25d..0000000000
--- a/awx/ui/client/features/output/legacy.route.js
+++ /dev/null
@@ -1,108 +0,0 @@
-function LegacyRedirect ($http, $stateRegistry) {
- const destination = 'output';
- const routes = [
- {
- name: 'legacyJobResult',
- url: '/jobs/:id?job_event_search',
- redirectTo: (trans) => {
- const {
- id,
- job_event_search // eslint-disable-line camelcase
- } = trans.params();
-
- return { state: destination, params: { type: 'playbook', id, job_event_search } };
- }
- },
- {
- name: 'legacyAdHocJobStdout',
- url: '/ad_hoc_commands/:id',
- redirectTo: (trans) => {
- const { id } = trans.params();
- return { state: destination, params: { type: 'command', id } };
- }
- },
- {
- name: 'legacyInventorySyncStdout',
- url: '/inventory_sync/:id',
- redirectTo: (trans) => {
- const { id } = trans.params();
- return { state: destination, params: { type: 'inventory', id } };
- }
- },
- {
- name: 'legacyManagementJobStdout',
- url: '/management_jobs/:id',
- redirectTo: (trans) => {
- const { id } = trans.params();
- return { state: destination, params: { type: 'system', id } };
- }
- },
- {
- name: 'legacyScmUpdateStdout',
- url: '/scm_update/:id',
- redirectTo: (trans) => {
- const { id } = trans.params();
- return { state: destination, params: { type: 'project', id } };
- }
- },
- {
- name: 'legacySchedulesList',
- url: '/jobs/schedules?schedule_search',
- redirectTo: (trans) => {
- const {
- schedule_search // eslint-disable-line camelcase
- } = trans.params();
- return { state: 'schedules', params: { schedule_search } };
- }
- },
- {
- name: 'legacySchedule',
- url: '/jobs/schedules/:schedule_id?schedule_search',
- redirectTo: (trans) => {
- const {
- schedule_id, // eslint-disable-line camelcase
- schedule_search // eslint-disable-line camelcase
- } = trans.params();
- return { state: 'schedules.edit', params: { schedule_id, schedule_search } };
- }
- },
- {
- name: 'workflowNodeRedirect',
- url: '/workflow_node_results/:id',
- redirectTo: (trans) => {
- // The workflow job viewer uses this route for playbook job nodes. The provided id
- // is used to lookup the corresponding unified job, which is then inspected to
- // determine if we need to redirect to a split (workflow) job or a playbook job.
- const { id } = trans.params();
- const endpoint = '/api/v2/unified_jobs/';
-
- return $http.get(endpoint, { params: { id } })
- .then(({ data }) => {
- const { results } = data;
- const [obj] = results;
-
- if (obj) {
- if (obj.type === 'workflow_job') {
- return { state: 'workflowResults', params: { id } };
- } else if (obj.type === 'job') {
- return { state: 'output', params: { type: 'playbook', id } };
- } else if (obj.type === 'inventory_update') {
- return { state: 'output', params: { type: 'inventory', id } };
- } else if (obj.type === 'project_update') {
- return { state: 'output', params: { type: 'project', id } };
- }
- }
-
- return { state: 'jobs' };
- })
- .catch(() => ({ state: 'dashboard' }));
- }
- },
- ];
-
- routes.forEach(state => $stateRegistry.register(state));
-}
-
-LegacyRedirect.$inject = ['$http', '$stateRegistry'];
-
-export default LegacyRedirect;
diff --git a/awx/ui/client/features/output/message.service.js b/awx/ui/client/features/output/message.service.js
deleted file mode 100644
index 7e15ff302f..0000000000
--- a/awx/ui/client/features/output/message.service.js
+++ /dev/null
@@ -1,41 +0,0 @@
-function MessageService () {
- const listeners = {};
- const registry = {};
-
- this.subscribe = (key, listener) => {
- registry[key] = registry[key] || 0;
-
- listeners[key] = listeners[key] || {};
- listeners[key][registry[key]] = listener;
-
- const unsubscribe = this.createCallback(key, registry[key]);
-
- registry[key]++;
-
- return unsubscribe;
- };
-
- this.dispatch = (key, data) => {
- if (!listeners[key]) {
- return;
- }
-
- const indices = Object.keys(listeners[key]);
-
- for (let i = 0; i < indices.length; i++) {
- listeners[key][indices[i]](data);
- }
- };
-
- this.createCallback = (key, index) => {
- const callback = () => {
- if (listeners[key]) {
- delete listeners[key][index];
- }
- };
-
- return callback;
- };
-}
-
-export default MessageService;
diff --git a/awx/ui/client/features/output/output.strings.js b/awx/ui/client/features/output/output.strings.js
deleted file mode 100644
index caa53e9fa7..0000000000
--- a/awx/ui/client/features/output/output.strings.js
+++ /dev/null
@@ -1,148 +0,0 @@
-function OutputStrings (BaseString) {
- BaseString.call(this, 'output');
-
- const { t } = this;
- const ns = this.output;
-
- ns.state = {
- BREADCRUMB_DEFAULT: t.s('RESULTS'),
- };
-
- ns.status = {
- RUNNING: t.s('The host status bar will update when the job is complete.'),
- UNAVAILABLE: t.s('Host status information for this job is unavailable.'),
- };
-
- ns.tooltips = {
- ARTIFACTS: t.s('Read-only view of artifacts added to the job template'),
- CANCEL: t.s('Cancel'),
- COLLAPSE_OUTPUT: t.s('Collapse Output'),
- DELETE: t.s('Delete'),
- DOWNLOAD_OUTPUT: t.s('Download Output'),
- CREDENTIAL: t.s('View the Credential'),
- EXPAND_OUTPUT: t.s('Expand Output'),
- EXTRA_VARS: t.s('Read-only view of extra variables added to the job template'),
- HOST_LIMIT: t.s('When this field is true, the job\'s inventory belongs to an organization that has exceeded it\'s limit of hosts as defined by the system administrator.'),
- INVENTORY: t.s('View the Inventory'),
- INVENTORY_SCM: t.s('View the Project'),
- INVENTORY_SCM_JOB: t.s('View Project checkout results'),
- JOB_TEMPLATE: t.s('View the Job Template'),
- SLICE_JOB_DETAILS: t.s('Job is one of several from a JT that slices on inventory'),
- PROJECT: t.s('View the Project'),
- PROJECT_UPDATE: t.s('View Project checkout results'),
- SCHEDULE: t.s('View the Schedule'),
- SOURCE_WORKFLOW_JOB: t.s('View the source Workflow Job'),
- USER: t.s('View the User'),
- MENU_FIRST: t.s('Go to first page'),
- MENU_DOWN: t.s('Get next page'),
- MENU_UP: t.s('Get previous page'),
- MENU_LAST: t.s('Go to last page of available output'),
- MENU_FOLLOWING: t.s('Currently following output as it arrives. Click to unfollow'),
- WEBHOOK_JOB_TEMPLATE: t.s('View the webhook configuration on the job template.'),
- WEBHOOK_WORKFLOW_JOB_TEMPLATE: t.s('View the webhook configuration on the workflow job template.'),
- };
-
- ns.details = {
- HEADER: t.s('Details'),
- ISOLATED: t.s('Isolated'),
- NOT_FINISHED: t.s('Not Finished'),
- NOT_STARTED: t.s('Not Started'),
- SHOW_LESS: t.s('Show Less'),
- SHOW_MORE: t.s('Show More'),
- UNKNOWN: t.s('Finished'),
- WEBHOOK: t.s('Webhook'),
- CANCEL_JOB: t.s('Cancel Job'),
- DELETE_JOB: t.s('Delete Job'),
- };
-
- ns.labels = {
- ARTIFACTS: t.s('Artifacts'),
- CREDENTIAL: t.s('Credential'),
- ENVIRONMENT: t.s('Environment'),
- EXECUTION_NODE: t.s('Execution Node'),
- EXTRA_VARS: t.s('Extra Variables'),
- FINISHED: t.s('Finished'),
- FORKS: t.s('Forks'),
- HOST_LIMIT_ERROR: t.s('Host Limit Error'),
- INSTANCE_GROUP: t.s('Instance Group'),
- CONTAINER_GROUP: t.s('Container Group'),
- INVENTORY: t.s('Inventory'),
- INVENTORY_SCM: t.s('Source Project'),
- JOB_EXPLANATION: t.s('Explanation'),
- JOB_TAGS: t.s('Job Tags'),
- JOB_TEMPLATE: t.s('Job Template'),
- SLICE_JOB: t.s('Slice Job'),
- JOB_TYPE: t.s('Job Type'),
- LABELS: t.s('Labels'),
- LAUNCHED_BY: t.s('Launched By'),
- LICENSE_ERROR: t.s('License Error'),
- LIMIT: t.s('Limit'),
- MACHINE_CREDENTIAL: t.s('Machine Credential'),
- MODULE_ARGS: t.s('Module Args'),
- NAME: t.s('Name'),
- OVERWRITE: t.s('Overwrite'),
- OVERWRITE_VARS: t.s('Overwrite Vars'),
- PLAYBOOK: t.s('Playbook'),
- PROJECT: t.s('Project'),
- SCM_BRANCH: t.s('Branch'),
- SCM_REFSPEC: t.s('Refspec'),
- RESULT_TRACEBACK: t.s('Error Details'),
- SCM_REVISION: t.s('Revision'),
- SKIP_TAGS: t.s('Skip Tags'),
- SOURCE: t.s('Source'),
- SOURCE_CREDENTIAL: t.s('Source Credential'),
- SOURCE_WORKFLOW_JOB: t.s('Source Workflow'),
- STARTED: t.s('Started'),
- STATUS: t.s('Status'),
- VERBOSITY: t.s('Verbosity'),
- };
-
- ns.search = {
- ADDITIONAL_INFORMATION_HEADER: t.s('ADDITIONAL_INFORMATION'),
- ADDITIONAL_INFORMATION: t.s('For additional information on advanced search syntax please see the Ansible Tower'),
- CLEAR_ALL: t.s('CLEAR ALL'),
- DOCUMENTATION: t.s('documentation'),
- EXAMPLES: t.s('EXAMPLES'),
- FIELDS: t.s('FIELDS'),
- KEY: t.s('KEY'),
- PLACEHOLDER_DEFAULT: t.s('SEARCH'),
- PLACEHOLDER_RUNNING: t.s('JOB IS STILL RUNNING'),
- REJECT_DEFAULT: t.s('Failed to update search results.'),
- REJECT_INVALID: t.s('Invalid search filter provided.'),
- SUBMIT: t.s('Submit search')
- };
-
- ns.stats = {
- ELAPSED: t.s('Elapsed'),
- PLAYS: t.s('Plays'),
- TASKS: t.s('Tasks'),
- HOSTS: t.s('Hosts'),
- TOGGLE_EXPANDED_OUTPUT: t.s('Toggle expanded output')
- };
-
- ns.stdout = {
- BACK_TO_TOP: t.s('Back to Top'),
- };
-
- ns.host_event_modal = {
- CREATED: t.s('CREATED'),
- ID: t.s('ID'),
- PLAY: t.s('PLAY'),
- TASK: t.s('TASK'),
- MODULE: t.s('MODULE'),
- NO_RESULT_FOUND: t.s('No result found'),
- STANDARD_OUT: t.s('Standard Out'),
- STANDARD_ERROR: t.s('Standard Error'),
- CLOSE_HOST_EVENT_MODAL: t.s('Close host event modal')
- };
-
- ns.workflow_status = {
- SUCCESSFUL: t.s('SUCCESSFUL'),
- FAILED: t.s('FAILED'),
- NO_JOBS_FINISHED: t.s('NO JOBS FINISHED')
- };
-}
-
-OutputStrings.$inject = ['BaseStringService'];
-
-export default OutputStrings;
diff --git a/awx/ui/client/features/output/page.service.js b/awx/ui/client/features/output/page.service.js
deleted file mode 100644
index 1502d39a63..0000000000
--- a/awx/ui/client/features/output/page.service.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/* eslint camelcase: 0 */
-import { OUTPUT_PAGE_LIMIT } from './constants';
-
-function PageService ($q) {
- this.init = ({ getPage, getFirst, getLast, getLastPageNumber }) => {
- this.api = {
- getPage,
- getFirst,
- getLast,
- getLastPageNumber,
- };
- this.pages = {};
- this.state = { head: 0, tail: 0 };
- };
-
- this.getNext = () => {
- const lastPageNumber = this.api.getLastPageNumber();
- const number = Math.min(this.state.tail + 1, lastPageNumber);
-
- if (number < 1) {
- return $q.resolve([]);
- }
-
- if (number > lastPageNumber) {
- return $q.resolve([]);
- }
-
- let promise;
-
- if (this.pages[number]) {
- promise = $q.resolve(this.pages[number]);
- } else {
- promise = this.api.getPage(number);
- }
-
- return promise
- .then(results => {
- if (results.length <= 0) {
- return $q.resolve([]);
- }
-
- this.state.tail = number;
- this.pages[number] = results;
-
- return $q.resolve(results);
- });
- };
-
- this.getPrevious = () => {
- const number = Math.max(this.state.head - 1, 1);
-
- if (number < 1) {
- return $q.resolve([]);
- }
-
- if (number > this.api.getLastPageNumber()) {
- return $q.resolve([]);
- }
-
- let promise;
-
- if (this.pages[number]) {
- promise = $q.resolve(this.pages[number]);
- } else {
- promise = this.api.getPage(number);
- }
-
- return promise
- .then(results => {
- if (results.length <= 0) {
- return $q.resolve([]);
- }
-
- this.state.head = number;
- this.pages[number] = results;
-
- return $q.resolve(results);
- });
- };
-
- this.getLast = () => this.api.getLast()
- .then(results => {
- if (results.length <= 0) {
- return $q.resolve([]);
- }
-
- const number = this.api.getLastPageNumber();
-
- this.state.head = number;
- this.state.tail = number;
- this.pages[number] = results;
-
- return $q.resolve(results);
- });
-
- this.getFirst = () => this.api.getFirst()
- .then(results => {
- if (results.length <= 0) {
- return $q.resolve([]);
- }
-
- this.state.head = 1;
- this.state.tail = 1;
- this.pages[1] = results;
-
- return $q.resolve(results);
- });
-
- this.trimTail = () => {
- const { tail, head } = this.state;
- let popCount = 0;
-
- for (let i = tail; i > head; i--) {
- if (!this.isOverCapacity()) {
- break;
- }
-
- if (this.pages[i]) {
- popCount += this.pages[i].length;
- }
-
- delete this.pages[i];
-
- this.state.tail--;
- }
-
- return popCount;
- };
-
- this.trimHead = () => {
- const { head, tail } = this.state;
- let popCount = 0;
-
- for (let i = head; i < tail; i++) {
- if (!this.isOverCapacity()) {
- break;
- }
-
- if (this.pages[i]) {
- popCount += this.pages[i].length;
- }
-
- delete this.pages[i];
-
- this.state.head++;
- }
-
- return popCount;
- };
-
- this.isOverCapacity = () => this.state.tail - this.state.head > OUTPUT_PAGE_LIMIT;
-}
-
-PageService.$inject = ['$q'];
-
-export default PageService;
diff --git a/awx/ui/client/features/output/render.service.js b/awx/ui/client/features/output/render.service.js
deleted file mode 100644
index 437dec589a..0000000000
--- a/awx/ui/client/features/output/render.service.js
+++ /dev/null
@@ -1,636 +0,0 @@
-import Ansi from 'ansi-to-html';
-import Entities from 'html-entities';
-
-import {
- EVENT_START_PLAY,
- EVENT_STATS_PLAY,
- EVENT_START_TASK,
- OUTPUT_ANSI_COLORMAP,
- OUTPUT_ELEMENT_TBODY,
- OUTPUT_EVENT_LIMIT,
-} from './constants';
-
-const EVENT_GROUPS = [
- EVENT_START_TASK,
- EVENT_START_PLAY,
-];
-
-const TIME_EVENTS = [
- EVENT_START_TASK,
- EVENT_START_PLAY,
- EVENT_STATS_PLAY,
-];
-
-const ansi = new Ansi({ stream: true, colors: OUTPUT_ANSI_COLORMAP });
-const entities = new Entities.AllHtmlEntities();
-
-// https://github.com/chalk/ansi-regex
-const pattern = [
- '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)',
- '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))'
-].join('|');
-
-const re = new RegExp(pattern);
-const hasAnsi = input => re.test(input);
-
-let $scope;
-
-function JobRenderService ($q, $compile, $sce, $window) {
- this.init = (_$scope_, { toggles }) => {
- $scope = _$scope_;
- this.setScope();
-
- this.el = $(OUTPUT_ELEMENT_TBODY);
- this.parent = null;
-
- this.state = {
- head: 0,
- tail: 0,
- collapseAll: false,
- toggleMode: toggles,
- };
-
- this.records = {};
- this.uuids = {};
- };
-
- this.setCollapseAll = value => {
- this.state.collapseAll = value;
- Object.keys(this.records).forEach(key => {
- this.records[key].isCollapsed = value;
- });
- };
-
- this.sortByCounter = (a, b) => {
- if (a.counter > b.counter) {
- return 1;
- }
-
- if (a.counter < b.counter) {
- return -1;
- }
-
- return 0;
- };
-
- //
- // Event Data Transformation / HTML Building
- //
-
- this.appendEventGroup = events => {
- let lines = 0;
- let html = '';
-
- events.sort(this.sortByCounter);
-
- for (let i = 0; i <= events.length - 1; i++) {
- const current = events[i];
-
- if (this.state.tail && current.counter !== this.state.tail + 1) {
- const missing = this.appendMissingEventGroup(current);
-
- html += missing.html;
- lines += missing.count;
- }
-
- const eventLines = this.transformEvent(current);
-
- html += eventLines.html;
- lines += eventLines.count;
- }
-
- return { html, lines };
- };
-
- this.appendMissingEventGroup = event => {
- const tailUUID = this.uuids[this.state.tail];
- const tailRecord = this.records[tailUUID];
-
- if (!tailRecord) {
- return { html: '', count: 0 };
- }
-
- let uuid;
-
- if (tailRecord.isMissing) {
- uuid = tailUUID;
- } else {
- uuid = `${event.counter}-${tailUUID}`;
- this.records[uuid] = { uuid, counters: [], lineCount: 1, isMissing: true };
- }
-
- for (let i = this.state.tail + 1; i < event.counter; i++) {
- this.records[uuid].counters.push(i);
- this.uuids[i] = uuid;
- }
-
- if (tailRecord.isMissing) {
- return { html: '', count: 0 };
- }
-
- if (tailRecord.end === event.start_line) {
- return { html: '', count: 0 };
- }
-
- const html = this.buildRowHTML(this.records[uuid]);
- const count = 1;
-
- return { html, count };
- };
-
- this.prependEventGroup = events => {
- let lines = 0;
- let html = '';
-
- events.sort(this.sortByCounter);
-
- for (let i = events.length - 1; i >= 0; i--) {
- const current = events[i];
-
- if (this.state.head && current.counter !== this.state.head - 1) {
- const missing = this.prependMissingEventGroup(current);
-
- html = missing.html + html;
- lines += missing.count;
- }
-
- const eventLines = this.transformEvent(current);
-
- html = eventLines.html + html;
- lines += eventLines.count;
- }
-
- return { html, lines };
- };
-
- this.prependMissingEventGroup = event => {
- const headUUID = this.uuids[this.state.head];
- const headRecord = this.records[headUUID];
-
- if (!headRecord) {
- return { html: '', count: 0 };
- }
-
- let uuid;
-
- if (headRecord.isMissing) {
- uuid = headUUID;
- } else {
- uuid = `${headUUID}-${event.counter}`;
- this.records[uuid] = { uuid, counters: [], lineCount: 1, isMissing: true };
- }
-
- for (let i = this.state.head - 1; i > event.counter; i--) {
- this.records[uuid].counters.unshift(i);
- this.uuids[i] = uuid;
- }
-
- if (headRecord.isMissing) {
- return { html: '', count: 0 };
- }
-
- if (event.end_line === headRecord.start) {
- return { html: '', count: 0 };
- }
-
- const html = this.buildRowHTML(this.records[uuid]);
- const count = 1;
-
- return { html, count };
- };
-
- this.transformEvent = event => {
- if (!event || event.stdout === null || event.stdout === undefined) {
- return { html: '', count: 0 };
- }
-
- if (event.uuid && this.records[event.uuid] && !this.records[event.uuid]._isIncomplete) {
- return { html: '', count: 0 };
- }
-
- const stdout = this.sanitize(event.stdout);
- const lines = stdout.split('\r\n');
- const record = this.createRecord(event, lines);
-
- if (lines.length === 1 && lines[0] === '') {
- // runner_on_start, runner_on_ok, and a few other events have an actual line count
- // of 1 (stdout = '') and a claimed line count of 0 (end_line - start_line = 0).
- // Since a zero-length string has an actual line count of 1, they'll still get
- // rendered as blank lines unless we intercept them and add some special
- // handling to remove them.
- //
- // Although we're not going to render the blank line, the actual line count of
- // the zero-length stdout string, which is 1, has already been recorded at this
- // point so we must also go back and set the event's recorded line length to 0
- // in order to avoid deleting too many lines when we need to pop or shift a
- // page that contains this event off of the view.
- this.records[record.uuid].lineCount = 0;
- return { html: '', count: 0 };
- }
-
- let html = '';
- let count = lines.length;
- let ln = event.start_line;
-
- for (let i = 0; i <= lines.length - 1; i++) {
- ln++;
-
- const line = lines[i];
- const isLastLine = i === lines.length - 1;
-
- let row = this.buildRowHTML(record, ln, line);
-
- if (record && record.isTruncated && isLastLine) {
- row += this.buildRowHTML(record);
- count++;
- }
-
- html += row;
- }
-
- if (this.records[event.uuid]) {
- this.records[event.uuid].lineCount = count;
- }
-
- return { html, count };
- };
-
- this.createRecord = (event, lines) => {
- if (!event.counter) {
- return null;
- }
-
- if (!this.state.head || event.counter < this.state.head) {
- this.state.head = event.counter;
- }
-
- if (!this.state.tail || event.counter > this.state.tail) {
- this.state.tail = event.counter;
- }
-
- if (!event.uuid) {
- this.uuids[event.counter] = event.counter;
- this.records[event.counter] = { counters: [event.counter], lineCount: lines.length };
-
- return this.records[event.counter];
- }
-
- let isClickable = false;
- if (typeof event.host === 'number' || event.event_data && event.event_data.res) {
- isClickable = true;
- } else if (event.type === 'project_update_event' &&
- event.event !== 'runner_on_skipped' &&
- event.event_data.host) {
- isClickable = true;
- }
-
- const children = (this.records[event.uuid] && this.records[event.uuid].children)
- ? this.records[event.uuid].children : [];
-
- const record = {
- isClickable,
- id: event.id,
- line: event.start_line + 1,
- name: event.event,
- uuid: event.uuid,
- level: event.event_level,
- start: event.start_line,
- end: event.end_line,
- isTruncated: (event.end_line - event.start_line) > lines.length,
- lineCount: lines.length,
- isCollapsed: this.state.collapseAll,
- counters: [event.counter],
- children
- };
-
- if (event.parent_uuid) {
- record.parents = this.getParentEvents(event.parent_uuid);
- if (this.records[event.parent_uuid]) {
- record.isCollapsed = this.records[event.parent_uuid].isCollapsed;
- }
- }
-
- if (record.isTruncated) {
- record.truncatedAt = event.start_line + lines.length;
- }
-
- if (EVENT_GROUPS.includes(event.event)) {
- record.isParent = true;
-
- if (event.event_level === 1) {
- this.parent = event.uuid;
- }
-
- if (event.parent_uuid) {
- if (this.records[event.parent_uuid]) {
- if (this.records[event.parent_uuid].children) {
- if (!this.records[event.parent_uuid].children.includes(event.uuid)) {
- this.records[event.parent_uuid].children.push(event.uuid);
- }
- } else {
- this.records[event.parent_uuid].children = [event.uuid];
- }
- } else {
- this.records[event.parent_uuid] = {
- _isIncomplete: true,
- children: [event.uuid]
- };
- }
- }
- }
-
- if (TIME_EVENTS.includes(event.event)) {
- record.time = this.getTimestamp(event.created);
- record.line++;
- }
-
- this.records[event.uuid] = record;
- this.uuids[event.counter] = event.uuid;
-
- return record;
- };
-
- this.getParentEvents = (uuid, list) => {
- list = list || [];
- // always push its parent if exists
- list.push(uuid);
- // if we can get grandparent in current visible lines, we also push it
- if (this.records[uuid] && this.records[uuid].parents) {
- list = list.concat(this.records[uuid].parents);
- }
-
- return list;
- };
-
- this.buildRowHTML = (record, ln, content) => {
- let id = '';
- let icon = '';
- let timestamp = '';
- let tdToggle = '';
- let tdEvent = '';
- let classList = '';
- let directives = '';
-
- if (record.isMissing) {
- return ``;
- }
-
- content = content || '';
-
- if (hasAnsi(content)) {
- content = ansi.toHtml(content);
- }
-
- if (record) {
- if (this.state.toggleMode && record.isParent && record.line === ln) {
- id = record.uuid;
-
- if (record.isCollapsed) {
- icon = 'fa-angle-right';
- } else {
- icon = 'fa-angle-down';
- }
-
- tdToggle = `
`;
- }
-
- if (record.time && record.line === ln) {
- timestamp = `${record.time} `;
- }
-
- if (record.parents) {
- classList = record.parents.reduce((list, uuid) => `${list} child-of-${uuid}`, '');
- }
- }
-
- if (!tdEvent) {
- tdEvent = `${content}
`;
- }
-
- if (!tdToggle) {
- tdToggle = '
';
- }
-
- if (!ln) {
- ln = '...';
- }
-
- if (record && record.isCollapsed) {
- if (record.level === 3 || record.level === 0) {
- classList += ' at-Stdout-row--hidden';
- }
- }
-
- if (record && record.isClickable) {
- classList += ' at-Stdout-row--clickable';
- directives = `ng-click="vm.showHostDetails('${record.id}', '${record.uuid}')"`;
- }
-
- return `
-
- ${tdToggle}
-
${ln}
-
${content}
-
${timestamp}
-
- `;
- };
-
- this.getTimestamp = created => {
- const date = new Date(created);
- const hour = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
- const minute = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
- const second = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds();
-
- return `${hour}:${minute}:${second}`;
- };
-
- //
- // Element Operations
- //
-
- this.remove = elements => this.requestAnimationFrame(() => elements.remove());
-
- this.requestAnimationFrame = fn => $q(resolve => {
- $window.requestAnimationFrame(() => {
- if (fn) {
- fn();
- }
-
- return resolve();
- });
- });
-
- this.setScope = () => {
- if (this.scope) this.scope.$destroy();
- delete this.scope;
-
- this.scope = $scope.$new();
- };
-
- this.compile = () => {
- this.setScope();
- $compile(this.el)(this.scope);
-
- return this.requestAnimationFrame();
- };
-
- this.removeAll = () => {
- const elements = this.el.contents();
- return this.remove(elements);
- };
-
- this.shift = lines => {
- // We multiply by two here under the assumption that one element and one text node
- // is generated for each line of output.
- const count = (2 * lines) + 1;
- const elements = this.el.contents().slice(0, count);
-
- return this.remove(elements);
- };
-
- this.pop = lines => {
- // We multiply by two here under the assumption that one element and one text node
- // is generated for each line of output.
- const count = (2 * lines) + 1;
- const elements = this.el.contents().slice(-count);
-
- return this.remove(elements);
- };
-
- this.prepend = events => {
- if (events.length < 1) {
- return $q.resolve();
- }
-
- const result = this.prependEventGroup(events);
- const html = this.trustHtml(result.html);
-
- return this.requestAnimationFrame(() => this.el.prepend(html))
- .then(() => result.lines);
- };
-
- this.append = events => {
- if (events.length < 1) {
- return $q.resolve();
- }
-
- const result = this.appendEventGroup(events);
- const html = this.trustHtml(result.html);
-
- return this.requestAnimationFrame(() => this.el.append(html))
- .then(() => result.lines);
- };
-
- this.trustHtml = html => $sce.getTrustedHtml($sce.trustAsHtml(html));
- this.sanitize = html => entities.encode(html);
-
- //
- // Event Counter Methods - External code should prefer these.
- //
-
- this.clear = () => this.removeAll()
- .then(() => {
- const head = this.getHeadCounter();
- const tail = this.getTailCounter();
-
- for (let i = head; i <= tail; ++i) {
- const uuid = this.uuids[i];
-
- if (uuid) {
- delete this.records[uuid];
- delete this.uuids[i];
- }
- }
-
- this.state.head = 0;
- this.state.tail = 0;
-
- return $q.resolve();
- });
-
- this.pushFront = events => {
- const tail = this.getTailCounter();
-
- return this.append(events.filter(({ counter }) => counter > tail));
- };
-
- this.pushBack = events => {
- const head = this.getHeadCounter();
- const tail = this.getTailCounter();
-
- return this.prepend(events.filter(({ counter }) => counter < head || counter > tail));
- };
-
- this.popFront = count => {
- if (!count || count <= 0) {
- return $q.resolve();
- }
-
- const max = this.state.tail;
- const min = max - count + 1;
-
- let lines = 0;
-
- for (let i = max; i >= min; --i) {
- const uuid = this.uuids[i];
-
- if (!uuid) {
- continue;
- }
-
- this.records[uuid].counters.pop();
- delete this.uuids[i];
-
- if (this.records[uuid].counters.length === 0) {
- lines += this.records[uuid].lineCount;
-
- delete this.records[uuid];
- this.state.tail--;
- }
- }
-
- return this.pop(lines);
- };
-
- this.popBack = count => {
- if (!count || count <= 0) {
- return $q.resolve();
- }
-
- const min = this.state.head;
- const max = min + count - 1;
-
- let lines = 0;
-
- for (let i = min; i <= max; ++i) {
- const uuid = this.uuids[i];
-
- if (!uuid) {
- continue;
- }
-
- this.records[uuid].counters.shift();
- delete this.uuids[i];
-
- if (this.records[uuid].counters.length === 0) {
- lines += this.records[uuid].lineCount;
-
- delete this.records[uuid];
- this.state.head++;
- }
- }
-
- return this.shift(lines);
- };
-
- this.getHeadCounter = () => this.state.head;
- this.getTailCounter = () => this.state.tail;
- this.getCapacity = () => OUTPUT_EVENT_LIMIT - (this.getTailCounter() - this.getHeadCounter());
-}
-
-JobRenderService.$inject = ['$q', '$compile', '$sce', '$window'];
-
-export default JobRenderService;
diff --git a/awx/ui/client/features/output/scroll.service.js b/awx/ui/client/features/output/scroll.service.js
deleted file mode 100644
index b8b7444928..0000000000
--- a/awx/ui/client/features/output/scroll.service.js
+++ /dev/null
@@ -1,228 +0,0 @@
-import {
- OUTPUT_ELEMENT_CONTAINER,
- OUTPUT_ELEMENT_TBODY,
- OUTPUT_SCROLL_DELAY,
- OUTPUT_SCROLL_THRESHOLD,
-} from './constants';
-
-function JobScrollService ($q, $timeout) {
- this.init = ({ next, previous, onThresholdLeave }) => {
- this.el = $(OUTPUT_ELEMENT_CONTAINER);
- this.chain = $q.resolve();
- this.timer = null;
-
- this.position = {
- previous: 0,
- current: 0
- };
-
- this.threshold = {
- previous: 0,
- current: 0,
- };
-
- this.hooks = {
- next,
- previous,
- onThresholdLeave,
- };
-
- this.state = {
- paused: false,
- locked: false,
- hover: false,
- thrash: 0,
- };
-
- this.el.scroll(this.listen);
- this.el.mouseenter(this.onMouseEnter);
- this.el.mouseleave(this.onMouseLeave);
- };
-
- this.onMouseEnter = () => {
- this.state.hover = true;
- };
-
- this.onMouseLeave = () => {
- this.state.hover = false;
- };
-
- this.listen = () => {
- if (this.isPaused()) {
- return;
- }
-
- if (this.isLocked()) {
- return;
- }
-
- if (!this.state.hover) {
- return;
- }
-
- if (this.timer) {
- $timeout.cancel(this.timer);
- }
-
- this.timer = $timeout(this.register, OUTPUT_SCROLL_DELAY);
- };
-
- this.register = () => {
- const position = this.getScrollPosition();
- const viewport = this.getScrollHeight() - this.getViewableHeight();
-
- const threshold = position / viewport;
- const downward = position > this.position.previous;
-
- const isBeyondUpperThreshold = threshold < OUTPUT_SCROLL_THRESHOLD;
- const isBeyondLowerThreshold = (1 - threshold) < OUTPUT_SCROLL_THRESHOLD;
-
- const wasBeyondUpperThreshold = this.threshold.previous < OUTPUT_SCROLL_THRESHOLD;
- const wasBeyondLowerThreshold = (1 - this.threshold.previous) < OUTPUT_SCROLL_THRESHOLD;
-
- const enteredUpperThreshold = isBeyondUpperThreshold && !wasBeyondUpperThreshold;
- const enteredLowerThreshold = isBeyondLowerThreshold && !wasBeyondLowerThreshold;
- const leftLowerThreshold = !isBeyondLowerThreshold && wasBeyondLowerThreshold;
-
- const transitions = [];
-
- if (position <= 0 || enteredUpperThreshold) {
- transitions.push(this.hooks.onThresholdLeave);
- transitions.push(this.hooks.previous);
- }
-
- if (leftLowerThreshold) {
- transitions.push(this.hooks.onThresholdLeave);
- }
-
- if (threshold >= 1 || enteredLowerThreshold) {
- transitions.push(this.hooks.next);
- }
-
- if (!downward) {
- transitions.reverse();
- }
-
- this.position.current = position;
- this.threshold.current = threshold;
-
- transitions.forEach(promise => {
- this.chain = this.chain.then(() => promise());
- });
-
- return this.chain
- .then(() => {
- this.setScrollPosition(this.getScrollPosition());
-
- return $q.resolve();
- });
- };
-
- /**
- * Move scroll position up by one page of visible content.
- */
- this.moveUp = () => {
- const position = this.getScrollPosition() - this.getViewableHeight();
-
- this.setScrollPosition(position);
- };
-
- /**
- * Move scroll position down by one page of visible content.
- */
- this.moveDown = () => {
- const position = this.getScrollPosition() + this.getViewableHeight();
-
- this.setScrollPosition(position);
- };
-
- this.getScrollHeight = () => this.el[0].scrollHeight;
- this.getViewableHeight = () => this.el[0].offsetHeight;
-
- /**
- * Get the vertical scroll position.
- *
- * @returns {Number} - The number of pixels that are hidden from view above the scrollable area.
- */
- this.getScrollPosition = () => this.el[0].scrollTop;
-
- this.setScrollPosition = position => {
- const viewport = this.getScrollHeight() - this.getViewableHeight();
-
- this.position.previous = this.position.current;
- this.threshold.previous = this.position.previous / viewport;
- this.position.current = position;
-
- this.el[0].scrollTop = position;
- };
-
- this.resetScrollPosition = () => {
- this.threshold.previous = 0;
- this.position.previous = 0;
- this.position.current = 0;
-
- this.el[0].scrollTop = 0;
- };
-
- this.scrollToBottom = () => {
- this.setScrollPosition(this.getScrollHeight());
- };
-
- this.lock = () => {
- this.state.locked = true;
- };
-
- this.unlock = () => {
- this.state.locked = false;
- };
-
- this.pause = () => {
- this.state.paused = true;
- };
-
- this.resume = () => {
- this.state.paused = false;
- };
-
- this.hide = () => {
- if (this.state.hidden) {
- return;
- }
-
- this.state.hidden = true;
- this.el.css('overflow-y', 'hidden');
- };
-
- this.unhide = () => {
- if (!this.state.hidden) {
- return;
- }
-
- this.state.hidden = false;
- this.el.css('overflow-y', 'auto');
- };
-
- this.isBeyondLowerThreshold = () => {
- const position = this.getScrollPosition();
- const viewport = this.getScrollHeight() - this.getViewableHeight();
- const threshold = position / viewport;
-
- return (1 - threshold) < OUTPUT_SCROLL_THRESHOLD;
- };
-
- this.isBeyondUpperThreshold = () => {
- const position = this.getScrollPosition();
- const viewport = this.getScrollHeight() - this.getViewableHeight();
- const threshold = position / viewport;
-
- return threshold < OUTPUT_SCROLL_THRESHOLD;
- };
-
- this.isPaused = () => this.state.paused;
- this.isLocked = () => this.state.locked;
- this.isMissing = () => $(OUTPUT_ELEMENT_TBODY)[0].clientHeight < this.getViewableHeight();
-}
-
-JobScrollService.$inject = ['$q', '$timeout'];
-
-export default JobScrollService;
diff --git a/awx/ui/client/features/output/search.component.js b/awx/ui/client/features/output/search.component.js
deleted file mode 100644
index cb8299be89..0000000000
--- a/awx/ui/client/features/output/search.component.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/* eslint camelcase: 0 */
-import {
- OUTPUT_SEARCH_DOCLINK,
- OUTPUT_SEARCH_FIELDS,
- OUTPUT_SEARCH_KEY_EXAMPLES,
-} from './constants';
-
-const templateUrl = require('~features/output/search.partial.html');
-
-let $state;
-let qs;
-let strings;
-
-let vm;
-
-function toggleSearchKey () {
- vm.key = !vm.key;
-}
-
-function getCurrentQueryset () {
- const { job_event_search } = $state.params;
-
- return qs.decodeArr(job_event_search);
-}
-
-function getSearchTags (queryset) {
- return qs.createSearchTagsFromQueryset(queryset)
- .filter(tag => !tag.startsWith('event'))
- .filter(tag => !tag.startsWith('-event'))
- .filter(tag => !tag.startsWith('page_size'))
- .filter(tag => !tag.startsWith('order_by'));
-}
-
-function reloadQueryset (queryset, rejection = strings.get('search.REJECT_DEFAULT')) {
- const params = angular.copy($state.params);
- const currentTags = vm.tags;
-
- params.handleErrors = false;
- params.job_event_search = qs.encodeArr(queryset);
-
- vm.disabled = true;
- vm.message = '';
- vm.tags = getSearchTags(queryset);
-
- return vm.reload(params)
- .catch(() => {
- vm.tags = currentTags;
- vm.message = rejection;
- vm.rejected = true;
- vm.disabled = false;
- });
-}
-
-const isFilterable = term => {
- const field = term[0].split('.')[0].replace(/^-/, '');
- return (OUTPUT_SEARCH_FIELDS.indexOf(field) > -1);
-};
-
-function removeSearchTag (index) {
- const searchTerm = vm.tags[index];
-
- const currentQueryset = getCurrentQueryset();
- const modifiedQueryset = qs.removeTermsFromQueryset(currentQueryset, searchTerm, isFilterable);
-
- reloadQueryset(modifiedQueryset);
-}
-
-function submitSearch () {
- // empty input, not submit new search, return.
- if (!vm.value) {
- return;
- }
-
- const currentQueryset = getCurrentQueryset();
- // check duplicate , see if search input already exists in current search tags
- if (currentQueryset.search) {
- if (currentQueryset.search.includes(vm.value)) {
- return;
- }
- }
-
- const searchInputQueryset = qs.getSearchInputQueryset(vm.value, isFilterable);
- const modifiedQueryset = qs.mergeQueryset(currentQueryset, searchInputQueryset);
-
- reloadQueryset(modifiedQueryset, strings.get('search.REJECT_INVALID'));
-}
-
-function clearSearch () {
- reloadQueryset();
-}
-
-function JobSearchController (_$state_, _qs_, _strings_, { subscribe }) {
- $state = _$state_;
- qs = _qs_;
- strings = _strings_;
-
- vm = this || {};
- vm.strings = strings;
-
- vm.examples = OUTPUT_SEARCH_KEY_EXAMPLES;
- vm.fields = OUTPUT_SEARCH_FIELDS;
- vm.docLink = OUTPUT_SEARCH_DOCLINK;
- vm.relatedFields = [];
-
- vm.clearSearch = clearSearch;
- vm.toggleSearchKey = toggleSearchKey;
- vm.removeSearchTag = removeSearchTag;
- vm.submitSearch = submitSearch;
-
- let unsubscribe;
-
- vm.$onInit = () => {
- vm.value = '';
- vm.message = '';
- vm.key = false;
- vm.rejected = false;
- vm.disabled = true;
- vm.isJobActive = false;
- vm.tags = getSearchTags(getCurrentQueryset());
-
- unsubscribe = subscribe(({ running, event_processing_finished }) => {
- const isJobActive = running || !event_processing_finished;
- vm.disabled = isJobActive;
- vm.isJobActive = isJobActive;
- });
- };
-
- vm.$onDestroy = () => {
- unsubscribe();
- };
-}
-
-JobSearchController.$inject = [
- '$state',
- 'QuerySet',
- 'OutputStrings',
- 'OutputStatusService',
-];
-
-export default {
- templateUrl,
- controller: JobSearchController,
- controllerAs: 'vm',
- bindings: {
- reload: '=',
- },
-};
diff --git a/awx/ui/client/features/output/search.partial.html b/awx/ui/client/features/output/search.partial.html
deleted file mode 100644
index d7d91ac493..0000000000
--- a/awx/ui/client/features/output/search.partial.html
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('search.EXAMPLES') }}:
-
-
{{ tag }}
-
-
-
-
- {{:: vm.strings.get('search.FIELDS') }}:
- {{ field }},
-
-
-
-
diff --git a/awx/ui/client/features/output/slide.service.js b/awx/ui/client/features/output/slide.service.js
deleted file mode 100644
index da1d9a4047..0000000000
--- a/awx/ui/client/features/output/slide.service.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/* eslint camelcase: 0 */
-import {
- OUTPUT_MAX_BUFFER_LENGTH,
- OUTPUT_PAGE_SIZE,
-} from './constants';
-
-function SlidingWindowService ($q) {
- this.init = ({ getRange, getFirst, getLast, getMaxCounter }, storage) => {
- const { getHeadCounter, getTailCounter } = storage;
-
- this.api = {
- getRange,
- getFirst,
- getLast,
- getMaxCounter,
- };
-
- this.storage = {
- getHeadCounter,
- getTailCounter,
- };
-
- this.buffer = {
- events: [],
- min: 0,
- max: 0,
- count: 0,
- };
-
- this.cache = {
- first: null
- };
- };
-
- this.getBoundedRange = range => {
- const bounds = [1, this.getMaxCounter()];
-
- return [Math.max(range[0], bounds[0]), Math.min(range[1], bounds[1])];
- };
-
- this.getNextRange = displacement => {
- const tail = this.getTailCounter();
-
- return this.getBoundedRange([tail + 1, tail + 1 + displacement]);
- };
-
- this.getPreviousRange = displacement => {
- const head = this.getHeadCounter();
-
- return this.getBoundedRange([head - 1 - displacement, head - 1]);
- };
-
- this.getNext = (displacement = OUTPUT_PAGE_SIZE) => {
- const next = this.getNextRange(displacement);
-
- return this.api.getRange(next);
- };
-
- this.getPrevious = (displacement = OUTPUT_PAGE_SIZE) => {
- const previous = this.getPreviousRange(displacement);
-
- return this.api.getRange(previous);
- };
-
- this.getFirst = () => {
- if (this.cache.first) {
- return $q.resolve(this.cache.first);
- }
-
- return this.api.getFirst()
- .then(events => {
- if (events.length === OUTPUT_PAGE_SIZE) {
- this.cache.first = events;
- }
-
- return $q.resolve(events);
- });
- };
-
- this.getLast = () => this.getFrames()
- .then(frames => {
- if (frames.length > 0) {
- return $q.resolve(frames);
- }
-
- return this.api.getLast();
- });
-
- this.pushFrames = events => {
- const head = this.getHeadCounter();
- const tail = this.getTailCounter();
- const frames = this.buffer.events.concat(events);
-
- let min;
- let max;
- let count = 0;
-
- for (let i = frames.length - 1; i >= 0; i--) {
- count++;
-
- if (count > OUTPUT_MAX_BUFFER_LENGTH) {
- frames.splice(i, 1);
-
- count--;
- continue;
- }
-
- if (!min || frames[i].counter < min) {
- min = frames[i].counter;
- }
-
- if (!max || frames[i].counter > max) {
- max = frames[i].counter;
- }
- }
-
- this.buffer.events.length = 0;
- delete this.buffer.events;
-
- this.buffer.events = frames;
- this.buffer.min = min;
- this.buffer.max = max;
- this.buffer.count = count;
-
- if (tail - head === 0) {
- return frames;
- }
-
- return frames.filter(({ counter }) => counter > tail);
- };
-
- this.clear = () => {
- this.buffer.events.length = 0;
- this.buffer.min = 0;
- this.buffer.max = 0;
- this.buffer.count = 0;
- };
-
- this.getFrames = () => $q.resolve(this.buffer.events);
-
- this.getMaxCounter = () => {
- if (this.buffer.max && this.buffer.max > 1) {
- return this.buffer.max;
- }
-
- return this.api.getMaxCounter();
- };
-
- this.isOnLastPage = () => {
- if (this.buffer.min) {
- return this.getTailCounter() >= this.buffer.min - 1;
- }
-
- return this.getTailCounter() >= this.getMaxCounter() - OUTPUT_PAGE_SIZE;
- };
-
- this.isOnFirstPage = () => this.getHeadCounter() === 1;
- this.getTailCounter = () => this.storage.getTailCounter();
- this.getHeadCounter = () => this.storage.getHeadCounter();
-}
-
-SlidingWindowService.$inject = ['$q'];
-
-export default SlidingWindowService;
diff --git a/awx/ui/client/features/output/stats.component.js b/awx/ui/client/features/output/stats.component.js
deleted file mode 100644
index 61f86d6709..0000000000
--- a/awx/ui/client/features/output/stats.component.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import { OUTPUT_NO_COUNT_JOB_TYPES } from './constants';
-
-const templateUrl = require('~features/output/stats.partial.html');
-
-let vm;
-
-function createStatsBarTooltip (key, count) {
- const label = `${key} `;
- const badge = `${count} `;
-
- return `${label}${badge}`;
-}
-
-function JobStatsController (strings, { subscribe }) {
- vm = this || {};
- vm.strings = strings;
-
- let unsubscribe;
-
- vm.tooltips = {
- running: strings.get('status.RUNNING'),
- unavailable: strings.get('status.UNAVAILABLE'),
- };
-
- vm.$onInit = () => {
- vm.hideCounts = OUTPUT_NO_COUNT_JOB_TYPES.includes(vm.resource.model.get('type'));
- vm.download = vm.resource.model.get('related.stdout');
- vm.tooltips.toggleExpand = vm.expanded ?
- strings.get('tooltips.COLLAPSE_OUTPUT') :
- strings.get('tooltips.EXPAND_OUTPUT');
-
- unsubscribe = subscribe(({ running, elapsed, counts, hosts }) => {
- vm.plays = counts.plays;
- vm.tasks = counts.tasks;
- vm.hosts = counts.hosts;
- vm.elapsed = elapsed;
- vm.running = running;
- vm.setHostStatusCounts(hosts);
- });
- };
-
- vm.$onDestroy = () => {
- unsubscribe();
- };
-
- vm.setHostStatusCounts = counts => {
- let statsAreAvailable;
-
- Object.keys(counts).forEach(key => {
- const count = counts[key];
- const statusBarElement = $(`.HostStatusBar-${key}`);
-
- statusBarElement.css('flex', `${count} 0 auto`);
-
- vm.tooltips[key] = createStatsBarTooltip(key, count);
-
- if (count) statsAreAvailable = true;
- });
-
- vm.statsAreAvailable = statsAreAvailable;
- };
-
- vm.toggleExpanded = () => {
- vm.expanded = !vm.expanded;
- vm.tooltips.toggleExpand = vm.expanded ?
- strings.get('tooltips.COLLAPSE_OUTPUT') :
- strings.get('tooltips.EXPAND_OUTPUT');
- };
-}
-
-JobStatsController.$inject = [
- 'OutputStrings',
- 'OutputStatusService',
-];
-
-export default {
- templateUrl,
- controller: JobStatsController,
- controllerAs: 'vm',
- bindings: {
- resource: '<',
- expanded: '=',
- },
-};
diff --git a/awx/ui/client/features/output/stats.partial.html b/awx/ui/client/features/output/stats.partial.html
deleted file mode 100644
index 18debf63b9..0000000000
--- a/awx/ui/client/features/output/stats.partial.html
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
{{:: vm.strings.get('stats.PLAYS')}}
-
...
-
{{ vm.plays || 0 }}
-
-
{{:: vm.strings.get('stats.TASKS')}}
-
...
-
{{ vm.tasks || 0 }}
-
-
{{:: vm.strings.get('stats.HOSTS')}}
-
...
-
{{ vm.hosts || 1 }}
-
-
{{:: vm.strings.get('stats.ELAPSED') }}
-
- {{ (vm.elapsed * 1000 || 0) | duration: "hh:mm:ss"}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/output/status.service.js b/awx/ui/client/features/output/status.service.js
deleted file mode 100644
index f661d5b491..0000000000
--- a/awx/ui/client/features/output/status.service.js
+++ /dev/null
@@ -1,371 +0,0 @@
-/* eslint camelcase: 0 */
-import {
- EVENT_START_PLAYBOOK,
- EVENT_STATS_PLAY,
- EVENT_START_PLAY,
- EVENT_START_TASK,
- HOST_STATUS_KEYS,
- JOB_STATUS_COMPLETE,
- JOB_STATUS_INCOMPLETE,
- JOB_STATUS_UNSUCCESSFUL,
- JOB_STATUS_FINISHED,
-} from './constants';
-
-function JobStatusService (moment, message) {
- this.dispatch = () => message.dispatch('status', this.state);
- this.subscribe = listener => message.subscribe('status', listener);
-
- this.init = ({ model }) => {
- this.model = model;
- this.created = model.get('created');
- this.job = model.get('id');
- this.jobType = model.get('type');
- this.project = model.get('project');
-
- this.active = false;
- this.latestTime = null;
- this.counter = -1;
-
- this.state = {
- running: false,
- anyFailed: false,
- counts: {
- plays: 0,
- tasks: 0,
- hosts: 0,
- },
- hosts: {},
- status: model.get('status'),
- elapsed: model.get('elapsed'),
- started: model.get('started'),
- finished: model.get('finished'),
- environment: model.get('custom_virtualenv'),
- artifacts: model.get('artifacts'),
- scm: {
- id: model.get('summary_fields.project_update.id'),
- status: model.get('summary_fields.project_update.status')
- },
- scmBranch: model.get('scm_branch'),
- scmRefspec: model.get('scm_refspec'),
- inventoryScm: {
- id: model.get('source_project_update'),
- status: model.get('summary_fields.inventory_source.status')
- },
- event_processing_finished: model.get('event_processing_finished'),
- };
-
- this.initHostStatusCounts({ model });
- this.initPlaybookCounts({ model });
-
- this.updateRunningState();
- this.dispatch();
- };
-
- this.initHostStatusCounts = ({ model }) => {
- if (model.has('host_status_counts')) {
- this.setHostStatusCounts(model.get('host_status_counts'));
- } else {
- const hostStatusCounts = this.createHostStatusCounts(this.state.status);
-
- this.setHostStatusCounts(hostStatusCounts);
- }
- };
-
- this.initPlaybookCounts = ({ model }) => {
- if (model.has('playbook_counts')) {
- this.setPlaybookCounts(model.get('playbook_counts'));
- } else {
- this.setPlaybookCounts({ task_count: 1, play_count: 1 });
- }
- };
-
- this.createHostStatusCounts = status => {
- if (JOB_STATUS_UNSUCCESSFUL.includes(status)) {
- return { failures: 1 };
- }
-
- if (JOB_STATUS_COMPLETE.includes(status)) {
- return { ok: 1 };
- }
-
- return null;
- };
-
- this.pushStatusEvent = data => {
- const isJobStatusEvent = (this.job === data.unified_job_id);
- const isProjectStatusEvent = (this.project && (this.project === data.project_id));
- const isInventoryScmStatus = (this.model.get('source_project_update') === data.unified_job_id);
-
- if (isJobStatusEvent) {
- this.setJobStatus(data.status);
- if (JOB_STATUS_FINISHED.includes(data.status)) {
- this.sync();
- }
- this.dispatch();
- } else if (isProjectStatusEvent) {
- this.setProjectStatus(data.status);
- this.setProjectUpdateId(data.unified_job_id);
- this.dispatch();
- } else if (isInventoryScmStatus) {
- this.setInventoryScmStatus(data.status);
- this.setInventoryScmId(data.unified_job_id);
- this.dispatch();
- }
- };
-
- this.pushJobEvent = data => {
- const isLatest = ((!this.counter) || (data.counter > this.counter));
-
- let changed = false;
-
- if (!this.active && !(data.event === EVENT_STATS_PLAY)) {
- this.active = true;
- this.setJobStatus('running');
- changed = true;
- }
-
- if (isLatest) {
- this.counter = data.counter;
- this.latestTime = data.created;
- this.setElapsed(moment(data.created).diff(this.created, 'seconds'));
- changed = true;
- }
-
- if (data.event === EVENT_START_PLAYBOOK) {
- this.setStarted(this.state.started || data.created);
- changed = true;
- }
-
- if (data.event === EVENT_START_PLAY) {
- this.state.counts.plays++;
- changed = true;
- }
-
- if (data.event === EVENT_START_TASK) {
- this.state.counts.tasks++;
- changed = true;
- }
-
- if (data.event === EVENT_STATS_PLAY) {
- this.setStatsEvent(data);
- changed = true;
- }
-
- if (data.failed) {
- this.state.anyFailed = true;
- }
-
- if (changed) {
- this.dispatch();
- }
- };
-
- this.isExpectingStatsEvent = () => (this.jobType === 'job') ||
- (this.jobType === 'project_update') ||
- (this.jobType === 'ad_hoc_command');
-
- this.updateStats = () => {
- this.updateHostCounts();
-
- if (this.statsEvent) {
- this.setFinished(this.statsEvent.created);
-
- const failures = _.get(this.statsEvent, ['event_data', 'failures'], {});
- const dark = _.get(this.statsEvent, ['event_data', 'dark'], {});
-
- if (this.statsEvent.failed ||
- Object.keys(failures).length > 0 ||
- Object.keys(dark).length > 0) {
- this.setJobStatus('failed');
- } else {
- this.setJobStatus('successful');
- }
- } else if (this.state.counter > -1) {
- this.setJobStatus(this.state.anyFailed ? 'failed' : 'unknown');
- } else {
- this.setJobStatus('unknown');
- }
- };
-
- this.updateRunningState = () => {
- this.state.running = (Boolean(this.state.started) && !this.state.finished) ||
- (this.state.status === 'running') ||
- (this.state.status === 'pending') ||
- (this.state.status === 'waiting');
- };
-
- this.updateHostCounts = () => {
- const countedHostNames = [];
-
- const counts = Object.assign(...HOST_STATUS_KEYS.map(key => ({ [key]: 0 })));
-
- HOST_STATUS_KEYS.forEach(key => {
- const hostData = _.get(this.statsEvent, ['event_data', key], {});
-
- Object.keys(hostData).forEach(hostName => {
- const isAlreadyCounted = (countedHostNames.indexOf(hostName) > -1);
- const shouldBeCounted = ((!isAlreadyCounted) && hostData[hostName] > 0);
-
- if (shouldBeCounted) {
- countedHostNames.push(hostName);
- counts[key]++;
- }
- });
- });
-
- this.state.counts.hosts = countedHostNames.length;
- this.setHostStatusCounts(counts);
- };
-
- this.setJobStatus = status => {
- const isExpectingStats = this.isExpectingStatsEvent();
- const isIncomplete = JOB_STATUS_INCOMPLETE.includes(status);
- const isFinished = JOB_STATUS_FINISHED.includes(status);
- const isAlreadyFinished = JOB_STATUS_FINISHED.includes(this.state.status);
-
- if (isAlreadyFinished && !isFinished) {
- return;
- }
-
- if ((isExpectingStats && isIncomplete) || (!isExpectingStats && isFinished)) {
- if (this.latestTime) {
- if (!this.state.finished) {
- this.setFinished(this.latestTime);
- }
-
- if (!this.state.started && this.state.elapsed) {
- this.setStarted(moment(this.latestTime)
- .subtract(this.state.elapsed, 'seconds'));
- }
- }
- }
-
- this.state.status = status;
- this.updateRunningState();
- };
-
- this.setElapsed = elapsed => {
- if (!elapsed) return;
-
- this.state.elapsed = elapsed;
- };
-
- this.setStarted = started => {
- if (!started) return;
-
- this.state.started = started;
- this.updateRunningState();
- };
-
- this.setProjectStatus = status => {
- this.state.scm.status = status;
- };
-
- this.setProjectUpdateId = id => {
- this.state.scm.id = id;
- };
-
- this.setInventoryScmStatus = status => {
- this.state.inventoryScm.status = status;
- };
-
- this.setInventoryScmId = id => {
- this.state.inventoryScm.id = id;
- };
-
- this.setFinished = time => {
- if (!time) return;
-
- this.state.finished = time;
- this.updateRunningState();
- };
-
- this.setEnvironment = env => {
- if (!env) return;
-
- this.state.environment = env;
- };
-
- this.setArtifacts = val => {
- if (!val) return;
-
- this.state.artifacts = val;
- };
-
- this.setExecutionNode = node => {
- if (!node) return;
-
- this.state.executionNode = node;
- };
-
- this.setStatsEvent = data => {
- if (!data) return;
-
- this.statsEvent = data;
- };
-
- this.setResultTraceback = traceback => {
- if (!traceback) return;
-
- this.state.resultTraceback = traceback;
- };
-
- this.setEventProcessingFinished = val => {
- this.state.event_processing_finished = val;
- };
-
- this.setHostStatusCounts = counts => {
- counts = counts || {};
-
- HOST_STATUS_KEYS.forEach(key => {
- counts[key] = counts[key] || 0;
- });
-
- if (!this.state.counts.hosts) {
- this.state.counts.hosts = Object.keys(counts)
- .reduce((sum, key) => sum + counts[key], 0);
- }
-
- this.state.hosts = counts;
- };
-
- this.setPlaybookCounts = ({ play_count, task_count }) => {
- this.state.counts.plays = play_count;
- this.state.counts.tasks = task_count;
- };
-
- this.resetCounts = () => {
- this.state.counts.plays = 0;
- this.state.counts.tasks = 0;
- this.state.counts.hosts = 0;
- };
-
- this.sync = () => {
- const { model } = this;
-
- return model.http.get({ resource: model.get('id') })
- .then(() => {
- this.setFinished(model.get('finished'));
- this.setElapsed(model.get('elapsed'));
- this.setStarted(model.get('started'));
- this.setJobStatus(model.get('status'));
- this.setEnvironment(model.get('custom_virtualenv'));
- this.setArtifacts(model.get('artifacts'));
- this.setExecutionNode(model.get('execution_node'));
- this.setResultTraceback(model.get('result_traceback'));
- this.setEventProcessingFinished(model.get('event_processing_finished'));
-
- this.initHostStatusCounts({ model });
- this.initPlaybookCounts({ model });
-
- this.dispatch();
- });
- };
-}
-
-JobStatusService.$inject = [
- 'moment',
- 'OutputMessageService',
-];
-
-export default JobStatusService;
diff --git a/awx/ui/client/features/output/stream.service.js b/awx/ui/client/features/output/stream.service.js
deleted file mode 100644
index c3cfa10622..0000000000
--- a/awx/ui/client/features/output/stream.service.js
+++ /dev/null
@@ -1,250 +0,0 @@
-/* eslint camelcase: 0 */
-import {
- EVENT_STATS_PLAY,
- OUTPUT_MAX_BUFFER_LENGTH,
- OUTPUT_MAX_LAG,
- OUTPUT_PAGE_SIZE,
- OUTPUT_EVENT_LIMIT,
-} from './constants';
-
-const rx = [];
-
-function OutputStream ($q) {
- this.init = ({ onFrames, onFrameRate, onStop }) => {
- this.hooks = {
- onFrames,
- onFrameRate,
- onStop,
- };
-
- this.bufferInit();
- };
-
- this.bufferInit = () => {
- rx.length = 0;
-
- this.counters = {
- min: 1,
- max: -1,
- ready: -1,
- final: null,
- used: [],
- missing: [],
- total: 0,
- length: 0,
- };
-
- this.state = {
- ending: false,
- ended: false,
- overflow: false,
- };
-
- this.lag = 0;
- this.chain = $q.resolve();
-
- this.factors = this.calcFactors(OUTPUT_EVENT_LIMIT);
- this.setFramesPerRender();
- };
-
- this.calcFactors = size => {
- const factors = [1];
-
- if (size !== parseInt(size, 10) || size <= 1) {
- return factors;
- }
-
- for (let i = 2; i <= size / 2; i++) {
- if (size % i === 0) {
- factors.push(i);
- }
- }
-
- factors.push(size);
-
- return factors;
- };
-
- this.setFramesPerRender = () => {
- const index = Math.floor((this.lag / OUTPUT_MAX_LAG) * this.factors.length);
- const boundedIndex = Math.min(this.factors.length - 1, index);
-
- this.framesPerRender = this.factors[boundedIndex];
- this.hooks.onFrameRate(this.framesPerRender);
- };
-
- this.setMissingCounterThreshold = counter => {
- if (counter > this.counters.min) {
- this.counters.min = counter;
- }
- };
-
- this.bufferAdd = event => {
- const { counter } = event;
-
- if (counter > this.counters.max) {
- this.counters.max = counter;
- }
-
- let ready;
- const used = [];
- const missing = [];
-
- for (let i = this.counters.min; i <= this.counters.max; i++) {
- if (this.counters.used.indexOf(i) === -1) {
- if (i === counter) {
- rx.push(event);
- used.push(i);
- this.counters.length += 1;
- } else {
- missing.push(i);
- }
- } else {
- used.push(i);
- }
- }
-
- const excess = this.counters.length - OUTPUT_MAX_BUFFER_LENGTH;
- this.state.overflow = (excess > 0);
-
- if (missing.length === 0) {
- ready = this.counters.max;
- } else if (this.state.overflow) {
- ready = this.counters.min + this.framesPerRender;
- } else {
- ready = missing[0] - 1;
- }
-
- this.counters.total += 1;
- this.counters.ready = ready;
- this.counters.used = used;
- this.counters.missing = missing;
-
- if (!window.liveUpdates) {
- this.counters.ready = event.counter;
- }
- };
-
- this.bufferEmpty = threshold => {
- let removed = [];
-
- for (let i = rx.length - 1; i >= 0; i--) {
- if (rx[i].counter <= threshold) {
- removed = removed.concat(rx.splice(i, 1));
- }
- }
-
- this.counters.min = threshold + 1;
- this.counters.used = this.counters.used.filter(c => c > threshold);
- this.counters.length = rx.length;
-
- return removed;
- };
-
- this.isReadyToRender = () => {
- const { total } = this.counters;
- const readyCount = this.getReadyCount();
-
- if (!window.liveUpdates) {
- return true;
- }
-
- if (readyCount <= 0) {
- return false;
- }
-
- if (this.state.ending) {
- return true;
- }
-
- if (total % this.framesPerRender === 0) {
- return true;
- }
-
- if (total < OUTPUT_PAGE_SIZE) {
- if (readyCount % this.framesPerRender === 0) {
- return true;
- }
- }
-
- return false;
- };
-
- this.pushJobEvent = data => {
- this.lag++;
-
- this.chain = this.chain
- .then(() => {
- if (data.event === EVENT_STATS_PLAY) {
- this.state.ending = true;
- this.counters.final = data.counter;
- }
-
- this.bufferAdd(data);
-
- if (this.counters.total % OUTPUT_PAGE_SIZE === 0) {
- this.setFramesPerRender();
- }
-
- if (!this.isReadyToRender()) {
- return $q.resolve();
- }
-
- const isLast = this.state.ending && (this.counters.ready >= this.counters.final);
- const events = this.bufferEmpty(this.counters.ready);
-
- if (events.length > 0) {
- return this.emitFrames(events, isLast);
- }
-
- return $q.resolve();
- })
- .then(() => --this.lag);
-
- return this.chain;
- };
-
- this.setFinalCounter = counter => {
- this.chain = this.chain
- .then(() => {
- this.state.ending = true;
- this.counters.final = counter;
-
- if (counter > this.counters.ready) {
- return $q.resolve();
- }
-
- const readyCount = this.getReadyCount();
-
- let events = [];
- if (readyCount > 0) {
- events = this.bufferEmpty(this.counters.ready);
-
- return this.emitFrames(events, true);
- }
-
- return $q.resolve();
- });
-
- return this.chain;
- };
-
- this.emitFrames = (events, last) => this.hooks.onFrames(events)
- .then(() => {
- if (last) {
- this.state.ending = false;
- this.state.ended = true;
-
- this.hooks.onStop();
- }
-
- return $q.resolve();
- });
-
- this.getMaxCounter = () => this.counters.max;
- this.getReadyCount = () => this.counters.ready - this.counters.min + 1;
-}
-
-OutputStream.$inject = ['$q'];
-
-export default OutputStream;
diff --git a/awx/ui/client/features/portalMode/_index.less b/awx/ui/client/features/portalMode/_index.less
deleted file mode 100644
index 418095942c..0000000000
--- a/awx/ui/client/features/portalMode/_index.less
+++ /dev/null
@@ -1,69 +0,0 @@
-.PortalMode-container{
- display: flex;
- flex-direction: row;
- @media screen and(max-width: 900px){
- flex-direction: column;
- height: 100%;
- }
-}
-
-.PortalMode-panel--left{
- .OnePlusOne-panel--left;
-}
-
-.PortalMode-panel--right{
- .OnePlusOne-panel--right;
- .List-tableHeader:last-of-type{
- text-align:left;
- }
-}
-
-.PortalMode-panel .List-header {
- height: 14px;
- margin-bottom: 20px;
-}
-
-.PortalMode-panelHeader{
- .OnePlusOne-panelHeader;
-}
-
-
-.PortalMode-headerContainer {
- display: flex;
- align-items: center;
- margin-bottom: 20px;
-
- .at-Panel-heading {
- margin-bottom: 0;
- }
-
- .FormToggle-container {
- padding-bottom: 0;
- }
-}
-
-.PortalMode-filterHolder {
- position: absolute;
- right: 1px;
- margin-right: 10px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- .btn.btn-xs {
- padding: 1px 10px;
- }
-}
-
-.PortalMode-filterButton--edges {
- &:first-child {
- border-right: none;
- }
- &:last-child {
- border-left: none;
- }
-}
-
-.PortalMode-refresh {
- margin-left: 10px;
-}
diff --git a/awx/ui/client/features/portalMode/index.controller.js b/awx/ui/client/features/portalMode/index.controller.js
deleted file mode 100644
index 05889bf1a5..0000000000
--- a/awx/ui/client/features/portalMode/index.controller.js
+++ /dev/null
@@ -1,27 +0,0 @@
-function IndexTemplatesController ($scope, $state, strings) {
- const vm = this;
- vm.strings = strings;
-
- $scope.filterUser = () => {
- $state.go('portalMode.myJobs');
- };
- $scope.filterAll = () => {
- $state.go('portalMode.allJobs');
- };
-
- $scope.$on('updateCount', (e, count, resource) => {
- if (resource === 'jobs') {
- vm.jobsCount = count;
- } else if (resource === 'templates') {
- vm.templatesCount = count;
- }
- });
-}
-
-IndexTemplatesController.$inject = [
- '$scope',
- '$state',
- 'PortalModeStrings',
-];
-
-export default IndexTemplatesController;
diff --git a/awx/ui/client/features/portalMode/index.js b/awx/ui/client/features/portalMode/index.js
deleted file mode 100644
index e09c6e35e1..0000000000
--- a/awx/ui/client/features/portalMode/index.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import PortalModeStrings from './portalMode.strings';
-
-import templatesRoute from './routes/portalModeTemplatesList.route';
-import myJobsRoute from './routes/portalModeMyJobs.route';
-import allJobsRoute from './routes/portalModeAllJobs.route';
-
-const MODULE_NAME = 'at.features.portalMode';
-
-angular
- .module(MODULE_NAME, [])
- .service('PortalModeStrings', PortalModeStrings)
- .run(['$stateExtender', ($stateExtender) => {
- $stateExtender.addState(templatesRoute);
- $stateExtender.addState(myJobsRoute);
- $stateExtender.addState(allJobsRoute);
- }]);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/portalMode/index.view.html b/awx/ui/client/features/portalMode/index.view.html
deleted file mode 100644
index e463df464c..0000000000
--- a/awx/ui/client/features/portalMode/index.view.html
+++ /dev/null
@@ -1,56 +0,0 @@
-
diff --git a/awx/ui/client/features/portalMode/portalMode.strings.js b/awx/ui/client/features/portalMode/portalMode.strings.js
deleted file mode 100644
index c1cdd893fd..0000000000
--- a/awx/ui/client/features/portalMode/portalMode.strings.js
+++ /dev/null
@@ -1,15 +0,0 @@
-function PortalModeStrings (BaseString) {
- BaseString.call(this, 'portalMode');
-
- const { t } = this;
- const ns = this.portalMode;
-
- ns.list = {
- TEMPLATES_PANEL_TITLE: t.s('JOB TEMPLATES'),
- JOBS_PANEL_TITLE: t.s('JOBS'),
- };
-}
-
-PortalModeStrings.$inject = ['BaseStringService'];
-
-export default PortalModeStrings;
diff --git a/awx/ui/client/features/portalMode/routes/portalModeAllJobs.route.js b/awx/ui/client/features/portalMode/routes/portalModeAllJobs.route.js
deleted file mode 100644
index fa2396b4df..0000000000
--- a/awx/ui/client/features/portalMode/routes/portalModeAllJobs.route.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import jobsListController from '../../jobs/jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- name: 'portalMode.allJobs',
- url: '/alljobs?{job_search:queryset}',
- ncyBreadcrumb: {
- skip: true
- },
- params: {
- job_search: {
- value: {
- page_size: '20',
- order_by: '-finished'
- },
- dynamic: true
- }
- },
- views: {
- 'jobs@portalMode': {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.job_search;
-
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- }
-};
diff --git a/awx/ui/client/features/portalMode/routes/portalModeMyJobs.route.js b/awx/ui/client/features/portalMode/routes/portalModeMyJobs.route.js
deleted file mode 100644
index 61de256d40..0000000000
--- a/awx/ui/client/features/portalMode/routes/portalModeMyJobs.route.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import jobsListController from '../../jobs/jobsList.controller';
-
-const jobsListTemplate = require('~features/jobs/jobsList.view.html');
-
-export default {
- name: 'portalMode.myJobs',
- url: '/myjobs?{job_search:queryset}',
- ncyBreadcrumb: {
- skip: true
- },
- params: {
- job_search: {
- value: {
- page_size: '20',
- order_by: '-finished',
- created_by: null
- },
- dynamic: true
- }
- },
- views: {
- 'jobs@portalMode': {
- templateUrl: jobsListTemplate,
- controller: jobsListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'UnifiedJobModel',
- (UnifiedJob) => {
- const models = [
- new UnifiedJob(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- '$rootScope',
- ($stateParams, Wait, GetBasePath, qs, $rootScope) => {
- const searchParam = _.assign($stateParams.job_search, {
- created_by: $rootScope.current_user.id });
-
- const searchPath = GetBasePath('unified_jobs');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- SearchBasePath: [
- 'GetBasePath',
- (GetBasePath) => GetBasePath('unified_jobs')
- ]
- }
-};
diff --git a/awx/ui/client/features/portalMode/routes/portalModeTemplatesList.route.js b/awx/ui/client/features/portalMode/routes/portalModeTemplatesList.route.js
deleted file mode 100644
index 8255cfb169..0000000000
--- a/awx/ui/client/features/portalMode/routes/portalModeTemplatesList.route.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import templatesListController from '../../templates/templatesList.controller';
-import indexController from '../index.controller';
-
-const templatesListTemplate = require('~features/templates/templatesList.view.html');
-const indexTemplate = require('~features/portalMode/index.view.html');
-
-export default {
- name: 'portalMode',
- url: '/portal',
- reloadOnSearch: true,
- ncyBreadcrumb: {
- label: N_('MY VIEW')
- },
- data: {
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- params: {
- template_search: {
- dynamic: true,
- value: {
- type: 'workflow_job_template,job_template',
- },
- }
- },
- searchPrefix: 'template',
- views: {
- '@': {
- templateUrl: indexTemplate,
- controller: indexController,
- controllerAs: 'vm'
- },
- 'templates@portalMode': {
- templateUrl: templatesListTemplate,
- controller: templatesListController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'JobTemplateModel',
- 'WorkflowJobTemplateModel',
- (JobTemplate, WorkflowJobTemplate) => {
- const models = [
- new JobTemplate(['options']),
- new WorkflowJobTemplate(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.template_search;
- const searchPath = GetBasePath('unified_job_templates');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- }
-};
diff --git a/awx/ui/client/features/projects/index.controller.js b/awx/ui/client/features/projects/index.controller.js
deleted file mode 100644
index 4722753e97..0000000000
--- a/awx/ui/client/features/projects/index.controller.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function IndexProjectsController ($scope, strings, dataset) {
- const vm = this;
- vm.strings = strings;
- vm.count = dataset.data.count;
-
- $scope.$on('updateCount', (e, count) => {
- if (typeof count === 'number') {
- vm.count = count;
- }
- });
-}
-
-IndexProjectsController.$inject = [
- '$scope',
- 'ProjectsStrings',
- 'Dataset',
-];
-
-export default IndexProjectsController;
diff --git a/awx/ui/client/features/projects/index.js b/awx/ui/client/features/projects/index.js
deleted file mode 100644
index c9e51f7fbc..0000000000
--- a/awx/ui/client/features/projects/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import ProjectsStrings from './projects.strings';
-
-const MODULE_NAME = 'at.features.projects';
-
-angular
- .module(MODULE_NAME, [])
- .service('ProjectsStrings', ProjectsStrings);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/projects/index.view.html b/awx/ui/client/features/projects/index.view.html
deleted file mode 100644
index 13e18dfb28..0000000000
--- a/awx/ui/client/features/projects/index.view.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
diff --git a/awx/ui/client/features/projects/projects.strings.js b/awx/ui/client/features/projects/projects.strings.js
deleted file mode 100644
index 612806febf..0000000000
--- a/awx/ui/client/features/projects/projects.strings.js
+++ /dev/null
@@ -1,55 +0,0 @@
-function ProjectsStrings (BaseString) {
- BaseString.call(this, 'projects');
-
- const { t } = this;
- const ns = this.projects;
-
- ns.list = {
- PANEL_TITLE: t.s('PROJECTS'),
- ROW_ITEM_LABEL_DESCRIPTION: t.s('DESCRIPTION'),
- ROW_ITEM_LABEL_REVISION: t.s('REVISION'),
- ROW_ITEM_LABEL_ORGANIZATION: t.s('ORGANIZATION'),
- ROW_ITEM_LABEL_MODIFIED: t.s('LAST MODIFIED'),
- ROW_ITEM_LABEL_USED: t.s('LAST USED'),
- ADD: t.s('Add a new project')
- };
-
- ns.update = {
- GET_LATEST: t.s('Get latest SCM revision'),
- UPDATE_RUNNING: t.s('SCM update currently running'),
- MANUAL_PROJECT_NO_UPDATE: t.s('Manual projects do not require an SCM update'),
- CANCEL_UPDATE_REQUEST: t.s('Your request to cancel the update was submitted to the task manager.'),
- NO_UPDATE_INFO: t.s('There is no SCM update information available for this project. An update has not yet been completed. If you have not already done so, start an update for this project.'),
- NO_PROJ_SCM_CONFIG: t.s('The selected project is not configured for SCM. To configure for SCM, edit the project and provide SCM settings, and then run an update.'),
- NO_ACCESS_OR_COMPLETED_UPDATE: t.s('Either you do not have access or the SCM update process completed'),
- NO_RUNNING_UPDATE: t.s('An SCM update does not appear to be running for project: '),
- };
-
- ns.alert = {
- NO_UPDATE: t.s('No Updates Available'),
- UPDATE_CANCEL: t.s('SCM Update Cancel'),
- CANCEL_NOT_ALLOWED: t.s('Cancel Not Allowed'),
- NO_SCM_CONFIG: t.s('No SCM Configuration'),
- UPDATE_NOT_FOUND: t.s('Update Not Found'),
- };
-
- ns.status = {
- NOT_CONFIG: t.s('Not configured for SCM'),
- NEVER_UPDATE: t.s('No SCM updates have run for this project'),
- UPDATE_QUEUED: t.s('Update queued. Click for details'),
- UPDATE_RUNNING: t.s('Update running. Click for details'),
- UPDATE_SUCCESS: t.s('Update succeeded. Click for details'),
- UPDATE_FAILED: t.s('Update failed. Click for details'),
- UPDATE_MISSING: t.s('Update missing. Click for details'),
- UPDATE_CANCELED: t.s('Update canceled. Click for details'),
- };
-
- ns.error = {
- HEADER: this.error.HEADER,
- CALL: this.error.CALL,
- };
-}
-
-ProjectsStrings.$inject = ['BaseStringService'];
-
-export default ProjectsStrings;
diff --git a/awx/ui/client/features/projects/projectsList.controller.js b/awx/ui/client/features/projects/projectsList.controller.js
deleted file mode 100644
index df06920f60..0000000000
--- a/awx/ui/client/features/projects/projectsList.controller.js
+++ /dev/null
@@ -1,503 +0,0 @@
-/** ***********************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- ************************************************ */
-
-const mapChoices = choices => Object.assign(...choices.map(([k, v]) => ({ [k]: v.toUpperCase() })));
-
-function projectsListController (
- $filter, $scope, $rootScope, $state, $log, Dataset, Alert, Rest,
- ProcessErrors, resolvedModels, strings, Wait, ngToast,
- Prompt, GetBasePath, qs, ProjectUpdate,
-) {
- const vm = this || {};
- const [ProjectModel] = resolvedModels;
- let paginateQuerySet = {};
- $scope.canAdd = ProjectModel.options('actions.POST');
-
- vm.strings = strings;
- vm.scm_choices = ProjectModel.options('actions.GET.scm_type.choices');
- vm.projectTypes = mapChoices(vm.scm_choices);
-
- // smart-search
- vm.list = {
- iterator: 'project',
- name: 'projects',
- basePath: 'projects',
- };
- vm.dataset = Dataset.data;
- vm.projects = Dataset.data.results;
-
- $scope.$watch('vm.dataset.count', () => {
- $scope.$emit('updateCount', vm.dataset.count, 'projects');
- });
- // build tooltips
- _.forEach(vm.projects, buildTooltips);
- $rootScope.flashMessage = null;
-
- // when a project is added/deleted, rebuild tooltips
- $scope.$watchCollection('vm.projects', () => {
- _.forEach(vm.projects, buildTooltips);
- });
- // show active item in the list
- $scope.$watch('$state.params', () => {
- const projectId = _.get($state.params, 'project_id');
- if ((projectId)) {
- vm.activeId = parseInt($state.params.project_id, 10);
- } else {
- vm.activeId = '';
- }
- setToolbarSort();
- }, true);
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'project_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'name'
- };
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
- { label: `${strings.get('sort.LAST_USED_ASCENDING')}`, value: 'last_job_run' },
- { label: `${strings.get('sort.LAST_USED_DESCENDING')}`, value: '-last_job_run' },
- { label: `${strings.get('sort.ORGANIZATION_ASCENDING')}`, value: 'organization' },
- { label: `${strings.get('sort.ORGANIZATION_DESCENDING')}`, value: '-organization' }
- ];
-
- vm.toolbarSortValue = toolbarSortDefault;
-
- // Temporary hack to retrieve $scope.querySet from the paginate directive.
- // Remove this event listener once the page and page_size params
- // are represented in the url.
- $scope.$on('updateDataset', (event, dataset, queryset) => {
- vm.dataset = dataset;
- vm.projects = dataset.results;
- paginateQuerySet = queryset;
- });
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.project_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update URL with params
- $state.go('.', {
- project_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- $scope.$on('ws-jobs', (e, data) => {
- $log.debug(data);
- if (vm.projects) {
- // Assuming we have a list of projects available
- const project = vm.projects.find((p) => p.id === data.project_id);
- if (project) {
- // And we found the affected project
- $log.debug(`Received event for project: ${project.name}`);
- $log.debug(`Status changed to: ${data.status}`);
- project.status = data.status;
- buildTooltips(project);
- }
- }
- });
-
- if ($scope.removeGoTojobResults) {
- $scope.removeGoTojobResults();
- }
-
- $scope.removeGoTojobResults = $scope.$on('GoTojobResults', (e, data) => {
- if (data.summary_fields.current_update || data.summary_fields.last_update) {
- Wait('start');
- // Grab the id from summary_fields
- const updateJobid = (data.summary_fields.current_update) ?
- data.summary_fields.current_update.id : data.summary_fields.last_update.id;
-
- $state.go('output', { id: updateJobid, type: 'project' }, { reload: true });
- } else {
- Alert(vm.strings.get('alert.NO_UPDATE'), vm.strings.get('update.NO_UPDATE_INFO'), 'alert-info');
- }
- });
-
- if ($scope.removeCancelUpdate) {
- $scope.removeCancelUpdate();
- }
-
- $scope.removeCancelUpdate = $scope.$on('Cancel_Update', (e, url) => {
- // Cancel the project update process
- Rest.setUrl(url);
- Rest.post()
- .then(() => {
- Alert(vm.strings.get('alert.UPDATE_CANCEL'), vm.strings.get('update.CANCEL_UPDATE_REQUEST'), 'alert-info');
- })
- .catch(createErrorHandler(url, 'POST'));
- });
-
- if ($scope.removeCheckCancel) {
- $scope.removeCheckCancel();
- }
-
- $scope.removeCheckCancel = $scope.$on('Check_Cancel', (e, projectData) => {
- // Check that we 'can' cancel the update
- const url = projectData.related.cancel;
- Rest.setUrl(url);
- Rest.get()
- .then(({ data }) => {
- if (data.can_cancel) {
- $scope.$emit('Cancel_Update', url);
- } else {
- Alert(vm.strings.get('alert.CANCEL_NOT_ALLOWED'), vm.strings.get('update.NO_ACCESS_OR_COMPLETED_UPDATE'), 'alert-info', null, null, null, null, true);
- }
- })
- .catch(createErrorHandler(url, 'GET'));
- });
-
- vm.showSCMStatus = (id) => {
- // Refresh the project list
- const project = vm.projects.find((p) => p.id === id);
-
- if ((!project.scm_type) || project.scm_type === 'Manual') {
- Alert(vm.strings.get('alert.NO_SCM_CONFIG'), vm.strings.get('update.NO_PROJ_SCM_CONFIG'), 'alert-info');
- } else {
- // Refresh what we have in memory
- // to insure we're accessing the most recent status record
- Rest.setUrl(project.url);
- Rest.get()
- .then(({ data }) => {
- $scope.$emit('GoTojobResults', data);
- })
- .catch(createErrorHandler(project.url, 'GET'));
- }
- };
-
- vm.getLastModified = project => {
- const modified = _.get(project, 'modified');
-
- if (!modified) {
- return undefined;
- }
-
- const html = $filter('longDate')(modified);
-
- // NEED api to add field project.summary_fields.modified_by
-
- // const { username, id } = _.get(project, 'summary_fields.modified_by', {});
-
- // if (username && id) {
- // html += ` by ${$filter('sanitize')(username)} `;
- // }
-
- return html;
- };
-
- vm.getLastUsed = project => {
- const modified = _.get(project, 'last_job_run');
-
- if (!modified) {
- return undefined;
- }
-
- const html = $filter('longDate')(modified);
-
- // NEED api to add last_job user information such as launch_by
-
- // const { id } = _.get(project, 'summary_fields.last_job', {});
- // if (id) {
- // html += ` by
- // ${$filter('sanitize')('placehoder')} `;
- // }
- return html;
- };
-
- vm.copyProject = project => {
- Wait('start');
- ProjectModel
- .create('get', project.id)
- .then(model => model.copy())
- .then((copiedProj) => {
- ngToast.success({
- content: `
-
-
-
-
-
- ${vm.strings.get('SUCCESSFUL_CREATION', copiedProj.name)}
-
-
`,
- dismissButton: false,
- dismissOnTimeout: true
- });
- reloadList();
- })
- .catch(createErrorHandler('copy project', 'GET'))
- .finally(() => Wait('stop'));
- };
-
- vm.deleteProject = (id, name) => {
- const action = () => {
- $('#prompt-modal').modal('hide');
- Wait('start');
- ProjectModel
- .request('delete', id)
- .then(() => {
- let reloadListStateParams = null;
-
- if (vm.projects.length === 1
- && $state.params.project_search
- && _.has($state, 'params.project_search.page')
- && $state.params.project_search.page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.project_search.page =
- (parseInt(reloadListStateParams.project_search.page, 10) - 1).toString();
- }
-
- if (parseInt($state.params.project_id, 10) === id) {
- $state.go('^', reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, { reload: true });
- }
- })
- .catch(createErrorHandler(`${ProjectModel.path}${id}/`, 'DELETE'))
- .finally(() => {
- Wait('stop');
- });
- };
-
- ProjectModel.getDependentResourceCounts(id)
- .then((counts) => {
- const invalidateRelatedLines = [];
- let deleteModalBody = `${vm.strings.get('deleteResource.CONFIRM', 'project')}
`;
-
- counts.forEach(countObj => {
- if (countObj.count && countObj.count > 0) {
- invalidateRelatedLines.push(`${countObj.label} ${countObj.count}
`);
- }
- });
-
- if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
- deleteModalBody = `${vm.strings.get('deleteResource.USED_BY', 'project')} ${vm.strings.get('deleteResource.CONFIRM', 'project')}
`;
- invalidateRelatedLines.forEach(invalidateRelatedLine => {
- deleteModalBody += invalidateRelatedLine;
- });
- }
-
- Prompt({
- hdr: vm.strings.get('DELETE'),
- resourceName: $filter('sanitize')(name),
- body: deleteModalBody,
- action,
- actionText: vm.strings.get('DELETE'),
- });
- });
- };
-
- vm.cancelUpdate = (project) => {
- project.pending_cancellation = true;
- Rest.setUrl(GetBasePath('projects') + project.id);
- Rest.get()
- .then(({ data }) => {
- if (data.related.current_update) {
- cancelSCMUpdate(data);
- } else {
- Alert(vm.strings.get('update.UPDATE_NOT_FOUND'), vm.strings.get('update.NO_RUNNING_UPDATE') + $filter('sanitize')(project.name), 'alert-info', undefined, undefined, undefined, undefined, true);
- }
- })
- .catch(createErrorHandler('get project', 'GET'));
- };
-
- vm.SCMUpdate = (id, event) => {
- try {
- $(event.target).tooltip('hide');
- } catch (e) {
- // ignore
- }
- vm.projects.forEach((project) => {
- if (project.id === id) {
- if (project.scm_type === 'Manual' || (!project.scm_type)) {
- // Do not respond. Button appears greyed out as if it is disabled.
- // Not disabled though, because we need mouse over event
- // to work. So user can click, but we just won't do anything.
- // Alert('Missing SCM Setup', 'Before running an SCM update,
- // edit the project and provide the SCM access information.', 'alert-info');
- } else if (project.status === 'updating' || project.status === 'running' || project.status === 'pending') {
- // Alert('Update in Progress', 'The SCM update process is running.
- // Use the Refresh button to monitor the status.', 'alert-info');
- } else {
- ProjectUpdate({ scope: $scope, project_id: project.id });
- }
- }
- });
- };
-
- function buildTooltips (project) {
- project.statusIcon = getJobStatusIcon(project);
- project.statusTip = getStatusTooltip(project);
- project.scm_update_tooltip = vm.strings.get('update.GET_LATEST');
- project.scm_update_disabled = false;
-
- if (project.status === 'pending' || project.status === 'waiting') {
- project.scm_update_disabled = true;
- }
-
- if (project.status === 'failed' && project.summary_fields.last_update && project.summary_fields.last_update.status === 'canceled') {
- project.statusTip = vm.strings.get('status.UPDATE_CANCELED');
- project.scm_update_disabled = true;
- }
-
- if (project.status === 'running' || project.status === 'updating') {
- project.scm_update_tooltip = vm.strings.get('update.UPDATE_RUNNING');
- project.scm_update_disabled = true;
- }
-
- if (project.scm_type === 'manual') {
- project.statusIcon = 'none';
- project.statusTip = vm.strings.get('status.NOT_CONFIG');
- project.scm_update_tooltip = vm.strings.get('update.MANUAL_PROJECT_NO_UPDATE');
- project.scm_update_disabled = true;
- }
- }
-
- function cancelSCMUpdate (projectData) {
- Rest.setUrl(projectData.related.current_update);
- Rest.get()
- .then(({ data }) => {
- $scope.$emit('Check_Cancel', data);
- })
- .catch(createErrorHandler(projectData.related.current_update, 'GET'));
- }
-
- function reloadList () {
- Wait('start');
- const path = GetBasePath(vm.list.basePath) || GetBasePath(vm.list.name);
- qs.search(path, $state.params.project_search)
- .then((searchResponse) => {
- vm.dataset = searchResponse.data;
- vm.projects = vm.dataset.results;
- })
- .finally(() => Wait('stop'));
- }
-
- function createErrorHandler (path, action) {
- return ({ data, status }) => {
- const hdr = strings.get('error.HEADER');
- const msg = strings.get('error.CALL', { path, action, status });
- ProcessErrors($scope, data, status, null, { hdr, msg });
- };
- }
-
- function getJobStatusIcon (project) {
- let icon = 'none';
- switch (project.status) {
- case 'n/a':
- case 'ok':
- case 'never updated':
- icon = 'none';
- break;
- case 'pending':
- case 'waiting':
- case 'new':
- icon = 'none';
- break;
- case 'updating':
- case 'running':
- icon = 'running';
- break;
- case 'successful':
- icon = 'success';
- break;
- case 'failed':
- case 'missing':
- case 'canceled':
- icon = 'error';
- break;
- default:
- break;
- }
- return icon;
- }
-
- function getStatusTooltip (project) {
- let tooltip = '';
- switch (project.status) {
- case 'n/a':
- case 'ok':
- case 'never updated':
- tooltip = vm.strings.get('status.NEVER_UPDATE');
- break;
- case 'pending':
- case 'waiting':
- case 'new':
- tooltip = vm.strings.get('status.UPDATE_QUEUED');
- break;
- case 'updating':
- case 'running':
- tooltip = vm.strings.get('status.UPDATE_RUNNING');
- break;
- case 'successful':
- tooltip = vm.strings.get('status.UPDATE_SUCCESS');
- break;
- case 'failed':
- tooltip = vm.strings.get('status.UPDATE_FAILED');
- break;
- case 'missing':
- tooltip = vm.strings.get('status.UPDATE_MISSING');
- break;
- case 'canceled':
- tooltip = vm.strings.get('status.UPDATE_CANCELED');
- break;
- default:
- break;
- }
- return tooltip;
- }
-
- vm.isCollapsed = true;
-
- vm.onCollapse = () => {
- vm.isCollapsed = true;
- };
-
- vm.onExpand = () => {
- vm.isCollapsed = false;
- };
-}
-
-projectsListController.$inject = [
- '$filter',
- '$scope',
- '$rootScope',
- '$state',
- '$log',
- 'Dataset',
- 'Alert',
- 'Rest',
- 'ProcessErrors',
- 'resolvedModels',
- 'ProjectsStrings',
- 'Wait',
- 'ngToast',
- 'Prompt',
- 'GetBasePath',
- 'QuerySet',
- 'ProjectUpdate',
-];
-
-export default projectsListController;
diff --git a/awx/ui/client/features/projects/projectsList.view.html b/awx/ui/client/features/projects/projectsList.view.html
deleted file mode 100644
index 1889e48d7b..0000000000
--- a/awx/ui/client/features/projects/projectsList.view.html
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- {{ :: vm.strings.get('list.ROW_ITEM_LABEL_REVISION') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/awx/ui/client/features/projects/routes/projectsList.route.js b/awx/ui/client/features/projects/routes/projectsList.route.js
deleted file mode 100644
index d89b80c3f1..0000000000
--- a/awx/ui/client/features/projects/routes/projectsList.route.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import projectsListController from '../projectsList.controller';
-import indexController from '../index.controller';
-
-const indexTemplate = require('~features/projects/index.view.html');
-const projectsListTemplate = require('~features/projects/projectsList.view.html');
-
-export default {
- searchPrefix: 'project',
- name: 'projects',
- route: '/projects',
- ncyBreadcrumb: {
- label: N_('PROJECTS')
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'project',
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- params: {
- project_search: {
- dynamic: true,
- }
- },
- views: {
- '@': {
- templateUrl: indexTemplate,
- controller: indexController,
- controllerAs: 'vm'
- },
- 'projectsList@projects': {
- templateUrl: projectsListTemplate,
- controller: projectsListController,
- controllerAs: 'vm',
- }
- },
- resolve: {
- CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors',
- (Rest, $stateParams, GetBasePath, ProcessErrors) => {
- const path = GetBasePath('credential_types');
- Rest.setUrl(path);
- return Rest.get()
- .then((data) => data.data.results)
- .catch((response) => {
- ProcessErrors(null, response.data, response.status, null, {
- hdr: 'Error!',
- msg: `Failed to get credential types. GET returned status: ${response.status}`,
- });
- });
- }
- ],
- ConfigData: ['ConfigService', 'ProcessErrors',
- (ConfigService, ProcessErrors) => ConfigService
- .getConfig()
- .then(response => response)
- .catch(({ data, status }) => {
- ProcessErrors(null, data, status, null, {
- hdr: 'Error!',
- msg: `Failed to get config. GET returned status: status: ${status}`,
- });
- })],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.project_search;
- const searchPath = GetBasePath('projects');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- resolvedModels: [
- 'ProjectModel',
- (Project) => {
- const models = [
- new Project(['options']),
- ];
- return Promise.all(models);
- },
- ],
- }
-};
diff --git a/awx/ui/client/features/templates/index.controller.js b/awx/ui/client/features/templates/index.controller.js
deleted file mode 100644
index bfbfeb84fd..0000000000
--- a/awx/ui/client/features/templates/index.controller.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function IndexTemplatesController ($scope, strings, dataset) {
- const vm = this;
- vm.strings = strings;
- vm.count = dataset.data.count;
-
- $scope.$on('updateCount', (e, count) => {
- if (typeof count === 'number') {
- vm.count = count;
- }
- });
-}
-
-IndexTemplatesController.$inject = [
- '$scope',
- 'TemplatesStrings',
- 'Dataset'
-];
-
-export default IndexTemplatesController;
diff --git a/awx/ui/client/features/templates/index.js b/awx/ui/client/features/templates/index.js
deleted file mode 100644
index fd0a49b45a..0000000000
--- a/awx/ui/client/features/templates/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import TemplatesStrings from './templates.strings';
-
-const MODULE_NAME = 'at.features.templates';
-
-angular
- .module(MODULE_NAME, [])
- .service('TemplatesStrings', TemplatesStrings);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/templates/index.view.html b/awx/ui/client/features/templates/index.view.html
deleted file mode 100644
index 90cab8f608..0000000000
--- a/awx/ui/client/features/templates/index.view.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/templates/routes/organizationsTemplatesList.route.js b/awx/ui/client/features/templates/routes/organizationsTemplatesList.route.js
deleted file mode 100644
index 4d306b2857..0000000000
--- a/awx/ui/client/features/templates/routes/organizationsTemplatesList.route.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import templatesListController from '../templatesList.controller';
-import indexController from '../index.controller';
-
-const indexTemplate = require('~features/templates/index.view.html');
-const templatesListTemplate = require('~features/templates/templatesList.view.html');
-
-export default {
- url: "/:organization_id/job_templates",
- name: 'organizations.job_templates',
- data: {
- activityStream: true,
- activityStreamTarget: 'template'
- },
- params: {
- template_search: {
- dynamic: true,
- value: {
- type: 'job_template',
- order_by: 'name',
- page_size: '20',
- or__jobtemplate__project__organization: null,
- or__jobtemplate__inventory__organization: null
- },
- }
- },
- ncyBreadcrumb: {
- label: N_("JOB TEMPLATES")
- },
- views: {
- 'form': {
- templateUrl: indexTemplate,
- controller: indexController,
- controllerAs: 'vm'
- },
- 'templatesList@organizations.job_templates': {
- controller: templatesListController,
- templateUrl: templatesListTemplate,
- controllerAs: 'vm',
- }
- },
- resolve: {
- resolvedModels: [
- 'JobTemplateModel',
- 'WorkflowJobTemplateModel',
- (JobTemplate, WorkflowJobTemplate) => {
- const models = [
- new JobTemplate(['options']),
- new WorkflowJobTemplate(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchPath = GetBasePath('unified_job_templates');
-
- const searchParam = Object.assign(
- $stateParams.template_search, {
- or__jobtemplate__project__organization: $stateParams.organization_id,
- or__jobtemplate__inventory__organization: $stateParams.organization_id}
- );
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- }
-};
diff --git a/awx/ui/client/features/templates/routes/projectsTemplatesList.route.js b/awx/ui/client/features/templates/routes/projectsTemplatesList.route.js
deleted file mode 100644
index be10a69b0d..0000000000
--- a/awx/ui/client/features/templates/routes/projectsTemplatesList.route.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import templatesListController from '../templatesList.controller';
-
-const templatesListTemplate = require('~features/templates/templatesList.view.html');
-
-export default {
- url: "/templates",
- name: 'projects.edit.templates',
- searchPrefix: 'template',
- params: {
- template_search: {
- dynamic: true,
- value: {
- type: 'job_template',
- order_by: 'name',
- page_size: '20',
- jobtemplate__project: null
- },
- }
- },
- data: {
- socket: {
- groups: {
- jobs: ['status_changed']
- }
- }
- },
- ncyBreadcrumb: {
- label: N_("JOB TEMPLATES")
- },
- views: {
- 'related': {
- controller: templatesListController,
- templateUrl: templatesListTemplate,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: [
- 'JobTemplateModel',
- 'WorkflowJobTemplateModel',
- (JobTemplate, WorkflowJobTemplate) => {
- const models = [
- new JobTemplate(['options']),
- new WorkflowJobTemplate(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchPath = GetBasePath('unified_job_templates');
-
- const searchParam = _.assign($stateParams.template_search, {
- jobtemplate__project: $stateParams.project_id });
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- }
-};
diff --git a/awx/ui/client/features/templates/routes/templatesList.route.js b/awx/ui/client/features/templates/routes/templatesList.route.js
deleted file mode 100644
index 4b17ab471d..0000000000
--- a/awx/ui/client/features/templates/routes/templatesList.route.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import templatesListController from '../templatesList.controller';
-import indexController from '../index.controller';
-
-const indexTemplate = require('~features/templates/index.view.html');
-const templatesListTemplate = require('~features/templates/templatesList.view.html');
-
-export default {
- name: 'templates',
- route: '/templates',
- ncyBreadcrumb: {
- label: N_("TEMPLATES")
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'template'
- },
- params: {
- template_search: {
- dynamic: true,
- value: {
- type: 'workflow_job_template,job_template',
- order_by: 'name',
- page_size: '20'
- },
- }
- },
- searchPrefix: 'template',
- views: {
- '@': {
- templateUrl: indexTemplate,
- controller: indexController,
- controllerAs: 'vm'
- },
- 'templatesList@templates': {
- controller: templatesListController,
- templateUrl: templatesListTemplate,
- controllerAs: 'vm',
- }
- },
- resolve: {
- resolvedModels: [
- 'JobTemplateModel',
- 'WorkflowJobTemplateModel',
- (JobTemplate, WorkflowJobTemplate) => {
- const models = [
- new JobTemplate(['options']),
- new WorkflowJobTemplate(['options']),
- ];
- return Promise.all(models);
- },
- ],
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.template_search;
- const searchPath = GetBasePath('unified_job_templates');
-
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => Wait('stop'));
- }
- ],
- }
-};
diff --git a/awx/ui/client/features/templates/templates.strings.js b/awx/ui/client/features/templates/templates.strings.js
deleted file mode 100644
index e3bdb18efb..0000000000
--- a/awx/ui/client/features/templates/templates.strings.js
+++ /dev/null
@@ -1,167 +0,0 @@
-function TemplatesStrings (BaseString) {
- BaseString.call(this, 'templates');
-
- const { t } = this;
- const ns = this.templates;
-
- ns.state = {
- LIST_BREADCRUMB_LABEL: t.s('TEMPLATES')
- };
-
- ns.list = {
- PANEL_TITLE: t.s('TEMPLATES'),
- ADD_DD_JT_LABEL: t.s('Job Template'),
- ADD_DD_WF_LABEL: t.s('Workflow Template'),
- OPEN_WORKFLOW_VISUALIZER: t.s('Click here to open the workflow visualizer'),
- ROW_ITEM_LABEL_ORGANIZATION: t.s('Organization'),
- ROW_ITEM_LABEL_DESCRIPTION: t.s('Description'),
- ROW_ITEM_LABEL_ACTIVITY: t.s('Activity'),
- ROW_ITEM_LABEL_INVENTORY: t.s('Inventory'),
- ROW_ITEM_LABEL_PROJECT: t.s('Project'),
- ROW_ITEM_LABEL_CREDENTIALS: t.s('Credentials'),
- ROW_ITEM_LABEL_MODIFIED: t.s('Last Modified'),
- ROW_ITEM_LABEL_RAN: t.s('Last Ran'),
- ADD: t.s('Add a new template')
- };
-
- ns.prompt = {
- INVENTORY: t.s('Inventory'),
- CREDENTIAL: t.s('Credential'),
- PROMPT: t.s('PROMPT'),
- OTHER_PROMPTS: t.s('Other Prompts'),
- SURVEY: t.s('Survey'),
- PREVIEW: t.s('Preview'),
- LAUNCH: t.s('LAUNCH'),
- CONFIRM: t.s('CONFIRM'),
- SELECTED: t.s('SELECTED'),
- NO_CREDENTIALS_SELECTED: t.s('No credentials selected'),
- NO_INVENTORY_SELECTED: t.s('No inventory selected'),
- REVERT: t.s('REVERT'),
- CREDENTIAL_TYPE: t.s('Credential Type'),
- CREDENTIAL_PASSWORD_WARNING: t.s('Credentials that require passwords on launch are not permitted for template schedules and workflow nodes. The following credentials must be removed or replaced to proceed:'),
- PASSWORDS_REQUIRED_HELP: t.s('Launching this job requires the passwords listed below. Enter each password before continuing.'),
- PLEASE_ENTER_PASSWORD: t.s('Please enter a password.'),
- credential_passwords: {
- SSH_PASSWORD: t.s('SSH Password'),
- PRIVATE_KEY_PASSPHRASE: t.s('Private Key Passphrase'),
- PRIVILEGE_ESCALATION_PASSWORD: t.s('Privilege Escalation Password'),
- VAULT_PASSWORD: t.s('Vault Password')
- },
- SHOW_CHANGES: t.s('Show Changes'),
- SHOW_CHANGES_HELP: t.s('If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansible’s --diff mode.'),
- SKIP_TAGS: t.s('Skip Tags'),
- SKIP_TAGS_HELP: t.s('Skip tags are useful when you have a large playbook, and you want to skip specific parts of a play or task. Use commas to separate multiple tags. Refer to Ansible Tower documentation for details on the usage of tags.'),
- JOB_TAGS: t.s('Job Tags'),
- JOB_TAGS_HELP: t.s('Tags are useful when you have a large playbook, and you want to run a specific part of a play or task. Use commas to separate multiple tags. Refer to Ansible Tower documentation for details on the usage of tags.'),
- LIMIT: t.s('Limit'),
- LIMIT_HELP: t.s('Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. Multiple patterns are allowed. Refer to Ansible documentation for more information and examples on patterns.'),
- JOB_TYPE: t.s('Job Type'),
- JOB_TYPE_HELP: t.s('For job templates, select run to execute the playbook. Select check to only check playbook syntax, test environment setup, and report problems without executing the playbook.'),
- VERBOSITY: t.s('Verbosity'),
- VERBOSITY_HELP: t.s('Control the level of output ansible will produce as the playbook executes.'),
- CHOOSE_JOB_TYPE: t.s('Choose a job type'),
- CHOOSE_VERBOSITY: t.s('Choose a verbosity'),
- EXTRA_VARIABLES: t.s('Extra Variables'),
- EXTRA_VARIABLES_HELP: t.s('Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON.
JSON:{ "somevar": "somevalue", "password": "magic" } YAML:--- somevar: somevalue password: magic '),
- PLEASE_ENTER_ANSWER: t.s('Please enter an answer.'),
- PLEASE_SELECT_VALUE: t.s('Please select a value'),
- VALID_INTEGER: t.s('Please enter an answer that is a valid integer.'),
- VALID_DECIMAL: t.s('Please enter an answer that is a decimal number.'),
- PLAYBOOK_RUN: t.s('Playbook Run'),
- SCM_BRANCH: t.s('SCM Branch'),
- SCM_BRANCH_HELP: t.s('Branch to use in job run. Project default used if blank.'),
- CHECK: t.s('Check'),
- NO_CREDS_MATCHING_TYPE: t.s('No Credentials Matching This Type Have Been Created'),
- CREDENTIAL_TYPE_MISSING: typeLabel => t.s('This job template has a default {{typeLabel}} credential which must be included or replaced before proceeding.', { typeLabel })
- };
-
- ns.alert = {
- MISSING_PARAMETER: t.s('Template parameter is missing.'),
- NO_PERMISSION: t.s('You do not have permission to perform this action.'),
- UNKNOWN_COPY: t.s('Unable to determine this template\'s type while copying.'),
- UNKNOWN_DELETE: t.s('Unable to determine this template\'s type while deleting.'),
- UNKNOWN_EDIT: t.s('Unable to determine this template\'s type while editing.'),
- UNKNOWN_LAUNCH: t.s('Unable to determine this template\'s type while launching.'),
- UNKNOWN_SCHEDULE: t.s('Unable to determine this template\'s type while scheduling.'),
- };
-
- ns.error = {
- HEADER: this.error.HEADER,
- CALL: this.error.CALL,
- EDIT: t.s('Unable to edit template.'),
- DELETE: t.s('Unable to delete template.'),
- LAUNCH: t.s('Unable to launch template.'),
- UNKNOWN: t.s('Unable to determine template type.'),
- SCHEDULE: t.s('Unable to schedule job.'),
- COPY: t.s('Unable to copy template.'),
- INVALID: t.s('Resources are missing from this template.')
- };
-
- ns.warnings = {
- WORKFLOW_RESTRICTED_COPY: t.s('You do not have access to all resources used by this workflow. Resources that you don\'t have access to will not be copied and will result in an incomplete workflow.')
- };
-
- ns.workflows = {
- INVALID_JOB_TEMPLATE: t.s('This Job Template is missing a default inventory or project. This must be addressed in the Job Template form before this node can be saved.'),
- CREDENTIAL_WITH_PASS: t.s('This Job Template has a credential that requires a password. Credentials requiring passwords on launch are not permitted on workflow nodes.')
- };
-
- ns.workflow_maker = {
- DELETE_NODE_PROMPT_TEXT: t.s('Are you sure you want to delete this workflow node?'),
- KEY: t.s('KEY'),
- ON_SUCCESS: t.s('On Success'),
- ON_FAILURE: t.s('On Failure'),
- ALWAYS: t.s('Always'),
- PAUSE: t.s('Wait For Approval'),
- JOB_TEMPLATE: t.s('Job Template'),
- PROJECT_SYNC: t.s('Project Sync'),
- INVENTORY_SYNC: t.s('Inventory Sync'),
- WORKFLOW: t.s('Workflow'),
- TEMPLATE: t.s('Template'),
- WARNING: t.s('Warning'),
- TOTAL_NODES: t.s('TOTAL NODES'),
- ADD_A_NODE: t.s('ADD A NODE'),
- EDIT_TEMPLATE: t.s('EDIT TEMPLATE'),
- JOBS: t.s('Jobs'),
- PLEASE_CLICK_THE_START_BUTTON: t.s('Please click the start button to build your workflow.'),
- PLEASE_HOVER_OVER_A_TEMPLATE: t.s('Please hover over a template for additional options.'),
- EDIT_LINK_TOOLTIP: t.s('Click to edit link'),
- VIEW_LINK_TOOLTIP: t.s('Click to view link'),
- RUN: t.s('RUN'),
- CHECK: t.s('CHECK'),
- SELECT: t.s('SELECT'),
- DELETED: t.s('DELETED'),
- START: t.s('START'),
- DETAILS: t.s('DETAILS'),
- TITLE: t.s('WORKFLOW VISUALIZER'),
- INVENTORY_WILL_OVERRIDE: t.s('The inventory of this node will be overridden by the parent workflow inventory.'),
- INVENTORY_WILL_NOT_OVERRIDE: t.s('The inventory of this node will not be overridden by the parent workflow inventory.'),
- INVENTORY_PROMPT_WILL_OVERRIDE: t.s('The inventory of this node will be overridden if a parent workflow inventory is provided at launch.'),
- INVENTORY_PROMPT_WILL_NOT_OVERRIDE: t.s('The inventory of this node will not be overridden if a parent workflow inventory is provided at launch.'),
- ADD_LINK: t.s('ADD LINK'),
- EDIT_LINK: t.s('EDIT LINK'),
- VIEW_LINK: t.s('VIEW LINK'),
- NEW_LINK: t.s('Please click on an available node to form a new link.'),
- UNLINK: t.s('UNLINK'),
- READ_ONLY_PROMPT_VALUES: t.s('The following promptable values were provided when this node was created:'),
- READ_ONLY_NO_PROMPT_VALUES: t.s('No promptable values were provided when this node was created.'),
- UNSAVED_CHANGES_HEADER: t.s('WARNING: UNSAVED CHANGES'),
- UNSAVED_CHANGES_PROMPT_TEXT: t.s('Are you sure you want to exit the Workflow Creator without saving your changes?'),
- EXIT: t.s('EXIT'),
- CANCEL: t.s('CANCEL'),
- SAVE_AND_EXIT: t.s('SAVE & EXIT'),
- APPROVAL: t.s('Approval'),
- TIMEOUT_POPOVER: t.s('The amount of time to wait before this approval step is automatically denied. Defaults to 0 for no timeout.'),
- TIMED_OUT: t.s('APPROVAL TIMED OUT'),
- TIMEOUT: t.s('Timeout'),
- APPROVED: t.s('APPROVED'),
- DENIED: t.s('DENIED'),
- CONVERGENCE: t.s('Convergence'),
- ALL: t.s('All'),
- ANY: t.s('Any'),
- };
-}
-
-TemplatesStrings.$inject = ['BaseStringService'];
-
-export default TemplatesStrings;
diff --git a/awx/ui/client/features/templates/templatesList.controller.js b/awx/ui/client/features/templates/templatesList.controller.js
deleted file mode 100644
index 2500a78816..0000000000
--- a/awx/ui/client/features/templates/templatesList.controller.js
+++ /dev/null
@@ -1,489 +0,0 @@
-/** ***********************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- ************************************************ */
-const JOB_TEMPLATE_ALIASES = ['job_template', 'Job Template'];
-const WORKFLOW_TEMPLATE_ALIASES = ['workflow_job_template', 'Workflow Job Template'];
-
-const isJobTemplate = ({ type }) => JOB_TEMPLATE_ALIASES.indexOf(type) > -1;
-const isWorkflowTemplate = ({ type }) => WORKFLOW_TEMPLATE_ALIASES.indexOf(type) > -1;
-const mapChoices = choices => Object.assign(...choices.map(([k, v]) => ({[k]: v})));
-
-function ListTemplatesController(
- $filter,
- $scope,
- $state,
- Alert,
- Dataset,
- ProcessErrors,
- Prompt,
- resolvedModels,
- strings,
- Wait,
- qs,
- GetBasePath,
- ngToast,
-) {
- const vm = this || {};
- const [jobTemplate, workflowTemplate] = resolvedModels;
-
- const choices = workflowTemplate.options('actions.GET.type.choices')
- .concat(jobTemplate.options('actions.GET.type.choices'));
-
- let paginateQuerySet = {};
-
- vm.strings = strings;
- vm.templateTypes = mapChoices(choices);
- vm.activeId = parseInt($state.params.job_template_id || $state.params.workflow_job_template_id);
- vm.invalidTooltip = {
- popover: {
- text: strings.get('error.INVALID'),
- on: 'mouseenter',
- icon: 'fa-exclamation',
- position: 'right',
- arrowHeight: 15
- }
- };
-
- $scope.canAddJobTemplate = jobTemplate.options('actions.POST');
- $scope.canAddWorkflowJobTemplate = workflowTemplate.options('actions.POST');
- $scope.canAdd = ($scope.canAddJobTemplate || $scope.canAddWorkflowJobTemplate);
-
- // smart-search
- vm.list = {
- iterator: 'template',
- name: 'templates'
- };
- vm.dataset = Dataset.data;
- vm.templates = Dataset.data.results;
- vm.defaultParams = $state.params.template_search;
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'name'
- };
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
- { label: `${strings.get('sort.LAST_JOB_RUN_ASCENDING')}`, value: 'last_job_run' },
- { label: `${strings.get('sort.LAST_JOB_RUN_DESCENDING')}`, value: '-last_job_run' },
- { label: `${strings.get('sort.INVENTORY_ASCENDING')}`, value: 'job_template__inventory__id' },
- { label: `${strings.get('sort.INVENTORY_DESCENDING')}`, value: '-job_template__inventory__id' },
- { label: `${strings.get('sort.PROJECT_ASCENDING')}`, value: 'jobtemplate__project__id' },
- { label: `${strings.get('sort.PROJECT_DESCENDING')}`, value: '-jobtemplate__project__id' },
- ];
-
- vm.toolbarSortValue = toolbarSortDefault;
-
- $scope.$on('updateDataset', (event, dataset, queryset) => {
- paginateQuerySet = queryset;
- });
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.template_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update params
- $state.go('.', {
- template_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- $scope.$watch('vm.dataset.count', () => {
- $scope.$emit('updateCount', vm.dataset.count, 'templates');
- });
-
- $scope.$watch('$state.params', function(newValue, oldValue) {
- const job_template_id = _.get($state.params, 'job_template_id');
- const workflow_job_template_id = _.get($state.params, 'workflow_job_template_id');
-
- if((job_template_id || workflow_job_template_id)) {
- vm.activeId = parseInt($state.params.job_template_id || $state.params.workflow_job_template_id);
- } else {
- vm.activeId = "";
- }
- setToolbarSort();
- }, true);
-
- $scope.$on(`ws-jobs`, (e, msg) => {
- if (msg.unified_job_template_id && vm.templates) {
- const template = vm.templates.find((t) => t.id === msg.unified_job_template_id);
- if (template) {
- if (msg.status === 'pending') {
- // This is a new job - add it to the front of the
- // recent_jobs array
- if (template.summary_fields.recent_jobs.length === 10) {
- template.summary_fields.recent_jobs.pop();
- }
-
- template.summary_fields.recent_jobs.unshift({
- id: msg.unified_job_id,
- status: msg.status,
- type: msg.type
- });
- } else {
- // This is an update to an existing job. Check to see
- // if we have it in our array of recent_jobs
- for (let i=0; i {
- if(isJobTemplate(template)) {
- return template.project === null || (template.inventory === null && template.ask_inventory_on_launch === false);
- } else {
- return false;
- }
- };
-
- vm.isPortalMode = $state.includes('portalMode');
-
- vm.openWorkflowVisualizer = template => {
- const name = 'templates.editWorkflowJobTemplate.workflowMaker';
- const params = { workflow_job_template_id: template.id };
- const options = { reload: true };
-
- $state.go(name, params, options);
- };
-
- vm.deleteTemplate = template => {
- if (!template) {
- Alert(strings.get('error.DELETE'), strings.get('alert.MISSING_PARAMETER'));
- return;
- }
-
- if (isWorkflowTemplate(template)) {
- displayWorkflowTemplateDeletePrompt(template);
- } else if (isJobTemplate(template)) {
- jobTemplate.getDependentResourceCounts(template.id)
- .then(counts => displayJobTemplateDeletePrompt(template, counts));
- } else {
- Alert(strings.get('error.UNKNOWN'), strings.get('alert.UNKNOWN_DELETE'));
- }
- };
-
- vm.copyTemplate = template => {
- if (!template) {
- Alert(strings.get('error.COPY'), strings.get('alert.MISSING_PARAMETER'));
- return;
- }
-
- if (isJobTemplate(template)) {
- copyJobTemplate(template);
- } else if (isWorkflowTemplate(template)) {
- copyWorkflowTemplate(template);
- } else {
- Alert(strings.get('error.UNKNOWN'), strings.get('alert.UNKNOWN_COPY'));
- }
- };
-
- vm.getModified = template => {
- const modified = _.get(template, 'modified');
-
- if (!modified) {
- return undefined;
- }
-
- let html = $filter('longDate')(modified);
-
- const { username, id } = _.get(template, 'summary_fields.modified_by', {});
-
- if (username && id) {
- html += ` by ${$filter('sanitize')(username)} `;
- }
-
- return html;
- };
-
- vm.buildCredentialTags = (credentials) => {
- return credentials.map(credential => {
- const icon = `${credential.kind}`;
- const link = `/#/credentials/${credential.id}`;
- const tooltip = strings.get('tooltips.VIEW_THE_CREDENTIAL');
- const value = $filter('sanitize')(credential.name);
-
- return { icon, link, tooltip, value };
- });
- };
-
- vm.getLastRan = template => {
- const lastJobRun = _.get(template, 'last_job_run');
-
- if (!lastJobRun) {
- return undefined;
- }
-
- let html = $filter('longDate')(lastJobRun);
-
- // TODO: uncomment and update when last job run user is returned by api
- // const { username, id } = _.get(template, 'summary_fields.last_job_run_by', {});
-
- // if (username && id) {
- // html += ` by ${$filter('sanitize')(username)} `;
- //}
-
- return html;
- };
-
- vm.getType = template => {
- if(isJobTemplate(template)) {
- return strings.get('list.ADD_DD_JT_LABEL');
- } else {
- return strings.get('list.ADD_DD_WF_LABEL');;
- }
- };
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'template_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- function refreshTemplates() {
- Wait('start');
- let path = GetBasePath('unified_job_templates');
- qs.search(path, $state.params.template_search, { 'X-WS-Session-Quiet': true })
- .then(function(searchResponse) {
- vm.dataset = searchResponse.data;
- vm.templates = vm.dataset.results;
- })
- .finally(() => Wait('stop'));
- }
-
- function createErrorHandler(path, action) {
- return ({ data, status }) => {
- const hdr = strings.get('error.HEADER');
- const msg = strings.get('error.CALL', { path, action, status });
- ProcessErrors($scope, data, status, null, { hdr, msg });
- };
- }
-
- function copyJobTemplate(template) {
- Wait('start');
- jobTemplate
- .create('get', template.id)
- .then(model => model.copy())
- .then((copiedJT) => {
- ngToast.success({
- content: `
-
-
-
-
-
- ${strings.get('SUCCESSFUL_CREATION', copiedJT.name)}
-
-
`,
- dismissButton: false,
- dismissOnTimeout: true
- });
- refreshTemplates();
- })
- .catch(createErrorHandler('copy job template', 'POST'))
- .finally(() => Wait('stop'));
- }
-
- function copyWorkflowTemplate(template) {
- Wait('start');
- workflowTemplate
- .create('get', template.id)
- .then(model => model.extend('get', 'copy'))
- .then(model => {
- const action = () => {
- $('#prompt-modal').modal('hide');
- Wait('start');
- model.copy()
- .then((copiedWFJT) => {
- ngToast.success({
- content: `
-
-
-
-
-
- ${strings.get('SUCCESSFUL_CREATION', copiedWFJT.name)}
-
-
`,
- dismissButton: false,
- dismissOnTimeout: true
- });
- refreshTemplates();
- })
- .catch(createErrorHandler('copy workflow', 'POST'))
- .finally(() => Wait('stop'));
- };
-
- if (model.get('related.copy.can_copy_without_user_input')) {
- action();
- } else if (model.get('related.copy.can_copy')) {
- Prompt({
- action,
- actionText: strings.get('COPY'),
- body: buildWorkflowCopyPromptHTML(model.get('related.copy')),
- class: 'Modal-primaryButton',
- hdr: strings.get('listActions.COPY', template.name),
- });
- } else {
- Alert(strings.get('error.COPY'), strings.get('alert.NO_PERMISSION'));
- }
- })
- .catch(createErrorHandler('copy workflow', 'GET'))
- .finally(() => Wait('stop'));
- }
-
- function handleSuccessfulDelete(template) {
- const { page } = _.get($state.params, 'template_search');
- let reloadListStateParams = null;
-
- if (vm.templates.length === 1 && page && page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- const pageNumber = (parseInt(reloadListStateParams.template_search.page, 0) - 1);
- reloadListStateParams.template_search.page = pageNumber.toString();
- }
-
- if (parseInt($state.params.job_template_id, 0) === template.id) {
- $state.go('templates', reloadListStateParams, { reload: true });
- } else if (parseInt($state.params.workflow_job_template_id, 0) === template.id) {
- $state.go('templates', reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, { reload: true });
- }
- }
-
- function displayJobTemplateDeletePrompt(template, counts) {
- Prompt({
- action() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- jobTemplate
- .request('delete', template.id)
- .then(() => handleSuccessfulDelete(template))
- .catch(createErrorHandler('delete template', 'DELETE'))
- .finally(() => Wait('stop'));
- },
- hdr: strings.get('DELETE'),
- resourceName: $filter('sanitize')(template.name),
- body: buildJobTemplateDeletePromptHTML(counts),
- });
- }
-
- function displayWorkflowTemplateDeletePrompt(template) {
- Prompt({
- action() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- workflowTemplate
- .request('delete', template.id)
- .then(() => handleSuccessfulDelete(template))
- .catch(createErrorHandler('delete template', 'DELETE'))
- .finally(() => Wait('stop'));
- },
- hdr: strings.get('DELETE'),
- resourceName: $filter('sanitize')(template.name),
- body: strings.get('deleteResource.CONFIRM', 'workflow template'),
- });
- }
-
- function buildJobTemplateDeletePromptHTML(counts) {
- const buildCount = count => `${count} `;
- const buildLabel = label => `
- ${$filter('sanitize')(label)} `;
- const buildCountLabel = ({ count, label }) => `
- ${buildLabel(label)}${buildCount(count)}
`;
-
- const displayedCounts = counts.filter(({ count }) => count > 0);
-
- const html = `
- ${displayedCounts.length ? strings.get('deleteResource.USED_BY', 'job template') : ''}
- ${strings.get('deleteResource.CONFIRM', 'job template')}
- ${displayedCounts.map(buildCountLabel).join('')}
- `;
-
- return html;
- }
-
- function buildWorkflowCopyPromptHTML(data) {
- const pull = (data, param) => _.get(data, param, []).map($filter('sanitize'));
-
- const credentials = pull(data, 'credentials_unable_to_copy');
- const inventories = pull(data, 'inventories_unable_to_copy');
- const templates = pull(data, 'templates_unable_to_copy');
-
- const html = `
-
- ${strings.get('warnings.WORKFLOW_RESTRICTED_COPY')}
-
-
- ${templates.length ? `
Unified Job Templates
` : ''}
- ${templates.map(item => `${item} `).join('')}
- ${templates.length ? ` ` : ''}
-
-
- ${credentials.length ? `
Credentials
` : ''}
- ${credentials.map(item => `${item} `).join('')}
- ${credentials.length ? ` ` : ''}
-
-
- ${inventories.length ? `
Inventories
` : ''}
- ${inventories.map(item => `${item} `).join('')}
- ${inventories.length ? ` ` : ''}
-
- `;
-
- return html;
- }
-
- vm.isCollapsed = true;
-
- vm.onCollapse = () => {
- vm.isCollapsed = true;
- };
-
- vm.onExpand = () => {
- vm.isCollapsed = false;
- };
-}
-
-ListTemplatesController.$inject = [
- '$filter',
- '$scope',
- '$state',
- 'Alert',
- 'Dataset',
- 'ProcessErrors',
- 'Prompt',
- 'resolvedModels',
- 'TemplatesStrings',
- 'Wait',
- 'QuerySet',
- 'GetBasePath',
- 'ngToast'
-];
-
-export default ListTemplatesController;
diff --git a/awx/ui/client/features/templates/templatesList.view.html b/awx/ui/client/features/templates/templatesList.view.html
deleted file mode 100644
index 52c9337382..0000000000
--- a/awx/ui/client/features/templates/templatesList.view.html
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/users/index.js b/awx/ui/client/features/users/index.js
deleted file mode 100644
index b8f6a8052f..0000000000
--- a/awx/ui/client/features/users/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import atFeaturesUsersTokens from '~features/users/tokens';
-
-const MODULE_NAME = 'at.features.users';
-
-angular
- .module(MODULE_NAME, [atFeaturesUsersTokens]);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/users/tokens/index.js b/awx/ui/client/features/users/tokens/index.js
deleted file mode 100644
index 6d635b572d..0000000000
--- a/awx/ui/client/features/users/tokens/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import TokensStrings from './tokens.strings';
-
-const MODULE_NAME = 'at.features.users.tokens';
-
-angular
- .module(MODULE_NAME, [])
- .service('TokensStrings', TokensStrings);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/features/users/tokens/tokens.strings.js b/awx/ui/client/features/users/tokens/tokens.strings.js
deleted file mode 100644
index 55ee772f2f..0000000000
--- a/awx/ui/client/features/users/tokens/tokens.strings.js
+++ /dev/null
@@ -1,49 +0,0 @@
-function TokensStrings (BaseString) {
- BaseString.call(this, 'tokens');
-
- const { t } = this;
- const ns = this.tokens;
-
- ns.state = {
- LIST_BREADCRUMB_LABEL: t.s('TOKENS'),
- ADD_BREADCRUMB_LABEL: t.s('CREATE TOKEN'),
- USER_LIST_BREADCRUMB_LABEL: t.s('TOKENS')
- };
-
- ns.tab = {
- DETAILS: t.s('Details')
- };
-
- ns.add = {
- PANEL_TITLE: t.s('CREATE TOKEN'),
- APP_PLACEHOLDER: t.s('SELECT AN APPLICATION'),
- SCOPE_HELP_TEXT: t.s('Specify a scope for the token\'s access'),
- TOKEN_MODAL_HEADER: t.s('TOKEN INFORMATION'),
- TOKEN_LABEL: t.s('TOKEN'),
- REFRESH_TOKEN_LABEL: t.s('REFRESH TOKEN'),
- TOKEN_EXPIRES_LABEL: t.s('EXPIRES'),
- ERROR_HEADER: t.s('COULD NOT CREATE TOKEN'),
- ERROR_BODY_LABEL: t.s('Returned status:'),
- LAST_USED_LABEL: t.s('by'),
- DELETE_ACTION_LABEL: t.s('DELETE'),
- SCOPE_PLACEHOLDER: t.s('Select a scope'),
- SCOPE_READ_LABEL: t.s('Read'),
- SCOPE_WRITE_LABEL: t.s('Write'),
- APPLICATION_HELP_TEXT: t.s('Leaving this field blank will result in the creation of a Personal Access Token which is not linked to an Application.')
- };
-
- ns.list = {
- ROW_ITEM_LABEL_DESCRIPTION: t.s('DESCRIPTION'),
- ROW_ITEM_LABEL_EXPIRED: t.s('EXPIRATION'),
- ROW_ITEM_LABEL_USED: t.s('LAST USED'),
- ROW_ITEM_LABEL_SCOPE: t.s('SCOPE'),
- ROW_ITEM_LABEL_APPLICATION: t.s('APPLICATION'),
- PERSONAL_ACCESS_TOKEN: t.s('Personal Access Token'),
- HEADER: appName => t.s('{{ appName }} Token', { appName }),
- ADD: t.s('Add a new token')
- };
-}
-
-TokensStrings.$inject = ['BaseStringService'];
-
-export default TokensStrings;
diff --git a/awx/ui/client/features/users/tokens/users-tokens-add-application.route.js b/awx/ui/client/features/users/tokens/users-tokens-add-application.route.js
deleted file mode 100644
index 05e8a6dfec..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-add-application.route.js
+++ /dev/null
@@ -1,72 +0,0 @@
-export default {
- name: 'users.edit.tokens.add.application',
- url: '/application?selected',
- searchPrefix: 'application',
- params: {
- application_search: {
- value: {
- page_size: 5,
- order_by: 'name'
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'applications'
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'application@users.edit.tokens.add': {
- templateProvider: (ListDefinition, generateList) => {
- const html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
-
- return `${html} `;
- }
- }
- },
- resolve: {
- ListDefinition: [() => ({
- name: 'applications',
- iterator: 'application',
- hover: true,
- index: false,
- fields: {
- name: {
- key: true,
- label: 'Name',
- columnClass: 'col-sm-6',
- awToolTip: '{{application.description | sanitize}}',
- dataPlacement: 'top'
- },
- organization: {
- label: 'Organization',
- columnClass: 'col-sm-6',
- key: false,
- ngBind: 'application.summary_fields.organization.name',
- sourceModel: 'organization',
- includeModal: true
- }
- }
- })],
- Dataset: ['QuerySet', 'GetBasePath', '$stateParams', 'ListDefinition',
- (qs, GetBasePath, $stateParams, list) => qs.search(
- GetBasePath('applications'),
- $stateParams[`${list.iterator}_search`]
- )
- ]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
-};
diff --git a/awx/ui/client/features/users/tokens/users-tokens-add.controller.js b/awx/ui/client/features/users/tokens/users-tokens-add.controller.js
deleted file mode 100644
index dcd47d2e37..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-add.controller.js
+++ /dev/null
@@ -1,123 +0,0 @@
-function AddTokensController (
- models, $state, strings, Alert, Wait,
- $filter, ProcessErrors, $scope, i18n
-) {
- const vm = this || {};
- const { application, token, user } = models;
-
- vm.mode = 'add';
- vm.strings = strings;
- vm.panelTitle = strings.get('add.PANEL_TITLE');
-
- vm.form = {
- application: {
- type: 'field',
- label: i18n._('Application'),
- id: 'application',
- required: false,
- help_text: strings.get('add.APPLICATION_HELP_TEXT'),
- _resource: 'application',
- _route: 'users.edit.tokens.add.application',
- _model: application,
- _placeholder: strings.get('add.APP_PLACEHOLDER')
- },
- description: {
- type: 'String',
- label: i18n._('Description'),
- id: 'description',
- required: false
- },
- scope: {
- choices: [
- [null, ''],
- ['read', strings.get('add.SCOPE_READ_LABEL')],
- ['write', strings.get('add.SCOPE_WRITE_LABEL')]
- ],
- help_text: strings.get('add.SCOPE_HELP_TEXT'),
- id: 'scope',
- label: i18n._('Scope'),
- required: true,
- _component: 'at-input-select',
- _data: [
- [null, ''],
- ['read', strings.get('add.SCOPE_READ_LABEL')],
- ['write', strings.get('add.SCOPE_WRITE_LABEL')]
- ],
- _exp: 'choice[1] for (index, choice) in state._data',
- _format: 'selectFromOptions'
- }
- };
-
- vm.form.save = payload => {
- const postToken = _.has(payload, 'application') ?
- user.postAuthorizedTokens({
- id: $state.params.user_id,
- payload
- }) : token.request('post', { data: payload });
-
- return postToken
- .then(({ data }) => {
- const refreshHTML = data.refresh_token ?
- `` : '';
-
- Alert(strings.get('add.TOKEN_MODAL_HEADER'), `
-
- ${refreshHTML}
-
- `, null, null, null, null, null, true);
- Wait('stop');
- })
- .catch(({ data, status }) => {
- ProcessErrors(null, data, status, null, {
- hdr: strings.get('add.ERROR_HEADER'),
- msg: `${strings.get('add.ERROR_BODY_LABEL')} ${status}`
- });
- Wait('stop');
- });
- };
-
- vm.form.onSaveSuccess = () => {
- $state.go('^', { user_id: $state.params.user_id }, { reload: true });
- };
-
- $scope.$watch('application', () => {
- if ($scope.application) {
- vm.form.application._idFromModal = $scope.application;
- }
- });
-}
-
-AddTokensController.$inject = [
- 'resolvedModels',
- '$state',
- 'TokensStrings',
- 'Alert',
- 'Wait',
- '$filter',
- 'ProcessErrors',
- '$scope',
- 'i18n'
-];
-
-export default AddTokensController;
diff --git a/awx/ui/client/features/users/tokens/users-tokens-add.partial.html b/awx/ui/client/features/users/tokens/users-tokens-add.partial.html
deleted file mode 100644
index 25bd01a21a..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-add.partial.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/features/users/tokens/users-tokens-add.route.js b/awx/ui/client/features/users/tokens/users-tokens-add.route.js
deleted file mode 100644
index 43a663433f..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-add.route.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import { N_ } from '../../../src/i18n';
-import AddController from './users-tokens-add.controller';
-
-const addTemplate = require('~features/users/tokens/users-tokens-add.partial.html');
-
-function TokensDetailResolve ($q, Application, Token, User) {
- const promises = {};
-
- promises.application = new Application('options');
- promises.token = new Token('options');
- promises.user = new User('options');
-
- return $q.all(promises);
-}
-
-TokensDetailResolve.$inject = [
- '$q',
- 'ApplicationModel',
- 'TokenModel',
- 'UserModel'
-];
-
-function isMeResolve ($rootScope, $stateParams, $state) {
- // The user should not be able to add tokens for users other than
- // themselves. Adding this redirect so that a user is not able to
- // visit the add-token URL directly for a different user.
- if (_.has($stateParams, 'user_id') && Number($stateParams.user_id) !== $rootScope.current_user.id) {
- $state.go('users');
- }
-}
-
-isMeResolve.$inject = [
- '$rootScope',
- '$stateParams',
- '$state'
-];
-
-export default {
- url: '/add-token',
- name: 'users.edit.tokens.add',
- params: {
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'o_auth2_access_token',
- noActivityStreamID: true
- },
- ncyBreadcrumb: {
- label: N_('CREATE TOKEN')
- },
- views: {
- 'preFormView@users': {
- templateUrl: addTemplate,
- controller: AddController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: TokensDetailResolve,
- isMe: isMeResolve
- }
-};
diff --git a/awx/ui/client/features/users/tokens/users-tokens-list.controller.js b/awx/ui/client/features/users/tokens/users-tokens-list.controller.js
deleted file mode 100644
index 27ae0514c5..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-list.controller.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/** ***********************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- ************************************************ */
-function ListTokensController (
- $filter,
- $scope,
- $state,
- Dataset,
- strings,
- ProcessErrors,
- GetBasePath,
- Prompt,
- Wait,
- models
-) {
- const vm = this || {};
- const { token } = models;
-
- vm.strings = strings;
- vm.activeId = $state.params.token_id;
-
- $scope.canAdd = true;
-
- // smart-search
- const name = 'tokens';
- const iterator = 'token';
- let paginateQuerySet = {};
-
- vm.token_dataset = Dataset.data;
- vm.tokens = Dataset.data.results;
- vm.list = { iterator, name, basePath: 'tokens' };
- vm.basePath = `${GetBasePath('users')}${$state.params.user_id}/tokens`;
-
- $scope.$on('updateDataset', (e, dataset, queryset) => {
- vm.token_dataset = dataset;
- vm.tokens = dataset.results;
- paginateQuerySet = queryset;
- });
-
- $scope.$watchCollection('$state.params', () => {
- setToolbarSort();
- });
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'application__name'
- };
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-application__name' },
- { label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
- { label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
- { label: `${strings.get('sort.EXPIRES_ASCENDING')}`, value: 'expires' },
- { label: `${strings.get('sort.EXPIRES_DESCENDING')}`, value: '-expires' }
- ];
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'token_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
- const queryParams = Object.assign(
- {},
- $state.params.token_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update URL with params
- $state.go('.', {
- token_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- vm.getScopeString = str => {
- if (str === 'Read') {
- return vm.strings.get('add.SCOPE_READ_LABEL');
- } else if (str === 'Write') {
- return vm.strings.get('add.SCOPE_WRITE_LABEL');
- }
-
- return undefined;
- };
-
- vm.getLastUsed = tokenToCheck => {
- const lastUsed = _.get(tokenToCheck, 'last_used');
-
- if (!lastUsed) {
- return undefined;
- }
-
- let html = $filter('longDate')(lastUsed);
-
- const { username, id } = _.get(tokenToCheck, 'summary_fields.last_used', {});
-
- if (username && id) {
- html += ` ${strings.get('add.LAST_USED_LABEL')} ${$filter('sanitize')(username)} `;
- }
-
- return html;
- };
-
- vm.deleteToken = (tok) => {
- const action = () => {
- $('#prompt-modal').modal('hide');
- Wait('start');
- token.request('delete', tok.id)
- .then(() => {
- let reloadListStateParams = null;
-
- if ($scope.vm.tokens.length === 1 && $state.params.token_search &&
- !_.isEmpty($state.params.token_search.page) &&
- $state.params.token_search.page !== '1') {
- const page = `${(parseInt(reloadListStateParams
- .token_search.page, 10) - 1)}`;
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.token_search.page = page;
- }
-
- if (parseInt($state.params.token_id, 10) === tok.id) {
- $state.go('^', reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, { reload: true });
- }
- }).catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${GetBasePath('tokens')}${tok.id}`, status })
- });
- }).finally(() => {
- Wait('stop');
- });
- };
-
- const deleteModalBody = `${strings.get('deleteResource.CONFIRM', 'token')}
`;
-
- Prompt({
- hdr: strings.get('deleteResource.HEADER'),
- resourceName: _.has(tok, 'summary_fields.application.name') ?
- strings.get('list.HEADER', tok.summary_fields.application.name) :
- strings.get('list.PERSONAL_ACCESS_TOKEN'),
- body: deleteModalBody,
- action,
- actionText: strings.get('add.DELETE_ACTION_LABEL')
- });
- };
-}
-
-ListTokensController.$inject = [
- '$filter',
- '$scope',
- '$state',
- 'Dataset',
- 'TokensStrings',
- 'ProcessErrors',
- 'GetBasePath',
- 'Prompt',
- 'Wait',
- 'resolvedModels'
-];
-
-export default ListTokensController;
diff --git a/awx/ui/client/features/users/tokens/users-tokens-list.partial.html b/awx/ui/client/features/users/tokens/users-tokens-list.partial.html
deleted file mode 100644
index 5f0c0d2fa7..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-list.partial.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/awx/ui/client/features/users/tokens/users-tokens-list.route.js b/awx/ui/client/features/users/tokens/users-tokens-list.route.js
deleted file mode 100644
index e370f6fb24..0000000000
--- a/awx/ui/client/features/users/tokens/users-tokens-list.route.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { N_ } from '../../../src/i18n';
-
-import ListController from './users-tokens-list.controller';
-
-const listTemplate = require('~features/users/tokens/users-tokens-list.partial.html');
-
-function TokensListResolve ($q, Token) {
- const promises = {};
-
- promises.token = new Token('options');
-
- return $q.all(promises);
-}
-
-TokensListResolve.$inject = [
- '$q',
- 'TokenModel',
-];
-
-export default {
- url: '/tokens',
- name: 'users.edit.tokens',
- ncyBreadcrumb: {
- label: N_('TOKENS')
- },
- views: {
- related: {
- templateUrl: listTemplate,
- controller: ListController,
- controllerAs: 'vm'
- }
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'o_auth2_access_token',
- noActivityStreamID: true
- },
- searchPrefix: 'token',
- params: {
- token_search: {
- value: {
- page_size: 10,
- order_by: 'application__name'
- }
- }
- },
- resolve: {
- resolvedModels: TokensListResolve,
- Dataset: [
- '$stateParams',
- 'Wait',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, Wait, GetBasePath, qs) => {
- const searchParam = $stateParams.token_search;
- const searchPath = `${GetBasePath('users')}${$stateParams.user_id}/tokens`;
- Wait('start');
- return qs.search(searchPath, searchParam)
- .finally(() => {
- Wait('stop');
- });
- }
- ],
- }
-};
diff --git a/awx/ui/client/index.template.ejs b/awx/ui/client/index.template.ejs
deleted file mode 100644
index 2e9c343f60..0000000000
--- a/awx/ui/client/index.template.ejs
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
-
-
-
-
-
-
- <% htmlWebpackPlugin.files.css.forEach(file => {%>
-
- <% }) %>
- <% htmlWebpackPlugin.files.js.forEach(file => {%>
-
- <% }) %>
-
-
-
- {% verbatim %}
-
-
-
-
-
-
-
-
Your session will expire in 60 seconds, would you like to continue?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% endverbatim %}
-
-
-
diff --git a/awx/ui/client/installing.template.ejs b/awx/ui/client/installing.template.ejs
deleted file mode 100644
index 3c19d76e9d..0000000000
--- a/awx/ui/client/installing.template.ejs
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
- {% load staticfiles %}
-
-
-
-
-
-
- <% htmlWebpackPlugin.files.css.forEach(file => {%>
-
- <% }) %>
- <% htmlWebpackPlugin.files.js.forEach(file => {%>
-
- <% }) %>
-
-
-
-
-
-
-
-
- is currently upgrading.
- This page will refresh when complete.
-
-
-
-
\ No newline at end of file
diff --git a/awx/ui/client/legacy/styles/angular-scheduler.less b/awx/ui/client/legacy/styles/angular-scheduler.less
deleted file mode 100644
index 10216c2056..0000000000
--- a/awx/ui/client/legacy/styles/angular-scheduler.less
+++ /dev/null
@@ -1,220 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * Styling for angular-scheduler
- *
- */
-
- /*
- #schedules-form-container -inventory group add/edit dialog
- */
-
-#schedules-tab {
- position: relative;
- top: 0;
- left: 0;
-}
-
-#schedules-overlay {
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 100;
- background-color: @black;
- opacity: 0;
-}
-
-#schedules-list {
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-#schedules-form-container {
- position: absolute;
- top: 0;
- left: 0;
- display: none;
- border: 1px solid #e5e5e5;
- border-radius: 4px;
- box-shadow: 3px 3px 6px 0 #666;
- padding: 0 10px 15px 8px;
- background-color: @white;
- z-index: 200;
-}
-
-#schedules-title {
- border-bottom: 1px solid #e5e5e5;
- padding-bottom: 8px;
- margin-bottom: 10px;
- margin-top: 0;
- h4 {
- display: inline-block;
- margin: 0;
- }
- button {
- display: inline-block;
- }
-}
-
-#schedules-form-container-body {
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-#schedules-form .form-group {
- margin-bottom: 15px;
-}
-
-#schedules-buttons {
- height: 46px;
- padding-top: 10px;
- text-align: right;
- border-top: 1px solid #A6C9E2;
- margin-top: 5px;
- a {
- margin-right: 8px;
- font-size: 12px;
- }
-}
-
-#schedules-detail {
- display: none;
-}
-
-#scheduler-modal-dialog, #schedules-form-container {
- display: none;
- overflow-x: hidden;
- overflow-y: auto;
- padding-top: 25px;
-
- form {
- width: 100%;
- }
-
- .sublabel {
- font-weight: normal;
- }
-
- #occurrence-label {
- display: inline-block;
- }
-
- .occurrence-list {
- border: 1px solid @well-border;
- padding: 8px 10px;
- border-radius: 4px;
- background-color: @well;
- list-style: none;
- margin-bottom: 5px;
- }
-
- #date-choice {
- display: inline-block;
- margin-left: 15px;
- font-size: 12px;
-
- .label-inline {
- display: inline-block;
- vertical-align: middle;
- }
- input {
- margin-bottom: 2px;
- height: 11px;
- width: 10px;
- }
- .label-inline:first-child {
- padding-bottom: 2px;
- margin-right: 10px;
- }
- .label-inline:nth-child(3) {
- margin-right: 10px;
- }
- }
-
- .ui-widget input {
- font-size: 12px;
- font-weight: normal;
- text-align: center;
- }
- .scheduler-time-spinner {
- width: 40px;
- height: 24px;
- }
- .scheduler-spinner {
- width: 50px;
- height: 24px;
- }
- .fmt-help {
- font-size: 12px;
- font-weight: normal;
- color: #999;
- padding-left: 10px;
- }
- .error {
- color: #dd1b16;
- font-size: 12px;
- margin-bottom: 0;
- margin-top: 0;
- padding-top: 3px;
- }
- .error-pull-up {
- position: relative;
- top: -20px;
- }
- .red-text {
- color: #dd1b16;
- }
- .help-text {
- font-size: 12px;
- font-weight: normal;
- color: #999;
- margin-top: 5px;
- }
- .inline-label {
- margin-left: 10px;
- }
- #scheduler-buttons {
- margin-top: 20px;
- }
- .no-label {
- padding-top: 25px;
- }
- .padding-top-slim {
- padding-top: 5px;
- }
- .option-pad-left {
- padding-left: 15px;
- }
- .option-pad-top {
- padding-top: 15px;
- }
- .option-pad-bottom {
- padding-bottom: 15px;
- }
- #monthlyOccurrence, #monthlyWeekDay {
- margin-top: 5px;
- }
- select {
- width: 100%;
- }
- .occurrence-list {
- border: 1px solid @well-border;
- padding: 8px 10px;
- border-radius: 4px;
- background-color: @well;
- list-style: none;
- margin-bottom: 5px;
- }
-
- #weekdaySelect .btn-default:hover,
- #weekdaySelect .btn-default:focus {
- background-color: #fff;
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
- }
-
- #weekdaySelect .btn-default.active:hover {
- background-color: #e0e0e0;
- }
-}
diff --git a/awx/ui/client/legacy/styles/animations.less b/awx/ui/client/legacy/styles/animations.less
deleted file mode 100644
index 98a5a1f6f8..0000000000
--- a/awx/ui/client/legacy/styles/animations.less
+++ /dev/null
@@ -1,27 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * animations.css
- *
- * custom animation mixins for ansible-ui
- *
- */
-
-
-.pulsate(@duration: 1.5s) {
- -webkit-animation:pulsate @duration linear infinite alternate;
- -moz-animation:pulsate @duration linear infinite alternate;
- animation:pulsate @duration linear infinite alternate;
-}
-@-webkit-keyframes pulsate {
- 0% { -moz-transform: scale(.3); opacity: .2; }
- 100% { -moz-transform: scale(1.1); opacity: 1; }
-}
-@-webkit-keyframes pulsate {
- 0% { -webkit-transform: scale(.3); opacity: .2; }
- 100% { -webkit-transform: scale(1.1); opacity: 1; }
-}
-@keyframes pulsate {
- 0% { -webkit-transform: scale(.3); transform:scale(.3); opacity: .2;}
- 100% { -webkit-transform: scale(1.1); transform:scale(1.1); opacity: 1;}
-}
diff --git a/awx/ui/client/legacy/styles/ansible-ui.less b/awx/ui/client/legacy/styles/ansible-ui.less
deleted file mode 100644
index 6b8b788c4c..0000000000
--- a/awx/ui/client/legacy/styles/ansible-ui.less
+++ /dev/null
@@ -1,2268 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * ansible-ui.css
- *
- * custom styles for ansible-ui
- *
- */
-
-@font-face {
- font-family: 'Open Sans';
- font-style: normal;
- font-weight: 400;
- src: url(/static/assets/OpenSans-Regular.ttf);
-}
-
-@font-face {
- font-family: 'Open Sans';
- font-style: bold;
- font-weight: 600;
- src: url(/static/assets/OpenSans-Bold.ttf);
-}
-
-/* Helper Classes */
-.pad-right-sm { padding-right: 10px; }
-.pad-left-md { padding-left: 30px; }
-.pad-left-sm { padding-left: 10px; }
-.pad-left-lg { padding-left: 50px; }
-.normal-weight { font-weight: normal; }
-.small-text { font-size: 12px; font-weight: normal; }
-.no-bullets { list-style: none; }
-.nowrap { white-space: nowrap; }
-.capitalize { text-transform: capitalize; }
-.grey-txt { color: @grey; }
-.text-center { text-align: center !important; }
-.cursor-pointer { cursor: pointer }
-
-.red-txt,
-a.red-txt:visited,
-a.red-txt:hover,
-a.red-txt:active {
- color: @red;
-}
-
-/* Used on inventory groups/hosts lists for long names */
-.ellipsis {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-blockquote {
- font-size: 14px;
-}
-
-.group-name {
- display: inline-block;
- width: 85%;
-}
-
-a {
- color: @blue-link;
- text-decoration: none;
-}
-
-a:hover,
-a:focus {
- color: @blue-dark;
- text-decoration: none;
-}
-.btn{
- text-transform: uppercase;
-}
-/* Old style TB default button with grey background */
-.btn-grey {
- color: @default-data-txt;
- background-color: @d7grey;
- border-color: @d7grey;
-}
-
-.btn-grey:hover {
- background-color: @default-bg;
-}
-
-#cowsay {
- padding-left: 30px;
- max-width: 340px;
- background-color: white;
- border-style: none;
-}
-
-
-#about-modal-titlelogo{
- margin-bottom: 10px;
- width: 160px;
- height: 53px;
-}
-
-#copyright-text{
- margin-top: 10px;
- margin-bottom: 10px;
-}
-
-/* Make buttons appear to be disabled, but allow mouse events */
-.btn-disabled {
- opacity: 1;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-
-.btn-disabled {
- cursor: not-allowed;
-}
-
-/* Bring primary (blue) buttons in line with link colors */
-.btn-primary {
- background-color: @default-link;
-}
-
-.btn-primary:hover {
- background-color: @default-link-hov;
-}
-
-/* List Actions column */
-.actions {
- a {
- font-size: 18px;
- }
- a:last-child {
- margin-right: 0;
- }
- a:hover {
- cursor: pointer;
- }
- .dropdown .caret {
- border-top-color: @blue-link;
- }
-}
-
-// removing all the pesky outlines on buttons/links/etc.
-a:focus,
-a:active,
-button:focus,
-button:active,
-i:focus,
-i:active,
-.btn:focus,
-.btn:active:focus {
- outline: 0;
-}
-
-.jqstooltip{
- background-color: black !important;
- border-radius:4px;
- border: 1px solid black;
-}
-
-.smart-status-tooltip{
- font-size: 12px;
- font-family: 'Open Sans';
- background-color: black;
- border-radius:4px;
- span {
- padding: 3px;
- }
-}
-
-.IdleModal-remainingSeconds{
- color: @default-err;
-}
-
-#configure-schedules-tab {
- position: relative;
- top: 0;
- left: 0;
-}
-
-#configure-schedules-overlay {
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 100;
- background-color: @black;
- opacity: 0;
- }
-
-#configure-schedules-buttons{
- height: 46px;
- padding-top: 10px;
- text-align: right;
- border-top: 1px solid @default-border;
- margin-top: 5px;
- a {
- margin-right: 8px;
- font-size: 12px;
- }
-}
-
-#configure-schedules-form-container {
- position: absolute;
- top: 0;
- left: 0;
- display: none;
- border: 1px solid @default-border;
- border-radius: 4px;
- box-shadow: 3px 3px 6px 0 @default-dark;
- padding: 0 10px 15px 8px;
- background-color: @white;
- z-index: 200;
-}
-
-#configure-schedules-title {
- border-bottom: 1px solid @default-border;
- padding-bottom: 8px;
- margin-bottom: 10px;
- margin-top: 0;
- h4 {
- display: inline-block;
- margin: 0;
- }
- button {
- display: inline-block;
- }
-}
-
-#configure-schedules-list {
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-#configure-schedules-overlay {
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 100;
- background-color: @black;
- opacity: 0;
-}
-
-#configure-dialog, #configure-schedules-form-container {
- display: none;
- overflow-x: hidden;
- overflow-y: auto;
- padding-top: 25px;
-
- form {
- width: 100%;
- }
-
- .sublabel {
- font-weight: normal;
- }
-
- #occurrence-label {
- display: inline-block;
- }
-
- .occurrence-list {
- border: 1px solid @well-border;
- padding: 8px 10px;
- border-radius: 4px;
- background-color: @well;
- list-style: none;
- margin-bottom: 5px;
- }
-
- #date-choice {
- display: inline-block;
- margin-left: 15px;
- font-size: 12px;
-
- .label-inline {
- display: inline-block;
- vertical-align: middle;
- }
- input {
- margin-bottom: 2px;
- height: 11px;
- width: 10px;
- }
- .label-inline:first-child {
- padding-bottom: 2px;
- margin-right: 10px;
- }
- .label-inline:nth-child(3) {
- margin-right: 10px;
- }
- }
-}
-#home_groups_table .actions .cancel { padding-right: 3px; }
-
-.success-badge {
- color: @default-bg;
- background-color: @default-succ;
-}
-
-/* Disable textarea re-sizing as a general rule */
-textarea {
- resize: none;
-}
-
-textarea.allowresize {
- resize: both;
-}
-
-/* Working... spinner */
-.spinny {
- display: none;
- position: fixed;
- z-index: 2000;
- width: 138px;
- height: 50px;
- text-align:center;
- color: @d7grey;
- background-color: @black;
- border: 1px solid @grey;
- border-radius: 6px;
- padding-top: 10px;
-
- p {
- padding-top: 0px;
- font-size: 18px;
- text-align: right;
- margin-right: 10px;
- }
-
- i {
- float: left;
- margin-left: 10px;
- }
-}
-
-.subtitle {
- font-size: 16px;
-}
-
-.license-version {
- font-size: 18px;
- color: @grey-txt;
-}
-
-// #license_eula{
-// white-space: nowrap;
-// }
-
-.modal-dialog .ui-accordion .ui-accordion-content {
- overflow: hidden;
-}
-
-.overlay {
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1080;
- background-color: @black;
- opacity: 0;
-}
-
-/* TB tooltip overrides */
- .popover-body {
- width: 100%;
- padding: 0;
- color: @default-bg;
-
- .table>tbody>tr>td {
- padding-left: 0;
- border-top: 1px solid @b7grey;
- }
- .popover-body_code-snippet{
- padding: 0 3px;
- }
- }
- h3.popover-header, .popover-body, .popover-body blockquote, .popover-body a {
- font-family: 'Open Sans', sans-serif;
- font-size: 12px;
- }
- .flyout {
- margin-bottom: 0;
- }
- .flyout thead> tr> th, .flyout tbody> tr> td, .flyout tbody> tr> td> a {
- font-size: 12px;
- }
- .flyout tbody > tr:last-child > td {
- padding-bottom: 0;
- }
- .popover-header {
- padding: 0 0 5px 0;
- background-color: @default-interface-txt;
- color: @default-bg;
- font-weight: 600;
- border-bottom: none;
- text-transform: uppercase;
- }
- .popover {
- z-index: 2000;
- min-width: 200px;
- max-width: 325px;
- background-color: @default-interface-txt;
- color: @default-bg; //white
- text-align: left;
- padding: 10px;
- font-weight: 400;
-
- code {
- color: @default-data-txt;
- background-color: @default-white-button-bord;
- line-height: 18px;
- }
-
- a {
- color: @default-warning;
- &:hover {
- color: @default-warning-hov;
- }
- }
-
- p {
- font-weight: 400;
- }
-
- p:last-child {
- margin-bottom: 0;
- }
-
- table {
- color: @default-bg; //white
- }
- }
- .popover.right>.arrow:after {
- border-right-color: @default-interface-txt;
- }
- .popover.left>.arrow:after {
- border-left-color: @default-interface-txt;
- }
- .popover.bottom>.arrow:after {
- border-bottom-color: @default-interface-txt;
- }
- .popover.top>.arrow:after {
- border-top-color: @default-interface-txt;
- }
- .popover pre {
- white-space: pre-wrap;
- }
- .popover-footer {
- font-size: 12px;
- margin-top: 10px;
- text-align: right;
- color: @grey;
- .key {
- color: @white;
- background-color: @grey;
- padding: 0 1px 1px 1px;
- border-radius: 3px;
- }
- }
-
-.alert {
- margin-top: 15px;
- margin-bottom: 15px;
-}
-
-hr {
- border-color: @default-border;
-}
-
-.help {
- display: inline-block;
-}
-
-.help-auto-off {
- margin-top: 15px;
- margin-bottom: 15px;
- margin-left: 10px;
- label {
- font-weight: normal;
- }
-}
-
-.tab-content {
- padding-top: 15px;
-}
-
-.btn .caret {
- border-top-color: @default-icon;
-}
-
-.btn-light {
- color: @default-data-txt;
- background-color: @d7grey;
- border-color: @d7grey;
-}
-
-.refresh-grp {
- display: inline-block;
- text-align: right;
- margin-left: 0;
- margin-top: 0;
- padding: 0;
- line-height: normal;
-
- .refresh-msg {
- font-size: 10px;
- }
-}
-
-.btn-light:hover {
- color: @d7grey;
- background-color: @default-icon;
- border-color: @default-icon;
-}
-
-/* Make a div or any element behave like pre. Use in conjunction with .mono-space */
-.pre {
- white-space: pre;
-}
-
-
-dd {
- margin-left: 15px;
-}
-
-/* Use code-breakable in pop-over text to indent and wrap code segments */
-
-.code-breakable {
- padding-left: 10px;
- word-wrap: break-word;
-}
-
-.break {
- word-break: break-all;
-}
-
-.controls {
- min-height: 15px;
-}
-
-#navbar-container, .main-menu {
- width: 100%;
- background-color: @default-dark;
-}
-
-.text-justify {
- text-align: justify;
-}
-
-.help-link,
-.help-link:active,
-.help-link:visited,
-.ui-widget-content a.help-link,
-.ui-widget-content a.help-link:active,
-.ui-widget-content a.help-link:visited {
- color: @default-icon;
- text-decoration: none;
- padding-left: 5px;
-}
-
-.help-link:hover,
-.ui-widget-content a.help-link:hover {
- color: @default-interface-txt;
- text-decoration: none;
-}
-
-.login-header img {
- width: 60%;
-}
-
-.form-title {
- display: inline-block;
- width: 100%;
- vertical-align: middle;
- font-weight: bold;
- padding-left: 15px;
- margin-bottom: 10px;
-}
-
-.form-cancel {
- float: right;
- margin-right: 10px;
-}
-
-.form-title-hr {
- margin-bottom: 20px;
-}
-
-.form-horizontal .buttons {
- margin-top: 25px;
-}
-
-.label-text {
- padding-right: 10px;
-}
-
-.label-hint-text {
- font-weight: normal;
- color: @grey;
-}
-.label-hint-text:before {
- /* for a line break before hintText */
- content: '\A';
- white-space: pre;
-}
-
-#group_form #group_tabs {
- margin-top: 25px;
-}
-
-/* Outline required fields in Red when there is an error */
- .form-control.ng-dirty.ng-invalid, .form-control.ng-dirty.ng-invalid:focus {
- border-color: @default-err;
- outline: 0;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px rgba(255, 88, 80, 0.6);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px rgba(255, 88, 80, 0.6);
- }
-
- .form-control.ng-dirty.ng-invalid + .select2 .select2-selection,
- .form-control.ng-dirty.ng-invalid + .select2 .select2-selection:focus {
- border-color: @default-err !important;
- outline: 0 !important;
- box-shadow: none !important;
- }
-
- .form-control.ng-dirty.ng-pristine {
- border-color: @b7grey;
- box-shadow: none;
- }
-
- .form-control.ng-dirty.ng-pristine:focus {
- border-color: @default-link;
- }
-/* For some reason TB 3 RC1 does not provide an input-mini */
-
-.input-mini {
- height: 26px;
- padding: 3px 8px;
- font-size: 12px;
- border-radius: 3px;
-}
-
-.error {
- font-size: 12px;
- line-height: normal;
- color: @red;
-}
-
-.xsmall {
- font-size: 12px;
-}
-
-.note {
- padding-top: 15px;
- font-size: 12px;
-}
-
-legend {
- font-size: medium;
- font-weight: bold;
-}
-
-.navigation {
- margin: 15px 0 15px 0;
-}
-
-.footer-navigation {
- margin: 10px 0 10px 0;
-}
-
-.lookup-navigation {
- margin: 15px 0 0 0;
- /*padding-top: 20px;*/
-
-}
-
-#lookup-modal-dialog {
- overflow-x: hidden;
- .instructions {
- margin-top: 0;
- margin-bottom: 20px;
- }
-}
-
-.related-footer {
- margin: 10px 0 0 0;
-}
-
-select.page-size {
- width: 65px;
- height: 24px;
- font-size: 10px;
-}
-
-.page-size-label {
- margin-left: 15px;
- font-size: 10.5px;
- font-weight: normal;
-}
-
-.accordion-heading {
- font-weight: bold;
- color: @blue-link;
-}
-
-.accordion-heading i {
- margin-right: 5px;
-}
-
-.status-actions {
- display: inline-block;
- height: 25px;
-}
-
-.status-spin {
- display: inline-block;
- margin-left: 15px;
- font-size: 22px;
- vertical-align: middle;
-}
-
-/* Search Widget */
-
- .search-widget label {
- display: inline-block;
- padding-right: 15px;
- vertical-align: middle;
- }
-
- #search-widget-spacer {
- height: 20px;
- }
-
-/* breadcrumbs */
-.nav-path {
- padding: 5px 0 10px 0;
- margin-right: 2px;
- margin-bottom: 15px;
- font-size: 14px;
- font-weight: bold;
- background-color: @default-no-items-bord;
- border: 1px solid @d7grey;
- border-radius: 6px;
- box-shadow: 3px 3px 4px 0 @default-icon;
-
- .breadcrumb {
- display: inline-block;
- padding-bottom: 0;
- padding-left: 0;
- padding-right: 0;
- margin-bottom: 0;
- margin-left: 10px;
- }
-
- .dropdown {
- display: inline-block;
- margin-right: 0;
- paddding-right: 0;
-
- .toggle, .toggle:visited, .toggle:hover, .toggle:active {
- color: @black;
- }
-
- li a.active {
- color: @grey;
- }
-
- .crumb-icon {
- font-size: 12px;
- }
- }
-}
-
-.actions .dropdown {
- display: inline-block;
-}
-
-.greeting {
- padding-right: 22px;
-}
-
-.breadcrumb .active {
- color: @black;
-}
-
-.nav-tabs > li > a {
- font-weight: bold;
-}
-
-input[type="text"].field-mini-height {
- height: 12px;
- font-size: 10.5px;
-}
-
-select.field-mini-height {
- height: 22px;
- font-size: 10.5px;
-}
-
-.no-padding {
- padding: 0;
- margin: 0;
-}
-
-input[type="checkbox"].checkbox-no-label {
- margin-top: 10px;
-}
-
-.checkbox-options {
- font-weight: normal;
-}
-
-/* Display list actions next to search widget */
-.list-actions {
- display: flex;
- height: 34px;
- justify-content: flex-end;
- margin-bottom: -34px;
- text-align: right;
-
- .fa-lg {
- vertical-align: -8%;
- }
-}
-
-.jqui-accordion {
- .list-actions {
- margin: 0;
- }
- /*.list-wrapper {
- background-color: @well;
- padding: 10px;
- border-radius: 4px;
- border: 1px solid @well-border;
- }*/
- .ui-accordion-content {
- padding-left: 15px;
- padding-right: 15px;
- }
- .page-label {
- margin-top: 5px;
- }
-}
-
-#home-list-actions {
- margin-bottom: 15px;
-}
-
-/* End Display list actions */
-
-
-/* Enable table-hover to work when table is in a well */
-
-.table-hover tbody tr:hover > td,
-.table-hover tbody tr:hover > th {
- background-color: @default-bg;
-}
-
-.table-hover-inverse tbody tr:hover > td,
-.table-hover-inverse tbody tr:hover > th {
- background-color: @active-color;
-}
-
-.table > thead > tr > td.success,
-.table > tbody > tr > td.success,
-.table > tfoot > tr > td.success,
-.table > thead > tr > th.success,
-.table > tbody > tr > th.success,
-.table > tfoot > tr > th.success,
-.table > thead > tr.success > td,
-.table > tbody > tr.success > td,
-.table > tfoot > tr.success > td,
-.table > thead > tr.success > th,
-.table > tbody > tr.success > th,
-.table > tfoot > tr.success > th {
- background-color: @active-color;
-}
-.table-hover > tbody > tr > td.success:hover,
-.table-hover > tbody > tr > th.success:hover,
-.table-hover > tbody > tr.success:hover > td,
-.table-hover > tbody > tr.success:hover > th {
- background-color: @active-color;
-}
-
-.table-summary thead > tr > th,
-.table-summary tbody > tr > th,
-.table-summary tfoot > tr > th,
-.table-summary thead > tr > td,
-.table-summary tbody > tr > td,
-.table-summary tfoot > tr > td {
- border-top: 1px solid @d7grey;
-}
-
-.table-summary thead > tr > th {
- border-bottom: 1px solid @d7grey;
-}
-
-/* Table without row borders */
-
-.table-no-border thead > tr > th,
-.table-no-border tbody > tr > th,
-.table-no-border tfoot > tr > th,
-.table-no-border thead > tr > td,
-.table-no-border tbody > tr > td,
-.table-no-border tfoot > tr > td {
- border-top: none;
-}
-
-.table > tbody > tr > td{
- padding: 0.5em 0.6em;
- &.actions{
- padding: 0px;
- > a {
- padding: 0.5em 0.6em;
- display: inline-block;
- }
- }
-}
-
-/* Less padding on .table-condensed */
-.table-condensed>tbody>tr>td:not(:last-child),
-.table-condensed>thead>tr>th:not(:last-child) {
- padding: 0.5em 20px 0.5em 0px;
-}
-
-.table-condensed>tbody>tr>td:last-child,
-.table-condensed>thead>tr>th:last-child {
- padding: 0.5em 0px;
-}
-
-.table.table-condensed.flyout {
- thead>tr>th {
- padding-left: 0;
- border: none;
- }
-}
-
-/* Table info rows */
-
-.loading-info {
- color: @grey-txt;
- font-weight: normal;
- padding: 15px 0;
-}
-
-/* Status Icons */
-
- .license-expired,
- .license-invalid,
- .icon-failures-true,
- .active-failures-true a,
- .active-failures-true a:active,
- .job-failed,
- .job-error {
- color: @default-err;
- }
-
- .icon-failures-true a:hover {
- color: @red;
- }
-
- .job-failures-true {
- padding-top: 5px;
- color: @default-err;
- }
-
- .job-event-status,
- .license-status {
- padding-top: 5px;
- }
-
-
- .job-new,
- .license-valid,
- .job-success,
- .job-successful {
- color: @green;
- }
-
- .icon-host-all:before,
- .icon-host-failed:before,
- .icon-job-active:before,
- .icon-job-running:before,
- .icon-job-success:before,
- .icon-job-successful:before,
- .icon-job-changed:before,
- .icon-job-ok:before,
- .icon-job-OK:before,
- .icon-job-failed:before,
- .icon-job-skipped:before {
- content: "\f111";
- }
-
- .icon-job-stopped:before,
- .icon-job-error:before,
- .icon-job-canceled:before,
- .icon-job-stdout-download-tooltip:before,
- .icon-job-unreachable:before,
- .icon-job-failed:before {
- content: "\f06a";
- }
-
- .icon-job-pending:before,
- .icon-job-waiting:before,
- .icon-job-new:before,
- .icon-job-none:before,
- .icon-job-no-matching-hosts:before {
- content: "\f10c";
- }
-
- .icon-job-active,
- .icon-job-running,
- .icon-job-success,
- .icon-job-successful,
- .icon-job-ok,
- .icon-job-OK {
- color: @green;
- }
-
- .icon-job-skipped {
- color: @skipped;
- }
-
- .icon-job-running {
- .pulsate();
- }
-
- .icon-job-changed,
- .job-changed {
- color: @changed;
- }
-
- .icon-host-failed,
- .icon-job-stopped,
- .icon-job-error,
- .icon-job-failed,
- .icon-job-stdout-download-tooltip,
- .icon-job-canceled {
- color: @red;
- }
-
- .icon-host-all {
- color: @at-blue;
- }
-
- .icon-job-unreachable {
- color: @unreachable;
- }
-
- .icon-job-none,
- .icon-job-pending,
- .icon-job-waiting,
- .icon-job-new,
- .icon-job-no-matching-hosts {
- color: @grey;
- opacity: 0.45;
- }
-
- .icon-schedule-enabled-true:before {
- content: "\f04d";
- }
-
- .icon-schedule-enabled-false:before {
- content: "\f04b";
- }
-
- .icon-socket-ok:before {
- content: "\f111";
- color: @green;
- }
- .icon-socket-error:before {
- content: "\f111";
- color: @red;
- }
- .icon-socket-connecting:before {
- content: "\f042";
- color: @warning;
- }
-
-/* job_events page */
-
- #jobevents_table {
- div.return-code {
- display: inline-block;
- margin-left: 10px;
- }
- textarea {
- white-space: pre-wrap;
- resize: vertical;
- }
- }
-
- #password-modal .alert-info {
- margin-top: 0;
- margin-bottom: 25px;
- }
-
-/* Inventory job status badge */
- .failures-true {
- background-color: @red;
- color: @default-bg;
- }
-
- .failures-false {
- background-color: @green;
- color: @default-bg;
- }
-
-/* Cloud inventory status. i.e. inventory_source.status values */
-
- .icon-cloud-na:before,
- .icon-cloud-never:before,
- .icon-cloud-updating:before,
- .icon-cloud-running:before,
- .icon-cloud-successful:before,
- .icon-cloud-pending:before,
- .icon-cloud-failed:before,
- .icon-cloud-canceled:before,
- .icon-cloud-error:before {
- content: "\f0c2";
- }
-
- /*.icon-cloud-failed:before,
- .icon-cloud-error:before {
- content: "\f06a";
- }*/
-
- .icon-cloud-na,
- .icon-cloud-never,
- a.icon-cloud-na:hover,
- a.icon-cloud-never:hover {
- color: @grey;
- }
-
- .icon-cloud-updating,
- .icon-cloud-running,
- .icon-cloud-successful,
- .icon-cloud-pending,
- a.icon-cloud-updating:hover,
- a.icon-cloud-successful:hover {
- color: @green;
- }
-
- .icon-cloud-failed,
- .icon-cloud-error,
- .icon-cloud-canceled,
- a.icon-cloud-failed:hover {
- color: @red;
- }
-
- .icon-cloud-updating,
- .icon-cloud-running,
- .icon-cloud-pending {
- .pulsate();
- }
-
- .icon-enabled-true:before {
- content: "\f046";
- }
-
- .icon-enabled-true {
- color: @green;
- width: 14px;
-
- }
- .icon-enabled-false:before {
- content: "\f096";
- }
-
- .icon-enabled-false{
- color: @red;
- width: 14px;
- }
-
-/* Inventory cloud sourced? indicator */
- .icon-cloud-true:before {
- content: "\f111";
- }
-
- .icon-cloud-false:before {
- content: "\f111";
- }
-
- .error-color {
- color:@red;
- }
-
- .error-border {
- border-color:@red;
- }
-
- .connecting-color {
- color: @warning;
- }
-
- .ok-color,
- .icon-cloud-true {
- color: @green;
- }
-
- .icon-cloud-false {
- color: @grey;
- }
-/* end */
-
- .field-success {
- color: @default-succ;
- }
-
- .field-success input {
- border-color: @default-succ;
- }
-
- .field-failure {
- color: @red;
- }
-
- .field-failure input {
- border-color: @red;
- }
-
- .field-badge {
- font-size: 12px;
- margin-right: 3px;
- }
-
- .license-warning,
- .license-demo {
- color: @warning;
- }
-
- .job-detail-status {
- display: inline-block;
- margin-top: 5px;
- font-size: 15px;
- }
-
- /*.form-items .search-widget {
- margin-top: 15px;
- }*/
-
- .form-items .item-count {
- display: inline-block;
- margin-top: 25px;
- font-size: small;
- }
-
- .child-event a {
- color: @black;
- cursor: default;
- }
- /* Padding levels used on job events and inventory groups */
- .level { display: inline-block; }
- .level-1 { padding-left: 15px; }
- .level-2 { padding-left: 30px; }
- .level-3 { padding-left: 45px; }
- .level-4 { padding-left: 60px; }
- .level-5 { padding-left: 75px; }
- .level-6 { padding-left: 90px; }
- .level-7 { padding-left: 105px; }
- .level-8 { padding-left: 120px; }
- .level-9 { padding-left: 135px; }
- .level-10 { padding-left: 150px; }
-
- .level-3-detail {
- padding-left: 80px;
- }
-
- #job_events .control-group {
- margin-top: 0;
- margin-bottom: 10px;
- }
-
-/* End Jobs Page */
-
-
-/* license modal */
- #license-modal-dialog {
- overflow-x: hidden;
-
- input[readonly],
- textarea[readonly] {
- background-color: @default-border;
- border: 1px solid @default-icon;
- }
-
- .fa-external-link {
- color: @grey;
- font-size: 10px;
- }
-
- .free-button {
- background-color: @default-err;
- border: 1px solid @default-err;
- color: @white;
- }
- .free-button:hover {
- background-color: @default-err-hov;
- border: 1px solid @default-err-hov;
- color: @white;
- }
- }
-
-/* Inventory nav links */
- .navigation-links {
-
- padding: 0;
- margin-top: -10px;
-
- a {
- margin-right: 15px;
- }
-
- a:last-child {
- margin-right: 20px;
- }
- }
-
-/* Dashboard */
- #home #container1.col-lg-6,
- #home #container3.col-lg-6 {
- padding-right: 7px;
- }
-
- #home #container2.col-lg-6,
- #home #container4.col-lg-6 {
- padding-left: 7px;
- }
-
-
-/* Inventory Edit */
-
- #hosts-container.col-lg-6 {
- padding-left: 7px;
- padding-right: 17px;
- }
-
- #groups-container .well,
- #hosts-container .well {
- padding: 8px;
- margin-bottom: 0;
- }
-
- #home_groups_table i[class*="icon-job-"] {
- margin-left: 5px;
- }
-
- .selected {
- font-weight: bold;
- color: @blue-dark;
- }
-
- .inventory-title {
- font-size: 16px;
- font-weight: bold;
- }
-
- .active-row {
- background-color: @white;
- border-bottom: 1px solid @default-tertiary-bg;
- border-right: 1px solid @default-tertiary-bg;
- }
-
- .node-toggle, .node-no-toggle {
- /* also used on job evetns */
- float: none;
- padding-top: 3px;
- padding-left: 0;
- margin-right: 5px;
- margin-left: 0;
- }
-
- .node-no-toggle {
- opacity: .30;
- }
-
- .draggable-clone {
- opacity: .60;
- font-weight: bold;
- /*z-index: 2000;
- overflow: visible;
- whitespace: wrap;
- text-overflow: clip;*/
- }
-
- .droppable-hover {
- background-color: @info;
- color: @info-color;
- padding: 6px;
- border: 1px solid @info-border;
- border-radius: 4px;
- /*overflow: visible;
- whitespace: wrap;
- text-overflow: clip;*/
- }
-
- #group-delete-dialog .help-container,
- #password-modal .help-container {
- .help-link,
- .help-link:active,
- .help-link:visited {
- color: @blue-link;
- }
-
- .help-link:hover {
- color: @blue-dark;
- }
- }
-
-
- .btn-danger {
- background-color: @red;
- border-color: @red-focus;
- }
-
- .btn-danger:hover,
- .btn-danger:focus,
- .btn-danger:active {
- border-color: @red-focus;
- background-color: @red-focus;
- }
-
-// ad hoc permission checkbox
-.squeeze.form-group {
- margin-bottom: 10px;
-}
-
-.disabled {
- color: @grey;
-}
-
-a.disabled:hover {
- color: @grey;
- cursor: not-allowed;
-}
-a.btn-disabled:hover {
- cursor: not-allowed;
-}
-
-/* Variable Editing */
- .parse-selection {
- display: inline-block;
- margin: 5px 0 8px 0;
- font-size: 12px;
- line-height: normal;
- }
-
- .parse-selection input {
- margin-left: 5px;
- }
-
- .parse-select .parse-label {
- margin-left: 3px;
- color: @field-input-text;
- }
-
- .parse-label {
- color: @field-input-text;
- font-weight: normal;
- }
-
- .external-editor-link {
- display: inline-block;
- margin-left: 20px;
- }
-
-.slider {
- display: inline-block;
- width: 100px;
- margin: 0 10px;
- vertical-align: middle;
-}
-
-/* Sort link styles */
-
-.list-header-noSort:hover.list-header:hover{
- cursor: default;
-}
-
-.list-header:hover {
- cursor: pointer;
-}
-
-.list-header i {
- margin-left: 10px;
-}
-
-.list-header .icon-sort {
- color: @default-icon;
-}
-
-.list-header .icon-sort-down,
-.list-header .icon-sort-up {
- color: @black;
-}
-
-/* job_events syles */
-
-#jobevents_table .actions i {
- padding-top: 0;
- margin-right: 0;
-}
-
-tr td button i {
- padding-top: 0;
- margin-right: 0;
-}
-
-.event-form {
- margin-top: 10px;
- margin-bottom: 5px;
-
- label {
- font-weight: normal;
- }
-}
-
-.event-detail-host {
- padding-top: 10px;
- padding-bottom: 5px;
-}
-
-.form-section-title {
- width: 100%;
- margin-top: 0;
- margin-bottom: 10px;
- font-weight: bold;
- border-bottom: 1px solid @default-border;
-}
-
-.modal-backdrop,
-.modal-backdrop.fade.in {
- opacity: 0.6;
- filter: alpha(opacity=60);
-}
-
-.modal-body .ui-accordion .ui-accordion-content {
- padding: 10px;
-}
-
-/* overrides to TB modal */
-.modal-content {
- padding: 20px;
- box-shadow: 0 5px 15px rgba(0,0,0,.5);
-}
-
-.modal-header {
- color: @default-interface-txt;
- white-space: nowrap;
- width: 90%;
- overflow: hidden;
- text-overflow: ellipsis;
- width: 100%;
- border: none;
- padding: 0;
-}
-
-.modal {
- border: 1px solid @black;
- overflow-y: auto;
-}
-
-.modal .SmartSearch-bar {
- width: 100%;
-}
-
-#alert-modal, #alert-modal2 {
- z-index: 2100;
-}
-
-.close {
- color: @grey;
- opacity: .7;
- filter: alpha(opacity=70);
-}
-
-.modal-header h3 {
- margin: 0;
- text-rendering: optimizeLegibility;
- font-size: 15px;
- color: @default-interface-txt;
- font-weight: bold;
- line-height: normal;
- font-family: 'Open Sans', helvetica;
- text-transform: uppercase;
-}
-
-.modal-body {
- min-height: 120px;
- padding: 20px 0;
-
- .alert {
- padding: 0px;
- margin: 0;
- word-wrap: break-word;
- }
- .alert-danger {
- background-color: @default-bg;
- border: none;
- color: @default-interface-txt;
- }
-}
-
-#prompt-modal .modal-body {
- padding-bottom: 30px;
-}
-
-.skinny-modal .modal-body {
- padding: 5px 10px 0 10px;
-}
-
-.modal-footer {
- padding: 0;
- border: none;
- margin-top: 0;
- display: flex;
- justify-content: flex-end;
-
- .btn.btn-primary {
- text-transform: uppercase;
- background-color: @default-succ;
- border-color: @default-succ;
- padding: 5px 15px;
- cursor: pointer;
-
- &:hover {
- background-color: @default-succ-hov;
- border-color: @default-succ-hov;
- }
-
- &:disabled {
- background-color: @default-succ-disabled;
- border-color: @default-succ-disabled;
- }
- }
-
- .btn + .btn {
- margin: 0;
- }
-}
-
-/* form navigation */
-.navigation-buttons {
- height: 40px;
-}
-
-
-/* PW progress bar */
-.pw-progress { margin-top: 10px;
-
- li {
- line-height: normal;
- margin-bottom: 10px;
- }
- ul:last-child {
- margin-top: 10px;
- }
-
-}
-
-/* Home page */
-
-.failed-column {
- a:link, a:visited {
- color: @red;
- }
- a:hover {
- color: @red-hover;
- }
-}
-
-/* Help modal dialog */
-
-#help-modal-dialog {
- overflow: hidden;
- padding: 10px;
-
- img {
- margin-top: 15px;
- margin-bottom: 15px;
- border: 1px solid @grey;
- box-shadow: 3px 3px 5px 0 @grey;
- }
-
- .img-container,
- .icon-container {
- width: 100%;
- text-align: center;
- }
-
- .icon-container {
- margin-top: 15px;
- margin-bottom: 15px;
- }
-
- .help-box {
- width: 100%;
- margin-top: 15px;
- border-radius: 6px;
- color: @grey-txt;
- font-size: 14px;
- }
-
- .fa-rss {
- transform:rotate(-45deg);
- }
-}
-
-/* job stdout */
-
- #pre-container {
- overflow: auto;
- width: 100%;
- border-radius: 4px;
- margin: 0;
- }
-
-
-/* ng-cloak directive */
-
-[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- display: none !important;
-}
-
-
-/* Socket testing page */
-#sockets {
- .section-title {
- font-weight: bold;
- color: @blue-link;
- margin-top: 30px;
- }
- #test-container .section-title {
- margin-top: 20px;
- }
- .well {
- padding: 9px;
- }
- .message-section {
- height: 150px;
- overflow: auto;
- }
- .events-section {
- margin-top: 40px;
- .section-title {
- margin-top: 0;
- }
- }
- #event-message-container {
- height: 200px;
- }
-}
-
-/* Large desktop */
-
-@media (min-width: 1200px) {
-
- .delete-btn {
- /* Used on job and project page to make cancel and delete buttons have an equal width */
- width: 60px;
- }
-
- .label-text {
- text-align: right;
- }
-
-}
-
-@media (min-width: 768px) and (max-width: 1199px) {
-
- .level-1,
- .level-2,
- .level-3,
- .level-4,
- .level-5,
- .level-6,
- .level-7,
- .level-8,
- .level-9,
- .level-10,
- .level-3-detail {
- padding-left: 0;
- }
-
- .label-text {
- text-align: left;
- }
-
- .group-name {
- width: 80%;
- }
-
- #groups-container.col-lg-6 {
- padding-right: 15px;
- }
-
- #hosts-container.col-lg-6 {
- margin-top: 15px;
- padding-left: 15px;
- padding-right: 15px;
- .well {
- margin-bottom: 0;
- }
- }
-
-}
-
-/* Landscape phone to portrait tablet */
-
-@media (max-width: 767px) {
-
- /* Job events */
-
- .level-1,
- .level-2,
- .level-3,
- .level-4,
- .level-5,
- .level-6,
- .level-7,
- .level-8,
- .level-9,
- .level-10,
- .level-3-detail {
- padding-left: 0;
- }
-
- table {
- word-wrap: break-word;
- table-layout: fixed;
- }
-
- th.actions-column,
- td.actions {
- white-space: normal;
- }
-
- td.actions .btn {
- width: 75px;
- margin-bottom: 5px;
- }
-
- .group-name {
- width: 80%;
- }
-
- .label-text {
- text-align: left;
- }
-
- .list-action-label {
- display: none;
- }
-
- #groups-container.col-lg-6 {
- padding-right: 15px;
- }
-
- #hosts-container.col-lg-6 {
- margin-top: 15px;
- padding-left: 15px;
- padding-right: 15px;
- }
-}
-
-// lists.less uses 600px as the breakpoint, doing same for consistency
-@media (max-width: 600px) {
- .list-actions {
- text-align: left;
- margin-bottom: 20px;
- }
-}
-
-.nvtooltip {
- border-radius: 4px;
-
- td.value {
- padding-right: 0px;
- }
-
- p {
- padding: 3px 0px;
- }
-
- & > table > thead > tr > td {
- font-weight: 700;
-
- &:first-child {
- padding-top: 0;
- }
- }
-
- & > table > tbody > tr:last-child > td {
- padding-bottom: 0;
- }
-}
-
-.nvd3 g.nv-groups path.nv-line {
- stroke-width: 3px;
-}
-
-.stdout-panel-body {
- background-color: @default-list-header-bg;
-}
-
-.job-stdout-panel {
- margin: 0 15px;
-}
-
-.show_input_button {
- width: 73px;
-}
-
-.red-text {
- color: @red;
-}
-
-.factDetailsNote {
- margin-bottom: 10px;
-}
-
-.inputSpacer {
- margin-bottom: 25px;
-}
-
-.cleanupStretcher {
- margin: 0 -15px;
-}
-
-.factDaysToKeepCompacter {
- margin-bottom: 15px;
-}
-
-.factDetailsHeader {
- font-weight: bold;
-}
-
-@media (max-width: 991px) {
- .inputCompactMobile {
- margin-bottom: 15px;
- }
-}
-
-#login-modal-body {
- padding-bottom: 5px;
-}
-
-.modal {
- transition: all 0.3s ease-out !important;
-}
-
-.modal.fade .modal-dialog {
- transform: translate(0, 0);
- margin: 100px auto;
-}
-
-.modal-backdrop, .modal-backdrop.fade.show {
- opacity: .25;
-}
-
-.form-control {
- border-color: @b7grey;
- background-color: @fcgrey;
- color: @default-data-txt;
- transition: border-color 0.3s;
- box-shadow: none;
- font-size: 14px;
- font-family: 'Open Sans', sans-serif;
-}
-
-.form-control + .select2 .select2-selection {
- border-color: @b7grey !important;
- background-color: @fcgrey !important;
- color: @default-data-txt !important;
- transition: border-color 0.3s !important;
- box-shadow: none !important;
-}
-
-.form-control + .select2-container--disabled .select2-selection {
- background-color: @ebgrey !important;
-}
-
-.form-control:active, .form-control:focus {
- box-shadow: none;
- border-color: @default-link;
-}
-
-.form-control:active + .select2 .select2-selection, .form-control:focus + .select2 .select2-selection {
- box-shadow: none !important;
- border-color: @default-link !important;
-}
-
-.form-control.ng-dirty.ng-invalid, .form-control.ng-dirty.ng-invalid:focus {
- box-shadow: none;
-}
-
-.form-control.ng-dirty.ng-invalid + .select2 .select2-selection, .form-control.ng-dirty.ng-invalid:focus + .select2 .select2-selection {
- box-shadow: none !important;
-}
-
-.error {
- opacity: 1;
- transition: opacity 0.2s;
-}
-
-.error.ng-hide-add {
- display: none;
-}
-
-.error.ng-hide {
- opacity: 0;
-}
-
-/* Overwrite select2 base styles for single/multiple selects so that match up with other form elements. Also overwrite disabled styles. */
-.select2-container--disabled,.select2-container--disabled .select2-selection--single,.select2-container--disabled .select2-selection--multiple {
- cursor: not-allowed;
- opacity: 100;
- background-color: @ebgrey;
- border-radius: 5px;
-}
-
-.select2-container--default .select2-selection--single {
- background-color: @fcgrey;
- border: 1px solid @d7grey;
- border-radius: 4px;
-}
-
-.select2-container--default .select2-selection--multiple {
- background-color: @field-secondary-bg;
- border-radius: 4px;
- border: 1px solid @d7grey;
- cursor: text;
- max-height: 135px;
- overflow-y: auto;
-}
-
-body.is-modalOpen {
- overflow: hidden;
-}
-
-input[type=file]:focus, input[type=radio]:focus, input[type=checkbox]:focus {
- outline: 0 !important;
-}
-
-.btn-success.disabled, .btn-success[disabled], fieldset[disabled] .btn-success, .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, .btn-success.disabled:active, .btn-success[disabled]:active, fieldset[disabled] .btn-success:active, .btn-success.disabled.active, .btn-success[disabled].active, fieldset[disabled] .btn-success.active {
- background-color: @d7grey;
- color: @default-bg;
- border: 0;
-}
-
-.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success {
- border-color: @default-succ;
-}
-
-a {
- color: @default-link;
-}
-
-a:hover {
- color: @default-link-hov;
-}
-
-.form-control:active, .form-control:focus {
- border-color: @default-link;
-}
-
-.nv-axislabel {
- font-weight: bold !important;
- fill: @db-graph-axis-label !important;
- font-family: 'Open Sans' !important;
-}
-
-.nv-axis text {
- fill: @db-graph-axis-label !important;
- font-family: 'Open Sans' !important;
-}
-
-.select2-container--default .select2-selection--multiple .select2-selection__choice {
- cursor: default;
- float: left;
- margin-right: 5px;
- margin-top: 5px;
- padding-left: 0px;
- border-left-width: 0px;
- border-bottom-width: 0px;
- border-top-width: 0px;
- padding-right: 10px;
- border-right-width: 0px;
- background-color: @default-link;
- color: @default-bg;
- border-radius: 5px;
- line-height: 21px;
- font-size: 13px;
- white-space: pre-wrap;
- word-wrap: break-word;
- word-break: break-all;
- white-space: normal;
-}
-
-.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
- cursor: pointer;
- display: inline-block;
- font-weight: bold;
- margin-right: 8px !important;
- padding: 0 6px;
- color: @default-bg !important;
- border-top-left-radius: 5px;
- border-bottom-left-radius: 5px;
- background-color: @default-link;
-}
-
-.select2-selection {
- & > .select2-selection__arrow {
- border-left: none;
- }
-}
-
-.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
- background-color: @default-err;
-}
-
-#scheduled-jobs-tab .List-header {
- display: none;
-}
-
-.ui-widget {
- font-family: 'Open Sans';
-}
-
-.WorkflowBadge{
- background-color: @b7grey;
- border-radius: 10px;
- color: @default-bg;
- display: inline-block;
- font-family: 'Open Sans';
- font-weight: bold;
- font-style: normal;
- font-size: x-small;
- height: 14px;
- margin-left: 5px;
- padding-left: 2px;
- width: 14px;
-}
-
-button[disabled],
-html input[disabled] {
- cursor: not-allowed;
-}
-
-.CodeMirror {
- font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
-}
-
-.CodeMirror--disabled .CodeMirror.cm-s-default,
-.CodeMirror--disabled .CodeMirror-line {
- background-color: @default-no-items-bord;
-}
-
-.CodeMirror--disabled .CodeMirror-gutter.CodeMirror-lint-markers,
-.CodeMirror--disabled .CodeMirror-gutter.CodeMirror-linenumbers {
- background-color: @default-list-header-bg;
- color: @b7grey;
-}
-
-.CodeMirror--disabled .CodeMirror-lines {
- cursor: default;
-}
-
-.CodeMirror--disabled .CodeMirror-cursors {
- display: none;
-}
-
-.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active {
- border-color: @field-border;
-}
-
-.btn-default {
- background: @default-bg;
- border-color: @b7grey;
- color: @default-interface-txt;
-}
-
-.select2-container--disabled .select2-selection,
-.select2-container--disabled .select2-arrow {
- background-color: @ebgrey;
-}
-
-.btn.disabled,.btn[disabled],fieldset[disabled] .bt {
- opacity: 0.65;
-}
-
-.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled {
- opacity: 1;
- background-color: @ebgrey;
-}
-
-input[disabled].ui-spinner-input {
- background-color: @ebgrey;
-}
-
-.CodeMirror-scroll {
- margin-bottom: 0;
- padding-bottom: 0;
- margin-right: 0;
- overflow: auto !important;
- overflow-y: auto !important;
- border-radius: 5px;
-}
-
-.CodeMirror-lines {
- margin-bottom: 20px;
-}
-
-.btn-default {
- border-color: @b7grey;
-}
-
-.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
- background-color: @f2grey;
- border-color: @b7grey;
- color: @default-interface-txt;
-}
-
-.ui-dialog .ui-dialog-content {
- background: @default-bg;
-}
-
-.ui-dialog.no-close button.close {
- display: none;
-}
-
-html { height: 100%; }
-
-body {
- font-family: 'Open Sans', sans-serif;
- font-weight: 400;
- color: @default-data-txt;
- background-color: @default-secondary-bg;
-}
-
-.container-fluid {
- padding-left: 20px;
- padding-right: 20px;
-}
-
-#content-container {
- padding-bottom: 0px;
-}
-
-.btn {
- text-transform: uppercase;
-}
-
-.ui-spinner-input {
- margin-top: .3em;
- margin-bottom: .3em;
-}
-
-.Toast-wrapper {
- display: flex;
- max-width: 250px;
- word-break: break-word;
-}
-
-.Toast-icon {
- display: flex;
- align-items: center;
- justify-content: center;
-}
diff --git a/awx/ui/client/legacy/styles/bootstrap-custom-overrides.less b/awx/ui/client/legacy/styles/bootstrap-custom-overrides.less
deleted file mode 100644
index ab6020ce86..0000000000
--- a/awx/ui/client/legacy/styles/bootstrap-custom-overrides.less
+++ /dev/null
@@ -1,191 +0,0 @@
-body {
- font-family: 'Open Sans', sans-serif;
- font-weight: 400;
- color: @default-data-txt;
- background-color: @default-secondary-bg;
- font-size: 0.88rem;
- /*
- * Bootstrap fix that's causing a right margin and padding
- * to appear whenever a modal is opened
- * https://github.com/twbs/bootstrap/issues/27071
- */
- margin-right: 0px !important;
- padding-right: 0px !important;
-}
-
-.dropdown-toggle::after {
- display:none;
-}
-
-.tooltip.show {
- opacity: 1;
-}
-
-.tooltip {
- font-family: 'Open Sans', sans-serif;
- font-size: 0.75rem;
- line-height: 1.4;
-}
-
-.bs-tooltip-top .arrow::before,
-.bs-tooltip-auto[x-placement^="top"] .arrow::before {
- border-top-color: @default-stdout-txt;
-}
-
-.bs-tooltip-bottom .arrow::before,
-.bs-tooltip-auto[x-placement^="bottom"] .arrow::before {
- border-bottom-color: @default-stdout-txt;
-}
-
-.bs-tooltip-left .arrow::before,
-.bs-tooltip-auto[x-placement^="left"] .arrow::before {
- border-left-color: @default-stdout-txt;
-}
-
-.bs-tooltip-right .arrow::before,
-.bs-tooltip-auto[x-placement^="right"] .arrow::before {
- border-right-color: @default-stdout-txt;
-}
-
-/* this used to exist but was removed */
-.form-horizontal .form-group {
- margin-left: -15px;
- margin-right: -15px;
-}
-
-label {
- margin-bottom: 0.3125rem;
-}
-
-.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
- line-height: 1.1;
-}
-
-p {
- margin-bottom: 0.625rem;
-}
-
-.dropdown-menu, .btn {
- font-size: 0.88rem;
-}
-
-.btn-xs, .btn-group-xs>.btn {
- padding: 1px 5px;
- font-size: 0.75rem;
- line-height: 1.5;
- border-radius: 3px;
-}
-
-.btn-sm, .btn-group-sm>.btn {
- padding: 5px 10px;
- font-size: 0.75rem;
- line-height: 1.5;
- border-radius: 3px;
-}
-
-button, html input[type=button], input[type=reset], input[type=submit] {
- cursor: pointer;
-}
-
-.dropdown-menu {
- padding: .2rem 0;
-}
-
-.dropdown-item {
- padding: 0.19rem 0.625rem;
-}
-
-@media (min-width: 768px) {
- .modal-dialog {
- width: 600px;
- }
-}
-
-.modal-dialog {
- max-width: none;
-}
-
-.modal-footer>:not(:last-child) {
- margin-right: 1.25rem;
-}
-
-.btn-group-vertical>.btn, .btn-group>.btn {
- -ms-flex: 1 1 auto;
- flex: 1 1 auto;
-}
-
-.bs-popover-auto[x-placement^=right] .arrow::after, .bs-popover-right .arrow::after {
- border-right-color: @default-stdout-txt;
-}
-
-.bs-popover-auto[x-placement^=left] .arrow::after, .bs-popover-left .arrow::after {
- border-left-color: @default-stdout-txt;
-}
-
-.bs-popover-auto[x-placement^=top] .arrow::after, .bs-popover-top .arrow::after {
- border-top-color: @default-stdout-txt;
-}
-
-.bs-popover-auto[x-placement^=bottom] .arrow::after, .bs-popover-bottom .arrow::after {
- border-bottom-color: @default-stdout-txt;
-}
-
-a:not([href]):not([tabindex]) {
- color: @default-link;
-}
-
-a:not([href]):not([tabindex]):hover {
- color: @default-link-hov;
-}
-
-.dropdown-menu>li>a {
- padding: 3px 10px;
- display: block;
- clear: both;
- font-weight: 400;
- line-height: 1.42857143;
- white-space: nowrap;
-}
-
-.dropdown-item.active,
-.dropdown-item:active,
-.dropdown-menu>li>a:hover,
-.dropdown-menu>li>a:focus {
- text-decoration: none;
- color: @default-data-txt;
- background-color: @f6grey;
-}
-
-.radio-inline+.radio-inline, .checkbox-inline+.checkbox-inline {
- margin-left: 10px;
-}
-
-label {
- font-weight: 700;
-}
-
-.radio-inline, .checkbox-inline {
- font-weight: 400;
-}
-
-.btn-success{
- background: @default-succ;
- border-color: transparent;
- :hover{
- background: @default-succ-hov;
- }
- :disabled{
- background: @default-succ-disabled;
- }
-}
-.btn-default{
- background: @btn-bg;
- border-color: @btn-bord;
- color: @btn-txt;
- :hover{
- background: @btn-bg-hov;
- }
- :focus{
- background: @btn-bg-sel;
- }
-}
diff --git a/awx/ui/client/legacy/styles/bootstrap-datepicker.less b/awx/ui/client/legacy/styles/bootstrap-datepicker.less
deleted file mode 100644
index dd5f9490dc..0000000000
--- a/awx/ui/client/legacy/styles/bootstrap-datepicker.less
+++ /dev/null
@@ -1,750 +0,0 @@
-/*!
- * Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker)
- *
- * Copyright 2012 Stefan Petre
- * Improvements by Andrew Rowls
- * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- */
-.datepicker {
- padding: 4px;
- border-radius: 4px;
- direction: ltr;
-}
-.datepicker-inline {
- width: 220px;
-}
-.datepicker.datepicker-rtl {
- direction: rtl;
-}
-.datepicker.datepicker-rtl table tr td span {
- float: right;
-}
-.datepicker-dropdown {
- top: 0;
- left: 0;
-}
-.datepicker-dropdown:before {
- content: '';
- display: none;
- border-left: 7px solid transparent;
- border-right: 7px solid transparent;
- border-bottom: 7px solid #ccc;
- border-top: 0;
- border-bottom-color: rgba(0, 0, 0, 0.2);
- position: absolute;
-}
-.datepicker-dropdown:after {
- content: '';
- display: none;
- border-left: 6px solid transparent;
- border-right: 6px solid transparent;
- border-bottom: 6px solid #fff;
- border-top: 0;
- position: absolute;
-}
-.datepicker-dropdown.datepicker-orient-left:before {
- left: 6px;
-}
-.datepicker-dropdown.datepicker-orient-left:after {
- left: 7px;
-}
-.datepicker-dropdown.datepicker-orient-right:before {
- right: 6px;
-}
-.datepicker-dropdown.datepicker-orient-right:after {
- right: 7px;
-}
-.datepicker-dropdown.datepicker-orient-top:before {
- top: -7px;
-}
-.datepicker-dropdown.datepicker-orient-top:after {
- top: -6px;
-}
-.datepicker-dropdown.datepicker-orient-bottom:before {
- bottom: -7px;
- border-bottom: 0;
- border-top: 7px solid #999;
-}
-.datepicker-dropdown.datepicker-orient-bottom:after {
- bottom: -6px;
- border-bottom: 0;
- border-top: 6px solid #fff;
-}
-.datepicker.days .datepicker-days,
-.datepicker.months .datepicker-months,
-.datepicker.years .datepicker-years {
- display: block;
-}
-.datepicker table {
- margin: 0;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-.datepicker .datepicker-days .table-condensed tr td,
-.datepicker .datepicker-days .table-condensed tr th {
- text-align: center;
- width: 30px;
- height: 30px;
- border-radius: 4px;
- border: none;
- padding: 0.5em 0.7em;
-}
-.table-striped .datepicker table tr td,
-.table-striped .datepicker table tr th {
- background-color: transparent;
-}
-.datepicker table tr td.day:hover,
-.datepicker table tr td.day.focused {
- background: #eeeeee;
- cursor: pointer;
-}
-.datepicker table tr td.old,
-.datepicker table tr td.new {
- color: #999999;
-}
-.datepicker table tr td.disabled,
-.datepicker table tr td.disabled:hover {
- background: none;
- color: #999999;
- cursor: default;
-}
-.datepicker table tr td.today,
-.datepicker table tr td.today:hover,
-.datepicker table tr td.today.disabled,
-.datepicker table tr td.today.disabled:hover {
- color: #000000;
- background-color: #ffdb99;
- border-color: #ffb733;
-}
-.datepicker table tr td.today:hover,
-.datepicker table tr td.today:hover:hover,
-.datepicker table tr td.today.disabled:hover,
-.datepicker table tr td.today.disabled:hover:hover,
-.datepicker table tr td.today:focus,
-.datepicker table tr td.today:hover:focus,
-.datepicker table tr td.today.disabled:focus,
-.datepicker table tr td.today.disabled:hover:focus,
-.datepicker table tr td.today:active,
-.datepicker table tr td.today:hover:active,
-.datepicker table tr td.today.disabled:active,
-.datepicker table tr td.today.disabled:hover:active,
-.datepicker table tr td.today.active,
-.datepicker table tr td.today:hover.active,
-.datepicker table tr td.today.disabled.active,
-.datepicker table tr td.today.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.today,
-.open .dropdown-toggle.datepicker table tr td.today:hover,
-.open .dropdown-toggle.datepicker table tr td.today.disabled,
-.open .dropdown-toggle.datepicker table tr td.today.disabled:hover {
- color: #000000;
- background-color: #ffcd70;
- border-color: #f59e00;
-}
-.datepicker table tr td.today:active,
-.datepicker table tr td.today:hover:active,
-.datepicker table tr td.today.disabled:active,
-.datepicker table tr td.today.disabled:hover:active,
-.datepicker table tr td.today.active,
-.datepicker table tr td.today:hover.active,
-.datepicker table tr td.today.disabled.active,
-.datepicker table tr td.today.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.today,
-.open .dropdown-toggle.datepicker table tr td.today:hover,
-.open .dropdown-toggle.datepicker table tr td.today.disabled,
-.open .dropdown-toggle.datepicker table tr td.today.disabled:hover {
- background-image: none;
-}
-.datepicker table tr td.today.disabled,
-.datepicker table tr td.today:hover.disabled,
-.datepicker table tr td.today.disabled.disabled,
-.datepicker table tr td.today.disabled:hover.disabled,
-.datepicker table tr td.today[disabled],
-.datepicker table tr td.today:hover[disabled],
-.datepicker table tr td.today.disabled[disabled],
-.datepicker table tr td.today.disabled:hover[disabled],
-fieldset[disabled] .datepicker table tr td.today,
-fieldset[disabled] .datepicker table tr td.today:hover,
-fieldset[disabled] .datepicker table tr td.today.disabled,
-fieldset[disabled] .datepicker table tr td.today.disabled:hover,
-.datepicker table tr td.today.disabled:hover,
-.datepicker table tr td.today:hover.disabled:hover,
-.datepicker table tr td.today.disabled.disabled:hover,
-.datepicker table tr td.today.disabled:hover.disabled:hover,
-.datepicker table tr td.today[disabled]:hover,
-.datepicker table tr td.today:hover[disabled]:hover,
-.datepicker table tr td.today.disabled[disabled]:hover,
-.datepicker table tr td.today.disabled:hover[disabled]:hover,
-fieldset[disabled] .datepicker table tr td.today:hover,
-fieldset[disabled] .datepicker table tr td.today:hover:hover,
-fieldset[disabled] .datepicker table tr td.today.disabled:hover,
-fieldset[disabled] .datepicker table tr td.today.disabled:hover:hover,
-.datepicker table tr td.today.disabled:focus,
-.datepicker table tr td.today:hover.disabled:focus,
-.datepicker table tr td.today.disabled.disabled:focus,
-.datepicker table tr td.today.disabled:hover.disabled:focus,
-.datepicker table tr td.today[disabled]:focus,
-.datepicker table tr td.today:hover[disabled]:focus,
-.datepicker table tr td.today.disabled[disabled]:focus,
-.datepicker table tr td.today.disabled:hover[disabled]:focus,
-fieldset[disabled] .datepicker table tr td.today:focus,
-fieldset[disabled] .datepicker table tr td.today:hover:focus,
-fieldset[disabled] .datepicker table tr td.today.disabled:focus,
-fieldset[disabled] .datepicker table tr td.today.disabled:hover:focus,
-.datepicker table tr td.today.disabled:active,
-.datepicker table tr td.today:hover.disabled:active,
-.datepicker table tr td.today.disabled.disabled:active,
-.datepicker table tr td.today.disabled:hover.disabled:active,
-.datepicker table tr td.today[disabled]:active,
-.datepicker table tr td.today:hover[disabled]:active,
-.datepicker table tr td.today.disabled[disabled]:active,
-.datepicker table tr td.today.disabled:hover[disabled]:active,
-fieldset[disabled] .datepicker table tr td.today:active,
-fieldset[disabled] .datepicker table tr td.today:hover:active,
-fieldset[disabled] .datepicker table tr td.today.disabled:active,
-fieldset[disabled] .datepicker table tr td.today.disabled:hover:active,
-.datepicker table tr td.today.disabled.active,
-.datepicker table tr td.today:hover.disabled.active,
-.datepicker table tr td.today.disabled.disabled.active,
-.datepicker table tr td.today.disabled:hover.disabled.active,
-.datepicker table tr td.today[disabled].active,
-.datepicker table tr td.today:hover[disabled].active,
-.datepicker table tr td.today.disabled[disabled].active,
-.datepicker table tr td.today.disabled:hover[disabled].active,
-fieldset[disabled] .datepicker table tr td.today.active,
-fieldset[disabled] .datepicker table tr td.today:hover.active,
-fieldset[disabled] .datepicker table tr td.today.disabled.active,
-fieldset[disabled] .datepicker table tr td.today.disabled:hover.active {
- background-color: #ffdb99;
- border-color: #ffb733;
-}
-.datepicker table tr td.today:hover:hover {
- color: #000;
-}
-.datepicker table tr td.today.active:hover {
- color: #fff;
-}
-.datepicker table tr td.range,
-.datepicker table tr td.range:hover,
-.datepicker table tr td.range.disabled,
-.datepicker table tr td.range.disabled:hover {
- background: #eeeeee;
- border-radius: 0;
-}
-.datepicker table tr td.range.today,
-.datepicker table tr td.range.today:hover,
-.datepicker table tr td.range.today.disabled,
-.datepicker table tr td.range.today.disabled:hover {
- color: #000000;
- background-color: #f7ca77;
- border-color: #f1a417;
- border-radius: 0;
-}
-.datepicker table tr td.range.today:hover,
-.datepicker table tr td.range.today:hover:hover,
-.datepicker table tr td.range.today.disabled:hover,
-.datepicker table tr td.range.today.disabled:hover:hover,
-.datepicker table tr td.range.today:focus,
-.datepicker table tr td.range.today:hover:focus,
-.datepicker table tr td.range.today.disabled:focus,
-.datepicker table tr td.range.today.disabled:hover:focus,
-.datepicker table tr td.range.today:active,
-.datepicker table tr td.range.today:hover:active,
-.datepicker table tr td.range.today.disabled:active,
-.datepicker table tr td.range.today.disabled:hover:active,
-.datepicker table tr td.range.today.active,
-.datepicker table tr td.range.today:hover.active,
-.datepicker table tr td.range.today.disabled.active,
-.datepicker table tr td.range.today.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.range.today,
-.open .dropdown-toggle.datepicker table tr td.range.today:hover,
-.open .dropdown-toggle.datepicker table tr td.range.today.disabled,
-.open .dropdown-toggle.datepicker table tr td.range.today.disabled:hover {
- color: #000000;
- background-color: #f4bb51;
- border-color: #bf800c;
-}
-.datepicker table tr td.range.today:active,
-.datepicker table tr td.range.today:hover:active,
-.datepicker table tr td.range.today.disabled:active,
-.datepicker table tr td.range.today.disabled:hover:active,
-.datepicker table tr td.range.today.active,
-.datepicker table tr td.range.today:hover.active,
-.datepicker table tr td.range.today.disabled.active,
-.datepicker table tr td.range.today.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.range.today,
-.open .dropdown-toggle.datepicker table tr td.range.today:hover,
-.open .dropdown-toggle.datepicker table tr td.range.today.disabled,
-.open .dropdown-toggle.datepicker table tr td.range.today.disabled:hover {
- background-image: none;
-}
-.datepicker table tr td.range.today.disabled,
-.datepicker table tr td.range.today:hover.disabled,
-.datepicker table tr td.range.today.disabled.disabled,
-.datepicker table tr td.range.today.disabled:hover.disabled,
-.datepicker table tr td.range.today[disabled],
-.datepicker table tr td.range.today:hover[disabled],
-.datepicker table tr td.range.today.disabled[disabled],
-.datepicker table tr td.range.today.disabled:hover[disabled],
-fieldset[disabled] .datepicker table tr td.range.today,
-fieldset[disabled] .datepicker table tr td.range.today:hover,
-fieldset[disabled] .datepicker table tr td.range.today.disabled,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:hover,
-.datepicker table tr td.range.today.disabled:hover,
-.datepicker table tr td.range.today:hover.disabled:hover,
-.datepicker table tr td.range.today.disabled.disabled:hover,
-.datepicker table tr td.range.today.disabled:hover.disabled:hover,
-.datepicker table tr td.range.today[disabled]:hover,
-.datepicker table tr td.range.today:hover[disabled]:hover,
-.datepicker table tr td.range.today.disabled[disabled]:hover,
-.datepicker table tr td.range.today.disabled:hover[disabled]:hover,
-fieldset[disabled] .datepicker table tr td.range.today:hover,
-fieldset[disabled] .datepicker table tr td.range.today:hover:hover,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:hover,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:hover:hover,
-.datepicker table tr td.range.today.disabled:focus,
-.datepicker table tr td.range.today:hover.disabled:focus,
-.datepicker table tr td.range.today.disabled.disabled:focus,
-.datepicker table tr td.range.today.disabled:hover.disabled:focus,
-.datepicker table tr td.range.today[disabled]:focus,
-.datepicker table tr td.range.today:hover[disabled]:focus,
-.datepicker table tr td.range.today.disabled[disabled]:focus,
-.datepicker table tr td.range.today.disabled:hover[disabled]:focus,
-fieldset[disabled] .datepicker table tr td.range.today:focus,
-fieldset[disabled] .datepicker table tr td.range.today:hover:focus,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:focus,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:hover:focus,
-.datepicker table tr td.range.today.disabled:active,
-.datepicker table tr td.range.today:hover.disabled:active,
-.datepicker table tr td.range.today.disabled.disabled:active,
-.datepicker table tr td.range.today.disabled:hover.disabled:active,
-.datepicker table tr td.range.today[disabled]:active,
-.datepicker table tr td.range.today:hover[disabled]:active,
-.datepicker table tr td.range.today.disabled[disabled]:active,
-.datepicker table tr td.range.today.disabled:hover[disabled]:active,
-fieldset[disabled] .datepicker table tr td.range.today:active,
-fieldset[disabled] .datepicker table tr td.range.today:hover:active,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:active,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:hover:active,
-.datepicker table tr td.range.today.disabled.active,
-.datepicker table tr td.range.today:hover.disabled.active,
-.datepicker table tr td.range.today.disabled.disabled.active,
-.datepicker table tr td.range.today.disabled:hover.disabled.active,
-.datepicker table tr td.range.today[disabled].active,
-.datepicker table tr td.range.today:hover[disabled].active,
-.datepicker table tr td.range.today.disabled[disabled].active,
-.datepicker table tr td.range.today.disabled:hover[disabled].active,
-fieldset[disabled] .datepicker table tr td.range.today.active,
-fieldset[disabled] .datepicker table tr td.range.today:hover.active,
-fieldset[disabled] .datepicker table tr td.range.today.disabled.active,
-fieldset[disabled] .datepicker table tr td.range.today.disabled:hover.active {
- background-color: #f7ca77;
- border-color: #f1a417;
-}
-.datepicker table tr td.selected,
-.datepicker table tr td.selected:hover,
-.datepicker table tr td.selected.disabled,
-.datepicker table tr td.selected.disabled:hover {
- color: #ffffff;
- background-color: #999999;
- border-color: #555555;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-.datepicker table tr td.selected:hover,
-.datepicker table tr td.selected:hover:hover,
-.datepicker table tr td.selected.disabled:hover,
-.datepicker table tr td.selected.disabled:hover:hover,
-.datepicker table tr td.selected:focus,
-.datepicker table tr td.selected:hover:focus,
-.datepicker table tr td.selected.disabled:focus,
-.datepicker table tr td.selected.disabled:hover:focus,
-.datepicker table tr td.selected:active,
-.datepicker table tr td.selected:hover:active,
-.datepicker table tr td.selected.disabled:active,
-.datepicker table tr td.selected.disabled:hover:active,
-.datepicker table tr td.selected.active,
-.datepicker table tr td.selected:hover.active,
-.datepicker table tr td.selected.disabled.active,
-.datepicker table tr td.selected.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.selected,
-.open .dropdown-toggle.datepicker table tr td.selected:hover,
-.open .dropdown-toggle.datepicker table tr td.selected.disabled,
-.open .dropdown-toggle.datepicker table tr td.selected.disabled:hover {
- color: #ffffff;
- background-color: #858585;
- border-color: #373737;
-}
-.datepicker table tr td.selected:active,
-.datepicker table tr td.selected:hover:active,
-.datepicker table tr td.selected.disabled:active,
-.datepicker table tr td.selected.disabled:hover:active,
-.datepicker table tr td.selected.active,
-.datepicker table tr td.selected:hover.active,
-.datepicker table tr td.selected.disabled.active,
-.datepicker table tr td.selected.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.selected,
-.open .dropdown-toggle.datepicker table tr td.selected:hover,
-.open .dropdown-toggle.datepicker table tr td.selected.disabled,
-.open .dropdown-toggle.datepicker table tr td.selected.disabled:hover {
- background-image: none;
-}
-.datepicker table tr td.selected.disabled,
-.datepicker table tr td.selected:hover.disabled,
-.datepicker table tr td.selected.disabled.disabled,
-.datepicker table tr td.selected.disabled:hover.disabled,
-.datepicker table tr td.selected[disabled],
-.datepicker table tr td.selected:hover[disabled],
-.datepicker table tr td.selected.disabled[disabled],
-.datepicker table tr td.selected.disabled:hover[disabled],
-fieldset[disabled] .datepicker table tr td.selected,
-fieldset[disabled] .datepicker table tr td.selected:hover,
-fieldset[disabled] .datepicker table tr td.selected.disabled,
-fieldset[disabled] .datepicker table tr td.selected.disabled:hover,
-.datepicker table tr td.selected.disabled:hover,
-.datepicker table tr td.selected:hover.disabled:hover,
-.datepicker table tr td.selected.disabled.disabled:hover,
-.datepicker table tr td.selected.disabled:hover.disabled:hover,
-.datepicker table tr td.selected[disabled]:hover,
-.datepicker table tr td.selected:hover[disabled]:hover,
-.datepicker table tr td.selected.disabled[disabled]:hover,
-.datepicker table tr td.selected.disabled:hover[disabled]:hover,
-fieldset[disabled] .datepicker table tr td.selected:hover,
-fieldset[disabled] .datepicker table tr td.selected:hover:hover,
-fieldset[disabled] .datepicker table tr td.selected.disabled:hover,
-fieldset[disabled] .datepicker table tr td.selected.disabled:hover:hover,
-.datepicker table tr td.selected.disabled:focus,
-.datepicker table tr td.selected:hover.disabled:focus,
-.datepicker table tr td.selected.disabled.disabled:focus,
-.datepicker table tr td.selected.disabled:hover.disabled:focus,
-.datepicker table tr td.selected[disabled]:focus,
-.datepicker table tr td.selected:hover[disabled]:focus,
-.datepicker table tr td.selected.disabled[disabled]:focus,
-.datepicker table tr td.selected.disabled:hover[disabled]:focus,
-fieldset[disabled] .datepicker table tr td.selected:focus,
-fieldset[disabled] .datepicker table tr td.selected:hover:focus,
-fieldset[disabled] .datepicker table tr td.selected.disabled:focus,
-fieldset[disabled] .datepicker table tr td.selected.disabled:hover:focus,
-.datepicker table tr td.selected.disabled:active,
-.datepicker table tr td.selected:hover.disabled:active,
-.datepicker table tr td.selected.disabled.disabled:active,
-.datepicker table tr td.selected.disabled:hover.disabled:active,
-.datepicker table tr td.selected[disabled]:active,
-.datepicker table tr td.selected:hover[disabled]:active,
-.datepicker table tr td.selected.disabled[disabled]:active,
-.datepicker table tr td.selected.disabled:hover[disabled]:active,
-fieldset[disabled] .datepicker table tr td.selected:active,
-fieldset[disabled] .datepicker table tr td.selected:hover:active,
-fieldset[disabled] .datepicker table tr td.selected.disabled:active,
-fieldset[disabled] .datepicker table tr td.selected.disabled:hover:active,
-.datepicker table tr td.selected.disabled.active,
-.datepicker table tr td.selected:hover.disabled.active,
-.datepicker table tr td.selected.disabled.disabled.active,
-.datepicker table tr td.selected.disabled:hover.disabled.active,
-.datepicker table tr td.selected[disabled].active,
-.datepicker table tr td.selected:hover[disabled].active,
-.datepicker table tr td.selected.disabled[disabled].active,
-.datepicker table tr td.selected.disabled:hover[disabled].active,
-fieldset[disabled] .datepicker table tr td.selected.active,
-fieldset[disabled] .datepicker table tr td.selected:hover.active,
-fieldset[disabled] .datepicker table tr td.selected.disabled.active,
-fieldset[disabled] .datepicker table tr td.selected.disabled:hover.active {
- background-color: #999999;
- border-color: #555555;
-}
-.datepicker table tr td.active,
-.datepicker table tr td.active:hover,
-.datepicker table tr td.active.disabled,
-.datepicker table tr td.active.disabled:hover {
- color: #ffffff;
- background-color: #428bca;
- border-color: #357ebd;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-.datepicker table tr td.active:hover,
-.datepicker table tr td.active:hover:hover,
-.datepicker table tr td.active.disabled:hover,
-.datepicker table tr td.active.disabled:hover:hover,
-.datepicker table tr td.active:focus,
-.datepicker table tr td.active:hover:focus,
-.datepicker table tr td.active.disabled:focus,
-.datepicker table tr td.active.disabled:hover:focus,
-.datepicker table tr td.active:active,
-.datepicker table tr td.active:hover:active,
-.datepicker table tr td.active.disabled:active,
-.datepicker table tr td.active.disabled:hover:active,
-.datepicker table tr td.active.active,
-.datepicker table tr td.active:hover.active,
-.datepicker table tr td.active.disabled.active,
-.datepicker table tr td.active.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.active,
-.open .dropdown-toggle.datepicker table tr td.active:hover,
-.open .dropdown-toggle.datepicker table tr td.active.disabled,
-.open .dropdown-toggle.datepicker table tr td.active.disabled:hover {
- color: #ffffff;
- background-color: #3276b1;
- border-color: #285e8e;
-}
-.datepicker table tr td.active:active,
-.datepicker table tr td.active:hover:active,
-.datepicker table tr td.active.disabled:active,
-.datepicker table tr td.active.disabled:hover:active,
-.datepicker table tr td.active.active,
-.datepicker table tr td.active:hover.active,
-.datepicker table tr td.active.disabled.active,
-.datepicker table tr td.active.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td.active,
-.open .dropdown-toggle.datepicker table tr td.active:hover,
-.open .dropdown-toggle.datepicker table tr td.active.disabled,
-.open .dropdown-toggle.datepicker table tr td.active.disabled:hover {
- background-image: none;
-}
-.datepicker table tr td.active.disabled,
-.datepicker table tr td.active:hover.disabled,
-.datepicker table tr td.active.disabled.disabled,
-.datepicker table tr td.active.disabled:hover.disabled,
-.datepicker table tr td.active[disabled],
-.datepicker table tr td.active:hover[disabled],
-.datepicker table tr td.active.disabled[disabled],
-.datepicker table tr td.active.disabled:hover[disabled],
-fieldset[disabled] .datepicker table tr td.active,
-fieldset[disabled] .datepicker table tr td.active:hover,
-fieldset[disabled] .datepicker table tr td.active.disabled,
-fieldset[disabled] .datepicker table tr td.active.disabled:hover,
-.datepicker table tr td.active.disabled:hover,
-.datepicker table tr td.active:hover.disabled:hover,
-.datepicker table tr td.active.disabled.disabled:hover,
-.datepicker table tr td.active.disabled:hover.disabled:hover,
-.datepicker table tr td.active[disabled]:hover,
-.datepicker table tr td.active:hover[disabled]:hover,
-.datepicker table tr td.active.disabled[disabled]:hover,
-.datepicker table tr td.active.disabled:hover[disabled]:hover,
-fieldset[disabled] .datepicker table tr td.active:hover,
-fieldset[disabled] .datepicker table tr td.active:hover:hover,
-fieldset[disabled] .datepicker table tr td.active.disabled:hover,
-fieldset[disabled] .datepicker table tr td.active.disabled:hover:hover,
-.datepicker table tr td.active.disabled:focus,
-.datepicker table tr td.active:hover.disabled:focus,
-.datepicker table tr td.active.disabled.disabled:focus,
-.datepicker table tr td.active.disabled:hover.disabled:focus,
-.datepicker table tr td.active[disabled]:focus,
-.datepicker table tr td.active:hover[disabled]:focus,
-.datepicker table tr td.active.disabled[disabled]:focus,
-.datepicker table tr td.active.disabled:hover[disabled]:focus,
-fieldset[disabled] .datepicker table tr td.active:focus,
-fieldset[disabled] .datepicker table tr td.active:hover:focus,
-fieldset[disabled] .datepicker table tr td.active.disabled:focus,
-fieldset[disabled] .datepicker table tr td.active.disabled:hover:focus,
-.datepicker table tr td.active.disabled:active,
-.datepicker table tr td.active:hover.disabled:active,
-.datepicker table tr td.active.disabled.disabled:active,
-.datepicker table tr td.active.disabled:hover.disabled:active,
-.datepicker table tr td.active[disabled]:active,
-.datepicker table tr td.active:hover[disabled]:active,
-.datepicker table tr td.active.disabled[disabled]:active,
-.datepicker table tr td.active.disabled:hover[disabled]:active,
-fieldset[disabled] .datepicker table tr td.active:active,
-fieldset[disabled] .datepicker table tr td.active:hover:active,
-fieldset[disabled] .datepicker table tr td.active.disabled:active,
-fieldset[disabled] .datepicker table tr td.active.disabled:hover:active,
-.datepicker table tr td.active.disabled.active,
-.datepicker table tr td.active:hover.disabled.active,
-.datepicker table tr td.active.disabled.disabled.active,
-.datepicker table tr td.active.disabled:hover.disabled.active,
-.datepicker table tr td.active[disabled].active,
-.datepicker table tr td.active:hover[disabled].active,
-.datepicker table tr td.active.disabled[disabled].active,
-.datepicker table tr td.active.disabled:hover[disabled].active,
-fieldset[disabled] .datepicker table tr td.active.active,
-fieldset[disabled] .datepicker table tr td.active:hover.active,
-fieldset[disabled] .datepicker table tr td.active.disabled.active,
-fieldset[disabled] .datepicker table tr td.active.disabled:hover.active {
- background-color: #428bca;
- border-color: #357ebd;
-}
-.datepicker table tr td span {
- display: block;
- width: 23%;
- height: 54px;
- line-height: 54px;
- float: left;
- margin: 1%;
- cursor: pointer;
- border-radius: 4px;
-}
-.datepicker table tr td span:hover {
- background: #eeeeee;
-}
-.datepicker table tr td span.disabled,
-.datepicker table tr td span.disabled:hover {
- background: none;
- color: #999999;
- cursor: default;
-}
-.datepicker table tr td span.active,
-.datepicker table tr td span.active:hover,
-.datepicker table tr td span.active.disabled,
-.datepicker table tr td span.active.disabled:hover {
- color: #ffffff;
- background-color: #428bca;
- border-color: #357ebd;
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-.datepicker table tr td span.active:hover,
-.datepicker table tr td span.active:hover:hover,
-.datepicker table tr td span.active.disabled:hover,
-.datepicker table tr td span.active.disabled:hover:hover,
-.datepicker table tr td span.active:focus,
-.datepicker table tr td span.active:hover:focus,
-.datepicker table tr td span.active.disabled:focus,
-.datepicker table tr td span.active.disabled:hover:focus,
-.datepicker table tr td span.active:active,
-.datepicker table tr td span.active:hover:active,
-.datepicker table tr td span.active.disabled:active,
-.datepicker table tr td span.active.disabled:hover:active,
-.datepicker table tr td span.active.active,
-.datepicker table tr td span.active:hover.active,
-.datepicker table tr td span.active.disabled.active,
-.datepicker table tr td span.active.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td span.active,
-.open .dropdown-toggle.datepicker table tr td span.active:hover,
-.open .dropdown-toggle.datepicker table tr td span.active.disabled,
-.open .dropdown-toggle.datepicker table tr td span.active.disabled:hover {
- color: #ffffff;
- background-color: #3276b1;
- border-color: #285e8e;
-}
-.datepicker table tr td span.active:active,
-.datepicker table tr td span.active:hover:active,
-.datepicker table tr td span.active.disabled:active,
-.datepicker table tr td span.active.disabled:hover:active,
-.datepicker table tr td span.active.active,
-.datepicker table tr td span.active:hover.active,
-.datepicker table tr td span.active.disabled.active,
-.datepicker table tr td span.active.disabled:hover.active,
-.open .dropdown-toggle.datepicker table tr td span.active,
-.open .dropdown-toggle.datepicker table tr td span.active:hover,
-.open .dropdown-toggle.datepicker table tr td span.active.disabled,
-.open .dropdown-toggle.datepicker table tr td span.active.disabled:hover {
- background-image: none;
-}
-.datepicker table tr td span.active.disabled,
-.datepicker table tr td span.active:hover.disabled,
-.datepicker table tr td span.active.disabled.disabled,
-.datepicker table tr td span.active.disabled:hover.disabled,
-.datepicker table tr td span.active[disabled],
-.datepicker table tr td span.active:hover[disabled],
-.datepicker table tr td span.active.disabled[disabled],
-.datepicker table tr td span.active.disabled:hover[disabled],
-fieldset[disabled] .datepicker table tr td span.active,
-fieldset[disabled] .datepicker table tr td span.active:hover,
-fieldset[disabled] .datepicker table tr td span.active.disabled,
-fieldset[disabled] .datepicker table tr td span.active.disabled:hover,
-.datepicker table tr td span.active.disabled:hover,
-.datepicker table tr td span.active:hover.disabled:hover,
-.datepicker table tr td span.active.disabled.disabled:hover,
-.datepicker table tr td span.active.disabled:hover.disabled:hover,
-.datepicker table tr td span.active[disabled]:hover,
-.datepicker table tr td span.active:hover[disabled]:hover,
-.datepicker table tr td span.active.disabled[disabled]:hover,
-.datepicker table tr td span.active.disabled:hover[disabled]:hover,
-fieldset[disabled] .datepicker table tr td span.active:hover,
-fieldset[disabled] .datepicker table tr td span.active:hover:hover,
-fieldset[disabled] .datepicker table tr td span.active.disabled:hover,
-fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover,
-.datepicker table tr td span.active.disabled:focus,
-.datepicker table tr td span.active:hover.disabled:focus,
-.datepicker table tr td span.active.disabled.disabled:focus,
-.datepicker table tr td span.active.disabled:hover.disabled:focus,
-.datepicker table tr td span.active[disabled]:focus,
-.datepicker table tr td span.active:hover[disabled]:focus,
-.datepicker table tr td span.active.disabled[disabled]:focus,
-.datepicker table tr td span.active.disabled:hover[disabled]:focus,
-fieldset[disabled] .datepicker table tr td span.active:focus,
-fieldset[disabled] .datepicker table tr td span.active:hover:focus,
-fieldset[disabled] .datepicker table tr td span.active.disabled:focus,
-fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus,
-.datepicker table tr td span.active.disabled:active,
-.datepicker table tr td span.active:hover.disabled:active,
-.datepicker table tr td span.active.disabled.disabled:active,
-.datepicker table tr td span.active.disabled:hover.disabled:active,
-.datepicker table tr td span.active[disabled]:active,
-.datepicker table tr td span.active:hover[disabled]:active,
-.datepicker table tr td span.active.disabled[disabled]:active,
-.datepicker table tr td span.active.disabled:hover[disabled]:active,
-fieldset[disabled] .datepicker table tr td span.active:active,
-fieldset[disabled] .datepicker table tr td span.active:hover:active,
-fieldset[disabled] .datepicker table tr td span.active.disabled:active,
-fieldset[disabled] .datepicker table tr td span.active.disabled:hover:active,
-.datepicker table tr td span.active.disabled.active,
-.datepicker table tr td span.active:hover.disabled.active,
-.datepicker table tr td span.active.disabled.disabled.active,
-.datepicker table tr td span.active.disabled:hover.disabled.active,
-.datepicker table tr td span.active[disabled].active,
-.datepicker table tr td span.active:hover[disabled].active,
-.datepicker table tr td span.active.disabled[disabled].active,
-.datepicker table tr td span.active.disabled:hover[disabled].active,
-fieldset[disabled] .datepicker table tr td span.active.active,
-fieldset[disabled] .datepicker table tr td span.active:hover.active,
-fieldset[disabled] .datepicker table tr td span.active.disabled.active,
-fieldset[disabled] .datepicker table tr td span.active.disabled:hover.active {
- background-color: #428bca;
- border-color: #357ebd;
-}
-.datepicker table tr td span.old,
-.datepicker table tr td span.new {
- color: #999999;
-}
-.datepicker .datepicker-switch {
- width: 145px;
-}
-.datepicker thead tr:first-child th,
-.datepicker tfoot tr th {
- cursor: pointer;
-}
-.datepicker thead tr:first-child th:hover,
-.datepicker tfoot tr th:hover {
- background: #eeeeee;
-}
-.datepicker .cw {
- font-size: 10px;
- width: 12px;
- padding: 0 2px 0 5px;
- vertical-align: middle;
-}
-.datepicker thead tr:first-child .cw {
- cursor: default;
- background-color: transparent;
-}
-.input-group.date .input-group-addon {
- cursor: pointer;
-}
-.input-daterange {
- width: 100%;
-}
-.input-daterange input {
- text-align: center;
-}
-.input-daterange input:first-child {
- border-radius: 3px 0 0 3px;
-}
-.input-daterange input:last-child {
- border-radius: 0 3px 3px 0;
-}
-.input-daterange .input-group-addon {
- width: auto;
- min-width: 16px;
- padding: 4px 5px;
- font-weight: normal;
- line-height: 1.42857143;
- text-align: center;
- text-shadow: 0 1px 0 #fff;
- vertical-align: middle;
- background-color: #eeeeee;
- border: solid #cccccc;
- border-width: 1px 0;
- margin-left: -5px;
- margin-right: -5px;
-}
diff --git a/awx/ui/client/legacy/styles/codemirror.less b/awx/ui/client/legacy/styles/codemirror.less
deleted file mode 100644
index 0a0a1ac47a..0000000000
--- a/awx/ui/client/legacy/styles/codemirror.less
+++ /dev/null
@@ -1,49 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- * Overrides to angular-codemirror
- *
- *
- */
-
-.CodeMirror {
- height: auto;
- overflow-x: auto;
- overflow-y: hidden;
- border: 1px solid @b7grey;
-}
-
-.CodeMirror,
-.CodeMirror-activeline-background {
- background-color: @default-secondary-bg;
-}
-
-/* Make sure code editor dialog is always at top of stack */
-[aria-describedby=af-code-editor-modal].ui-front {
- z-index: 2050;
-}
-
-.CodeMirror-lint-tooltip {
- z-index: 2060;
-}
-
-.CodeMirror-gutters {
- border-color: @d7grey;
- background-color: @default-no-items-bord;
-}
-
-.CodeMirror-linenumber {
- color: @at-gray-70;
-}
-
-// Disabled
-textarea[disabled="disabled"] + div[id*="-container"]{
- .CodeMirror-gutters {
- border-color: @b7grey;
- }
-
- .CodeMirror-gutter.CodeMirror-lint-markers,
- .CodeMirror-gutter.CodeMirror-linenumbers {
- background-color: @default-bg;
- color: @default-interface-txt;
- }
-}
diff --git a/awx/ui/client/legacy/styles/dashboard.less b/awx/ui/client/legacy/styles/dashboard.less
deleted file mode 100644
index 2b1ee7c00e..0000000000
--- a/awx/ui/client/legacy/styles/dashboard.less
+++ /dev/null
@@ -1,114 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * dashboard.css
- *
- * custom styles for the new dashboard
- *
- */
-
-.graph-wrapper {
- width: 100%;
-}
-
-.graph {
- background-color: white;
- // @include transition(width 2s ease-in-out, height 2s ease-in-out);
- position: relative;
- text-align: center;
- width: 100%;
- height: 100%;
- margin: 0 auto;
-}
-
-.job-status-graph, .host-count-graph{
- font: 10px sans-serif;
-}
-
-.axis path,
-.axis line {
- fill: none;
- stroke: #000;
- shape-rendering: crispEdges;
-}
-
-.line {
- fill: none;
- stroke: steelblue;
- stroke-width: 1.5px;
-}
-
-
-.dashboard-jobs-list-container {
- border: 1px solid @grey;
- border-radius: 4px;
- padding: 5px;
-}
-
-/*
-.graph-container{
- border: 1px solid @grey;
- border-radius: 4px;
- padding: 5px;
- margin-bottom: 15px;
-}
-due to the login screen showing on top of the dashboard, we're hiding the borders until after the user logs in*/
-
-.count-container{
- border: 1px solid @grey;
- border-radius: 4px;
- margin-left: 0px;
- margin-right: 0px;
- margin-bottom: 15px;
-}
-
-#replacementImg{
- align:center;
- width: 100px;
- height: 100px;
-
-}
-
-#dashboard-tab-content{
- padding-top: 5px;
-}
-
-#dashboard-tab-content .search-row #active-jobs-search-container{
- height: 35px;
-}
-
-
-#dashboard-tab-content table{
- margin-bottom: 10px;
-}
-
-.dashboard-jobs-list-container {
- #jobs_table,
- #schedules_table {
- table-layout:fixed;
- }
- #jobs_table .name-column,
- #schedules_table .name-column {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-}
-
-#dash-jobs-list{
- padding-bottom: 15px;
-}
-
- @media (min-width: 769px) {
- .left-side {
- padding-right: 7px;
- }
-
- .right-side {
- padding-left: 7px;
- }
-}
-
-.m, .n{
- cursor:pointer;
-}
diff --git a/awx/ui/client/legacy/styles/event-viewer.less b/awx/ui/client/legacy/styles/event-viewer.less
deleted file mode 100644
index ac575b4c03..0000000000
--- a/awx/ui/client/legacy/styles/event-viewer.less
+++ /dev/null
@@ -1,60 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * event-viewer.less
- *
- * custom styles for EventViewer.js helper
- *
- */
-
-#eventviewer-modal-dialog {
-
- textarea {
- overflow: scroll;
- }
- pre {
- overflow: scroll;
- word-wrap: normal;
- word-break: normal;
- white-space: pre-wrap;
- }
-}
-
-table.eventviewer-status {
- margin-top: 20px;
-
- .key {
- width: 20%;
- font-weight: bold;
- }
- .value i {
- font-size: 12px;
- }
-}
-
-.nested-table {
- border: none;
- padding: 0;
- table {
- border-top: none;
- border-bottom: none;
- width: auto;
- td {
- vertical-align: top;
- padding: 0 3px 3px 3px;
- }
- tr {
- border-top: none;
- border-bottom: 1px solid #ddd;
- }
- /*tr td:first-of-type {
- width: auto;
- }*/
- tr:last-of-type {
- border-bottom: none;
- }
- .key {
- font-weight: 400;
- }
- }
-}
\ No newline at end of file
diff --git a/awx/ui/client/legacy/styles/fonts.less b/awx/ui/client/legacy/styles/fonts.less
deleted file mode 100644
index e75c35f699..0000000000
--- a/awx/ui/client/legacy/styles/fonts.less
+++ /dev/null
@@ -1,19 +0,0 @@
-.include-font(@family-name; @filename; @weight: normal; @style: normal) {
- @font-face {
- font-family: @family-name;
- src: url("/static/assets/@{filename}.woff2") format('woff2'),
- url("/static/assets/@{filename}.woff") format('woff');
- font-weight: @weight;
- font-style: @style;
- }
-}
-
-.include-font('merriweather'; 'merriweather_light-webfont'; 200);
-.include-font('merriweather'; 'merriweather-regular-webfont');
-.include-font('merriweather'; 'merriweather-bold-webfont'; bold);
-.include-font('merriweather'; 'merriweather_ultrabold-webfont'; 800);
-.include-font('merriweather'; 'merriweather-lightitalic-webfont'; 200; italic);
-.include-font('merriweather'; 'merriweather-bolditalic-webfont'; bold; italic);
-.include-font('merriweather'; 'merriweather-heavyitalic-webfont'; 800; italic);
-.include-font('merriweather'; 'merriweather-italic-webfont'; normal; italic);
-
diff --git a/awx/ui/client/legacy/styles/forms.less b/awx/ui/client/legacy/styles/forms.less
deleted file mode 100644
index ccfc95f412..0000000000
--- a/awx/ui/client/legacy/styles/forms.less
+++ /dev/null
@@ -1,815 +0,0 @@
-/*********************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * Forms.less
- *
- * custom styles for generated forms
- *
- */
-
-.noselect {
- -webkit-touch-callout: none; /* iOS Safari */
- -webkit-user-select: none; /* Chrome/Safari/Opera */
- -khtml-user-select: none; /* Konqueror */
- -moz-user-select: none; /* Firefox */
- -ms-user-select: none; /* Internet Explorer/Edge */
- user-select: none; /* Non-prefixed version, currently
- not supported by any browser */
-}
-
-.Form {
- display:flex;
- flex-wrap:wrap;
- flex-direction: row;
-}
-
-.Form-header--fields {
- flex: 1 1 auto;
-}
-
-.Form-header-field {
- margin-left: 10px;
- flex: 1 1 auto;
-}
-
-.Form-header {
- display: flex;
-}
-
-.Form-title {
- flex: 0 1 auto;
- color: @list-header-txt;
- font-size: 14px;
- font-weight: bold;
- word-break: break-all;
- max-width: 90%;
- word-wrap: break-word;
- margin-bottom: 20px;
-}
-
-.Form-title--uppercase {
- text-transform: uppercase;
-}
-
-.Form-secondaryTitle {
- color: @default-icon;
- padding-bottom: 20px;
- min-height: 40px;
-}
-
-.Form-title--is_smartinventory,
-.Form-title--is_superuser,
-.Form-title--is_system_auditor,
-.Form-title--is_ldap_user,
-.Form-title--is_external_account,
-.Form-title--roleType {
- background-color: @default-list-header-bg;
- border-radius: 5px;
- color: @default-interface-txt;
- font-size: 10px;
- font-weight: 100;
- height:15px;
- margin-left: 10px;
- margin-top: 2.25px;
- padding: 0 10px;
- text-transform: uppercase;
-}
-
-.Form-title--last_login {
- border-radius: 5px;
- color: @default-interface-txt;
- font-size: 10px;
- font-weight: 100;
- height:15px;
- margin-left: 10px;
- margin-top: 2.25px;
- padding: 0 10px;
- text-transform: uppercase;
-}
-
-.Form-exitHolder {
- justify-content: flex-end;
- display:flex;
-}
-
-.Form-exit {
- cursor:pointer;
- padding:0px;
- border: none;
- height:20px;
- font-size: 20px;
- background-color:@default-bg;
- color:@d7grey;
- transition: color 0.2s;
- line-height:1;
-}
-
-.Form-exit:hover {
- color:@default-icon;
-}
-
-.Form-tabHolder {
- display: flex;
- min-height: 30px;
- flex-wrap:wrap;
-}
-
-.Form-tabHolder--licenseSelected {
- margin-bottom: -20px;
-}
-
-.Form-tabs {
- flex: 1 0 auto;
- display: flex;
-}
-
-.Form-tab {
- color: @btn-txt;
- background-color: @btn-bg;
- font-size: 12px;
- border: 1px solid @b7grey;
- height: 30px;
- border-radius: 5px;
- margin-right: 20px;
- margin-bottom: 20px;
- padding-left: 10px;
- padding-right: 10px;
- padding-bottom: 5px;
- padding-top: 5px;
- transition: background-color 0.2s;
- text-transform: uppercase;
- text-align: center;
- white-space: nowrap;
- .noselect;
-}
-
-.Form-tab--notitle {
- margin-bottom: 0px;
-}
-
-.Form-tab:hover {
- color: @btn-txt;
- background-color: @btn-bg-hov;
- cursor: pointer;
-}
-
-.Form-tab:active {
- color: @btn-txt-sel;
- background-color: @btn-bg-sel;
- cursor: pointer;
-}
-
-.Form-tab:focus {
- color: @btn-txt-sel;
-}
-
-.Form-tab.is-selected {
- color: @btn-txt-sel;
- background-color: @default-icon;
- border-color: @default-icon;
-}
-
-.Form-tab--disabled,
-.Form-button--disabled {
- opacity: 0.65;
- color: @btn-txt;
-}
-
-.Form-tab--disabled:hover,
-.Form-button--disabled:hover {
- color: @btn-txt;
- background-color: @btn-bg;
- cursor:not-allowed!important;
-}
-
-.Form-tabSection {
- display: none;
- width: 0%;
-}
-
-.Form-tabSection.is-selected {
- width: 100%;
- display: block;
-}
-
-.Form-tabActions {
- display: flex;
-}
-
-.Form-formGroup {
- flex: 1 0 auto;
- margin-bottom: 20px;
- width: 33%;
- max-width: 33%;
- padding-right: 30px;
-}
-
-.Form-formGroup--fullWidth {
- max-width: none !important;
- width: 100% !important;
- padding-right: 0px !important;
- margin-top: 10px;
-}
-
-.Form-formGroup--checkbox{
- display: flex;
- margin-top: 10px;
-}
-
-.Form-formGroup {
- input.form-control {
- background-color: @fcgrey;
- border-color: @b7grey;
- border-radius: 5px;
- height: auto;
- min-height: 30px;
- padding: 0 10px;
- }
-
- input.form-control[disabled], input.form-control[readonly], fieldset[disabled] input.form-control {
- border-color: @b7grey;
- background-color: @ebgrey;
- }
-}
-
-.Form-checkbox--subCheckbox {
- font-size: 10px;
- color: @default-stdout-txt;
- text-transform: uppercase;
- margin-top: 2px;
-
- input {
- margin-top: 2px;
- }
-}
-
-.Form-textUneditable {
- .Form-textInput {
- border: none;
- padding: 0;
- }
-}
-
-.Form-subForm {
- width: 100%;
- margin-bottom: 15px;
- display: flex;
- flex-wrap: wrap;
- flex-direction: row;
- justify-content: flex-start;
- position: relative;
-}
-
-.Form-subForm:before {
- content: '';
- left: -20px;
- position: absolute;
- width: 5px;
- background-color: @b7grey;
- height: 100%;
-}
-
-.Form-subForm--title {
- font-weight: bold;
- text-transform: uppercase;
- color: @default-interface-txt;
- font-size: small;
- width: 100%;
- float: left;
- margin-bottom: 10px;
-}
-
-.Form-textAreaLabel {
- width:100%;
- order: 1;
-}
-
-.Form-formGroup.Form-textAreaLabel {
- max-width: 100%;
-}
-
-.Form-textArea {
- border-radius: 5px;
- color: @field-input-text;
- background-color: @field-secondary-bg;
- width:100%!important;
-}
-
-.Form-textInput {
- height: 30px;
- background-color: @field-secondary-bg;
- border-radius: 5px;
- border:1px solid @field-border;
- color: @field-input-text;
-}
-
-.Form-textInput:active {
- border:1px solid @field-border-sel;
-}
-
-.Form-monospace {
- font-family: Menlo,Monaco,Consolas,"Courier New",monospace!important;
-}
-
-.Form-alertblock {
- margin: 0;
- font-size: 12px;
- width: 100%;
- padding: 20px;
- margin-bottom: 15px;
- border-radius: 4px;
- border: 1px solid @login-notice-border;
- background-color: @login-notice-bg;
- color: @login-notice-text;
-}
-
-.Button-primary--hollow {
- border: 1px solid @default-link;
- color: @default-link;
- background: @default-bg;
-}
-.Button-primary--hollow:hover {
- color: @default-link-hov;
- border: 1px solid @default-link-hov;
-}
-
-.ui-spinner {
- height: 30px;
- background-color: @fcgrey !important;
- border-radius: 5px;
- border:1px solid @field-border !important;
- color: @field-input-text;
- width:100%
-}
-
-.ui-spinner-input {
- color: @field-input-text;
- background-color: @fcgrey;
-}
-
-.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-inputButton {
- border-color: @d7grey;
- color: @default-data-txt;
-}
-
-.Form-numberInputButton {
- color: @default-icon!important;
- font-size: 14px;
- display: block;
-}
-
-.Form-dropDown {
- min-height: 30px !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;
- width: 30px!important;
- height: 28px!important;
-}
-
-.select2-container--disabled .select2-selection__arrow {
- background-color: @ebgrey !important;
-}
-
-.select2-results__option {
- color: @field-label !important;
- min-height: 33px;
-}
-
-.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: @default-white-button-bord !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-container--default.select2-container--open.select2-container--below .select2-selection--single {
- border-bottom-left-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
-}
-
-.select2-dropdown {
- border:1px solid @field-border;
- z-index: 1030;
-}
-
-.select2-container--open .select2-dropdown--below {
- margin-top: -1px;
- border-top: 1px solid @field-border;
-}
-
-.Form-dropDown:focus {
- outline: none!important;
-}
-
-.Form-dropDown--scmType {
- width: 100%;
-}
-
-.Form-browseButton, .Form-passwordButton {
- height: 30px;
- color: @default-interface-txt;
- text-transform: uppercase;
- line-height: 1.2;
- padding: 6px 12px;
- background-color: @default-bg;
- border:1px solid @b7grey;
-}
-
-.Form-passwordButton:hover {
- cursor: pointer;
- background-color: @f2grey;
- border: 1px solid @b7grey;
- 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: auto;
- 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;
- color: @default-interface-txt;
-}
-
-.Form-lookupButton:active,
-.Form-lookupButton:focus {
- border: 1px solid @field-border;
-}
-
-.CodeMirror {
- min-height: initial !important;
- max-height: initial !important;
- border-radius: 5px;
- font-style: normal;
- color: @field-input-text;
-}
-
-.CodeMirror-gutters {
- background-color:@code-mirror-gutter !important;
-}
-
-input[type='radio'] {
- -webkit-appearance:none;
- width:14px;
- height:14px;
- border:1px solid @radio-bg;
- border-radius:50%;
- outline:none;
- vertical-align: sub;
-}
-
-input[type='radio']:focus {
- outline:none;
-}
-
-input[type='radio']:hover {
- box-shadow:0 0 5px 0px @btn-bg-hov inset;
-}
-
-input[type='radio']:before {
- content:'';
- display:block;
- width:65%;
- height:60%;
- margin: 20% auto;
- border-radius:50%;
-}
-
-input[type='radio']:checked:before {
- background:@radio-bg;
- outline:none;
-}
-
-.Form-inputLabelContainer {
- width: 100%;
- display: block !important;
-}
-
-.Form-inputLabelContainer[for=variables],
-.Form-inputLabelContainer--codeMirror {
- width: auto;
- display: inline-block !important;
-}
-
-.Form-mixedInputGroup {
- display: flex;
- width: 100%;
-
- .form-control {
- flex-flow: row wrap;
- padding: 0 12px !important;
- }
-
- .input-group-btn {
- display: flex;
- width: auto;
- }
-}
-
-.FormToggle-container {
- margin: 0 0 0 10px;
- display: initial;
- padding-bottom: 5px;
-
- label {
- &:first-child {
- border-right: none;
- }
- &:last-child {
- border-left: none;
- }
- }
-
- input {
- visibility: hidden;
- position: absolute;
- }
-
- .btn.btn-xs {
- padding: 0px 10px;
- }
-}
-
-.Form-inputLabelContainer {
- width: 100%;
- display: block !important;
-}
-
-.Form-inputLabelContainer[for=variables] {
- width: 100%;
- display: inline-block !important;
-}
-
-.Form-inputLabel {
- text-transform: uppercase;
- color: @default-interface-txt;
- font-weight: normal;
- font-size: small;
- width: 100%;
- .noselect;
-}
-
-.Form-labelAction {
- text-transform: uppercase;
- font-weight: normal;
- font-size: 0.8em;
- padding-left:5px;
- float: right;
- margin-top: 3px;
- .noselect;
-}
-
-.Form-buttons {
- height: 30px;
- display: flex;
- justify-content: flex-end;
-
- button {
- margin-left: 20px;
- }
-
- .at-Tab {
- margin-left: 0px;
- }
-}
-
-.Form-button {
- margin-left: 4px;
-}
-
-.Form-buttonDefault {
- background-color: @default-bg;
- color: @default-interface-txt;
- border-color: @default-border;
-}
-
-.Form-saveButton, .Form-launchButton {
- background-color: @submit-button-bg;
- color: @submit-button-text;
- text-transform: uppercase;
- transition: background-color 0.2s;
- padding-left:15px;
- padding-right: 15px;
-}
-
-.Form-saveButton:disabled, .Form-launchButton:disabled {
- background-color: @submit-button-bg-dis;
-}
-
-.Form-saveButton--disabled {
- background-color: @submit-button-bg-dis;
- cursor: not-allowed;
-}
-
-.Form-saveButton:hover, .Form-launchButton:hover {
- background-color: @submit-button-bg-hov;
- color: @submit-button-text;
-}
-
-.Form-saveButton--disabled:hover {
- background-color: @submit-button-bg-dis;
-}
-
-.Form-cancelButton {
- background-color: @default-bg;
- color: @btn-txt;
- text-transform: uppercase;
- border-radius: 5px;
- border: 1px solid @field-border;
- transition: background-color 0.2s;
- padding-left:15px;
- padding-right: 15px;
-}
-
-.Form-cancelButton:hover {
- background-color: @btn-bg-hov;
- color: @btn-txt;
-}
-
-.Form-primaryButton {
- background-color: @default-link;
- color: @default-bg;
- text-transform: uppercase;
- padding-left:15px;
- padding-right: 15px;
- margin-right: 20px;
- min-height: 30px;
- margin-bottom: 20px;
-}
-
-.Form-buttons .Form-primaryButton {
- margin-right: 0;
-}
-
-.Form-primaryButton:hover {
- background-color: @default-link-hov;
- color: @default-bg;
-}
-
-.Form-primaryButton.Form-tab--disabled:hover,
-.Form-primaryButton.Form-button--disabled:hover {
- background-color: @default-link;
-}
-
-.Form-primaryButton--noMargin {
- margin-right: 0px;
-}
-
-.Form-formGroup--singleColumn {
- width: 100% !important;
- padding-right: 0px;
- max-width: 100% !important;
-}
-
-.Form-checkbox {
- float: right;
-}
-
-.Form-subCheckbox {
- margin-top: 5px;
- font-size: small;
- color: @default-interface-txt;
- .noselect;
-}
-
-.Form-textInput--variableHeight {
- height: inherit;
- min-height: 30px;
- max-height: 120px;
- overflow-y: auto;
-}
-
-.Form-variableHeightButtonGroup {
- display: flex;
- height: auto;
- width: 30px;
-}
-
-.Form-requiredAsterisk {
- color: @red;
-}
-
-@media only screen and (max-width: 650px) {
- .Form-formGroup {
- flex: 1 0 auto;
- margin-bottom: 25px;
- max-width: 100%;
- width: 100%;
- padding-right: 50px;
- }
-}
-
-@media (min-width: 651px) and (max-width: 900px) {
- .Form-formGroup {
- flex: 1 0 auto;
- margin-bottom: 25px;
- max-width: 50%;
- width: 50%;
- padding-right: 50px;
- }
-}
-
-.action_column {
- float: right;
-}
-
-.alert-info {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: 100px;
- border-radius: 5px;
- border: 1px solid @default-no-items-bord;
- background-color: @default-no-items-bord;
- color: @default-icon;
- text-transform: uppercase;
-}
-
-.alert-info--noTextTransform {
- text-transform: none;
-}
-
-.select2-results__option {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.select2-results__option:hover {
- overflow-wrap: break-word;
- white-space: normal;
-}
-
-::-webkit-input-placeholder { /* Chrome/Opera/Safari */
- color: @b7grey;
-}
-::-moz-placeholder { /* Firefox 19+ */
- color: @b7grey;
-}
-:-ms-input-placeholder { /* IE 10+ */
- color: @b7grey;
-}
-:-moz-placeholder { /* Firefox 18- */
- color: @b7grey;
-}
-
-.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control {
- border-color: @b7grey;
- background-color: @ebgrey;
-}
-
-.Form-checkbox {
- label {
- font-weight: 400;
- }
-}
diff --git a/awx/ui/client/legacy/styles/inventory-edit.less b/awx/ui/client/legacy/styles/inventory-edit.less
deleted file mode 100644
index b608f854c3..0000000000
--- a/awx/ui/client/legacy/styles/inventory-edit.less
+++ /dev/null
@@ -1,66 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * inventory-edit.less
- *
- * custom animation mixins for ansible-ui
- *
- */
-#inventory_edit {
- #breadcrumbs .nav-path {
- margin-bottom: 8px;
- }
- #hosts_table .actions{
- float: right;
- }
- #groups_table .actions{
- float:right;
- }
-}
-
-#group-copy-dialog,
-#host-copy-dialog {
- .highlight {
- font-size: 16px;
- font-weight: bold;
- color: red;
- padding-right: 5px;
- }
- .title {
- font-weight: bold;
- margin-bottom: 15px;
- }
- .well {
- padding-left: 8px;
- padding-right: 8px;
- padding-top: 8px;
- padding-bottom: 8px;
- }
- .page-row ul li a {
- font-size: 12px;
- }
- .page-row .col-lg-8 {
- width: 100%;
- }
- .page-row .col-md-8 {
- width: 100%;
- }
-}
-
-#copy-group-radio-container .form-group {
- margin-left: 20px;
- margin-bottom: 10px;
-}
-
-#copy-group-target-container .form-group {
- margin-top: 10px;
- margin-left: 20px;
- margin-bottom: 15px;
-}
-
-#group-list-container,
-#hosts-container {
- .page-row {
- margin-top: 5px;
- }
-}
diff --git a/awx/ui/client/legacy/styles/job-details.less b/awx/ui/client/legacy/styles/job-details.less
deleted file mode 100644
index 5d79971bfc..0000000000
--- a/awx/ui/client/legacy/styles/job-details.less
+++ /dev/null
@@ -1,567 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * job-details.less
- *
- * Styles for job details page
- *
- */
-
-
-@failed-hosts-color: @red;
-@successful-hosts-color: @green;
-@changed-hosts-color: @changed;
-@skipped-hosts-color: @skipped;
-@unreachable-hosts-color: @unreachable;
-
-
-#host-events-modal-dialog {
- overflow: hidden;
- i[class*='icon-job'] {
- font-size: 12px;
- vertical-align: middle;
- }
- #search-form {
- margin-left: 7px;
- }
- #host-events-search-name {
- width: 200px;
- padding-right: 15px;
- }
- #search-all-input-icons {
- position: absolute;
- right: 3px;
- top: 3px;
- a {
- color: #a9a9a9;
- }
- a:hover {
- color: @black;
- }
- }
- #status-field {
- margin-left: 15px;
- }
- #host-events-table {
- margin-top: 15px;
- }
- #host-events {
- height: 200px;
- overflow: scroll;
- tr:first-of-type {
- border-top-color: @white;
- td {
- border-top-color: @white;
- }
- }
- }
- #fixed-table-header {
- margin-bottom: 0;
- }
- #search-indicator {
- margin-left: 15px;
- }
-}
-
-@media (max-width: 768px) {
- #host-events-modal-dialog {
- #search-form-input-icons {
- position: absolute;
- top: 30px;
- left: 185px;
- }
- #status-field {
- margin-left: 0;
- }
- .form-group {
- margin-bottom: 15px;
- }
- }
-}
-
-#jobs-detail {
-
- #play-help {
- width: 1px;
- height: 1px;
- color: #fff;
- }
-
- .job_summary {
- .table {
- margin-bottom: 0;
- border: 1px solid @grey;
- background-color: @white;
- }
- .table>tbody>tr>td {
- border-top-color: @grey;
- padding-bottom: 0;
- }
- .table>thead>tr>th {
- border-bottom-color: @grey;
- padding-bottom: 0;
- height: 22px;
- }
- }
-
- .status-bar {
- height: 16px;
- overflow: hidden;
- border-radius: 4px;
- border: 1px solid @grey;
- margin-top: 2px;
- }
-
- .inner-bar {
- display: inline-block;
- overflow: hidden;
- height: 16px;
- text-align: center;
- font-size: 12px;
- font-weight: bold;
- line-height: normal;
- }
-
- .scroll-spinner {
- display: none;
- background-color: transparent;
- color:#000;
- float:right;
- margin-right: 5px;
- }
-
- #hostResultsMoreRows.scroll-spinner {
- padding-top: 0;
- position: relative;
- top: 12px;
- }
-
- #hostSummariesMoreRows.scroll-spinner {
- margin-right: 0;
- }
-
- .failed-hosts {
- background-color: @failed-hosts-color;
- }
- .failed-hosts-color {
- color: @failed-hosts-color;
- }
- .successful-hosts {
- background-color: @successful-hosts-color;
- }
- .successful-hosts-color {
- color: @successful-hosts-color;
- }
- .changed-hosts {
- background-color: @changed-hosts-color;
- }
- .changed-hosts-color {
- color: @changed-hosts-color;
- }
- .skipped-hosts, .no-matching-hosts {
- background-color: @skipped-hosts-color;
- }
- .unreachable-hosts {
- background-color: @unreachable-hosts-color;
- }
- .unreachable-hosts-color {
- color: @unreachable-hosts-color;
- }
-
- .job_well {
- padding: 8px;
- background-color: @white;
- border: 1px solid @grey;
- border-radius: 4px;
- /*-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);*/
- }
-
- #hide-summary-button {
- text-align: right;
- margin-bottom: 15px;
- }
-
- .section {
- margin-bottom: 20px;
- h5 {
- margin-top: 0;
- margin-bottom: 12px;
- font-weight: bold;
- }
- }
-
- .section:last-child {
- margin-bottom: 0;
- }
-
-
- #job_options {
- height: 100px;
- overflow-y: auto;
- overflow-x: none;
- }
-
- #job_plays, #job_tasks {
- overflow-y: auto;
- overflow-x: none;
- }
-
- #breadcrumb-container {
- padding-right: 15px;
- .nav-path {
- margin-bottom: 15px;
- }
- }
-
- #job-detail-container {
-
- .well {
- overflow: hidden;
- }
-
- #job-status-form {
- label {
- font-weight: bold;
- }
- .control-label {
- padding-top: 0;
- padding-right: 0;
- text-align: left;
- }
- .form-group {
- margin-bottom: 15px;
- }
- hr {
- margin-top: 0;
- }
- .more-or-less {
- font-size: 12px;
- text-align: left;
- margin-bottom: 15px;
- }
- #started-time,
- #finished-time,
- #elapsed-time {
- display: inline-block;
- }
- #finished-time,
- #elapsed-time {
- padding-left: 15px;
- }
- }
-
- }
-
- #job-summary-container {
- position: absolute;
- top: 0;
- right: 0;
- padding-right: 15px;
- padding-left: 7px;
- width: 41.66666667%;
- }
-
- .table-header {
- font-weight: bold;
- font-size: 12px;
- .table>thead>tr>th {
- border-bottom-color: @white;
- }
- .table {
- margin-bottom: 0;
- }
- }
-
- .table-detail {
- overflow-x: hidden;
- overflow-y: auto;
- background-color: @white;
- min-height: 40px;
-
- .row {
- border-top: 1px solid @grey;
- }
- .row:first-child {
- border: none;
- }
- .loading-info {
- padding-top: 5px;
- padding-left: 3px;
- }
- .table {
- margin-bottom: 0;
- }
- .table-condensed > tbody > tr > td {
- padding-top: 0;
- padding-bottom: 0;
- }
- }
-
- .status-column i {
- font-size: 12px;
- }
-
- #plays-table-header table,
- #plays-table-detail table,
- #tasks-table-detail table,
- #tasks-table-header table,
- #tasks-table-detail table {
- table-layout:fixed;
- }
-
- #plays-table-detail td,
- #plays-table-header td,
- #tasks-table-detail td,
- #tasks-table-header td {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- #play-section {
- .table-detail {
- min-height: 40px;
- }
- }
-
- .title {
- font-size: 14px;
- font-weight: 600;
- }
-
- .header {
- width: 100%;
- height: 28px;
- padding-bottom: 5px;
-
-
- .search-field {
- display: inline-block;
- position: relative;
- float: right;
- input {
- width: 250px;
- padding-right: 20px;
- }
- a {
- position: absolute;
- right: 3px;
- top: 3px;
- color: #a9a9a9;
- }
- a:hover {
- color: @black;
- }
- }
- }
-
- #summary-search-section {
- .remove-left-padding {
- padding-left: 0;
- }
- label {
- text-align: left;
- font-weight: normal;
- padding-left: 0;
- padding-right: 0;
- padding-top: 6px;
- }
- #search_all_hosts_name {
- width: 100%;
- padding-left: 3px;
- padding-right: 20px;
- }
- }
-
- #event-help-link {
- margin-left: 3px;
- font-size: 14px;
- }
-
- .title-row {
- margin-bottom: 15px;
- margin-top: 20px;
- }
-
- .search-form {
- font-size: 12px;
- .form-control {
- font-size: 12px;
- }
- .form-group:nth-of-type(2) {
- margin-left: 10px;
- }
- }
-
- .search-name {
- .input-xs {
- height: 25px;
- }
- }
-
- #search-all-input-icons {
- position: absolute;
- right: 3px;
- top: 3px;
- a {
- color: #a9a9a9;
- }
- a:hover {
- color: @black;
- }
- }
-
- label.small-label {
- font-size: 12px;
- }
-
- #task-hosts-section {
- position: relative;
- top: 0;
- left: 0;
- #hosts-table-header table {
- table-layout: fixed;
- }
- #hosts-table-detail {
- background-color: @white;
- }
- #hosts-table-detail table {
- table-layout: fixed;
- }
- #hosts-table-detail td {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- }
-
- #hosts-summary-section {
- .col-lg-4, .col-md-4, .col-sm-4, .col-xs-4 {
- width: 33%;
- }
- .col-lg-2, .col-md-2, .col-sm-2, .col-xs-2 {
- width: 16.5%;
- }
- .table-header {
- font-size: 12px;
- }
- .table-detail {
- height: 200px;
- }
- .name {
- word-break: break-all;
- }
- .badge {
- font-size: 12px;
- }
- .badge-column a {
- width: 20%;
- }
- }
-
- // .legend-row {
- // margin-bottom: 15px;
- // }
-
- // .legend {
- // display: inline-block;
- // font-size: 12px;
- // text-align: center;
- // i {
- // font-size: 10px;
- // margin-left: 5px;
- // }
- // i:first-child {
- // margin-left: 0;
- // }
- // }
-
- #graph-section {
- position: relative;
- .legend {
- font-size: 12px;
- font-family: 'Open Sans';
- }
- rect {
- stroke-width: 2;
- }
- .donut-tooltip {
- display: none;
- font-size: 12px;
- font-family: 'Open Sans';
- left: 280px;
- padding: 10px;
- position: absolute;
- text-align: center;
- top: 85px;
- width: 100px;
- z-index: 10;
- color: white;
- background-color: black !important;
- border-radius:4px;
- border: 1px solid black;
- }
- }
-
- #graph-section svg{
- margin: 0 auto;
- }
-
- path.slice{
- stroke-width:2px;
- }
-
- polyline{
- opacity: .3;
- stroke: black;
- stroke-width: 2px;
- fill: none;
- }
-
- svg text.percent{
- fill:@black;
- text-anchor:middle;
- font-size:12px;
- font-weight: bold;
- }
-
- #pre-formatted-variables {
- border-radius: 4px;
- border: 1px solid @grey;
- overflow: auto;
- white-space: pre;
- word-break: break-all;
- word-wrap: break-word;
- padding: 9.5px;
- font-family: Fixed, monospace;
- max-height: 200px;
- }
-
- .footer-row {
- height: 20px;
- }
-
- .host_summary_row {
- margin-top: 15px;
- margin-bottom: -15px;
- margin-left: 0;
- }
-
- @media (max-width: 767px) {
- #job-detail-container {
- #job-status-form {
- #finished-time,
- #elapsed-time {
- display: block;
- }
- #finished-time,
- #elapsed-time {
- padding-left: 0;
- margin-left: 0;
- padding-top: 15px;
- }
- }
- }
- }
-}
diff --git a/awx/ui/client/legacy/styles/jobs.less b/awx/ui/client/legacy/styles/jobs.less
deleted file mode 100644
index 887a979d5a..0000000000
--- a/awx/ui/client/legacy/styles/jobs.less
+++ /dev/null
@@ -1,99 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * jobs.less
- *
- * custom styles for the jobs pages
- *
- */
-
-#jobs-page {
-
- .jobs-list-container {
- border: 1px solid @grey;
- border-radius: 4px;
- padding: 5px;
- }
-
- .job-list {
-
- i[class*="icon-job-"] {
- font-size: 13px;
- }
- }
-
- #completed_jobs_table i[class*="icon-job-"] {
- font-size: 13px;
- }
-
- #completed_jobs_table,
- #schedules_table,
- #running_jobs_table,
- #queued_jobs_table {
- table-layout:fixed;
- }
- #completed_jobs_table .name-column,
- #schedules_table .name-column,
- #running_jobs_table .name-column,
- #queued_jobs_table .name-column,
- {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .title {
- font-weight: bold;
- margin-top: 5px;
- margin-left: 3px;
- }
-
- #breadcrumbs .nav-path {
- background-color: @white;
- }
-
- #breadcrumb-list.breadcrumb {
- background-color: @white;
- }
-
- .List-noItems {
- margin-top: 0;
- }
-
-}
-
-@media (min-width: 1201px) {
- #jobs-page {
- .left-side {
- padding-right: 7px;
- }
-
- .right-side {
- padding-left: 7px;
- }
-
- .bottom-row {
- margin-top: 15px;
- }
- }
-}
-
-@media (max-width: 1200px) {
- #jobs-page .jobs-list-container {
- margin-top: 15px;
- }
- #jobs .jobs-list-container.completed {
- margin-top: 0;
- }
- .title{
- margin-bottom: 8px;
- }
- #jobs-page {
- .left-side {
- padding-right: 15px;
- }
- .right-side {
- padding-left: 15px;
- }
- }
-}
diff --git a/awx/ui/client/legacy/styles/jquery-ui-overrides.less b/awx/ui/client/legacy/styles/jquery-ui-overrides.less
deleted file mode 100644
index 8656b3693f..0000000000
--- a/awx/ui/client/legacy/styles/jquery-ui-overrides.less
+++ /dev/null
@@ -1,227 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * jquery-ui-overrides.less
- *
- * Additions to the custom-theme to make things
- * look closer to Twitter Bootstrap
- *
- */
-table.ui-datepicker-calendar {
- background-color: @well;
-}
-
-/* Modal dialog */
-.ui-dialog-title {
- font-size: 15px;
- color: @default-interface-txt;
- font-weight: bold;
- line-height: normal;
- font-family: 'Open Sans', helvetica;
- text-transform: uppercase;
-}
-.ui-dialog {
- .close {
- font-size: 18px;
- font-weight: bold;
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
- line-height: 1;
- opacity: 1;
- text-shadow: 0 1px 0 @white;
- color:@d7grey;
- }
- .close:hover{
- color:@default-icon;
- }
- .ui-widget {
- font-family: 'Open Sans', sans-serif;
- }
- .ui-widget-header {
- border-radius: 0;
- border: none;
- }
- .ui-dialog-titlebar {
- padding-bottom: 0;
- padding-top: 12px;
-
- button.close i {
- font-size: 24px;
- }
- }
- .ui-dialog-titlebar .ui-state-default {
- background-image: none;
- background-color: @white;
- border-color: @white;
- color: #A9A9A9;
- }
- .mono-space {
- font-family: Fixed, monospace;
- }
- textarea.resizable {
- resize: vertical;
- }
- .ui-resizable-se {
- right: 5px;
- bottom: 5px;
- background-position: -80px -224px;
- color: @black;
- }
-
- button.btn.btn-primary,
- button.btn.btn-default {
- padding: 5px 15px;
- font-size: 12px;
- line-height: 1.5;
- transition: background-color 0.2s;
- font-size: 12px;
- }
-
- button.btn.btn-primary {
- text-transform: uppercase;
- background-color: @default-succ;
- border-color: @default-succ;
-
- &:hover {
- background-color: @default-succ-hov;
- border-color: @default-succ-hov;
- }
-
- &:disabled {
- background-color: @default-succ-disabled;
- border-color: @default-succ-disabled;
- }
- }
-
- button.btn.btn-default {
- text-transform: uppercase;
- border-color: @b7grey;
- color: @default-interface-txt;
- }
-
- .ui-dialog-buttonpane.ui-widget-content {
- border: none;
- margin: 0;
- padding-top: 0;
- padding-right: 8px;
- }
-
- .input-group-btn.dropdown, .List-pagination, .List-tableHeader {
- font-family: 'Open Sans', sans-serif;
- }
-
-}
-.ui-dialog-buttonpane > .ui-dialog-buttonset {
- button {
- margin-left: 20px;
- }
-}
-
-.ui-dialog-buttonset {
- text-transform: uppercase;
-
- button.btn.btn-default.ui-state-hover,
- button.btn.btn-default.ui-state-active,
- button.btn.btn-default.ui-state-focus {
- font-weight: normal;
- }
- button.btn.btn-primary.ui-state-hover,
- button.btn.btn-primary.ui-state-active,
- button.btn.btn-primary.ui-state-focus {
- background-image: none;
- color: @white;
- background-color: @blue-dark;
- border-color: #285e8e;
- text-decoration: none;
- font-weight: normal;
- }
- max-height: 48px;
-}
-
-.ui-widget-overlay.ui-front {
- background-image: none;
- background-color: #000;
- opacity: .6;
-}
-
-.ui-dialog-content.ui-widget-content {
- padding-top: 20px;
-}
-
-.ui-widget-content {
- background-image: none;
- background-color: @default-bg;
-
- a,
- a:visited,
- a:active {
- color: @blue-link;
- text-decoration: none;
- }
-
- a:hover,
- a:focus {
- color: @blue-dark;
- text-decoration: none;
- }
-
- .red-txt,
- a.red-txt:visited,
- a.red-txt:hover,
- a.red-txt:active {
- color: @red;
- }
-
- .dropdown-menu>li>a {
- color: @default-interface-txt;
- }
-
- .pagination .active {
- a, a:visited, a:active {
- color: @white;
- }
- }
-}
-
-.ui-state-default {
- background-image: none;
- background-color: @white;
- border: 1px solid @grey;
-}
-
-.ui-accordion-header-active {
- background-color: #E8E8E8;
-}
-
-/*.ui-state-active {
- background-image: none;
- background-color: #f5f5f5;
-}*/
-
-.ui-widget-content {
- border: 1px solid @grey;
-}
-
-.ui-spinner a.ui-spinner-button {
- border-left: 1px solid #A6C9E2;
-}
-
-.ui-front {
- z-index: 1100;
-}
-
-.ui-accordion .ui-accordion-header {
- margin-top: 1px;
-}
-
-.ui-spinner.ui-state-disabled,
-.ui-state-disabled .ui-spinner-button {
- cursor: not-allowed !important;
-}
-
-.ui-state-disabled .ui-spinner-button:hover {
- background-color: @default-bg !important;
-}
-
-.ui-state-disabled.ui-widget-content {
- background-color: @ebgrey !important;
-}
diff --git a/awx/ui/client/legacy/styles/lists.less b/awx/ui/client/legacy/styles/lists.less
deleted file mode 100644
index 6a4922fd2b..0000000000
--- a/awx/ui/client/legacy/styles/lists.less
+++ /dev/null
@@ -1,644 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * lists.less
- *
- * custom styles for generated lists
- *
- */
-
-table, tbody {
- border-collapse: collapse;
-}
-
-.List-well {
- margin-top: 20px;
-}
-
-.List-table{
- width: 100%;
- margin-top: 20px;
- table-layout: fixed;
-}
-
-.List-tableHeader{
- height: 34px;
- font-size: 14px;
- font-weight: normal;
- text-transform: uppercase;
- color: @list-header-txt;
- padding-left: 15px;
- padding-right: 15px;
- border-bottom-width:0px!important;
- align-items: center;
- display: flex;
-}
-
-.List-tableHeader--info, .List-tableHeader--actions {
- justify-content: flex-end;
-}
-
-.List-tableHeader:not([ng-click]) {
- cursor: default !important;
-}
-
-.List-tableHeaderSort {
- color: @list-header-icon;
-}
-
-.List-tableRow {
- min-height: 44px;
- font-size: 14px;
- color: @list-item;
- border-bottom: 1px solid @default-border;
-}
-
-.List-tableRow:last-of-type {
- border-bottom: none;
-}
-
-.List-tableRow:hover {
- background-color: @f2grey;
-}
-
-.List-tableRow--selected {
- background-color: @list-row-select-bord;
-}
-
-.List-tableRow--disabled {
- .List-tableCell, .List-tableCell * {
- color: @b7grey;
- cursor: not-allowed;
- }
-}
-
-.List-tableRow--disabled {
- .List-actionButton:hover {
- color: @list-action-icon;
- background-color: @list-actn-bg !important;
- }
-}
-
-.List-tableRow--disabled {
- .List-actionButtonCell * {
- color: @default-err;
- font-size: 11px;
- text-transform: uppercase;
- }
-}
-
-.List-tableRow--invalid {
- height: 40px;
-}
-
-.List-tableRow--invalidBar {
- align-items: center;
- border-left: solid @at-space-2x @at-color-error;
- color: @at-white;
- display: flex;
- height: 100%;
- justify-content: center;
- position: relative;
-
- i {
- position: absolute;
- left: -7px;
- }
-}
-
-.List-tableCell {
- padding: 7px 15px;
- border-top:0px!important;
- word-break: break-word;
- display: flex;
- align-items: center;
- height: 100%;
-}
-
-.List-tableCell.description-column {
- padding-top: 15px;
- padding-bottom: 15px;
-}
-
-.List-actionButtonCell {
- padding-top:5px;
- padding-right: 0px;
- display:flex;
- justify-content: flex-end;
-}
-
-.List-actionButton {
- font-size: 16px;
- height: 30px;
- min-width: 30px;
- color: @list-action-icon;
- background-color: @list-actn-bg;
- border: none;
- border-radius: 4px;
- margin-left: 15px;
-}
-
-.List-actionButton:hover {
- background-color: @list-actn-bg-hov !important;
- color: @list-actn-icn-hov;
-}
-
-.List-actionButton + .btn-disabled {
- &:hover {
- color: @default-icon-hov;
- background-color: @list-actn-bg !important;
- }
- color: @default-icon-hov;
-}
-
-.List-actionButton--delete:hover {
- background-color: @list-actn-del-bg-hov !important;
-}
-
-.List-header {
- display: flex;
-}
-
-.List-title {
- align-items: center;
- flex: 1 0 auto;
- display: flex;
-}
-
-.List-titleBadge {
- font-size: 11px;
- font-weight: normal;
- padding: 2px 10px;
- height: 14px;
- line-height: 10px;
- margin: 0;
- background-color: @list-title-badge;
- border-radius: 5px;
- color: @at-white;
-}
-
-.List-titleBadge--selected {
- background-color: @default-link;
-}
-
-.List-titleText {
- color: @list-title-txt;
- font-size: 14px;
- font-weight: bold;
- margin-right: 10px;
- line-height: 0.8;
- text-transform: uppercase;
-}
-
-.List-exitHolder {
- justify-content: flex-end;
- display:flex;
-}
-
-.List-exit {
- cursor:pointer;
- padding:0px;
- border: none;
- height:20px;
- font-size: 20px;
- background-color:@default-bg;
- color:@d7grey;
- transition: color 0.2s;
- line-height:1;
-}
-
-.List-exit:hover{
- color:@default-icon;
-}
-
-.List-actionHolder {
- justify-content: flex-end;
- display: flex;
- // margin-bottom: 20px;
- // float: right;
-}
-
-@media screen and (max-width: 1200px) {
- .List-actionHolder--rootGroups {
- justify-content: flex-start;
- margin-bottom: 55px;
- }
-}
-
-.List-actionHolder--leftAlign {
- margin-left: 50%;
- justify-content: flex-start;
- button {
- height: 34px;
- }
-}
-
-.List-actions {
- align-items: center;
- display: flex;
- margin-bottom: -34px;
-
- .List-buttonDefault {
- margin-left: 20px;
- }
-
- .List-toggleButton {
- height: 30px;
- line-height: 14px;
- }
-}
-
-.List-auxAction {
- align-items: center;
- display: flex;
- order: 1;
- margin-left: 20px;
-}
-
-.List-auxActionStream {
- width: 200px;
-}
-
-.List-buttonSubmit {
- background-color: @submit-button-bg;
- color: @submit-button-text;
-}
-
-.List-buttonSubmit:hover,
-.List-buttonSubmit:focus {
- color: @submit-button-text;
- background-color: @submit-button-bg-hov;
-}
-
-.List-buttonDefault {
- background-color: @btn-bg;
- color: @btn-txt;
- border-color: @b7grey;
- height: 30px;
- line-height: 14px;
-}
-
-.List-buttonDefault:hover,
-.List-buttonDefault:focus {
- background-color: @btn-bg-hov;
- color: @btn-txt;
-}
-
-.List-buttonDefault[disabled] {
- opacity: 0.65;
-}
-
-.List-actionButton {
- margin-left: 20px;
-}
-
-.List-searchDropdown {
- border-top-left-radius: 5px!important;
- border-bottom-left-radius: 5px!important;
- height: 34px!important;
- border-color: @d7grey;
- 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 {
- background-color: @list-srch-inpt-bg!important;
- font-size: 14px!important;
- color: @list-srch-inpt-txt!important;
- border-color: @list-srch-inpt-bord!important;
- border-radius: 0px 5px 5px 0px!important;
- padding-left: 15px!important;
- height: 34px!important;
- padding-right: 45px!important;
- font-family: 'Open Sans', sans-serif;
-}
-
-.List-searchInput:placeholder-shown {
- color: @list-srch-inpt-ph-txt!important;
- text-transform: uppercase;
-}
-
-.List-searchInput:focus {
- border-color: @list-srch-inpt-focus!important;
-}
-
-.List-searchInputIcon {
- height: 32px;
- width: 32px;
- border-left: 1px solid @list-srch-inpt-bord;
- color: @list-srch-btn-icon!important;
- float: right;
- position: relative;
- top: -33px;
- left: -2px;
- z-index: 10;
- font-size: 16px;
- background-color: @list-srch-btn-bg;
- display: flex;
- align-items: center;
- justify-content: center;
- border-top-right-radius: 5px;
- border-bottom-right-radius: 5px;
-}
-
-.List-searchInputIcon:hover {
- cursor: pointer;
- background-color: @list-srch-btn-hov-bg;
- color: @list-srch-btn-icon;
-}
-
-.List-searchNoResults {
- color: @default-interface-txt;
- margin-top: 20px;
-}
-
-.List-noItems {
- margin-top: 52px;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: 200px;
- border-radius: 5px;
- border: 1px solid @d7grey;
- background-color: @default-no-items-bord;
- color: @list-no-items-txt;
- text-transform: uppercase;
- text-align: center;
- padding: 10px;
-}
-
-.modal-body > .List-noItems {
- margin-top: 0px;
-}
-
-.modal-body > .List-emptyHostFilter {
- margin-top: 20px;
-}
-
-.List-actionButton--selected,
-.List-editButton--selected {
- background-color: @list-actn-bg-hov !important;
- color: @list-actn-icn-hov;
-}
-
-.List-searchWidget {
- height: 34px;
-}
-
-.List-searchWidget--compact {
- max-width: ~"calc(100% - 91px)";
- margin-top: 10px;
-}
-
-.List-searchRow {
- margin-bottom: 20px;
-}
-
-.List-staticColumn--smallStatus {
- width: 25px;
- padding-right: 0px!important;
-}
-
-.List-staticColumn--mediumStatus {
- width: 53px;
- padding-right: 0px!important;
-}
-
-.List-staticColumn--toggle {
- width: 55px;
- padding-right: 0px !important;
-}
-
-.List-staticColumn--schedulerTime {
- max-width: 164px;
-}
-
-.List-staticColumn--invalidBar {
- width: 10px;
- padding-right: 0px!important;
-}
-
-.List-staticColumnAdjacent {
- padding-left: 10px!important;
-}
-
-.List-staticColumnAdjacent--monospace {
- font-family: monospace;
-}
-
-.List-titleLockup {
- margin-left: 4px;
- margin-right: 6px;
- display: inline-block;
- margin-top: 0px;
- padding-bottom: 2px;
- vertical-align: bottom;
-}
-
-.List-titleLockup:before {
- content: "\007C";
- color: #d7d7d7;
- display: block;
- font-size: 13px;
-}
-
-.List-action--showTooltipOnDisabled {
- display: inline-block;
- cursor: not-allowed;
-}
-
-.List-action--showTooltipOnDisabled .btn[disabled] {
- pointer-events: none;
-}
-
-.List-action--showTooltipOnDisabled.disabled {
- cursor: not-allowed;
-}
-
-.List-action--notificationAdd {
- text-align: right;
- font-size: 11px;
-}
-
-.List-dropdownSuccess {
- background-color: @submit-button-bg;
- color: @submit-button-text;
- border-color: @submit-button-bg-hov;
-}
-
-.List-dropdownSuccess:hover,
-.List-dropdownSuccess:focus {
- color: @submit-button-text;
- background-color: @submit-button-bg-hov;
-}
-
-.List-infoCell {
- display: flex;
- justify-content: flex-end;
- font-size: 0.8em;
- cursor: pointer;
-
- .popover-content {
- dl {
- display: flex;
- margin: 0;
- }
- dt, dd {
- flex: 1 1 50%;
- font-weight: inherit;
- margin: 0;
- }
- }
-}
-
-.List-actionsInner {
- display: flex;
-}
-
-@media (max-width: 991px) {
- .List-searchWidget + .List-searchWidget {
- margin-top: 20px;
- }
-}
-
-@media (max-width: 700px) {
- .List-header {
- flex-direction: column;
- align-items: stretch;
- }
- .List-actionHolder {
- justify-content: flex-start;
- align-items: center;
- flex: 1 0 auto;
- margin-top: 12px;
- }
- .List-actions {
- margin-bottom: 20px;
- }
- .List-well {
- margin-top: 20px;
- }
-
- .List-action {
- margin-left: 20px;
- }
-
- .List-actionsInner {
- margin-left: -20px;
- }
-}
-
-.InventoryManage-container, .modal-body {
- .List-header {
- flex-direction: column;
- align-items: stretch;
- }
- .List-actionHolder {
- justify-content: flex-start;
- align-items: center;
- flex: 1 0 auto;
- margin-top: 12px;
- }
- .List-actions {
- margin-bottom: 20px;
- }
- .List-well {
- margin-top: 20px;
- }
- .List-action:not(.ng-hide) ~ .List-action:not(.ng-hide) {
- margin-left: 0;
- }
-}
-
-// Inventory Manage exceptions
-.InventoryManage-container {
- .List-actionHolder {
- justify-content: flex-end;
- }
- .List-actions {
- margin: 0 0 -34px 0;
- }
- .SmartSearch-searchTermContainer {
- width: 100%;
- }
-}
-
-.List-defaultLayout {
- display: grid;
- grid-template-columns: 5px auto;
-}
-
-.List-lookupLayout {
- display: grid;
- grid-template-columns: 26px auto;
-}
-
-.List-staticColumnLayout--statusOrCheckbox {
- display: grid;
- grid-template-columns: 5px 25px auto;
-}
-
-.List-staticColumnLayout--groups {
- display: grid;
- grid-template-columns: @at-space @at-space-5x auto;
-}
-
-.List-staticColumnLayout--hostNestedGroups {
- display: grid;
- grid-template-columns: @at-space @at-space-5x @at-space-5x auto;
-}
-
-.List-staticColumnLayout--hosts {
- display: grid;
- grid-template-columns: 5px 55px 25px auto;
-}
-
-.List-staticColumnLayout--hostsWithCheckbox {
- display: grid;
- grid-template-columns: 5px 25px 55px 25px auto;
-}
-
-.List-staticColumnLayout--schedules {
- display: grid;
- grid-template-columns: 5px 15px 55px auto;
-}
-
-.List-staticColumnLayout--toggleOnOff {
- display: grid;
- grid-template-columns: 5px 55px auto;
-}
-
-.List-table {
- margin-top: 20px;
-}
-
-.List-tableHeaderRow {
- background-color: @list-header-bg;
- border-top-left-radius: 5px;
- border-top-right-radius: 5px;
-}
-
-.List-centerEnd {
- display: flex;
- align-items: center;
- justify-content: flex-end;
-}
diff --git a/awx/ui/client/legacy/styles/log-viewer.less b/awx/ui/client/legacy/styles/log-viewer.less
deleted file mode 100644
index 0690205d9a..0000000000
--- a/awx/ui/client/legacy/styles/log-viewer.less
+++ /dev/null
@@ -1,29 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * log-viewer.css
- *
- * custom styles for LogViewer.js helper
- *
- */
-
-#logviewer-modal-dialog {
-
- textarea {
- overflow: scroll;
- }
- pre {
- overflow: scroll;
- word-wrap: normal;
- word-break: normal;
- white-space: pre-wrap;
- }
-}
-
-table.logviewer-status {
- margin-top: 20px;
-
- .fld-label {
- font-weight: bold;
- }
-}
diff --git a/awx/ui/client/legacy/styles/stdout.less b/awx/ui/client/legacy/styles/stdout.less
deleted file mode 100644
index 061e90383a..0000000000
--- a/awx/ui/client/legacy/styles/stdout.less
+++ /dev/null
@@ -1,70 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * Styles for job stdout
- *
- */
-
- #jobs-stdout {
- margin-bottom: 0px;
-
- #job-status {
- label {
- margin-right: 15px;
- }
- margin-bottom: 15px;
- }
-
- .scroll-spinner {
- display: none;
- background-color: transparent;
- color:#000;
- }
- #stdoutMoreRowsTop {
- position: absolute;
- top: 10px;
- right: 20px;
- }
- #stdoutMoreRowsBottom {
- float: right;
- padding-right: 15px;
- }
- #pre-container {
- overflow-x: scroll;
- overflow-y: auto;
- padding: 10px;
- }
-
- }
-
-.ansi_fore { color: #AAAAAA; }
-.ansi_back { background-color: @black; }
-.ansi1 { font-weight: bold; }
-.ansi3 { font-weight: italic; }
-.ansi4 { text-decoration: underline; }
-.ansi9 { text-decoration: line-through; }
-.ansi30 { color: @default-data-txt; }
-.ansi31 { color: @default-err; }
-.ansi1.ansi31 {
- color: @default-unreachable;
-}
-.ansi32 { color: @default-succ; }
-.ansi33 { color: @default-warning; }
-.ansi34 { color: @default-link; }
-.ansi35 { color: @default-magenta; }
-.ansi36 { color: @default-cyan; }
-.ansi37 { color: @default-bg; }
-.ansi40 { background-color: @default-stdout-txt; }
-.ansi41 { background-color: @default-err; }
-.ansi42 { background-color: @default-succ; }
-.ansi43 { background-color: @default-warning; }
-.ansi44 { background-color: @default-link; }
-.ansi45 { background-color: @default-magenta; }
-.ansi46 { background-color: @default-cyan; }
-.ansi47 { background-color: @default-bg; }
-
-#pre-container-content > span {
- display: inline-block;
- white-space: pre-wrap;
- word-wrap: normal;
-}
diff --git a/awx/ui/client/legacy/styles/survey-maker.less b/awx/ui/client/legacy/styles/survey-maker.less
deleted file mode 100644
index 176ee7694f..0000000000
--- a/awx/ui/client/legacy/styles/survey-maker.less
+++ /dev/null
@@ -1,92 +0,0 @@
-/*********************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * survey-maker.css
- *
- * custom styles for the survey maker
- *
- */
-
-
-/**
-* #survey_maker_question_area{
-* border: 1px solid;
-* border-color: rgb(204,204,204);
-* border-radius: 4px;
-* padding: 15px;
-* }
-*/
-
-.question_form{
- border: 1px solid;
- border-color: rgb(204,204,204);
- border-radius: 4px;
- padding: 5px;
- margin-bottom: 15px;
- height: 500px;
-}
-
-.survey_maker_question{
- border: 1px solid;
- border-color: rgb(204,204,204);
- border-radius: 4px;
- margin-bottom: 10px;
-}
-
-.question_final{
- border-top: 1px dashed;
- border-color: rgb(204,204,204);
- border-radius: 4px;
- padding: 5px;
- position: relative;
-
- .survey-maker-password{
- margin-left: 30px;
- }
-
- .final{
- margin-left: 15px;
- margin-top: 5px;
- }
- .question_title{
- opacity: 0.7;
- }
- .description{
- opacity: 0.7;
- margin-left: 15px;
- }
- .input_area{
- opacity: 0.7;
- }
- .mc{
- margin-left: 18px;
- margin-right: 7px;
- }
-
-}
-
-.question_actions{
- opacity: 1.0;
-}
-
-#new_question{
- margin-top: 5px;
-}
-
-#add_question_btn{
- margin-top: 15px;
- margin-bottom: 15px;
-}
-
-
-.survey_taker_input{
-
- .mc{
- margin-left: 18px;
- margin-right: 7px;
- }
-}
-
-.survey_taker_description{
- margin-bottom:10px
-}
diff --git a/awx/ui/client/legacy/styles/text-label.less b/awx/ui/client/legacy/styles/text-label.less
deleted file mode 100644
index eca6e83cf4..0000000000
--- a/awx/ui/client/legacy/styles/text-label.less
+++ /dev/null
@@ -1,15 +0,0 @@
-.host-disabled-label {
- &:after {
- display: inline-block;
- content: "disabled";
- border-radius: 3px;
- color: @default-icon;
- text-transform: uppercase;
- font-size: .7em;
- font-style: normal;
- margin-left: 0.5em;
- padding: 0.35em;
- padding-bottom: 0.2em;
- line-height: 1.1;
- }
-}
diff --git a/awx/ui/client/lib/components/_index.less b/awx/ui/client/lib/components/_index.less
deleted file mode 100644
index ea4da9a9c9..0000000000
--- a/awx/ui/client/lib/components/_index.less
+++ /dev/null
@@ -1,19 +0,0 @@
-@import 'action/_index';
-@import 'approvalsDrawer/_index';
-@import 'dialog/_index';
-@import 'input/_index';
-@import 'launchTemplateButton/_index';
-@import 'layout/_index';
-@import 'list/_index';
-@import 'modal/_index';
-@import 'panel/_index';
-@import 'popover/_index';
-@import 'relaunchButton/_index';
-@import 'tabs/_index';
-@import 'tag/_index';
-@import 'toggle-tag/_index';
-@import 'truncate/_index';
-@import 'utility/_index';
-@import 'code-mirror/_index';
-@import 'cards/_index';
-@import 'switch/_index';
diff --git a/awx/ui/client/lib/components/action/_index.less b/awx/ui/client/lib/components/action/_index.less
deleted file mode 100644
index c5be9803a3..0000000000
--- a/awx/ui/client/lib/components/action/_index.less
+++ /dev/null
@@ -1,7 +0,0 @@
-.at-ActionGroup {
- margin-top: @at-margin-panel;
-
- button {
- margin-left: 15px;
- }
-}
diff --git a/awx/ui/client/lib/components/action/action-button.directive.js b/awx/ui/client/lib/components/action/action-button.directive.js
deleted file mode 100644
index 733faa6f97..0000000000
--- a/awx/ui/client/lib/components/action/action-button.directive.js
+++ /dev/null
@@ -1,48 +0,0 @@
-const templateUrl = require('~components/action/action-button.partial.html');
-
-function link (scope, element, attrs, controllers) {
- const [actionButtonController] = controllers;
-
- actionButtonController.init(scope);
-}
-
-function ActionButtonController () {
- const vm = this || {};
-
- vm.init = (scope) => {
- const { variant } = scope;
-
- if (variant === 'primary') {
- vm.color = 'success';
- vm.fill = '';
- }
-
- if (variant === 'secondary') {
- vm.color = 'info';
- vm.fill = '';
- }
-
- if (variant === 'tertiary') {
- vm.color = 'default';
- vm.fill = 'Hollow';
- }
- };
-}
-
-function atActionButton () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- templateUrl,
- require: ['atActionButton'],
- controller: ActionButtonController,
- controllerAs: 'vm',
- link,
- scope: {
- variant: '@',
- }
- };
-}
-
-export default atActionButton;
diff --git a/awx/ui/client/lib/components/action/action-button.partial.html b/awx/ui/client/lib/components/action/action-button.partial.html
deleted file mode 100644
index d9f9283351..0000000000
--- a/awx/ui/client/lib/components/action/action-button.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/awx/ui/client/lib/components/action/action-group.directive.js b/awx/ui/client/lib/components/action/action-group.directive.js
deleted file mode 100644
index 1974ab1d43..0000000000
--- a/awx/ui/client/lib/components/action/action-group.directive.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const templateUrl = require('~components/action/action-group.partial.html');
-
-function atActionGroup () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- col: '@',
- pos: '@'
- }
- };
-}
-
-export default atActionGroup;
diff --git a/awx/ui/client/lib/components/action/action-group.partial.html b/awx/ui/client/lib/components/action/action-group.partial.html
deleted file mode 100644
index e0df9581ac..0000000000
--- a/awx/ui/client/lib/components/action/action-group.partial.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/approvalsDrawer/_index.less b/awx/ui/client/lib/components/approvalsDrawer/_index.less
deleted file mode 100644
index a2c58c854a..0000000000
--- a/awx/ui/client/lib/components/approvalsDrawer/_index.less
+++ /dev/null
@@ -1,68 +0,0 @@
-.at-ApprovalsDrawer {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- // z-index of the nav header is 1040
- z-index: 1041;
- background-color: rgba(0, 0, 0, 0.3);
-
- &--drawer {
- position: absolute;
- right: 0;
- top: 0;
- height: 100%;
- width: 540px;
- background-color: @default-bg;
- padding: 20px;
- overflow-y: scroll;
- }
-
- &--header {
- display: flex;
- width: 100%;
- margin-bottom: 20px;
- }
-
- &--title {
- flex: 1 0 auto;
- color: @default-interface-txt;
- font-size: 14px;
- font-weight: bold;
- }
-
- &--actionRow {
- display: flex;
- justify-content: flex-end;
- width: 100%;
- margin-top: 10px;
- line-height: 30px;
-
- button {
- margin-left: 15px;
- }
- }
-
- &--exit {
- justify-content: flex-end;
- display: flex;
-
- button {
- height: 20px;
- font-size: 20px;
- color: @d7grey;
- line-height: 1;
- opacity: 1;
- }
-
- button:hover{
- color: @default-icon;
- opacity: 1;
- }
- }
-
- &--expires {
- color: @default-err;
- }
-}
diff --git a/awx/ui/client/lib/components/approvalsDrawer/approvalsDrawer.directive.js b/awx/ui/client/lib/components/approvalsDrawer/approvalsDrawer.directive.js
deleted file mode 100644
index 47443c524e..0000000000
--- a/awx/ui/client/lib/components/approvalsDrawer/approvalsDrawer.directive.js
+++ /dev/null
@@ -1,76 +0,0 @@
-const templateUrl = require('~components/approvalsDrawer/approvalsDrawer.partial.html');
-
-function AtApprovalsDrawerController (strings, Rest, GetBasePath, $rootScope) {
- const vm = this || {};
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.CREATED_ASCENDING')}`,
- value: 'created'
- };
-
- vm.strings = strings;
- vm.toolbarSortValue = toolbarSortDefault;
- vm.queryset = {
- page: 1,
- page_size: 5,
- order_by: 'created',
- status: 'pending'
- };
- vm.emptyListReason = vm.strings.get('approvals.NONE');
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${vm.strings.get('sort.CREATED_DESCENDING')}`, value: '-created' }
- ];
-
- const loadTheList = () => {
- const queryParams = Object.keys(vm.queryset).map(key => `${key}=${vm.queryset[key]}`).join('&');
- Rest.setUrl(`${GetBasePath('workflow_approvals')}?${queryParams}`);
- return Rest.get()
- .then(({ data }) => {
- vm.dataset = data;
- vm.approvals = data.results;
- vm.count = data.count;
- $rootScope.pendingApprovalCount = data.count;
- });
- };
-
- loadTheList()
- .then(() => { vm.listLoaded = true; });
-
- vm.approve = (approval) => {
- Rest.setUrl(`${GetBasePath('workflow_approvals')}${approval.id}/approve`);
- Rest.post()
- .then(() => loadTheList());
- };
-
- vm.deny = (approval) => {
- Rest.setUrl(`${GetBasePath('workflow_approvals')}${approval.id}/deny`);
- Rest.post()
- .then(() => loadTheList());
- };
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
- vm.queryset.page = 1;
- vm.queryset.order_by = sort.value;
- loadTheList();
- };
-}
-
-AtApprovalsDrawerController.$inject = ['ComponentsStrings', 'Rest', 'GetBasePath', '$rootScope'];
-
-function atApprovalsDrawer () {
- return {
- restrict: 'E',
- transclude: true,
- templateUrl,
- controller: AtApprovalsDrawerController,
- controllerAs: 'vm',
- scope: {
- closeApprovals: '&'
- },
- };
-}
-
-export default atApprovalsDrawer;
diff --git a/awx/ui/client/lib/components/approvalsDrawer/approvalsDrawer.partial.html b/awx/ui/client/lib/components/approvalsDrawer/approvalsDrawer.partial.html
deleted file mode 100644
index 5c61d06673..0000000000
--- a/awx/ui/client/lib/components/approvalsDrawer/approvalsDrawer.partial.html
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{:: vm.strings.get('approvals.CONTINUE') }}
-
- {{:: vm.strings.get('approvals.APPROVE') }}
-
-
- {{:: vm.strings.get('approvals.DENY') }}
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/cards/_index.less b/awx/ui/client/lib/components/cards/_index.less
deleted file mode 100644
index b85e7ef50e..0000000000
--- a/awx/ui/client/lib/components/cards/_index.less
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Cards Group */
-.at-CardContainer {
- padding: 20px;
-}
-
-.at-CardGroup {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- grid-gap: 20px;
-}
-
-/* Card */
-.at-Card {
- min-height: 103px;
- display: flex;
- flex-direction: column;
- flex: 1;
- background-color: @at-white;
- text-decoration: none;
- text-align: center;
- padding: 20px;
- border-left: 3px solid @at-white;
- border-radius: 2px;
- box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
- transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
- cursor: pointer;
-}
-
-.at-Card:hover {
- background-color: @at-color-body-background;
- border-left: 3px solid @at-blue;
- box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
-}
-
-.at-Card-title {
- font-size: 14px;
- color: @at-gray-70;
- font-weight: bold;
- line-height: 14px;
-}
-
-.at-Card-text {
- font-size: 12px;
- color: @at-gray-161b1f;
-}
-
-/* Spacers */
-
-.at-Card--spacer {
- min-height: 15px;
-}
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/cards/card.directive.js b/awx/ui/client/lib/components/cards/card.directive.js
deleted file mode 100644
index f81c712f8b..0000000000
--- a/awx/ui/client/lib/components/cards/card.directive.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const templateUrl = require('~components/cards/card.partial.html');
-
-function atCard () {
- return {
- restrict: 'E',
- transclude: true,
- templateUrl,
- scope: {
- title: '@',
- },
- };
-}
-
-export default atCard;
diff --git a/awx/ui/client/lib/components/cards/card.partial.html b/awx/ui/client/lib/components/cards/card.partial.html
deleted file mode 100644
index fdbe3a1ca1..0000000000
--- a/awx/ui/client/lib/components/cards/card.partial.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
- {{ title }}
-
-
-
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/cards/group.directive.js b/awx/ui/client/lib/components/cards/group.directive.js
deleted file mode 100644
index e2f61e4543..0000000000
--- a/awx/ui/client/lib/components/cards/group.directive.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const templateUrl = require('~components/cards/group.partial.html');
-
-function atCardGroup () {
- return {
- restrict: 'E',
- transclude: true,
- templateUrl,
- };
-}
-
-export default atCardGroup;
diff --git a/awx/ui/client/lib/components/cards/group.partial.html b/awx/ui/client/lib/components/cards/group.partial.html
deleted file mode 100644
index aa07696b12..0000000000
--- a/awx/ui/client/lib/components/cards/group.partial.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/code-mirror/_index.less b/awx/ui/client/lib/components/code-mirror/_index.less
deleted file mode 100644
index 98c258d528..0000000000
--- a/awx/ui/client/lib/components/code-mirror/_index.less
+++ /dev/null
@@ -1,89 +0,0 @@
-.noselect {
- -webkit-touch-callout: none; /* iOS Safari */
- -webkit-user-select: none; /* Chrome/Safari/Opera */
- -khtml-user-select: none; /* Konqueror */
- -moz-user-select: none; /* Firefox */
- -ms-user-select: none; /* Internet Explorer/Edge */
- user-select: none; /* Non-prefixed version, currently
- not supported by any browser */
-}
-
-.atCodeMirror-label{
- display: flex;
- width: 100%;
- margin-bottom: 5px;
-}
-
-.atCodeMirror-labelLeftSide{
- flex: 1 0 auto;
-}
-
-.atCodeMirror-labelRightSide{
- display: flex;
- align-items: center;
-}
-
-.atCodeMirror-labelText{
- text-transform: uppercase;
- color: #707070;
- font-weight: normal;
- font-size: small;
- padding-right: 5px;
- width: 100%;
-}
-
-.atCodeMirror-toggleContainer{
- margin: 0 0 0 10px;
- display: initial;
- padding-bottom: 5px;
-}
-
-.atCodeMirror-expandTextContainer{
- flex: 1 0 auto;
- text-align: right;
- font-weight: normal;
- color: @default-link;
- cursor: pointer;
- font-size: 12px;
-}
-
-.CodeMirror-modal .modal-dialog{
- width: calc(~"100% - 200px");
- height: calc(~"100vh - 80px");
-}
-
-@media screen and (min-width: 768px){
- .NetworkingExtraVars .modal-dialog{
- width: 700px;
- }
-}
-
-.CodeMirror-modal .modal-dialog{
- width: calc(~"100% - 200px");
- height: calc(~"100vh - 80px");
-}
-
-.CodeMirror-modal .modal-content{
- height: 100%;
-}
-
-.CodeMirror-modal .CodeMirror {
- max-height: calc(~"100vh - 230px");
-}
-
-.NetworkingExtraVars .CodeMirror{
- overflow-x: hidden;
-}
-
-.CodeMirror-modalControls{
- float: right;
- margin-top: 15px;
- button {
- margin-left: 10px;
- }
-}
-
-.atCodeMirror-badge{
- display: initial;
- margin-right: 20px;
-}
diff --git a/awx/ui/client/lib/components/code-mirror/code-mirror.directive.js b/awx/ui/client/lib/components/code-mirror/code-mirror.directive.js
deleted file mode 100644
index 4ca2af09f2..0000000000
--- a/awx/ui/client/lib/components/code-mirror/code-mirror.directive.js
+++ /dev/null
@@ -1,138 +0,0 @@
-const templateUrl = require('~components/code-mirror/code-mirror.partial.html');
-
-const CodeMirrorModalID = '#CodeMirror-modal';
-
-function atCodeMirrorController (
- $scope,
- strings,
- ParseTypeChange
-) {
- const vm = this;
- const variablesName = `${$scope.name}_variables`;
-
- function init () {
- if ($scope.disabled === 'true') {
- $scope.disabled = true;
- } else if ($scope.disabled === 'false') {
- $scope.disabled = false;
- }
- $scope.variables = sanitizeVars($scope.variables);
- $scope.parseType = 'yaml';
-
- $scope.variablesName = variablesName;
- $scope[variablesName] = $scope.variables;
- ParseTypeChange({
- scope: $scope,
- variable: variablesName,
- parse_variable: 'parseType',
- field_id: `${$scope.name}_variables`,
- readOnly: $scope.disabled
- });
-
- $scope.$watch(variablesName, () => {
- $scope.variables = $scope[variablesName];
- });
- }
-
- function expand () {
- vm.expanded = true;
- }
-
- function close (varsFromModal, parseTypeFromModal) {
- $scope.variables = varsFromModal;
- $scope[variablesName] = $scope.variables;
- $scope.parseType = parseTypeFromModal;
- // New set of variables from the modal, reinit codemirror
- ParseTypeChange({
- scope: $scope,
- variable: variablesName,
- parse_variable: 'parseType',
- field_id: `${$scope.name}_variables`,
- readOnly: $scope.disabled
- });
- $(CodeMirrorModalID).off('hidden.bs.modal');
- $(CodeMirrorModalID).modal('hide');
- $('.popover').popover('hide');
- vm.expanded = false;
- }
-
- // Adding this function b/c sometimes extra vars are returned to the
- // UI as yaml (ex: "foo: bar"), and other times as a
- // json-object-string (ex: "{"foo": "bar"}"). The latter typically
- // occurs when host vars were system generated and not user-input
- // (such as adding a cloud host);
- function sanitizeVars (str) {
- // Quick function to test if the host vars are a json-object-string,
- // by testing if they can be converted to a JSON object w/o error.
- function IsJsonString (varStr) {
- try {
- JSON.parse(varStr);
- } catch (e) {
- return false;
- }
- return true;
- }
-
- if (typeof str === 'undefined') {
- return '---';
- }
- if (typeof str !== 'string') {
- const yamlStr = jsyaml.safeDump(str);
- // jsyaml.safeDump doesn't process an empty object correctly
- if (yamlStr === '{}\n') {
- return '---';
- }
- return yamlStr;
- }
- if (str === '' || str === '{}') {
- return '---';
- } else if (IsJsonString(str)) {
- str = JSON.parse(str);
- return jsyaml.safeDump(str);
- }
- return str;
- }
-
- vm.name = $scope.name;
- vm.strings = strings;
- vm.expanded = false;
- vm.close = close;
- vm.expand = expand;
- vm.variablesName = variablesName;
- vm.parseType = $scope.parseType;
- if ($scope.init) {
- $scope.init = init;
- }
- angular.element(document).ready(() => {
- init();
- });
-}
-
-atCodeMirrorController.$inject = [
- '$scope',
- 'CodeMirrorStrings',
- 'ParseTypeChange'
-];
-
-function atCodeMirrorTextarea () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- controller: atCodeMirrorController,
- controllerAs: 'vm',
- scope: {
- disabled: '@',
- label: '@',
- labelClass: '@',
- tooltip: '@',
- tooltipPlacement: '@',
- variables: '=',
- name: '@',
- init: '='
- }
- };
-}
-
-export default atCodeMirrorTextarea;
diff --git a/awx/ui/client/lib/components/code-mirror/code-mirror.partial.html b/awx/ui/client/lib/components/code-mirror/code-mirror.partial.html
deleted file mode 100644
index 736d82a9ec..0000000000
--- a/awx/ui/client/lib/components/code-mirror/code-mirror.partial.html
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
- {{ label || vm.strings.get('code_mirror.label.VARIABLES') }}
-
-
-
-
-
-
-
-
-
{{ vm.strings.get('label.EXPAND') }}
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/code-mirror/code-mirror.strings.js b/awx/ui/client/lib/components/code-mirror/code-mirror.strings.js
deleted file mode 100644
index a95ded436b..0000000000
--- a/awx/ui/client/lib/components/code-mirror/code-mirror.strings.js
+++ /dev/null
@@ -1,57 +0,0 @@
-function CodeMirrorStrings (BaseString) {
- BaseString.call(this, 'code_mirror');
-
- const { t } = this;
- const ns = this.code_mirror;
-
- ns.CLOSE_MODAL = t.s('Close variables modal');
-
- ns.label = {
- EXTRA_VARIABLES: t.s('EXTRA VARIABLES'),
- VARIABLES: t.s('VARIABLES'),
- EXPAND: t.s('EXPAND'),
- YAML: t.s('YAML'),
- JSON: t.s('JSON'),
- READONLY: t.s('READ ONLY')
- };
-
- ns.tooltip = {
- TOOLTIP: t.s(`
-
- Enter inventory variables using either JSON or YAML
- syntax. Use the radio button to toggle between the two.
-
- JSON:
-
-
- {
- "somevar": "somevalue",
- "password": "magic"
-
- }
-
- YAML:
-
-
- ---
- somevar: somevalue
- password: magic
-
-
-
- View JSON examples at
- www.json.org
-
-
- View YAML examples at
-
- docs.ansible.com
-
`),
- TOOLTIP_TITLE: t.s('EXTRA VARIABLES'),
- JOB_RESULTS: t.s('Read-only view of extra variables added to the job template.')
- };
-}
-
-CodeMirrorStrings.$inject = ['BaseStringService'];
-
-export default CodeMirrorStrings;
diff --git a/awx/ui/client/lib/components/code-mirror/index.js b/awx/ui/client/lib/components/code-mirror/index.js
deleted file mode 100644
index 21d4aedc09..0000000000
--- a/awx/ui/client/lib/components/code-mirror/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import codemirror from './code-mirror.directive';
-import modal from './modal/code-mirror-modal.directive';
-import strings from './code-mirror.strings';
-
-const MODULE_NAME = 'at.code.mirror';
-
-angular.module(MODULE_NAME, [])
- .directive('atCodeMirror', codemirror)
- .directive('atCodeMirrorModal', modal)
- .service('CodeMirrorStrings', strings);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/lib/components/code-mirror/modal/code-mirror-modal.directive.js b/awx/ui/client/lib/components/code-mirror/modal/code-mirror-modal.directive.js
deleted file mode 100644
index 3c0ad60a07..0000000000
--- a/awx/ui/client/lib/components/code-mirror/modal/code-mirror-modal.directive.js
+++ /dev/null
@@ -1,100 +0,0 @@
-const templateUrl = require('~components/code-mirror/modal/code-mirror-modal.partial.html');
-
-const CodeMirrorModalID = '#CodeMirror-modal';
-const ModalHeight = '#CodeMirror-modal .modal-dialog';
-const ModalHeader = '.atCodeMirror-label';
-const ModalFooter = '.CodeMirror-modalControls';
-
-function atCodeMirrorModalController (
- $scope,
- strings,
- ParseTypeChange
-) {
- const vm = this;
- function resize () {
- if ($scope.disabled === 'true') {
- $scope.disabled = true;
- } else if ($scope.disabled === 'false') {
- $scope.disabled = false;
- }
- const editor = $(`${CodeMirrorModalID} .CodeMirror`)[0];
- if (editor) {
- const height = $(ModalHeight).height() - $(ModalHeader).height() -
- $(ModalFooter).height() - 100;
- editor.CodeMirror.setSize('100%', height);
- }
- }
-
- function toggle () {
- $scope.parseTypeChange('modalParseType', 'modalVars');
- setTimeout(resize, 0);
- }
-
- $scope.close = () => {
- $scope.closeFn({
- values: $scope.modalVars,
- parseType: $scope.modalParseType,
- });
- };
-
- function init () {
- if ($scope.disabled === 'true') {
- $scope.disabled = true;
- } else if ($scope.disabled === 'false') {
- $scope.disabled = false;
- }
- $(CodeMirrorModalID).modal('show');
- ParseTypeChange({
- scope: $scope,
- variable: 'modalVars',
- parse_variable: 'modalParseType',
- field_id: 'variables_modal',
- readOnly: $scope.disabled
- });
- resize();
- $(CodeMirrorModalID).on('hidden.bs.modal', $scope.close);
- $(`${CodeMirrorModalID} .modal-dialog`).resizable({
- minHeight: 523,
- minWidth: 600
- });
- $(`${CodeMirrorModalID} .modal-dialog`).on('resize', resize);
- }
-
- vm.strings = strings;
- vm.toggle = toggle;
- if ($scope.init) {
- $scope.init = init;
- }
- angular.element(document).ready(() => {
- init($scope.variablesName, $scope.name);
- });
-}
-
-atCodeMirrorModalController.$inject = [
- '$scope',
- 'CodeMirrorStrings',
- 'ParseTypeChange',
-];
-
-function atCodeMirrorModal () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- controller: atCodeMirrorModalController,
- controllerAs: 'vm',
- scope: {
- disabled: '@',
- label: '@',
- labelClass: '@',
- tooltip: '@',
- modalVars: '=',
- modalParseType: '=',
- name: '@',
- closeFn: '&'
- }
- };
-}
-
-export default atCodeMirrorModal;
diff --git a/awx/ui/client/lib/components/code-mirror/modal/code-mirror-modal.partial.html b/awx/ui/client/lib/components/code-mirror/modal/code-mirror-modal.partial.html
deleted file mode 100644
index 97786fc3c4..0000000000
--- a/awx/ui/client/lib/components/code-mirror/modal/code-mirror-modal.partial.html
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
- {{ label }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/components.strings.js b/awx/ui/client/lib/components/components.strings.js
deleted file mode 100644
index 38e26ad818..0000000000
--- a/awx/ui/client/lib/components/components.strings.js
+++ /dev/null
@@ -1,145 +0,0 @@
-function ComponentsStrings (BaseString) {
- BaseString.call(this, 'components');
-
- const { t } = this;
- const ns = this.components;
-
- ns.REPLACE = t.s('Replace');
- ns.REVERT = t.s('Revert');
- ns.ENCRYPTED = t.s('ENCRYPTED');
- ns.OPTIONS = t.s('OPTIONS');
- ns.SHOW = t.s('Show');
- ns.HIDE = t.s('Hide');
-
- ns.message = {
- REQUIRED_INPUT_MISSING: t.s('Please enter a value.'),
- INVALID_INPUT: t.s('Invalid input for this type.')
- };
-
- ns.file = {
- PLACEHOLDER: t.s('CHOOSE A FILE'),
- SELECT_FILE: t.s('Select file')
- };
-
- ns.form = {
- SUBMISSION_ERROR_TITLE: t.s('Unable to Submit'),
- SUBMISSION_ERROR_MESSAGE: t.s('Unexpected server error. View the console for more information'),
- SUBMISSION_ERROR_PREFACE: t.s('Unexpected Error')
- };
-
- ns.group = {
- UNSUPPORTED_ERROR_PREFACE: t.s('Unsupported input type')
- };
-
- ns.label = {
- PROMPT_ON_LAUNCH: t.s('Prompt on launch')
- };
-
- ns.select = {
- UNSUPPORTED_TYPE_ERROR: t.s('Unsupported display model type'),
- EMPTY_PLACEHOLDER: t.s('NO OPTIONS AVAILABLE')
- };
-
- ns.textarea = {
- SSH_KEY_HINT: t.s('HINT: Drag and drop private file on the field below.')
- };
-
- ns.lookup = {
- NOT_FOUND: t.s('That value was not found. Please enter or select a valid value.'),
- PERFORM_LOOKUP: t.s('Perform lookup')
- };
-
- ns.truncate = {
- DEFAULT: t.s('Copy full revision to clipboard.'),
- COPIED: t.s('Copied to clipboard.')
- };
-
- ns.toggle = {
- VIEW_MORE: t.s('VIEW MORE'),
- VIEW_LESS: t.s('VIEW LESS')
- };
-
- ns.tooltips = {
- VIEW_THE_CREDENTIAL: t.s('View the Credential'),
- };
-
- ns.layout = {
- CURRENT_USER_LABEL: t.s('Logged in as'),
- VIEW_DOCS: t.s('View Documentation'),
- LOGOUT: t.s('Logout'),
- DASHBOARD: t.s('Dashboard'),
- JOBS: t.s('Jobs'),
- SCHEDULES: t.s('Schedules'),
- MY_VIEW: t.s('My View'),
- PROJECTS: t.s('Projects'),
- CREDENTIALS: t.s('Credentials'),
- CREDENTIAL_TYPES: t.s('Credential Types'),
- INVENTORIES: t.s('Inventories'),
- TEMPLATES: t.s('Templates'),
- ORGANIZATIONS: t.s('Organizations'),
- USERS: t.s('Users'),
- TEAMS: t.s('Teams'),
- INVENTORY_SCRIPTS: t.s('Inventory Scripts'),
- NOTIFICATIONS: t.s('Notifications'),
- MANAGEMENT_JOBS: t.s('Management Jobs'),
- INSTANCES: t.s('Instances'),
- INSTANCE_GROUPS: t.s('Instance Groups'),
- APPLICATIONS: t.s('Applications'),
- SETTINGS: t.s('Settings'),
- ABOUT: t.s('About'),
- COPYRIGHT: t.s('Copyright © 2019 Red Hat, Inc.'),
- VIEWS_HEADER: t.s('Views'),
- RESOURCES_HEADER: t.s('Resources'),
- ACCESS_HEADER: t.s('Access'),
- ADMINISTRATION_HEADER: t.s('Administration'),
- AUTHENTICATION: t.s('Authentication'),
- SYSTEM: t.s('System'),
- USER_INTERFACE: t.s('User Interface'),
- LICENSE: t.s('License')
- };
-
- ns.relaunch = {
- DEFAULT: t.s('Relaunch using the same parameters'),
- HOSTS: t.s('Relaunch using host parameters'),
- DROPDOWN_TITLE: t.s('Relaunch On'),
- ALL: t.s('All'),
- FAILED: t.s('Failed')
- };
-
- ns.launchTemplate = {
- DEFAULT: t.s('Start a job using this template'),
- DISABLED: t.s('Please save before launching this template.'),
- BUTTON_LABEL: t.s('LAUNCH')
- };
-
- ns.list = {
- DEFAULT_EMPTY_LIST: t.s('Please add items to this list.')
- };
-
- ns.toolbar = {
- COMPACT: t.s('Compact'),
- EXPANDED: t.s('Expanded'),
- SORT_BY: t.s('SORT BY')
- };
-
- ns.approvals = {
- APPROVAL: t.s('APPROVAL'),
- NONE: t.s('There are no jobs awaiting approval'),
- APPROVE: t.s('APPROVE'),
- DENY: t.s('DENY'),
- CONTINUE: t.s('Continue workflow job?'),
- NOTIFICATIONS: t.s('NOTIFICATIONS'),
- WORKFLOW_TEMPLATE: t.s('Workflow Template'),
- EXPIRES: t.s('Expires:'),
- EXPIRES_NEVER: t.s('Expires: Never'),
- CLOSE_APPROVALS: t.s('Close Approvals')
- };
-
- ns.secret = {
- REPLACE: t.s('Replace secret')
- };
-}
-
-ComponentsStrings.$inject = ['BaseStringService'];
-
-export default ComponentsStrings;
diff --git a/awx/ui/client/lib/components/dialog/_index.less b/awx/ui/client/lib/components/dialog/_index.less
deleted file mode 100644
index 60ff25c935..0000000000
--- a/awx/ui/client/lib/components/dialog/_index.less
+++ /dev/null
@@ -1,43 +0,0 @@
-.at-Dialog {
- display: block;
- border: none;
- opacity: 1;
- background: rgba(0, 0, 0, 0.3);
- animation-name: at-DialogFadeIn;
- animation-iteration-count: 1;
- animation-timing-function: ease-in;
- animation-duration: 0.3s;
-}
-
-@keyframes at-DialogFadeIn {
- 0% { opacity: 0; background: rgba(0, 0, 0, 0); }
- 100% { opacity: 1; background: rgba(0, 0, 0, 0.3); }
-}
-
-.at-Dialog-body {
- font-size: @at-font-size;
- padding: @at-padding-panel 0;
-}
-
-.at-Dialog-dismiss {
- .at-mixin-ButtonIcon();
- font-size: @at-font-size-modal-dismiss;
- color: @at-color-icon-dismiss;
- text-align: right;
-}
-
-.at-Dialog-heading {
- margin: 0;
- overflow: visible;
-
- & > .at-Dialog-dismiss {
- margin: 0;
- }
-}
-
-.at-Dialog-title {
- margin: 0;
- padding: 0;
-
- .at-mixin-Heading(@at-font-size-modal-heading);
-}
diff --git a/awx/ui/client/lib/components/dialog/dialog.component.js b/awx/ui/client/lib/components/dialog/dialog.component.js
deleted file mode 100644
index 888c47033c..0000000000
--- a/awx/ui/client/lib/components/dialog/dialog.component.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const templateUrl = require('~components/dialog/dialog.partial.html');
-
-export default {
- templateUrl,
- controllerAs: 'vm',
- transclude: true,
- bindings: {
- title: '=',
- onClose: '=',
- },
-};
diff --git a/awx/ui/client/lib/components/dialog/dialog.partial.html b/awx/ui/client/lib/components/dialog/dialog.partial.html
deleted file mode 100644
index 639a2fed97..0000000000
--- a/awx/ui/client/lib/components/dialog/dialog.partial.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/form/action.directive.js b/awx/ui/client/lib/components/form/action.directive.js
deleted file mode 100644
index ab8d6e72a3..0000000000
--- a/awx/ui/client/lib/components/form/action.directive.js
+++ /dev/null
@@ -1,78 +0,0 @@
-const templateUrl = require('~components/form/action.partial.html');
-
-function link (scope, element, attrs, controllers) {
- const [formController, actionController] = controllers;
-
- actionController.init(formController, scope);
-}
-
-function atFormActionController ($state, strings) {
- const vm = this || {};
-
- let form;
- let scope;
-
- vm.init = (_form_, _scope_) => {
- form = _form_;
- scope = _scope_;
-
- switch (scope.type) {
- case 'cancel':
- vm.setCancelDefaults();
- break;
- case 'save':
- vm.setSaveDefaults();
- break;
- case 'secondary':
- vm.setSecondaryDefaults();
- break;
- default:
- vm.setCustomDefaults();
- }
-
- form.register('action', scope);
- };
-
- vm.setCancelDefaults = () => {
- scope.text = strings.get('CANCEL');
- scope.fill = 'Hollow';
- scope.color = 'default';
- scope.action = () => { $state.go(scope.to || '^'); };
- };
-
- vm.setSaveDefaults = () => {
- scope.text = strings.get('SAVE');
- scope.fill = '';
- scope.color = 'success';
- scope.action = () => { form.submit(); };
- };
-
- vm.setSecondaryDefaults = () => {
- scope.text = strings.get('TEST');
- scope.fill = '';
- scope.color = 'info';
- scope.action = () => { form.submitSecondary(); };
- };
-}
-
-atFormActionController.$inject = ['$state', 'ComponentsStrings'];
-
-function atFormAction () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atFormAction'],
- templateUrl,
- controller: atFormActionController,
- controllerAs: 'vm',
- link,
- scope: {
- state: '=',
- type: '@',
- to: '@'
- }
- };
-}
-
-export default atFormAction;
diff --git a/awx/ui/client/lib/components/form/action.partial.html b/awx/ui/client/lib/components/form/action.partial.html
deleted file mode 100644
index 78c89d0f91..0000000000
--- a/awx/ui/client/lib/components/form/action.partial.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
- {{::text}}
-
diff --git a/awx/ui/client/lib/components/form/form.directive.js b/awx/ui/client/lib/components/form/form.directive.js
deleted file mode 100644
index 7a4d7154d8..0000000000
--- a/awx/ui/client/lib/components/form/form.directive.js
+++ /dev/null
@@ -1,248 +0,0 @@
-const templateUrl = require('~components/form/form.partial.html');
-
-function atFormLink (scope, el, attrs, controllers) {
- const formController = controllers[0];
- const form = el[0];
-
- scope.ns = 'form';
- scope[scope.ns] = { modal: {} };
-
- formController.init(scope, form);
-}
-
-function AtFormController (eventService, strings) {
- const vm = this || {};
-
- let scope;
- let modal;
- let form;
-
- vm.components = [];
- vm.state = {
- isValid: false,
- disabled: false,
- value: {},
- };
-
- vm.init = (_scope_, _form_) => {
- scope = _scope_;
- form = _form_;
- ({ modal } = scope[scope.ns]);
-
- vm.state.disabled = scope.state.disabled;
- vm.setListeners();
- };
-
- vm.register = (category, component) => {
- component.category = category;
- component.form = vm.state;
-
- if (category === 'input') {
- scope.state[component.state.id] = component.state;
- }
-
- vm.components.push(component);
- };
-
- vm.setListeners = () => {
- const listeners = eventService.addListeners([
- [form, 'keypress', vm.submitOnEnter]
- ]);
-
- scope.$on('$destroy', () => eventService.remove(listeners));
- };
-
- vm.submitOnEnter = event => {
- if (event.key !== 'Enter' || event.srcElement.type === 'textarea') {
- return;
- }
-
- event.preventDefault();
- scope.$apply(vm.submit);
- };
-
- vm.getSubmitData = () => vm.components
- .filter(component => component.category === 'input')
- .reduce((values, component) => {
- if (component.state._value === undefined) {
- return values;
- }
-
- if (component.state._format === 'selectFromOptions') {
- values[component.state.id] = component.state._value[0];
- } else if (component.state._key && typeof component.state._value === 'object') {
- values[component.state.id] = component.state._value[component.state._key];
- } else if (component.state._group) {
- values[component.state._key] = values[component.state._key] || {};
- values[component.state._key][component.state.id] = component.state._value;
- } else {
- values[component.state.id] = component.state._value;
- }
-
- return values;
- }, {});
-
- vm.submitSecondary = () => {
- if (!vm.state.isValid) {
- return;
- }
- const data = vm.getSubmitData();
- scope.state.secondary(data);
- };
-
- vm.submit = () => {
- if (!vm.state.isValid) {
- return;
- }
-
- vm.state.disabled = true;
-
- const data = vm.getSubmitData();
-
- scope.state.save(data)
- .then(scope.state.onSaveSuccess)
- .catch(err => vm.onSaveError(err))
- .finally(() => { vm.state.disabled = false; });
- };
-
- vm.onSaveError = err => {
- let handled;
-
- if (err.status === 400) {
- handled = vm.handleValidationError(err.data);
- }
-
- if (err.status === 500) {
- handled = vm.handleUnexpectedError(err);
- }
-
- if (!handled) {
- let message;
- const title = strings.get('form.SUBMISSION_ERROR_TITLE');
- const preface = strings.get('form.SUBMISSION_ERROR_PREFACE');
-
- if (typeof err.data === 'object') {
- message = JSON.stringify(err.data);
- } if (_.has(err, 'data.__all__')) {
- if (typeof err.data.__all__ === 'object' && Array.isArray(err.data.__all__)) {
- message = JSON.stringify(err.data.__all__[0]);
- } else {
- message = JSON.stringify(err.data.__all__);
- }
- } else {
- message = err.data;
- }
-
- modal.show(title, `${preface}: ${message}`);
- }
- };
-
- vm.handleUnexpectedError = () => {
- const title = strings.get('form.SUBMISSION_ERROR_TITLE');
- const message = strings.get('form.SUBMISSION_ERROR_MESSAGE');
-
- modal.show(title, message);
-
- return true;
- };
-
- vm.handleValidationError = errors => {
- const errorMessageSet = vm.setValidationMessages(errors);
-
- if (errorMessageSet) {
- vm.check();
- }
-
- return errorMessageSet;
- };
-
- vm.setValidationMessages = (errors, errorSet) => {
- let errorMessageSet = errorSet || false;
-
- Object.keys(errors).forEach(id => {
- if (!Array.isArray(errors[id]) && typeof errors[id] === 'object') {
- errorMessageSet = vm.setValidationMessages(errors[id], errorMessageSet);
-
- return;
- }
-
- vm.components
- .filter(component => component.category === 'input')
- .filter(component => errors[component.state.id])
- .forEach(component => {
- errorMessageSet = true;
-
- component.state._rejected = true;
- component.state._message = errors[component.state.id].join(' ');
- });
- });
-
- return errorMessageSet;
- };
-
- vm.validate = () => {
- let isValid = true;
-
- for (let i = 0; i < vm.components.length; i++) {
- if (vm.components[i].category !== 'input') {
- continue;
- }
-
- if (vm.components[i].state.asTag) {
- continue;
- }
-
- if (!vm.components[i].state._isValid) {
- isValid = false;
- break;
- }
- }
-
- return isValid;
- };
-
- vm.check = () => {
- const isValid = vm.validate();
-
- if (isValid !== vm.state.isValid) {
- vm.state.isValid = isValid;
- }
-
- if (isValid !== scope.state.isValid) {
- scope.state.isValid = isValid;
- }
- };
-
- vm.deregisterInputGroup = components => {
- for (let i = 0; i < components.length; i++) {
- for (let j = 0; j < vm.components.length; j++) {
- if (components[i] === vm.components[j].state) {
- vm.components.splice(j, 1);
- delete scope.state[components[i].id];
- break;
- }
- }
- }
- };
-}
-
-AtFormController.$inject = ['EventService', 'ComponentsStrings'];
-
-function atForm () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- require: ['atForm'],
- templateUrl,
- controller: AtFormController,
- controllerAs: 'vm',
- link: atFormLink,
- scope: {
- state: '=',
- autocomplete: '@'
- }
- };
-}
-
-export default atForm;
diff --git a/awx/ui/client/lib/components/form/form.partial.html b/awx/ui/client/lib/components/form/form.partial.html
deleted file mode 100644
index 3d45276cd6..0000000000
--- a/awx/ui/client/lib/components/form/form.partial.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/index.js b/awx/ui/client/lib/components/index.js
deleted file mode 100644
index cc3cd55bb0..0000000000
--- a/awx/ui/client/lib/components/index.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import atLibServices from '~services';
-
-import actionGroup from '~components/action/action-group.directive';
-import actionButton from '~components/action/action-button.directive';
-import approvalsDrawer from '~components/approvalsDrawer/approvalsDrawer.directive';
-import dialog from '~components/dialog/dialog.component';
-import divider from '~components/utility/divider.directive';
-import dynamicSelect from '~components/input/dynamic-select.directive';
-import form from '~components/form/form.directive';
-import formAction from '~components/form/action.directive';
-import inputCheckbox from '~components/input/checkbox.directive';
-import inputFile from '~components/input/file.directive';
-import inputGroup from '~components/input/group.directive';
-import inputLabel from '~components/input/label.directive';
-import inputLookup from '~components/input/lookup.directive';
-import inputMessage from '~components/input/message.directive';
-import inputSecret from '~components/input/secret.directive';
-import inputSelect from '~components/input/select.directive';
-import inputSlider from '~components/input/slider.directive';
-import inputText from '~components/input/text.directive';
-import inputTextarea from '~components/input/textarea.directive';
-import inputTextareaSecret from '~components/input/textarea-secret.directive';
-import launchTemplate from '~components/launchTemplateButton/launchTemplateButton.component';
-import layout from '~components/layout/layout.directive';
-import list from '~components/list/list.directive';
-import lookupList from '~components/lookup-list/lookup-list.component';
-import modal from '~components/modal/modal.directive';
-import panel from '~components/panel/panel.directive';
-import panelBody from '~components/panel/body.directive';
-import panelHeading from '~components/panel/heading.directive';
-import popover from '~components/popover/popover.directive';
-import relaunch from '~components/relaunchButton/relaunchButton.component';
-import row from '~components/list/row.directive';
-import rowItem from '~components/list/row-item.directive';
-import rowAction from '~components/list/row-action.directive';
-import sideNav from '~components/layout/side-nav.directive';
-import sideNavItem from '~components/layout/side-nav-item.directive';
-import tab from '~components/tabs/tab.directive';
-import tabGroup from '~components/tabs/group.directive';
-import tag from '~components/tag/tag.directive';
-import toggleTag from '~components/toggle-tag/toggle-tag.directive';
-import toolbar from '~components/list/list-toolbar.directive';
-import topNavItem from '~components/layout/top-nav-item.directive';
-import truncate from '~components/truncate/truncate.directive';
-import atCodeMirror from '~components/code-mirror';
-import atSyntaxHighlight from '~components/syntax-highlight';
-import card from '~components/cards/card.directive';
-import cardGroup from '~components/cards/group.directive';
-import atSwitch from '~components/switch/switch.directive';
-
-import BaseInputController from '~components/input/base.controller';
-import ComponentsStrings from '~components/components.strings';
-
-const MODULE_NAME = 'at.lib.components';
-
-angular
- .module(MODULE_NAME, [
- atLibServices,
- atCodeMirror,
- atSyntaxHighlight,
- ])
- .directive('atActionGroup', actionGroup)
- .directive('atActionButton', actionButton)
- .directive('atApprovalsDrawer', approvalsDrawer)
- .component('atDialog', dialog)
- .directive('atDivider', divider)
- .directive('atDynamicSelect', dynamicSelect)
- .directive('atForm', form)
- .directive('atFormAction', formAction)
- .directive('atInputCheckbox', inputCheckbox)
- .directive('atInputFile', inputFile)
- .directive('atInputGroup', inputGroup)
- .directive('atInputLabel', inputLabel)
- .directive('atInputLookup', inputLookup)
- .directive('atInputMessage', inputMessage)
- .directive('atInputSecret', inputSecret)
- .directive('atInputSelect', inputSelect)
- .directive('atInputSlider', inputSlider)
- .directive('atInputText', inputText)
- .directive('atInputTextarea', inputTextarea)
- .directive('atInputTextareaSecret', inputTextareaSecret)
- .component('atLaunchTemplate', launchTemplate)
- .directive('atLayout', layout)
- .directive('atList', list)
- .component('atLookupList', lookupList)
- .directive('atListToolbar', toolbar)
- .component('atRelaunch', relaunch)
- .directive('atRow', row)
- .directive('atRowItem', rowItem)
- .directive('atRowAction', rowAction)
- .directive('atModal', modal)
- .directive('atPanel', panel)
- .directive('atPanelBody', panelBody)
- .directive('atPanelHeading', panelHeading)
- .directive('atPopover', popover)
- .directive('atSideNav', sideNav)
- .directive('atSideNavItem', sideNavItem)
- .directive('atTab', tab)
- .directive('atTabGroup', tabGroup)
- .directive('atTag', tag)
- .directive('atToggleTag', toggleTag)
- .directive('atTopNavItem', topNavItem)
- .directive('atTruncate', truncate)
- .directive('atCard', card)
- .directive('atCardGroup', cardGroup)
- .directive('atSwitch', atSwitch)
- .service('BaseInputController', BaseInputController)
- .service('ComponentsStrings', ComponentsStrings);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/lib/components/input/_index.less b/awx/ui/client/lib/components/input/_index.less
deleted file mode 100644
index 68be7f59d0..0000000000
--- a/awx/ui/client/lib/components/input/_index.less
+++ /dev/null
@@ -1,359 +0,0 @@
-.at-Input {
- .at-mixin-Placeholder(@at-color-input-placeholder);
-
- height: @at-height-input;
- background: @at-color-input-background;
- border-radius: @at-border-radius;
- color: @at-color-input-text;
- padding: 0 @at-padding-input;
-
- &, &:active {
- border-color: @at-color-input-border;
- }
-
- &:focus {
- border-color: @at-color-input-focus;
- }
-
- &[readonly] {
- background: @at-color-input-readonly;
- }
-
- &[disabled] {
- background: @at-color-input-disabled;
- }
-}
-
-.at-InputCheckbox {
- margin: 0;
- padding: 0;
- display: block;
- min-height: 20px;
-
- & > label {
- font-weight: normal;
-
- & > input[type=checkbox] {
- height: @at-height-input;
- margin: 0;
- padding: 0;
- float: left;
- }
-
- & > p {
- margin: 0;
- padding: 0 0 0 @at-padding-panel;
- line-height: @at-line-height-tall;
- }
- }
-}
-
-.at-InputContainer {
- margin-top: @at-margin-panel;
-}
-
-.at-Input-button {
- .at-mixin-InputButton();
-}
-
-.at-Input-button--fixed-xs {
- .at-mixin-InputButton();
- min-width: @at-width-input-button-sm;
- height: @at-height-input;
-}
-
-.at-Input-button--fixed-sm {
- .at-mixin-InputButton();
- min-width: @at-width-input-button-md;
- height: @at-height-input;
-}
-
-.at-Input-button--fixed-md {
- .at-mixin-InputButton();
- display: inherit;
- min-width: @at-width-input-button-md;
- height: @at-height-textarea;
-}
-
-.at-Input-button--long-sm {
- .at-mixin-InputButton();
- max-width: @at-width-input-button-md;
- min-height: @at-height-textarea;
-}
-
-.at-Input-button--active {
- .at-mixin-ButtonColor(at-color-info, at-color-default);
-}
-
-.at-Input--focus {
- border-color: @at-color-input-focus;
-}
-
-.at-Input--rejected {
- &, &:focus {
- border-color: @at-color-input-error;
- }
-}
-
-.at-InputFile--hidden {
- position: absolute;
- height: 100%;
- width: 100%;
- left: 0;
- z-index: -2;
- opacity: 0;
-}
-
-.at-InputFile--drag {
- z-index: 3;
-}
-
-.at-InputGroup {
- padding: 0;
- margin: @at-margin-panel 0 0 0;
-}
-
-.at-InputGroup-border {
- position: absolute;
- width: 5px;
- height: 100%;
- background: @at-color-panel-border;
- left: -5px;
-}
-
-.at-InputGroup-title {
- .at-mixin-Heading(@at-font-size-panel-inset-heading);
- margin: 0 0 0 @at-margin-panel-inset;
-}
-
-.at-InputGroup-divider {
- clear: both;
- margin: 0;
- padding: 0;
- height: @at-height-divider;
-}
-
-.at-InputLabel {
- display: inline-block;
- width: 100%;
-}
-
-.at-InputLabel-name {
- color: @at-color-form-label;
- font-size: @at-font-size-form-label;
- font-weight: @at-font-weight-body;
- text-transform: uppercase;
-}
-
-.at-InputLabel-hint {
- margin-left: @at-margin-form-label-hint;
- color: @at-color-input-hint;
- font-size: @at-font-size-help-text;
- font-weight: @at-font-weight-body;
- line-height: @at-line-height-short;
-}
-
-.at-InputLabel-checkbox {
- margin: 0;
- padding: 0;
-}
-
-.at-InputLabel-checkboxLabel {
- margin-bottom: 0;
-
- & > input[type=checkbox] {
- margin: 0 3px 0 0;
- }
-
- & > p {
- font-size: @at-font-size-help-text;
- color: @at-color-form-label;
- font-weight: @at-font-weight-body;
- display: inline;
- margin: 0;
- padding: 0;
- }
-}
-
-.at-InputMessage--rejected {
- font-size: @at-font-size-help-text;
- color: @at-color-error;
- margin: @at-margin-input-message 0 0 0;
- padding: 0;
-}
-
-.at-InputLabel-required {
- color: @at-color-error;
- font-weight: @at-font-weight-heading;
- font-size: @at-font-size-form-label;
- margin: 0;
-}
-
-.at-InputSelect {
- position: relative;
- width: 100%;
-
- & > i {
- font-size: @at-font-size-button;
- position: absolute;
- z-index: 3;
- pointer-events: none;
- top: @at-height-input / 3;
- right: @at-height-input / 3;
- color: @at-color-input-icon;
- }
-}
-
-.at-InputSelect-input {
- position: relative;
- z-index: 2;
- pointer-events: none;
-}
-
-.at-InputSelect-select {
- height: @at-height-input;
- cursor: pointer;
- position: absolute;
- z-index: 1;
- top: 0;
-
- & > optgroup {
- text-transform: uppercase;
-
- & > option {
- text-transform: none;
- }
- }
-}
-
-.at-InputTextarea {
- .at-mixin-FontFixedWidth();
- min-height: @at-height-textarea;
- padding: 6px @at-padding-input 0 @at-padding-input;
-}
-
-.at-InputLookup {
- display: flex;
-
- .at-InputLookup-button {
- .at-mixin-InputButton();
- border-radius: @at-border-radius 0 0 @at-border-radius;
- border-right: none;
- flex: 0 0 35px;
- height: auto;
- min-height: 30px
- }
-
- .at-InputLookup-tagContainer {
- .at-mixin-Border;
- display: flex;
- flex-flow: row wrap;
- padding: 0 10px;
- width: 100%;
- }
-
- .at-InputLookup-button + .at-Input,
- .at-InputLookup-tagContainer {
- border-radius: 0 @at-border-radius @at-border-radius 0;
- }
-}
-
-.at-InputSlider {
- display: flex;
- padding: 5px 0;
-
- p {
- color: @at-color-form-label;
- font-size: @at-font-size-help-text;
- font-weight: @at-font-weight-body;
- margin: 0 0 0 10px;
- padding: 0;
- width: 50px;
- }
-
- input[type=range] {
- -webkit-appearance: none;
- width: 100%;
- background: transparent;
- height: 20px;
- border-right: 1px solid @at-color-input-slider-track;
- border-left: 1px solid @at-color-input-slider-track;
-
- &:focus {
- outline: none;
- }
-
- &::-webkit-slider-runnable-track {
- background: @at-color-input-slider-track;
- cursor: pointer;
- height: 1px;
- width: 100%;
- }
-
- &::-webkit-slider-thumb {
- -webkit-appearance: none;
- background-color: @at-color-input-slider-thumb;
- border-radius: 50%;
- border: none;
- cursor: pointer;
- height: 16px;
- margin-top: -7px;
- width: 16px;
- }
-
- }
-
- input[type=range]::-moz-range-thumb {
- -webkit-appearance: none;
- background-color: @at-color-input-slider-thumb;
- border-radius: 50%;
- border: none;
- cursor: pointer;
- height: 16px;
- width: 16px;
- }
-
- input[type=range]::-moz-range-track {
- background: @at-color-input-slider-track;
- cursor: pointer;
- height: 1px;
- width: 100%;
- }
-
- input[type=range][disabled] {
- &::-webkit-slider-thumb {
- background: @at-color-disabled;
- border: solid 1px @at-color-disabled;
- cursor: not-allowed;
- }
- }
-}
-
-.at-InputGroup-container {
- .row {
- margin: 0;
- }
-}
-
-.at-InputTaggedTextarea {
- .at-mixin-FontFixedWidth();
- min-height: @at-height-textarea;
- padding: 6px @at-padding-input 0 @at-padding-input;
- border-radius: @at-border-radius;
-}
-
-.at-InputTagContainer {
- display: flex;
- width: 100%;
- flex-wrap: wrap;
-
- .TagComponent {
- max-height: @at-space-4x;
- }
-
- .TagComponent-name {
- align-self: auto;
- word-break: break-all;
- font-family: 'Open Sans', sans-serif;
- }
-}
diff --git a/awx/ui/client/lib/components/input/base.controller.js b/awx/ui/client/lib/components/input/base.controller.js
deleted file mode 100644
index 9a08ed0f2e..0000000000
--- a/awx/ui/client/lib/components/input/base.controller.js
+++ /dev/null
@@ -1,155 +0,0 @@
-function BaseInputController (strings) {
- // Default values are universal. Don't translate.
- const PROMPT_ON_LAUNCH_VALUE = 'ASK';
- const ENCRYPTED_VALUE = '$encrypted$';
-
- return function extend (type, scope, element, form) {
- const vm = this;
-
- vm.strings = strings;
-
- scope.state = scope.state || {};
-
- scope.state._touched = false;
- scope.state._required = scope.state.required || false;
-
- if (scope.state.type === 'boolean') {
- scope.state._isValid = scope.state._isValid || true;
- } else {
- scope.state._isValid = scope.state._isValid || false;
- }
-
- scope.state._disabled = scope.state._disabled || false;
- scope.state._activeModel = scope.state._activeModel || '_value';
-
- if (scope.state.ask_at_runtime) {
- scope.state._displayPromptOnLaunch = true;
- }
-
- if (typeof scope.state._value !== 'undefined') {
- scope.state._edit = true;
- scope.state._preEditValue = scope.state._value;
-
- if (scope.state._value === PROMPT_ON_LAUNCH_VALUE) {
- scope.state._promptOnLaunch = true;
- scope.state._disabled = true;
- scope.state._activeModel = '_displayValue';
- }
-
- if (scope.state._value === ENCRYPTED_VALUE) {
- scope.state._displayRevertReplace = true;
- scope.state._enableToggle = true;
- scope.state._disabled = true;
- scope.state._isBeingReplaced = false;
- scope.state._activeModel = '_displayValue';
- }
- } else if (typeof scope.state.default !== 'undefined') {
- scope.state._value = scope.state.default;
- }
-
- form.register(type, scope);
-
- if (scope.form && scope.form.disabled) {
- scope.state._enableToggle = false;
- }
-
- vm.validate = () => {
- let isValid = true;
- let message = '';
-
- if (scope.state.asTag) {
- return (isValid, message);
- }
-
- if (scope.state._value || scope.state._displayValue) {
- scope.state._touched = true;
- }
-
- if (scope.state.type === 'boolean') {
- return { isValid, message };
- }
-
- if (scope.state._required && (!scope.state._value || !scope.state._value[0]) &&
- !scope.state._displayValue) {
- isValid = false;
- message = vm.strings.get('message.REQUIRED_INPUT_MISSING');
- } else if (scope.state._validate) {
- const result = scope.state._validate(scope.state._value);
-
- if (!result.isValid) {
- isValid = false;
- message = result.message || vm.strings.get('message.INVALID_INPUT');
- }
- }
-
- return {
- isValid,
- message
- };
- };
-
- vm.updateValidationState = result => {
- if (!scope.state._touched && scope.state._required) {
- return;
- }
-
- scope.state._rejected = !result.isValid;
- scope.state._isValid = result.isValid;
- scope.state._message = result.message;
-
- form.check();
- };
-
- vm.check = result => {
- result = result || vm.validate();
-
- vm.updateValidationState(result);
- };
-
- vm.onRevertReplaceToggle = () => {
- if (!scope.state._isBeingReplaced) {
- scope.state._buttonText = vm.strings.get('REPLACE');
- scope.state._disabled = true;
- scope.state._enableToggle = true;
- scope.state._value = scope.state._preEditValue;
- scope.state._activeModel = '_displayValue';
- scope.state._placeholder = vm.strings.get('ENCRYPTED');
- vm.check();
- } else {
- scope.state._buttonText = vm.strings.get('REVERT');
- scope.state._disabled = false;
- scope.state._enableToggle = false;
- scope.state._activeModel = '_value';
- scope.state._value = '';
- scope.state._placeholder = '';
- vm.check();
- }
- if (scope.form && scope.form.disabled) {
- scope.state._enableToggle = false;
- }
- };
-
- vm.togglePromptOnLaunch = () => {
- if (scope.state._promptOnLaunch) {
- scope.state._value = PROMPT_ON_LAUNCH_VALUE;
- scope.state._activeModel = '_displayValue';
- scope.state._disabled = true;
- scope.state._enableToggle = false;
- } else if (scope.state._isBeingReplaced === false) {
- scope.state._disabled = true;
- scope.state._enableToggle = true;
- scope.state._value = scope.state._preEditValue;
- } else {
- scope.state._activeModel = '_value';
- scope.state._disabled = false;
- scope.state._value = '';
- }
-
- vm.check();
- };
- };
-}
-
-BaseInputController.$inject = ['ComponentsStrings'];
-
-export default BaseInputController;
diff --git a/awx/ui/client/lib/components/input/checkbox.directive.js b/awx/ui/client/lib/components/input/checkbox.directive.js
deleted file mode 100644
index 00fcdcf05c..0000000000
--- a/awx/ui/client/lib/components/input/checkbox.directive.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const templateUrl = require('~components/input/checkbox.partial.html');
-
-function atInputCheckboxLink (scope, element, attrs, controllers) {
- const formController = controllers[0];
- const inputController = controllers[1];
-
- if (scope.tab === '1') {
- element.find('input')[0].focus();
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputCheckboxController (baseInputController) {
- const vm = this || {};
-
- vm.init = (scope, element, form) => {
- baseInputController.call(vm, 'input', scope, element, form);
- scope.label = scope.state.label;
- scope.state.label = vm.strings.get('OPTIONS');
-
- vm.check();
- };
-}
-
-AtInputCheckboxController.$inject = ['BaseInputController'];
-
-function atInputCheckbox () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputCheckbox'],
- templateUrl,
- controller: AtInputCheckboxController,
- controllerAs: 'vm',
- link: atInputCheckboxLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputCheckbox;
diff --git a/awx/ui/client/lib/components/input/checkbox.partial.html b/awx/ui/client/lib/components/input/checkbox.partial.html
deleted file mode 100644
index df171e5cb5..0000000000
--- a/awx/ui/client/lib/components/input/checkbox.partial.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/dynamic-select.directive.js b/awx/ui/client/lib/components/input/dynamic-select.directive.js
deleted file mode 100644
index ee3bca40ed..0000000000
--- a/awx/ui/client/lib/components/input/dynamic-select.directive.js
+++ /dev/null
@@ -1,49 +0,0 @@
-const templateUrl = require('~components/input/dynamic-select.partial.html');
-
-function atDynamicSelectLink (scope, element, attrs, controllers) {
- const [formController, inputController] = controllers;
-
- inputController.init(scope, element, formController);
-}
-
-function AtDynamicSelectController (baseInputController, CreateSelect2) {
- const vm = this || {};
-
- let scope;
-
- vm.init = (_scope_, _element_, form) => {
- baseInputController.call(vm, 'input', _scope_, _element_, form);
- scope = _scope_;
- CreateSelect2({
- element: `#${scope.state._formId}_${scope.state.id}_dynamic_select`,
- model: 'state._value',
- multiple: false,
- addNew: true,
- scope,
- options: 'state._data'
- });
- vm.check();
- };
-}
-
-AtDynamicSelectController.$inject = ['BaseInputController', 'CreateSelect2'];
-
-function atDynamicSelect () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^at-form', 'atDynamicSelect'],
- templateUrl,
- controller: AtDynamicSelectController,
- controllerAs: 'vm',
- link: atDynamicSelectLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atDynamicSelect;
diff --git a/awx/ui/client/lib/components/input/dynamic-select.partial.html b/awx/ui/client/lib/components/input/dynamic-select.partial.html
deleted file mode 100644
index b1b5eaf616..0000000000
--- a/awx/ui/client/lib/components/input/dynamic-select.partial.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/file.directive.js b/awx/ui/client/lib/components/input/file.directive.js
deleted file mode 100644
index 42aa2c4fba..0000000000
--- a/awx/ui/client/lib/components/input/file.directive.js
+++ /dev/null
@@ -1,94 +0,0 @@
-const templateUrl = require('~components/input/file.partial.html');
-
-function atInputFileLink (scope, element, attrs, controllers) {
- const formController = controllers[0];
- const inputController = controllers[1];
-
- if (scope.tab === '1') {
- element.find('input')[0].focus();
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputFileController (baseInputController, eventService) {
- const vm = this || {};
-
- let input;
- let scope;
-
- vm.init = (_scope_, element, form) => {
- baseInputController.call(vm, 'input', _scope_, element, form);
-
- scope = _scope_;
- input = element.find('input')[0]; // eslint-disable-line prefer-destructuring
-
- vm.listeners = vm.setFileListeners(input);
-
- vm.check();
- };
-
- vm.onButtonClick = () => {
- if (scope.state._value) {
- vm.removeFile();
- } else {
- input.click();
- }
- };
-
- vm.setFileListeners = inputEl => eventService.addListeners([
- [inputEl, 'change', event => vm.handleFileChangeEvent(inputEl, event)]
- ]);
-
- vm.handleFileChangeEvent = (element, event) => {
- if (element.files.length > 0) {
- const reader = new FileReader();
-
- reader.onload = () => vm.readFile(reader, event);
- reader.readAsText(element.files[0]);
- } else {
- scope.$apply(vm.removeFile);
- }
- };
-
- vm.readFile = (reader, event) => {
- scope.$apply(() => {
- scope.state._value = reader.result;
- scope.state._displayValue = event.target.files[0].name;
-
- vm.check();
- });
- };
-
- vm.removeFile = () => {
- delete scope.state._value;
- delete scope.state._displayValue;
-
- input.value = '';
- };
-}
-
-AtInputFileController.$inject = [
- 'BaseInputController',
- 'EventService'
-];
-
-function atInputFile () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputFile'],
- templateUrl,
- controller: AtInputFileController,
- controllerAs: 'vm',
- link: atInputFileLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputFile;
diff --git a/awx/ui/client/lib/components/input/file.partial.html b/awx/ui/client/lib/components/input/file.partial.html
deleted file mode 100644
index d779bf4c62..0000000000
--- a/awx/ui/client/lib/components/input/file.partial.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/group.directive.js b/awx/ui/client/lib/components/input/group.directive.js
deleted file mode 100644
index 5272b6cbe7..0000000000
--- a/awx/ui/client/lib/components/input/group.directive.js
+++ /dev/null
@@ -1,209 +0,0 @@
-const templateUrl = require('~components/input/group.partial.html');
-
-function atInputGroupLink (scope, el, attrs, controllers) {
- const groupController = controllers[0];
- const formController = controllers[1];
- const element = el[0].getElementsByClassName('at-InputGroup-container')[0];
-
- groupController.init(scope, formController, element);
-}
-
-function AtInputGroupController ($scope, $compile) {
- const vm = this || {};
-
- let form;
- let scope;
- let state;
- let source;
- let element;
- let formId;
-
- vm.init = (_scope_, _form_, _element_) => {
- form = _form_;
- scope = _scope_;
- element = _element_;
- state = scope.state || {};
- source = state._source;
- ({ formId } = scope);
-
- $scope.$watch('state._source._value', vm.update);
- };
-
- vm.isValidSource = () => {
- if (!source._value || source._value === state._value) {
- return false;
- }
-
- return true;
- };
-
- vm.update = () => {
- if (state._group) {
- vm.clear();
- }
-
- if (!vm.isValidSource()) {
- return;
- }
-
- state._value = source._value;
-
- const inputs = state._get(form);
- const group = vm.createComponentConfigs(inputs);
-
- vm.insert(group);
- state._group = group;
- };
-
- vm.createComponentConfigs = inputs => {
- const group = [];
-
- if (inputs) {
- inputs.forEach((input, i) => {
- input = Object.assign(input, vm.getComponentType(input));
-
- group.push(Object.assign({
- _element: vm.createComponent(input, i),
- _key: 'inputs',
- _group: true,
- _groupIndex: i,
- _onInputLookup: state._onInputLookup,
- _onRemoveTag: state._onRemoveTag,
- }, input));
- });
- }
-
- return group;
- };
-
- vm.getComponentType = input => {
- const config = {
- _formId: formId
- };
-
- if (input.type === 'string') {
- if (input._isDynamic) {
- config._component = 'at-dynamic-select';
- config._format = 'array';
- config._data = input._choices;
- config._exp = 'choice for (index, choice) in state._data';
- config._isDynamic = true;
- } else if (!input.multiline) {
- if (input.secret) {
- config._component = 'at-input-secret';
- } else {
- config._component = 'at-input-text';
- }
- } else {
- config._expand = true;
-
- if (input.secret) {
- config._component = 'at-input-textarea-secret';
- input.format = 'ssh_private_key';
- } else {
- config._component = 'at-input-textarea';
- }
- }
-
- if (input.format === 'ssh_private_key') {
- config._format = 'ssh-key';
- }
- } else if (input.type === 'number') {
- config._component = 'at-input-number';
- } else if (input.type === 'boolean') {
- config._component = 'at-input-checkbox';
- } else if (input.type === 'file') {
- config._component = 'at-input-file';
- }
-
- if (input.choices) {
- config._component = 'at-input-select';
- config._format = 'array';
- config._data = input.choices;
- config._exp = 'choice for (index, choice) in state._data';
- }
-
- if (!config._component) {
- const preface = vm.strings.get('group.UNSUPPORTED_ERROR_PREFACE');
- throw new Error(`${preface}: ${input.type}`);
- }
-
- return config;
- };
-
- vm.insert = group => {
- const container = document.createElement('div');
- container.className = 'row';
- let col = 1;
- const colPerRow = 12 / scope.col;
- let isDivided = true;
-
- group.forEach((input, i) => {
- if (input._expand && !isDivided) {
- container.appendChild(vm.createDivider()[0]);
- }
-
- container.appendChild(input._element[0]);
-
- if ((input._expand || col % colPerRow === 0) && i !== group.length - 1) {
- container.appendChild(vm.createDivider()[0]);
- isDivided = true;
- col = 0;
- } else {
- isDivided = false;
- }
-
- col++;
- });
-
- element.appendChild(container);
- };
-
- vm.createComponent = (input, index) => {
- const tabindex = Number(scope.tab) + index;
- const col = input._expand ? 12 : scope.col;
- const component = angular.element(`<${input._component} col="${col}" tab="${tabindex}"
- state="${state._reference}._group[${index}]" id="${formId}_${input.id}_group">
- ${input._component}>`);
-
- $compile(component)(scope.$parent);
- return component;
- };
-
- vm.createDivider = () => {
- const divider = angular.element(' ');
- $compile(divider[0])(scope.$parent);
-
- return divider;
- };
-
- vm.clear = () => {
- form.deregisterInputGroup(state._group);
- element.innerHTML = '';
- state._group = undefined;
- state._value = undefined;
- };
-}
-
-AtInputGroupController.$inject = ['$scope', '$compile'];
-
-function atInputGroup () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- require: ['atInputGroup', '^^atForm'],
- templateUrl,
- controller: AtInputGroupController,
- controllerAs: 'vm',
- link: atInputGroupLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@',
- formId: '@'
- }
- };
-}
-
-export default atInputGroup;
diff --git a/awx/ui/client/lib/components/input/group.partial.html b/awx/ui/client/lib/components/input/group.partial.html
deleted file mode 100644
index c32d29bb1e..0000000000
--- a/awx/ui/client/lib/components/input/group.partial.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/label.directive.js b/awx/ui/client/lib/components/input/label.directive.js
deleted file mode 100644
index ea1fafd23a..0000000000
--- a/awx/ui/client/lib/components/input/label.directive.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const templateUrl = require('~components/input/label.partial.html');
-
-function atInputLabel () {
- return {
- restrict: 'E',
- replace: true,
- templateUrl
- };
-}
-
-export default atInputLabel;
diff --git a/awx/ui/client/lib/components/input/label.partial.html b/awx/ui/client/lib/components/input/label.partial.html
deleted file mode 100644
index 5f4cab5ee9..0000000000
--- a/awx/ui/client/lib/components/input/label.partial.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
- *
- {{::state.label | translate}}
-
- {{::state._hint}}
-
-
diff --git a/awx/ui/client/lib/components/input/lookup.directive.js b/awx/ui/client/lib/components/input/lookup.directive.js
deleted file mode 100644
index 43810d1796..0000000000
--- a/awx/ui/client/lib/components/input/lookup.directive.js
+++ /dev/null
@@ -1,152 +0,0 @@
-const templateUrl = require('~components/input/lookup.partial.html');
-
-const DEFAULT_DEBOUNCE = 250;
-const DEFAULT_KEY = 'name';
-
-function atInputLookupLink (scope, element, attrs, controllers) {
- const formController = controllers[0];
- const inputController = controllers[1];
-
- if (scope.tab === '1') {
- element.find('input')[0].focus();
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputLookupController (baseInputController, $q, $state) {
- const vm = this || {};
-
- let scope;
- let model;
- let search;
-
- vm.init = (_scope_, element, form) => {
- baseInputController.call(vm, 'input', _scope_, element, form);
-
- scope = _scope_;
- model = scope.state._model;
- scope.state._debounce = scope.state._debounce || DEFAULT_DEBOUNCE;
- search = scope.state._search || {
- key: DEFAULT_KEY,
- config: {
- unique: true
- }
- };
-
- // This should get triggered when the user selects something in the lookup modal and
- // hits save to close the modal. This won't get triggered when the user types in
- // a value in the input.
- scope.$watch('state._idFromModal', () => {
- if (scope.state._idFromModal &&
- (scope.state._idFromModal !== scope.state._value)
- ) {
- vm.search({ id: scope.state._idFromModal });
- }
- });
-
- vm.check();
- };
-
- vm.lookup = () => {
- const params = {};
-
- if (scope.state._value && scope.state._isValid) {
- params.selected = scope.state._value;
- }
-
- $state.go(scope.state._route, params);
- };
-
- vm.reset = () => {
- scope.state._idFromModal = undefined;
- scope.state._value = undefined;
- scope[scope.state._resource] = undefined;
- };
-
- vm.searchAfterDebounce = () => {
- vm.isDebouncing = true;
-
- vm.debounce = window.setTimeout(() => {
- vm.isDebouncing = false;
- vm.search();
- }, scope.state._debounce);
- };
-
- vm.resetDebounce = () => {
- clearTimeout(vm.debounce);
- vm.searchAfterDebounce();
- };
-
- vm.search = (searchParams) => {
- scope.state._touched = true;
-
- if (!scope.state._required &&
- scope.state._displayValue === '' &&
- !scope.state._idFromModal
- ) {
- scope.state._value = null;
- return vm.check({ isValid: true });
- }
- searchParams = searchParams || { [search.key]: scope.state._displayValue };
-
- return model.search(searchParams, search.config)
- .then(found => {
- if (!found) {
- vm.reset();
- return;
- }
- scope[scope.state._resource] = model.get('id');
- scope.state._value = model.get('id');
- scope.state._displayValue = model.get('name');
- scope.state._idFromModal = undefined;
- })
- .catch(() => vm.reset())
- .finally(() => {
- const isValid = scope.state._value !== undefined;
- const message = isValid ? '' : vm.strings.get('lookup.NOT_FOUND');
-
- vm.check({ isValid, message });
- });
- };
-
- vm.searchOnInput = () => {
- if (vm.isDebouncing) {
- vm.resetDebounce();
-
- return;
- }
-
- vm.searchAfterDebounce();
- };
-
- vm.removeTag = (tagToRemove) => {
- _.remove(scope.state._value, (tag) => tag === tagToRemove);
- };
-}
-
-AtInputLookupController.$inject = [
- 'BaseInputController',
- '$q',
- '$state'
-];
-
-function atInputLookup () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputLookup'],
- templateUrl,
- controller: AtInputLookupController,
- controllerAs: 'vm',
- link: atInputLookupLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputLookup;
diff --git a/awx/ui/client/lib/components/input/lookup.partial.html b/awx/ui/client/lib/components/input/lookup.partial.html
deleted file mode 100644
index 62eb2145da..0000000000
--- a/awx/ui/client/lib/components/input/lookup.partial.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/message.directive.js b/awx/ui/client/lib/components/input/message.directive.js
deleted file mode 100644
index 6e4dba6da3..0000000000
--- a/awx/ui/client/lib/components/input/message.directive.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const templateUrl = require('~components/input/message.partial.html');
-
-function atInputMessage () {
- return {
- restrict: 'E',
- replace: true,
- templateUrl
- };
-}
-
-export default atInputMessage;
diff --git a/awx/ui/client/lib/components/input/message.partial.html b/awx/ui/client/lib/components/input/message.partial.html
deleted file mode 100644
index cb73ab9620..0000000000
--- a/awx/ui/client/lib/components/input/message.partial.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
- {{ state._message }}
-
-
diff --git a/awx/ui/client/lib/components/input/secret.directive.js b/awx/ui/client/lib/components/input/secret.directive.js
deleted file mode 100644
index de16f12269..0000000000
--- a/awx/ui/client/lib/components/input/secret.directive.js
+++ /dev/null
@@ -1,90 +0,0 @@
-const templateUrl = require('~components/input/secret.partial.html');
-
-function atInputSecretLink (scope, element, attrs, controllers) {
- const formController = controllers[0];
- const inputController = controllers[1];
-
- if (scope.tab === '1') {
- element.find('input')[0].focus();
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputSecretController (baseInputController) {
- const vm = this || {};
-
- let scope;
-
- vm.init = (_scope_, element, form) => {
- baseInputController.call(vm, 'input', _scope_, element, form);
-
- scope = _scope_;
- scope.type = 'password';
- scope.state._show = false;
- scope.state._showHideText = vm.strings.get('SHOW');
-
- if (!scope.state._value || scope.state._promptOnLaunch) {
- scope.mode = 'input';
- } else {
- scope.mode = 'encrypted';
- scope.state._placeholder = vm.strings.get('ENCRYPTED');
- scope.state._buttonText = vm.strings.get('REPLACE');
- }
-
- vm.check();
- };
-
- vm.toggleRevertReplace = () => {
- scope.state._isBeingReplaced = !scope.state._isBeingReplaced;
-
- vm.onRevertReplaceToggle();
-
- if (scope.state._isBeingReplaced) {
- if (scope.type !== 'password') {
- vm.toggleShowHide();
- }
- }
- };
-
- vm.toggleShowHide = () => {
- if (scope.type === 'password') {
- scope.type = 'text';
- scope.state._show = true;
- scope.state._showHideText = vm.strings.get('HIDE');
- } else {
- scope.type = 'password';
- scope.state._show = false;
- scope.state._showHideText = vm.strings.get('SHOW');
- }
- };
-
- vm.onLookupClick = () => {
- if (scope.state._onInputLookup) {
- const { id, label, required, type } = scope.state;
- scope.state._onInputLookup({ id, label, required, type });
- }
- };
-}
-
-AtInputSecretController.$inject = ['BaseInputController'];
-
-function atInputSecret () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputSecret'],
- templateUrl,
- controller: AtInputSecretController,
- controllerAs: 'vm',
- link: atInputSecretLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputSecret;
diff --git a/awx/ui/client/lib/components/input/secret.partial.html b/awx/ui/client/lib/components/input/secret.partial.html
deleted file mode 100644
index 9f72965e7c..0000000000
--- a/awx/ui/client/lib/components/input/secret.partial.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/select.directive.js b/awx/ui/client/lib/components/input/select.directive.js
deleted file mode 100644
index ddc0e23766..0000000000
--- a/awx/ui/client/lib/components/input/select.directive.js
+++ /dev/null
@@ -1,96 +0,0 @@
-const templateUrl = require('~components/input/select.partial.html');
-
-function atInputSelectLink (scope, element, attrs, controllers) {
- const [formController, inputController] = controllers;
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputSelectController (baseInputController, eventService) {
- const vm = this || {};
-
- let scope;
- let element;
- let input;
- let select;
-
- vm.init = (_scope_, _element_, form) => {
- baseInputController.call(vm, 'input', _scope_, _element_, form);
-
- scope = _scope_;
- element = _element_;
- [input] = element.find('input');
- [select] = element.find('select');
-
- if (scope.tab === '1') {
- select.focus();
- }
-
- if (!scope.state._data || scope.state._data.length === 0) {
- scope.state._disabled = true;
- scope.state._placeholder = vm.strings.get('select.EMPTY_PLACEHOLDER');
- }
-
- vm.setListeners();
- vm.check();
-
- if (scope.state._value) {
- vm.updateDisplayModel();
- }
- };
-
- vm.setListeners = () => {
- const listeners = eventService.addListeners([
- [input, 'focus', () => select.focus],
- [select, 'mousedown', () => scope.$apply(() => { scope.open = !scope.open; })],
- [select, 'focus', () => input.classList.add('at-Input--focus')],
- [select, 'change', () => scope.$apply(() => {
- scope.open = false;
- vm.updateDisplayModel();
- vm.check();
- })],
- [select, 'blur', () => {
- input.classList.remove('at-Input--focus');
- scope.open = scope.open && false;
- }]
- ]);
-
- scope.$on('$destroy', () => eventService.remove(listeners));
- };
-
- vm.updateDisplayModel = () => {
- if (scope.state._format === 'selectFromOptions') {
- scope.displayModel = scope.state._value[1];
- } else if (scope.state._format === 'array') {
- scope.displayModel = scope.state._value;
- } else if (scope.state._format === 'objects') {
- scope.displayModel = scope.state._value[scope.state._display];
- } else if (scope.state._format === 'grouped-object') {
- scope.displayModel = scope.state._value[scope.state._display];
- } else {
- throw new Error(vm.strings.get('select.UNSUPPORTED_TYPE_ERROR'));
- }
- };
-}
-
-AtInputSelectController.$inject = ['BaseInputController', 'EventService'];
-
-function atInputSelect () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^at-form', 'atInputSelect'],
- templateUrl,
- controller: AtInputSelectController,
- controllerAs: 'vm',
- link: atInputSelectLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputSelect;
diff --git a/awx/ui/client/lib/components/input/select.partial.html b/awx/ui/client/lib/components/input/select.partial.html
deleted file mode 100644
index f3ba5e845a..0000000000
--- a/awx/ui/client/lib/components/input/select.partial.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/slider.directive.js b/awx/ui/client/lib/components/input/slider.directive.js
deleted file mode 100644
index a2e1b8c28e..0000000000
--- a/awx/ui/client/lib/components/input/slider.directive.js
+++ /dev/null
@@ -1,38 +0,0 @@
-const templateUrl = require('~components/input/slider.partial.html');
-
-function atInputSliderLink (scope, element, attrs, controllers) {
- const [formController, inputController] = controllers;
-
- inputController.init(scope, element, formController);
-}
-
-function atInputSliderController (baseInputController) {
- const vm = this || {};
-
- vm.init = (_scope_, _element_, form) => {
- baseInputController.call(vm, 'input', _scope_, _element_, form);
-
- vm.check();
- };
-}
-
-atInputSliderController.$inject = ['BaseInputController'];
-
-function atInputSlider () {
- return {
- restrict: 'E',
- require: ['^^atForm', 'atInputSlider'],
- replace: true,
- templateUrl,
- controller: atInputSliderController,
- controllerAs: 'vm',
- link: atInputSliderLink,
- scope: {
- state: '=?',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputSlider;
diff --git a/awx/ui/client/lib/components/input/slider.partial.html b/awx/ui/client/lib/components/input/slider.partial.html
deleted file mode 100644
index e07abdadfa..0000000000
--- a/awx/ui/client/lib/components/input/slider.partial.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/text.directive.js b/awx/ui/client/lib/components/input/text.directive.js
deleted file mode 100644
index c24c807cd4..0000000000
--- a/awx/ui/client/lib/components/input/text.directive.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const templateUrl = require('~components/input/text.partial.html');
-
-function atInputTextLink (scope, element, attrs, controllers) {
- const formController = controllers[0];
- const inputController = controllers[1];
-
- if (scope.tab === '1') {
- const el = element.find('input')[0];
- if (el) {
- el.focus();
- }
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputTextController (baseInputController) {
- const vm = this || {};
-
- let scope;
-
- vm.init = (_scope_, element, form) => {
- baseInputController.call(vm, 'input', _scope_, element, form);
- scope = _scope_;
-
- scope.$watch('state._value', () => vm.check());
- };
-
- vm.onLookupClick = () => {
- if (scope.state._onInputLookup) {
- const { id, label, required, type } = scope.state;
- scope.state._onInputLookup({ id, label, required, type });
- }
- };
-}
-
-AtInputTextController.$inject = ['BaseInputController'];
-
-function atInputText () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputText'],
- templateUrl,
- controller: AtInputTextController,
- controllerAs: 'vm',
- link: atInputTextLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputText;
diff --git a/awx/ui/client/lib/components/input/text.partial.html b/awx/ui/client/lib/components/input/text.partial.html
deleted file mode 100644
index 0d9fb78e17..0000000000
--- a/awx/ui/client/lib/components/input/text.partial.html
+++ /dev/null
@@ -1,53 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/textarea-secret.directive.js b/awx/ui/client/lib/components/input/textarea-secret.directive.js
deleted file mode 100644
index fb4b29d870..0000000000
--- a/awx/ui/client/lib/components/input/textarea-secret.directive.js
+++ /dev/null
@@ -1,129 +0,0 @@
-const templateUrl = require('~components/input/textarea-secret.partial.html');
-
-function atInputTextareaSecretLink (scope, element, attrs, controllers) {
- const [formController, inputController] = controllers;
-
- if (scope.tab === '1') {
- element.find('textarea')[0].focus();
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputTextareaSecretController (baseInputController, eventService) {
- const vm = this || {};
-
- let scope;
- let textarea;
- let input;
-
- vm.init = (_scope_, element, form) => {
- baseInputController.call(vm, 'input', _scope_, element, form);
-
- scope = _scope_;
-
- [textarea] = element.find('textarea');
-
- if (scope.state.format === 'ssh_private_key') {
- scope.ssh = true;
- scope.state._hint = scope.state._hint || vm.strings.get('textarea.SSH_KEY_HINT');
- [input] = element.find('input');
- }
-
- if (scope.state._value) {
- scope.state._buttonText = vm.strings.get('REPLACE');
- scope.state._placeholder = vm.strings.get('ENCRYPTED');
- } else if (scope.state.format === 'ssh_private_key') {
- vm.listeners = vm.setFileListeners(textarea, input);
- scope.state._displayHint = true;
- }
-
- vm.check();
-
- scope.$watch('state[state._activeModel]', () => vm.check());
- scope.$watch('state._isBeingReplaced', () => vm.onIsBeingReplacedChanged());
- };
-
- vm.onIsBeingReplacedChanged = () => {
- if (!scope.state) return;
- if (!scope.state._touched) return;
-
- vm.onRevertReplaceToggle();
-
- if (scope.state._isBeingReplaced) {
- scope.state._placeholder = '';
- scope.state._displayHint = true;
- vm.listeners = vm.setFileListeners(textarea, input);
- } else {
- scope.state._displayHint = false;
- scope.state._placeholder = vm.strings.get('ENCRYPTED');
-
- if (vm.listeners) {
- eventService.remove(vm.listeners);
- }
- }
- };
-
- vm.setFileListeners = (textareaEl, inputEl) => eventService.addListeners([
- [textareaEl, 'dragenter', event => {
- event.stopPropagation();
- event.preventDefault();
- scope.$apply(() => { scope.drag = true; });
- }],
-
- [inputEl, 'dragleave', event => {
- event.stopPropagation();
- event.preventDefault();
- scope.$apply(() => { scope.drag = false; });
- }],
-
- [inputEl, 'change', event => {
- const reader = new FileReader();
-
- reader.onload = () => vm.readFile(reader, event);
- reader.readAsText(inputEl.files[0]);
- }]
- ]);
-
- vm.readFile = (reader) => {
- scope.$apply(() => {
- scope.state._value = reader.result;
- vm.check();
- scope.drag = false;
- input.value = '';
- });
- };
-
- vm.onLookupClick = () => {
- if (scope.state._onInputLookup) {
- const { id, label, required, type } = scope.state;
- scope.state._onInputLookup({ id, label, required, type });
- }
- };
-}
-
-AtInputTextareaSecretController.$inject = [
- 'BaseInputController',
- 'EventService',
- 'ComponentsStrings'
-];
-
-function atInputTextareaSecret () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputTextareaSecret'],
- templateUrl,
- controller: AtInputTextareaSecretController,
- controllerAs: 'vm',
- link: atInputTextareaSecretLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputTextareaSecret;
diff --git a/awx/ui/client/lib/components/input/textarea-secret.partial.html b/awx/ui/client/lib/components/input/textarea-secret.partial.html
deleted file mode 100644
index 912dc4160b..0000000000
--- a/awx/ui/client/lib/components/input/textarea-secret.partial.html
+++ /dev/null
@@ -1,70 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/input/textarea.directive.js b/awx/ui/client/lib/components/input/textarea.directive.js
deleted file mode 100644
index 2456f90252..0000000000
--- a/awx/ui/client/lib/components/input/textarea.directive.js
+++ /dev/null
@@ -1,53 +0,0 @@
-const templateUrl = require('~components/input/textarea.partial.html');
-
-function atInputTextareaLink (scope, element, attrs, controllers) {
- const formController = controllers[0];
- const inputController = controllers[1];
-
- if (scope.tab === '1') {
- element.find('input')[0].focus();
- }
-
- inputController.init(scope, element, formController);
-}
-
-function AtInputTextareaController (baseInputController) {
- const vm = this || {};
- let scope;
-
- vm.init = (_scope_, element, form) => {
- baseInputController.call(vm, 'input', _scope_, element, form);
- scope = _scope_;
-
- vm.check();
- };
-
- vm.onLookupClick = () => {
- if (scope.state._onInputLookup) {
- const { id, label, required, type } = scope.state;
- scope.state._onInputLookup({ id, label, required, type });
- }
- };
-}
-
-AtInputTextareaController.$inject = ['BaseInputController'];
-
-function atInputTextarea () {
- return {
- restrict: 'E',
- transclude: true,
- replace: true,
- require: ['^^atForm', 'atInputTextarea'],
- templateUrl,
- controller: AtInputTextareaController,
- controllerAs: 'vm',
- link: atInputTextareaLink,
- scope: {
- state: '=',
- col: '@',
- tab: '@'
- }
- };
-}
-
-export default atInputTextarea;
diff --git a/awx/ui/client/lib/components/input/textarea.partial.html b/awx/ui/client/lib/components/input/textarea.partial.html
deleted file mode 100644
index 044d2c119f..0000000000
--- a/awx/ui/client/lib/components/input/textarea.partial.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/launchTemplateButton/_index.less b/awx/ui/client/lib/components/launchTemplateButton/_index.less
deleted file mode 100644
index 94c9988872..0000000000
--- a/awx/ui/client/lib/components/launchTemplateButton/_index.less
+++ /dev/null
@@ -1,23 +0,0 @@
-.at-LaunchTemplate {
- &--button {
- font-size: 16px;
- height: 30px;
- min-width: 30px;
- color: #646972;
- background-color: inherit;
- border: none;
- border-radius: 5px;
- }
-
- &--button:hover {
- background-color: @at-blue;
- color: white;
- }
-}
-
-.open {
- .at-LaunchTemplate--button {
- background-color: @at-blue;
- color: white;
- }
-}
diff --git a/awx/ui/client/lib/components/launchTemplateButton/launchTemplateButton.component.js b/awx/ui/client/lib/components/launchTemplateButton/launchTemplateButton.component.js
deleted file mode 100644
index 52ee2ea4a9..0000000000
--- a/awx/ui/client/lib/components/launchTemplateButton/launchTemplateButton.component.js
+++ /dev/null
@@ -1,197 +0,0 @@
-import templateUrl from './launchTemplateButton.partial.html';
-
-const atLaunchTemplate = {
- templateUrl,
- bindings: {
- template: '<',
- showTextButton: '<',
- disabled: '='
- },
- controller: ['JobTemplateModel', 'WorkflowJobTemplateModel', 'PromptService', '$state',
- 'ComponentsStrings', 'ProcessErrors', '$scope', 'TemplatesStrings', 'Alert',
- atLaunchTemplateCtrl],
- controllerAs: 'vm'
-};
-
-function atLaunchTemplateCtrl (
- JobTemplate, WorkflowTemplate, PromptService, $state,
- componentsStrings, ProcessErrors, $scope, templatesStrings, Alert
-) {
- const vm = this;
- const jobTemplate = new JobTemplate();
- const workflowTemplate = new WorkflowTemplate();
- vm.strings = componentsStrings;
- vm.launchTooltip = vm.strings.get('launchTemplate.DEFAULT');
-
- $scope.$watch('vm.disabled', (val) => {
- vm.launchTooltip = (val) ? vm.strings.get('launchTemplate.DISABLED') : vm.strings.get('launchTemplate.DEFAULT');
- });
-
- const createErrorHandler = (path, action) =>
- ({ data, status }) => {
- const hdr = templatesStrings.get('error.HEADER');
- const msg = templatesStrings.get('error.CALL', { path, action, status });
- ProcessErrors($scope, data, status, null, { hdr, msg });
- };
-
- vm.startLaunchTemplate = () => {
- if (!vm.disabled) {
- if (vm.template.type === 'job_template') {
- const selectedJobTemplate = jobTemplate.create();
- const preLaunchPromises = [
- selectedJobTemplate.getLaunch(vm.template.id)
- .catch(createErrorHandler(`/api/v2/job_templates/${vm.template.id}/launch`, 'GET')),
- selectedJobTemplate.optionsLaunch(vm.template.id)
- .catch(createErrorHandler(`/api/v2/job_templates/${vm.template.id}/launch`, 'OPTIONS'))
- ];
-
- Promise.all(preLaunchPromises)
- .then(([launchData, launchOptions]) => {
- // If we don't get both of these things then one of the
- // promises was rejected
- if (launchData && launchOptions) {
- if (selectedJobTemplate.canLaunchWithoutPrompt()) {
- selectedJobTemplate
- .postLaunch({ id: vm.template.id })
- .then(({ data }) => {
- /* Slice Jobs: Redirect to WF Details page if returned
- job type is a WF job */
- if (data.type === 'workflow_job' && data.workflow_job !== null) {
- $state.go('workflowResults', { id: data.workflow_job }, { reload: true });
- } else {
- $state.go('output', { id: data.job, type: 'playbook' }, { reload: true });
- }
- })
- .catch(createErrorHandler(`/api/v2/job_templates/${vm.template.id}/launch`, 'POST'));
- } else {
- const promptData = {
- launchConf: launchData.data,
- launchOptions: launchOptions.data,
- template: vm.template.id,
- templateName: vm.template.name,
- templateType: vm.template.type,
- prompts: PromptService.processPromptValues({
- launchConf: launchData.data,
- launchOptions: launchOptions.data
- }),
- triggerModalOpen: true
- };
-
- if (launchData.data.survey_enabled) {
- selectedJobTemplate.getSurveyQuestions(vm.template.id)
- .then(({ data }) => {
- const processed = PromptService.processSurveyQuestions({
- surveyQuestions: data.spec
- });
- promptData.surveyQuestions = processed.surveyQuestions;
- vm.promptData = promptData;
- })
- .catch(createErrorHandler(`/api/v2/job_templates/${vm.template.id}/survey_spec`, 'GET'));
- } else {
- vm.promptData = promptData;
- }
- }
- }
- });
- } else if (vm.template.type === 'workflow_job_template') {
- const selectedWorkflowJobTemplate = workflowTemplate.create();
- const preLaunchPromises = [
- selectedWorkflowJobTemplate.request('get', vm.template.id)
- .catch(createErrorHandler(`/api/v2/workflow_job_templates/${vm.template.id}`, 'GET')),
- selectedWorkflowJobTemplate.getLaunch(vm.template.id)
- .catch(createErrorHandler(`/api/v2/workflow_job_templates/${vm.template.id}/launch`, 'GET')),
- selectedWorkflowJobTemplate.optionsLaunch(vm.template.id)
- .catch(createErrorHandler(`/api/v2/workflow_job_templates/${vm.template.id}/launch`, 'OPTIONS')),
- ];
-
- Promise.all(preLaunchPromises)
- .then(([wfjtData, launchData, launchOptions]) => {
- // If we don't get all of these things then one of the
- // promises was rejected
- if (wfjtData && launchData && launchOptions) {
- if (selectedWorkflowJobTemplate.canLaunchWithoutPrompt()) {
- selectedWorkflowJobTemplate
- .postLaunch({ id: vm.template.id })
- .then(({ data }) => {
- $state.go('workflowResults', { id: data.workflow_job }, { reload: true });
- })
- .catch(createErrorHandler(`/api/v2/workflow_job_templates/${vm.template.id}/launch`, 'POST'));
- } else {
- launchData.data.defaults.extra_vars = wfjtData.data.extra_vars;
-
- const promptData = {
- launchConf: selectedWorkflowJobTemplate.getLaunchConf(),
- launchOptions: launchOptions.data,
- template: vm.template.id,
- templateName: vm.template.name,
- templateType: vm.template.type,
- prompts: PromptService.processPromptValues({
- launchConf: selectedWorkflowJobTemplate.getLaunchConf(),
- launchOptions: launchOptions.data
- }),
- triggerModalOpen: true,
- };
-
- if (launchData.data.survey_enabled) {
- selectedWorkflowJobTemplate.getSurveyQuestions(vm.template.id)
- .then(({ data }) => {
- const processed = PromptService.processSurveyQuestions({
- surveyQuestions: data.spec
- });
- promptData.surveyQuestions = processed.surveyQuestions;
- vm.promptData = promptData;
- })
- .catch(createErrorHandler(`/api/v2/workflow_job_templates/${vm.template.id}/survey_spec`, 'GET'));
- } else {
- vm.promptData = promptData;
- }
- }
- }
- });
- } else {
- Alert(templatesStrings.get('error.UNKNOWN'), templatesStrings.get('alert.UNKNOWN_LAUNCH'));
- }
- }
- };
-
- vm.launchTemplateWithPrompts = () => {
- const jobLaunchData = PromptService.bundlePromptDataForLaunch(vm.promptData);
-
- // If the extra_vars dict is empty, we don't want to include it
- // if we didn't prompt for anything.
- if (
- _.isEmpty(jobLaunchData.extra_vars) &&
- !(
- vm.promptData.launchConf.ask_variables_on_launch &&
- vm.promptData.launchConf.survey_enabled &&
- vm.promptData.surveyQuestions.length > 0
- )
- ) {
- delete jobLaunchData.extra_vars;
- }
-
- if (vm.promptData.templateType === 'job_template') {
- jobTemplate.create().postLaunch({
- id: vm.promptData.template,
- launchData: jobLaunchData
- }).then((launchRes) => {
- /* Slice Jobs: Redirect to WF Details page if returned
- job type is a WF job */
- if (launchRes.data.type === 'workflow_job' && launchRes.data.workflow_job !== null) {
- $state.go('workflowResults', { id: launchRes.data.workflow_job }, { reload: true });
- } else {
- $state.go('output', { id: launchRes.data.job, type: 'playbook' }, { reload: true });
- }
- }).catch(createErrorHandler(`/api/v2/job_templates/${vm.template.id}/launch`, 'POST'));
- } else if (vm.promptData.templateType === 'workflow_job_template') {
- workflowTemplate.create().postLaunch({
- id: vm.promptData.template,
- launchData: jobLaunchData
- }).then((launchRes) => {
- $state.go('workflowResults', { id: launchRes.data.workflow_job }, { reload: true });
- }).catch(createErrorHandler(`/api/v2/workflow_job_templates/${vm.template.id}/launch`, 'POST'));
- }
- };
-}
-
-export default atLaunchTemplate;
diff --git a/awx/ui/client/lib/components/launchTemplateButton/launchTemplateButton.partial.html b/awx/ui/client/lib/components/launchTemplateButton/launchTemplateButton.partial.html
deleted file mode 100644
index dfa32b7082..0000000000
--- a/awx/ui/client/lib/components/launchTemplateButton/launchTemplateButton.partial.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- {{:: vm.strings.get('launchTemplate.BUTTON_LABEL') }}
-
-
-
diff --git a/awx/ui/client/lib/components/layout/_index.less b/awx/ui/client/lib/components/layout/_index.less
deleted file mode 100644
index 4491118bef..0000000000
--- a/awx/ui/client/lib/components/layout/_index.less
+++ /dev/null
@@ -1,321 +0,0 @@
-.at-Layout {
- min-height: 100vh;
- width: 100%;
- display: flex;
-
- &-topNav {
- display: flex;
- background-color: @at-color-top-nav-background;
- border-bottom: @at-border-default-width solid @at-color-top-nav-border-bottom;
- z-index: @at-z-index-nav;
- position: fixed;
- right: 0;
- left: 0;
- top: 0;
- height: @at-height-top-nav;
-
- .at-Layout-topNavRightAligner {
- margin-left: auto;
- }
-
- .at-Layout-topNavItem {
- color: @at-color-top-nav-item-text;
- padding: 0 @at-padding-top-nav-item-sides;
-
- a {
- cursor: pointer;
- }
-
- a, div {
- color: @at-color-top-nav-item-text;
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
- }
-
- i {
- color: @at-color-top-nav-item-icon;
- font-size: @at-height-top-nav-item-icon;
- }
-
- &--logo {
- padding-left: 0px;
-
- img {
- max-width: @main-menu-max-width;
- max-height: @main-menu-max-height;
- height: @main-menu-height;
- width: @main-menu-width;
- margin: @main-menu-margin;
- flex: initial;
- pointer-events: none;
- }
- }
-
- &--user {
- i {
- margin-right: @at-margin-top-nav-item-between-icon-and-name;
- }
- }
-
- &--socket {
- i {
- margin-top: @at-margin-top-nav-item-icon-socket-top-makeup;
- font-size: @at-height-top-nav-item-icon-socket;
- text-shadow:
- -@at-border-default-width -@at-border-default-width 0 @at-color-top-nav-item-icon-socket-outline,
- @at-border-default-width -@at-border-default-width 0 @at-color-top-nav-item-icon-socket-outline,
- -@at-border-default-width @at-border-default-width 0 @at-color-top-nav-item-icon-socket-outline,
- @at-border-default-width @at-border-default-width 0 @at-color-top-nav-item-icon-socket-outline
- }
- }
-
- &:focus,
- &:hover,
- &.is-currentRoute {
- background-color: @at-color-top-nav-item-background-hover;
- }
-
- &.is-loggedOut {
- opacity: 0;
- }
- }
-
- .at-Layout-Approvals {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
- }
-
- .at-Layout-ApprovalsBadge {
- margin-left: 10px;
- padding: 5px;
- border-radius: 3px;
- background-color: @at-gray-646972;
- color: @at-white;
- height: 16px;
- font-size: 11px;
- cursor: default;
- display: flex;
- align-items: center;
- }
-
- .at-Layout-ApprovalsBadgeActive {
- background-color: @at-red-bright;
- }
- }
-
- &-sideContainer {
- background: @at-color-side-nav-background;
- }
-
- &-side {
- margin-top: @at-height-top-side-nav-makeup;
- width: @at-width-collapsed-side-nav;
-
- .at-Popover-container {
- margin-top: 2px;
- margin-left: -11px;
- }
-
- .at-Popover-arrow {
- padding-top: 7px;
- margin-left: -10px;
- }
-
- .at-Layout-sideNavItem {
- background: inherit;
- color: @at-color-side-nav-content;
- display: flex;
- cursor: pointer;
- font-size: 13px;
- line-height: 1.42857143;
- i {
- cursor: pointer;
- color: @at-color-side-nav-item-icon;
- font-size: @at-font-size-side-nav-icon;
- padding: @at-padding-side-nav-item-icon;
- padding-left: @at-padding-left-side-nav-item-icon;
- text-align: center;
- width: 50px;
- }
-
- i.is-no-tooltip {
- padding-left: @at-padding-left-side-nav-item-icon-no-tooltip;
- }
-
- &:hover,
- &.is-active {
- background: @at-color-side-nav-item-background-hover;
- border-left: @at-highlight-left-border-size solid @at-color-side-nav-item-border-hover;
-
- i {
- color: @at-color-side-nav-content;
- margin-left: @at-highlight-left-border-margin-makeup;
- }
- }
- }
-
- .at-Layout-sideNavToggle {
- padding-top: @at-padding-top-side-nav-toggle;
-
- i {
- padding-left: @at-padding-left-side-nav-toggle-icon;
- }
- }
-
- .at-Layout-sideNavSpacer {
- border-bottom: 1px solid @at-color-side-nav-space-collapsed-border;
- padding: 0;
- margin: @at-margin-side-nav-space-collapsed;
- }
-
- .at-Layout-sideNavSpacer--first {
- display: none;
- }
-
- .at-Layout-sideNavHeader {
- display: none;
- }
-
- &--expanded {
- width: @at-width-expanded-side-nav;
-
- .at-Layout-sideNavItem {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- padding-right: @at-padding-between-side-nav-icon-text;
-
- i {
- padding-left: @at-padding-left-side-nav-item-icon-expanded;
- }
- }
-
- + .at-Layout-main {
- padding-left: @at-width-expanded-side-nav;
- }
-
- + .at-Layout-main--noLicense {
- padding-left: 0;
- }
-
- .at-Layout-sideNavSpacer--first {
- display: inherit;
- }
-
- .at-Layout-sideNavSpacer {
- height: @at-height-side-nav-spacer;
- font-size: @at-font-size-side-nav-space;
- color: @at-color-side-nav-item-spacer;
- padding: @at-padding-side-nav-item-spacer;
- text-transform: uppercase;
- border-bottom: 0;
- margin: 0;
- }
-
- .at-Layout-sideNavHeader {
- display: inherit;
- }
- }
- }
-
- &-main {
- display: flex;
- width: 100%;
- flex-direction: column;
- padding-bottom: @at-space-4x;
- overflow-x: hidden;
- }
-
- &-content {
- flex: 1px;
- }
-}
-
-@media screen and (max-width: @at-breakpoint-mobile-layout) {
- .at-Layout {
- &-side {
- top: 60px;
- background-color: transparent;
-
- .at-Layout-sideNavItem.at-Layout-sideNavToggle {
- display: flex;
- height: @at-height-side-nav-toggle-mobile;
- align-items: center;
- width: @at-width-side-nav-toggle-mobile;
-
- i {
- padding-bottom: @at-padding-bottom-side-nav-toggle-mobile;
- }
- }
-
- .at-Layout-sideNavItem,
- .at-Layout-sideNavSpacer {
- display: none;
- background-color: @at-color-side-nav-background;
- }
-
- &--expanded {
- width: 100vw;
- z-index: @at-z-index-side-nav;
-
- .at-Layout-sideNavItem,
- .at-Layout-sideNavSpacer {
- display: flex;
- }
- }
- }
-
- .at-Layout-main {
- padding-left: 0;
-
- #content-container {
- padding-top: 100px;
- }
- }
- }
-}
-
-/* Tower Sub Nav Dropdown */
-.at-SettingsSubPane {
- position: relative;
-}
-.at-SettingsSubPane-content {
- display: none;
- position: absolute;
- background-color: @at-color-side-nav-background;
- min-width: 140px;
- box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
- bottom: 0px;
- left: @at-width-collapsed-side-nav;
- z-index: 2000;
-}
-
-.at-Layout-side--expanded + .at-SettingsSubPane {
- .at-SettingsSubPane-content {
- left: @at-width-expanded-side-nav;
- }
-}
-
-.at-SettingsSubPane-content a {
- color: @at-white;
- font-size: 13px;
- padding: 10px 20px;
- text-decoration: none;
- display: block;
- height: 39px;
-}
-
-// hover stuff
-.at-SettingsSubPane-content a:hover {
- background-color: @at-color-side-nav-item-background-hover;
-}
-.at-SettingsSubPane.at-SettingsSubPane--visible .at-SettingsSubPane-content {
- display: block;
-}
-.at-SettingsSubPane.at-SettingsSubPane--visible .nav-button {
- background-color: @at-color-side-nav-item-background-hover;
-}
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/layout/layout.directive.js b/awx/ui/client/lib/components/layout/layout.directive.js
deleted file mode 100644
index a5d9332f2a..0000000000
--- a/awx/ui/client/lib/components/layout/layout.directive.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import defaultStrings from '~assets/default.strings.json';
-
-const templateUrl = require('~components/layout/layout.partial.html');
-
-function AtLayoutController ($scope, $http, strings, ProcessErrors, $transitions) {
- const vm = this || {};
-
- vm.product = defaultStrings.BRAND_NAME;
-
- $transitions.onSuccess({}, (transition) => {
- vm.currentState = transition.to().name;
- });
-
- $scope.$watch('$root.current_user', (val) => {
- vm.isLoggedIn = val && val.username;
- if (!_.isEmpty(val)) {
- vm.isSuperUser = $scope.$root.user_is_superuser || $scope.$root.user_is_system_auditor;
- vm.currentUsername = val.username;
- vm.currentUserId = val.id;
-
- if (!vm.isSuperUser) {
- checkOrgAdmin();
- checkNotificationAdmin();
- }
- }
- });
-
- $scope.$watch('$root.pendingApprovalCount', () => {
- vm.approvalsCount = _.get($scope, '$root.pendingApprovalCount') || 0;
- });
-
- $scope.$watch('$root.socketStatus', (newStatus) => {
- vm.socketState = newStatus;
- vm.socketIconClass = `icon-socket-${vm.socketState}`;
- });
-
- $scope.$watch('$root.licenseMissing', (licenseMissing) => {
- vm.licenseIsMissing = licenseMissing;
- });
-
- vm.getString = string => {
- try {
- return strings.get(`layout.${string}`);
- } catch (err) {
- return strings.get(string);
- }
- };
-
- vm.openApprovals = () => {
- vm.showApprovals = true;
- };
-
- vm.closeApprovals = () => {
- vm.showApprovals = false;
- };
-
- function checkOrgAdmin () {
- const usersPath = `/api/v2/users/${vm.currentUserId}/admin_of_organizations/`;
- $http.get(usersPath)
- .then(({ data }) => {
- if (data.count > 0) {
- vm.isOrgAdmin = true;
- } else {
- vm.isOrgAdmin = false;
- }
- })
- .catch(({ data, status }) => {
- ProcessErrors(null, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: usersPath, action: 'GET', status })
- });
- });
- }
-
- function checkNotificationAdmin () {
- const notifAdminOrgsPath = 'api/v2/organizations/?role_level=notification_admin_role';
- $http.get(notifAdminOrgsPath)
- .then(({ data }) => {
- if (data.count > 0) {
- vm.isNotificationAdmin = true;
- } else {
- vm.isNotificationAdmin = false;
- }
- })
- .catch(({ data, status }) => {
- ProcessErrors(null, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: notifAdminOrgsPath, action: 'GET', status })
- });
- });
- }
-}
-
-AtLayoutController.$inject = ['$scope', '$http', 'ComponentsStrings', 'ProcessErrors', '$transitions'];
-
-function atLayout () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- controller: AtLayoutController,
- controllerAs: 'vm',
- scope: {}
- };
-}
-
-export default atLayout;
diff --git a/awx/ui/client/lib/components/layout/layout.partial.html b/awx/ui/client/lib/components/layout/layout.partial.html
deleted file mode 100644
index f8a00879d5..0000000000
--- a/awx/ui/client/lib/components/layout/layout.partial.html
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/layout/side-nav-item.directive.js b/awx/ui/client/lib/components/layout/side-nav-item.directive.js
deleted file mode 100644
index a4af383182..0000000000
--- a/awx/ui/client/lib/components/layout/side-nav-item.directive.js
+++ /dev/null
@@ -1,70 +0,0 @@
-const templateUrl = require('~components/layout/side-nav-item.partial.html');
-
-function atSideNavItemLink (scope, element, attrs, ctrl) {
- [scope.navVm, scope.layoutVm] = ctrl;
-
- if (attrs.showSettingsSubMenu) {
- element.hover(() => {
- scope.navVm.onSettingsNavItem = true;
- scope.navVm.showSettingsSubMenu = true;
- }, () => {
- scope.navVm.onSettingsNavItem = false;
- setTimeout(() => {
- if (!scope.navVm.onSettingsSubPane) {
- scope.navVm.showSettingsSubMenu = false;
- }
- }, 100);
- });
- }
-}
-
-function AtSideNavItemController ($scope, strings) {
- const vm = this || {};
-
- $scope.$watch('layoutVm.currentState', current => {
- if ($scope.name === 'portal mode') {
- vm.isRoute = (current && current.indexOf('portalMode') === 0);
- } else if (current && current.indexOf($scope.route) === 0) {
- if (current.indexOf('schedules') === 0 && $scope.route === 'jobs') {
- vm.isRoute = false;
- } else {
- vm.isRoute = true;
- }
- } else {
- vm.isRoute = false;
- }
- });
-
- vm.tooltip = {
- popover: {
- text: strings.get(`layout.${$scope.name}`),
- on: 'mouseenter',
- icon: $scope.iconClass,
- position: 'right',
- arrowHeight: 18
- }
- };
-}
-
-AtSideNavItemController.$inject = ['$scope', 'ComponentsStrings'];
-
-function atSideNavItem () {
- return {
- restrict: 'E',
- templateUrl,
- require: ['^^atSideNav', '^^atLayout'],
- controller: AtSideNavItemController,
- controllerAs: 'vm',
- link: atSideNavItemLink,
- transclude: true,
- scope: {
- iconClass: '@',
- name: '@',
- route: '@',
- systemAdminOnly: '@',
- noTooltipOnCollapsed: '@'
- }
- };
-}
-
-export default atSideNavItem;
diff --git a/awx/ui/client/lib/components/layout/side-nav-item.partial.html b/awx/ui/client/lib/components/layout/side-nav-item.partial.html
deleted file mode 100644
index 380ed08f10..0000000000
--- a/awx/ui/client/lib/components/layout/side-nav-item.partial.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
- {{ layoutVm.getString(name) }}
-
-
diff --git a/awx/ui/client/lib/components/layout/side-nav.directive.js b/awx/ui/client/lib/components/layout/side-nav.directive.js
deleted file mode 100644
index 6edd96869d..0000000000
--- a/awx/ui/client/lib/components/layout/side-nav.directive.js
+++ /dev/null
@@ -1,78 +0,0 @@
-const templateUrl = require('~components/layout/side-nav.partial.html');
-
-let $document;
-
-function atSideNavLink (scope, element, attrs, ctrl) {
- scope.layoutVm = ctrl;
-
- $document.on('click', (e) => {
- if ($(e.target).parents('.at-Layout-side').length === 0) {
- scope.$emit('clickOutsideSideNav');
- }
- });
-
- element.find('.at-SettingsSubPane').hover(() => {
- scope.vm.onSettingsSubPane = true;
- }, () => {
- scope.vm.onSettingsSubPane = false;
- setTimeout(() => {
- if (!scope.vm.onSettingsNavItem) {
- scope.vm.showSettingsSubMenu = false;
- }
- }, 100);
- });
-}
-
-function AtSideNavController ($scope, $window) {
- const vm = this || {};
- const breakpoint = 700;
-
- vm.isExpanded = true;
-
- vm.toggleExpansion = () => {
- vm.isExpanded = !vm.isExpanded;
- };
-
- $scope.$watch('layoutVm.currentState', () => {
- if ($window.innerWidth <= breakpoint) {
- vm.isExpanded = false;
- }
- });
-
- $scope.$on('clickOutsideSideNav', () => {
- if ($window.innerWidth <= breakpoint) {
- vm.isExpanded = false;
- }
- });
-
- $(window).resize(() => {
- if ($window.innerWidth <= breakpoint) {
- vm.isExpanded = false;
- } else {
- vm.isExpanded = true;
- }
- });
-}
-
-AtSideNavController.$inject = ['$scope', '$window'];
-
-function atSideNav (_$document_) {
- $document = _$document_;
-
- return {
- restrict: 'E',
- replace: true,
- require: '^^atLayout',
- controller: AtSideNavController,
- controllerAs: 'vm',
- link: atSideNavLink,
- transclude: true,
- templateUrl,
- scope: {
- }
- };
-}
-
-atSideNav.$inject = ['$document'];
-
-export default atSideNav;
diff --git a/awx/ui/client/lib/components/layout/side-nav.partial.html b/awx/ui/client/lib/components/layout/side-nav.partial.html
deleted file mode 100644
index 028888d14b..0000000000
--- a/awx/ui/client/lib/components/layout/side-nav.partial.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/layout/top-nav-item.directive.js b/awx/ui/client/lib/components/layout/top-nav-item.directive.js
deleted file mode 100644
index 8851565a3f..0000000000
--- a/awx/ui/client/lib/components/layout/top-nav-item.directive.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const templateUrl = require('~components/layout/top-nav-item.partial.html');
-
-function atTopNavItemLink (scope, element, attrs, ctrl) {
- scope.layoutVm = ctrl;
-
- scope.isHidden = false;
-
- const shownWhen = attrs.isShown;
-
- if (shownWhen !== 'missingLicense') {
- scope.$watch('layoutVm.licenseIsMissing', (val) => {
- scope.isHidden = val;
- });
- }
-}
-
-function atTopNavItem () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- require: '^^atLayout',
- link: atTopNavItemLink,
- scope: {
- }
- };
-}
-
-export default atTopNavItem;
diff --git a/awx/ui/client/lib/components/layout/top-nav-item.partial.html b/awx/ui/client/lib/components/layout/top-nav-item.partial.html
deleted file mode 100644
index 2071888e0f..0000000000
--- a/awx/ui/client/lib/components/layout/top-nav-item.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
diff --git a/awx/ui/client/lib/components/list/_index.less b/awx/ui/client/lib/components/list/_index.less
deleted file mode 100644
index ae88096a62..0000000000
--- a/awx/ui/client/lib/components/list/_index.less
+++ /dev/null
@@ -1,388 +0,0 @@
-.at-List {
- margin-top: @at-margin-top-list;
-}
-
-.at-List--empty {
- margin-top: @at-margin-top-list;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: @at-height-list-empty;
- border-radius: @at-border-radius;
- border: @at-border-default-width solid @at-color-list-empty-border;
- background-color: @at-color-list-empty-background;
- color: @at-color-list-empty;
- text-transform: uppercase;
- text-align: center;
- padding: @at-padding-list-empty;
-}
-
-.at-List-toolbar {
- width: 100%;
- display: flex;
- align-items: center;
- margin-bottom: @at-margin-bottom-list-toolbar;
-}
-
-.at-List--toolbar-padAbove{
- margin-top: @at-margin-above-list-toolbar
-}
-
-.at-List-search {
- flex: auto;
-}
-
-.at-List-toolbarAction {
- margin-left: @at-margin-left-toolbar-action;
- display: flex;
- align-items: center;
- justify-content: center;
- height: @at-height-toolbar-action;
- border-radius: @at-border-radius;
- position: relative;
-}
-
-.at-List-toolbarActionButton {
- border: none;
- border-radius: @at-border-radius;
- min-width: 80px;
-}
-
-.at-List-toolbarActionDropdownMenu {
- border-top-right-radius: 0;
- border: 1px solid @at-gray-d7;
- float: right;
- left: auto;
- margin: 0;
- right: 0;
-}
-
-.at-List-toolbar--attached {
- display: flex;
- justify-content: flex-end;
- border: @at-border-default-width solid @at-color-list-border;
- border-bottom: none;
- border-radius: @at-border-radius;
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
-}
-
-.at-List-toolbar-item {
- padding: 2px 10px;
- border-left: 1px solid @at-color-list-border;
-
- &:hover {
- cursor: pointer;
- background: @at-gray-f2;
- }
-
- &.active {
- background: @at-blue;
- color: @at-white;
- }
-}
-
-.at-List-toolbarDropdown {
- border-top-right-radius: @at-border-radius;
-
- &-toggle {
- background: none;
- border: none;
- padding: 0;
- }
-
- &-toggleText {
- margin-right: 10px;
- }
-
- &-menu {
- border-bottom-left-radius: @at-border-radius;
- border-bottom-right-radius: @at-border-radius;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- left: auto;
- margin: 0;
- right: 0;
- width: auto;
- }
-
- &-menuHeader {
- color: @at-gray-646972;
- font-weight: bold;
- pointer-events: none;
- }
-}
-
-.at-List-container {
- border: @at-border-default-width solid @at-color-list-border;
- border-radius: @at-border-radius;
-
- & > div:last-of-type {
- border-bottom-left-radius:@at-border-radius;
- }
-}
-
-// Remove top left and right rounded corners of a list if there is a toolbar above it
-.at-List-toolbar--attached + .at-List > .at-List-container {
- border-top-left-radius: 0;
- border-top-right-radius: 0;
-}
-
-.at-List-toolbar--attached + .at-List > .at-List-container{
- .at-Row--active {
- border-top-left-radius: 0;
- }
-}
-
-.at-List-toolbar--attached + .at-List {
- margin-top: 0;
-}
-
-.at-Row {
- display: grid;
- grid-template-columns: 10px 1fr;
-}
-
-.at-Row--collapsed {
- .at-Row-container--wrapped {
- visibility: hidden;
- opacity: 0;
- height: 0;
- }
-}
-
-.at-Row--active {
- border-left: @at-border-style-list-active-indicator;
- border-top-left-radius: @at-border-radius;
- border-top-right-radius: @at-border-radius;
-}
-
-.at-Row--active .at-Row--invalid {
- border-left: @at-white solid 1px;
-}
-
-.at-Row--active .at-Row-content {
- margin-left: -5px;
-}
-
-.at-Row ~ .at-Row {
- border-top-left-radius: 0px;
- border-top-right-radius: 0px;
- border-top: @at-border-default-width solid @at-color-list-border;
-}
-
-.at-Row--invalid {
- align-items: center;
- background: @at-color-error;
- display: flex;
- justify-content: center;
-
- .at-Popover {
- padding: 0;
-
- &-icon i {
- color: @at-white;
- }
-
- &-icon i:hover {
- color: @at-white;
- }
- }
-}
-
-.at-Row-content {
- align-items: center;
- display: flex;
- flex-wrap: wrap;
- grid-column-start: 2;
- padding: @at-padding-list-row;
-}
-
-.at-Row-toggle {
- align-self: flex-start;
- margin-right: @at-space-4x;
- margin-left: 15px;
-}
-
-.at-Row-actions {
- display: flex;
-}
-
-.at-Row-items {
- flex: 1;
-}
-
-.at-RowItem {
- align-items: center;
- line-height: @at-height-list-row-item;
- word-wrap: break-word;
- word-break: break-all;
- display: block;
- margin-right: 10px;
-}
-
-.at-RowItem-status {
- margin-right: @at-margin-right-list-row-item-status;
- & > a {
- cursor: pointer;
- }
-}
-
-.at-RowItem--isHeader {
- display: flex;
- color: @at-color-body-text;
- margin-bottom: @at-margin-bottom-list-header;
- line-height: @at-line-height-list-row-item-header;
-}
-
-.at-Row-container {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.at-Row-rightSide{
- justify-content: flex-end;
-}
-
-.at-Row-container--wrapped {
- display: flex;
- flex-wrap: wrap;
- visibility: visible;
- opacity: 1;
- height: auto;
- transition: visibility 0s, opacity 0.25s linear;
-}
-
-.at-RowItem--isHeaderLink {
- color: @at-blue;
- cursor: pointer;
-}
-.at-RowItem--isHeaderLink:hover {
- color: @at-blue-hover;
-}
-
-.at-RowItem--labels {
- line-height: @at-line-height-list-row-item-labels;
- display: inline-flex;
-
- * {
- font-size: 10px;
- }
-}
-
-.at-RowItem-header {
- font-weight: bold;
-}
-
-.at-RowItem-tagContainer {
- display: inline-block;
- flex-wrap: wrap;
- line-height: initial;
-}
-
-.at-RowItem-tag {
- font-weight: 100;
- background-color: @at-color-list-row-item-tag-background;
- border-radius: @at-border-radius;
- color: @at-color-list-row-item-tag;
- font-size: @at-font-size-list-row-item-tag;
- margin: @at-space @at-space-4x;
- padding: @at-padding-list-row-item-tag;
- line-height: @at-line-height-list-row-item-tag;
- word-break: keep-all;
- display: inline-flex;
- margin-right: 10px;
- margin-left: 10px;
-}
-
-.at-RowItem-tag--primary {
- background: @at-color-list-row-item-tag-primary-background;
- color: @at-color-list-row-item-tag-primary;
-}
-
-.at-RowItem-tag--header, .at-RowItem-tag--secondary {
- line-height: inherit;
-}
-
-.at-RowItem-tagIcon {
- margin-right: @at-margin-right-list-row-item-tag-icon;
-}
-
-.at-RowItem-label {
- display: inline-block;
- text-transform: uppercase;
- color: @at-color-list-row-item-label;
- font-size: @at-font-size;
- margin-right: 10px;
-}
-
-.at-RowItem-value {
- display: inline-block;
- font-size: @at-font-size-3x;
- margin-right: 20px;
-}
-
-.at-RowItem-badge {
- background-color: @at-gray-646972;
- border-radius: @at-border-radius;
- color: @at-white;
- font-size: 11px;
- font-weight: normal;
- height: 14px;
- line-height: 10px;
- margin: 0 10px;
- padding: 2px 10px;
-}
-
-.at-RowAction {
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-left: @at-margin-left-list-row-action;
- padding: @at-padding-list-row-action;
- background: @at-color-list-row-action-background;
- border-radius: @at-border-radius;
- height: @at-height-list-row-action;
- width: @at-width-list-row-action;
-
- i {
- font-size: @at-font-size-list-row-action-icon;
- color: @at-color-list-row-action-icon;
- }
-}
-
-.at-RowAction:hover {
- background-color: @at-color-list-row-action-hover;
-
- i {
- color: @at-color-list-row-action-icon-hover;
- }
-}
-
-.at-RowAction--danger:hover {
- background-color: @at-color-list-row-action-hover-danger;
-}
-
-.at-RowAction--disabled {
- pointer-events: none;
- opacity: 0.5;
- cursor: not-allowed;
-}
-
-.at-Row .at-Row-checkbox {
- align-self: start;
- margin: 2px 20px 0 0;
-}
-
-.at-RowItem--inline {
- display: inline-flex;
- margin-right: @at-margin-right-list-row-item-inline;
-
- .at-RowItem-label {
- width: auto;
- margin-right: @at-margin-right-list-row-item-inline-label;
- }
-}
diff --git a/awx/ui/client/lib/components/list/list-toolbar.directive.js b/awx/ui/client/lib/components/list/list-toolbar.directive.js
deleted file mode 100644
index 7e3ed8eee9..0000000000
--- a/awx/ui/client/lib/components/list/list-toolbar.directive.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const templateUrl = require('~components/list/list-toolbar.partial.html');
-
-function AtListToolbar (strings) {
- const vm = this || {};
- vm.strings = strings;
-}
-
-AtListToolbar.$inject = ['ComponentsStrings'];
-
-function atListToolbar () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- onExpand: '=',
- onCollapse: '=',
- isCollapsed: '=',
- onSort: '<',
- sortOnly: '=',
- sortOptions: '<',
- sortValue: '<'
- },
- controller: AtListToolbar,
- controllerAs: 'vm'
- };
-}
-
-export default atListToolbar;
diff --git a/awx/ui/client/lib/components/list/list-toolbar.partial.html b/awx/ui/client/lib/components/list/list-toolbar.partial.html
deleted file mode 100644
index 0db249ccce..0000000000
--- a/awx/ui/client/lib/components/list/list-toolbar.partial.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/list/list.directive.js b/awx/ui/client/lib/components/list/list.directive.js
deleted file mode 100644
index 7c6a1c1adc..0000000000
--- a/awx/ui/client/lib/components/list/list.directive.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const templateUrl = require('~components/list/list.partial.html');
-
-function atListLink (scope, element, attrs) {
- if (!attrs.results) {
- throw new Error('at-list directive requires results attr to set up the empty list properly');
- }
-}
-
-function AtListController (strings) {
- this.strings = strings;
-}
-
-AtListController.$inject = ['ComponentsStrings'];
-
-function atList () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- results: '=',
- emptyListReason: '@'
- },
- link: atListLink,
- controller: AtListController,
- controllerAs: 'vm',
- };
-}
-
-export default atList;
diff --git a/awx/ui/client/lib/components/list/list.partial.html b/awx/ui/client/lib/components/list/list.partial.html
deleted file mode 100644
index 3bd90e6663..0000000000
--- a/awx/ui/client/lib/components/list/list.partial.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
- {{ emptyListReason || vm.strings.get("list.DEFAULT_EMPTY_LIST") }}
-
-
diff --git a/awx/ui/client/lib/components/list/row-action.directive.js b/awx/ui/client/lib/components/list/row-action.directive.js
deleted file mode 100644
index 7cc7f44a04..0000000000
--- a/awx/ui/client/lib/components/list/row-action.directive.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const templateUrl = require('~components/list/row-action.partial.html');
-
-function atRowAction () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- icon: '@',
- tooltip: '@'
- }
- };
-}
-
-export default atRowAction;
diff --git a/awx/ui/client/lib/components/list/row-action.partial.html b/awx/ui/client/lib/components/list/row-action.partial.html
deleted file mode 100644
index b26301f198..0000000000
--- a/awx/ui/client/lib/components/list/row-action.partial.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
diff --git a/awx/ui/client/lib/components/list/row-item.directive.js b/awx/ui/client/lib/components/list/row-item.directive.js
deleted file mode 100644
index b7e9abb7ad..0000000000
--- a/awx/ui/client/lib/components/list/row-item.directive.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const templateUrl = require('~components/list/row-item.partial.html');
-
-function atRowItem () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- inline: '@',
- badge: '@',
- headerValue: '@',
- headerLink: '@',
- headerState: '@',
- headerTag: '@',
- secondaryTag: '@',
- status: '@',
- statusTip: '@',
- statusClick: '&?',
- labelValue: '@',
- labelState: '@',
- value: '@',
- valueLink: '@',
- valueBindHtml: '@',
- smartStatus: '=?',
- tagValues: '=?',
- // TODO: add see more for tags if applicable
- tagsAreCreds: '@'
- }
- };
-}
-
-export default atRowItem;
diff --git a/awx/ui/client/lib/components/list/row-item.partial.html b/awx/ui/client/lib/components/list/row-item.partial.html
deleted file mode 100644
index b8582d2d70..0000000000
--- a/awx/ui/client/lib/components/list/row-item.partial.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
- {{ secondaryTag }}
-
-
- {{ labelValue }}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/list/row.directive.js b/awx/ui/client/lib/components/list/row.directive.js
deleted file mode 100644
index e64ed8ff88..0000000000
--- a/awx/ui/client/lib/components/list/row.directive.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const templateUrl = require('~components/list/row.partial.html');
-
-function atRow () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- invalid: '=',
- invalidTooltip: '='
- }
- };
-}
-
-export default atRow;
diff --git a/awx/ui/client/lib/components/list/row.partial.html b/awx/ui/client/lib/components/list/row.partial.html
deleted file mode 100644
index ce1c506e5c..0000000000
--- a/awx/ui/client/lib/components/list/row.partial.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/awx/ui/client/lib/components/lookup-list/lookup-list.component.js b/awx/ui/client/lib/components/lookup-list/lookup-list.component.js
deleted file mode 100644
index 241fce2b02..0000000000
--- a/awx/ui/client/lib/components/lookup-list/lookup-list.component.js
+++ /dev/null
@@ -1,52 +0,0 @@
-const templateUrl = require('~components/lookup-list/lookup-list.partial.html');
-
-function LookupListController (GetBasePath, Rest, strings) {
- const vm = this || {};
-
- vm.strings = strings;
-
- vm.$onInit = () => {
- const params = vm.baseParams;
- setBaseParams(params);
- setData({ results: [], count: 0 });
-
- const resultsFilter = vm.resultsFilter || (data => data);
- Rest.setUrl(GetBasePath(`${vm.resourceName}s`));
- Rest.get({ params })
- .then(({ data }) => {
- setData(resultsFilter(data));
- })
- .finally(() => vm.onReady());
- };
-
- function setData ({ results, count }) {
- vm.dataset = { results, count };
- vm.collection = vm.dataset.results;
- }
-
- function setBaseParams (params) {
- vm.list = { name: vm.resourceName, iterator: vm.resourceName };
- vm.defaultParams = params;
- vm.queryset = params;
- }
-}
-
-LookupListController.$inject = [
- 'GetBasePath',
- 'Rest',
- 'ComponentsStrings',
-];
-
-export default {
- templateUrl,
- controller: LookupListController,
- controllerAs: 'vm',
- bindings: {
- onItemSelect: '=',
- onReady: '=',
- selectedId: '=',
- resourceName: '@',
- baseParams: '=',
- resultsFilter: '=',
- },
-};
diff --git a/awx/ui/client/lib/components/lookup-list/lookup-list.partial.html b/awx/ui/client/lib/components/lookup-list/lookup-list.partial.html
deleted file mode 100644
index 11167678ee..0000000000
--- a/awx/ui/client/lib/components/lookup-list/lookup-list.partial.html
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
- {{::vm.strings.get('NO_MATCH')}}
-
-
-
- {{::vm.strings.get('NO_ITEMS')}}
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/modal/_index.less b/awx/ui/client/lib/components/modal/_index.less
deleted file mode 100644
index 1d3b2be342..0000000000
--- a/awx/ui/client/lib/components/modal/_index.less
+++ /dev/null
@@ -1,28 +0,0 @@
-.at-Modal-body {
- font-size: @at-font-size;
- padding: @at-padding-panel 0;
-}
-
-.at-Modal-dismiss {
- .at-mixin-ButtonIcon();
- font-size: @at-font-size-modal-dismiss;
- color: @at-color-icon-dismiss;
- text-align: right;
-}
-
-.at-Modal-heading {
- margin: 0;
- overflow: visible;
-
- & > .at-Modal-dismiss {
- margin: 0;
- }
-}
-
-.at-Modal-title {
- margin: 0;
- padding: 0;
-
- .at-mixin-Heading(@at-font-size-modal-heading);
-}
-
diff --git a/awx/ui/client/lib/components/modal/modal.directive.js b/awx/ui/client/lib/components/modal/modal.directive.js
deleted file mode 100644
index 2550669b41..0000000000
--- a/awx/ui/client/lib/components/modal/modal.directive.js
+++ /dev/null
@@ -1,76 +0,0 @@
-const templateUrl = require('~components/modal/modal.partial.html');
-
-const DEFAULT_ANIMATION_DURATION = 150;
-
-function atModalLink (scope, el, attrs, controllers) {
- const modalController = controllers[0];
- const property = `scope.${scope.ns}.modal`;
-
- const done = scope.$watch(property, () => {
- modalController.init(scope, el);
- done();
- });
-}
-
-function AtModalController (strings) {
- const vm = this;
-
- let overlay;
-
- vm.strings = strings;
-
- vm.init = (scope, el) => {
- overlay = el[0]; // eslint-disable-line prefer-destructuring
-
- vm.modal = scope[scope.ns].modal;
- vm.modal.show = vm.show;
- vm.modal.hide = vm.hide;
- vm.modal.onClose = scope.onClose;
- };
-
- vm.show = (title, message) => {
- vm.modal.title = title;
- vm.modal.message = message;
-
- overlay.style.display = 'block';
- overlay.style.opacity = 1;
- };
-
- vm.hide = () => {
- overlay.style.opacity = 0;
-
- setTimeout(() => {
- overlay.style.display = 'none';
- }, DEFAULT_ANIMATION_DURATION);
-
- if (vm.modal.onClose) {
- vm.modal.onClose();
- }
- };
-
- vm.clickToHide = event => {
- if ($(event.target).hasClass('at-Modal')) {
- vm.hide();
- }
- };
-}
-
-AtModalController.$inject = [
- 'ComponentsStrings'
-];
-
-function atModal () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- require: ['atModal'],
- templateUrl,
- controller: AtModalController,
- controllerAs: 'vm',
- link: atModalLink,
- scope: true
- };
-}
-
-export default atModal;
diff --git a/awx/ui/client/lib/components/modal/modal.partial.html b/awx/ui/client/lib/components/modal/modal.partial.html
deleted file mode 100644
index 38f0407e97..0000000000
--- a/awx/ui/client/lib/components/modal/modal.partial.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
{{ vm.modal.message }}
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/panel/_index.less b/awx/ui/client/lib/components/panel/_index.less
deleted file mode 100644
index 4330d8fbae..0000000000
--- a/awx/ui/client/lib/components/panel/_index.less
+++ /dev/null
@@ -1,72 +0,0 @@
-.at-Panel {
- margin: @at-margin-panel 0 0 0;
- padding: @at-padding-panel;
- border-color: @at-color-panel-border;
-}
-
-.at-Panel-heading {
- margin-bottom: 20px;
- padding: 0;
-}
-
-.at-Panel-headingRow {
- display: flex;
- align-items: center;
- justify-content: space-between;
-}
-
-.at-Panel-dismiss {
- .at-mixin-ButtonIcon();
- color: @at-color-icon-dismiss;
- text-align: right;
-}
-
-.at-Panel-body {
- margin: 0;
- padding: 0;
-}
-
-.at-Panel-headingTitle {
- .at-mixin-Heading(@at-font-size-panel-heading);
- text-transform: none;
-}
-
-.at-Panel-headingTitleBadge {
- font-size: 11px;
- font-weight: normal;
- padding: 2px 10px;
- line-height: 10px;
- background-color: #646972;
- border-radius: 5px;
- display: inline-block;
- min-width: 10px;
- color: #fff;
- vertical-align: middle;
- white-space: nowrap;
- text-align: center;
- margin-left: 10px;
- margin-right: auto;
-
- &--inline {
- margin-right: @at-space-2x;
- margin-left: 0;
- }
-}
-
-.at-Panel-headingCustomContent {
- display: flex;
- flex: 1;
-}
-
-.at-Panel-label {
- text-transform: uppercase;
- color: @default-interface-txt;
- font-size: 12px;
- font-weight: normal!important;
- width: 30%;
- margin: @at-space-2x;
-
- @media screen and (max-width: @breakpoint-md) {
- flex: 2.5 0 auto;
- }
-}
diff --git a/awx/ui/client/lib/components/panel/body.directive.js b/awx/ui/client/lib/components/panel/body.directive.js
deleted file mode 100644
index 1cf795596a..0000000000
--- a/awx/ui/client/lib/components/panel/body.directive.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const templateUrl = require('~components/panel/body.partial.html');
-
-function atPanelBody () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- state: '='
- }
- };
-}
-
-export default atPanelBody;
diff --git a/awx/ui/client/lib/components/panel/body.partial.html b/awx/ui/client/lib/components/panel/body.partial.html
deleted file mode 100644
index bdb193b9a1..0000000000
--- a/awx/ui/client/lib/components/panel/body.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/awx/ui/client/lib/components/panel/heading.directive.js b/awx/ui/client/lib/components/panel/heading.directive.js
deleted file mode 100644
index 34296e7f94..0000000000
--- a/awx/ui/client/lib/components/panel/heading.directive.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const templateUrl = require('~components/panel/heading.partial.html');
-
-function link (scope, el, attrs, panel) {
- scope.hideDismiss = Boolean(attrs.hideDismiss);
- panel.use(scope);
-}
-
-function atPanelHeading () {
- return {
- restrict: 'E',
- require: '^^atPanel',
- replace: true,
- transclude: true,
- templateUrl,
- link,
- scope: {
- title: '@',
- badge: '@?'
- }
- };
-}
-
-export default atPanelHeading;
diff --git a/awx/ui/client/lib/components/panel/heading.partial.html b/awx/ui/client/lib/components/panel/heading.partial.html
deleted file mode 100644
index 186435588c..0000000000
--- a/awx/ui/client/lib/components/panel/heading.partial.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- {{ title }}
-
-
- {{ badge }}
-
-
-
-
-
-
-
-
-
-
-
- {{ title }}
-
-
- {{ badge }}
-
-
-
diff --git a/awx/ui/client/lib/components/panel/panel.directive.js b/awx/ui/client/lib/components/panel/panel.directive.js
deleted file mode 100644
index a58b386acf..0000000000
--- a/awx/ui/client/lib/components/panel/panel.directive.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const templateUrl = require('~components/panel/panel.partial.html');
-
-function atPanelLink (scope, el, attrs, controller) {
- const panelController = controller;
-
- panelController.init(scope);
-}
-
-function AtPanelController ($state) {
- const vm = this;
-
- let scope;
-
- vm.init = (_scope_) => {
- scope = _scope_;
- };
-
- vm.dismiss = () => {
- $state.go(scope.onDismiss || '^');
- };
-
- vm.use = child => {
- child.dismiss = vm.dismiss;
- };
-}
-
-AtPanelController.$inject = ['$state'];
-
-function atPanel () {
- return {
- restrict: 'E',
- replace: true,
- require: 'atPanel',
- transclude: true,
- templateUrl,
- controller: AtPanelController,
- controllerAs: 'vm',
- link: atPanelLink,
- scope: {
- state: '=',
- onDismiss: '@'
- }
- };
-}
-
-export default atPanel;
diff --git a/awx/ui/client/lib/components/panel/panel.partial.html b/awx/ui/client/lib/components/panel/panel.partial.html
deleted file mode 100644
index f572b34008..0000000000
--- a/awx/ui/client/lib/components/panel/panel.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/awx/ui/client/lib/components/popover/_index.less b/awx/ui/client/lib/components/popover/_index.less
deleted file mode 100644
index e6356217ca..0000000000
--- a/awx/ui/client/lib/components/popover/_index.less
+++ /dev/null
@@ -1,57 +0,0 @@
-.at-Popover {
- padding: 0 0 0 5px;
-}
-
-.at-Popover--inline {
- display: inline-block;
-}
-
-.at-Popover-icon {
- .at-mixin-ButtonIcon();
- color: @at-color-icon-popover;
- font-size: @at-font-size-icon;
- margin: 0;
-}
-
-.at-Popover-icon--defaultCursor {
- i > {
- cursor: default;
- }
-}
-
-.at-Popover-container {
- visibility: hidden;
- opacity: 0;
- color: @at-white;
- background-color: @at-color-body-background-dark;
- max-width: @at-popover-maxwidth;
- padding: @at-padding-popover;
- height: auto;
- position: fixed;
- z-index: 2000;
- margin: 0;
- border-radius: @at-border-radius;
- box-shadow: 0 5px 10px rgba(0,0,0, 0.2);
- transition: opacity .15s linear;
- font-weight: @at-font-weight-body;
-}
-
-.at-Popover-arrow {
- color: @at-color-body-background-dark;
- position: fixed;
- z-index: 1999;
- padding: 0;
- margin: 0;
-}
-
-.at-Popover-title {
- .at-mixin-Heading(@at-font-size-body);
- color: @at-color-body-text-dark;
- margin-bottom: @at-margin-popover;
-}
-
-.at-Popover-text {
- margin: 0;
- padding: 0;
- font-size: @at-font-size;
-}
diff --git a/awx/ui/client/lib/components/popover/popover.directive.js b/awx/ui/client/lib/components/popover/popover.directive.js
deleted file mode 100644
index ae23f06209..0000000000
--- a/awx/ui/client/lib/components/popover/popover.directive.js
+++ /dev/null
@@ -1,220 +0,0 @@
-const templateUrl = require('~components/popover/popover.partial.html');
-
-const DEFAULT_POSITION = 'right';
-const DEFAULT_ACTION = 'click';
-const DEFAULT_ICON = 'fa fa-question-circle';
-const DEFAULT_ALIGNMENT = 'inline';
-const DEFAULT_ARROW_HEIGHT = 14;
-const DEFAULT_PADDING = 10;
-const DEFAULT_REFRESH_DELAY = 50;
-const DEFAULT_RESET_ON_EXIT = false;
-
-function atPopoverLink (scope, el, attr, controllers) {
- const popoverController = controllers[0];
- const container = el[0];
- const popover = container.getElementsByClassName('at-Popover-container')[0];
- const icon = container.getElementsByTagName('i')[0];
-
- const done = scope.$watch('state', () => {
- popoverController.init(scope, container, icon, popover);
- done();
- });
-}
-
-function AtPopoverController () {
- const vm = this;
-
- let icon;
- let popover;
- let scope;
-
- vm.init = (_scope_, _container_, _icon_, _popover_) => {
- scope = _scope_;
- icon = _icon_;
- popover = _popover_;
-
- scope.popover = scope.state.popover || {};
-
- scope.popover.text = scope.state.help_text || scope.popover.text;
- scope.popover.title = scope.state.label || scope.popover.title;
- scope.popover.inline = scope.popover.inline || DEFAULT_ALIGNMENT;
- scope.popover.position = scope.popover.position || DEFAULT_POSITION;
- scope.popover.icon = scope.popover.icon || DEFAULT_ICON;
- scope.popover.on = scope.popover.on || DEFAULT_ACTION;
- scope.popover.resetOnExit = scope.popover.resetOnExit || DEFAULT_RESET_ON_EXIT;
- scope.popover.arrowHeight = scope.popover.arrowHeight || DEFAULT_ARROW_HEIGHT;
-
- if (scope.popover.resetOnExit) {
- scope.originalText = scope.popover.text;
- scope.originalTitle = scope.popover.title;
- }
-
- icon.addEventListener(scope.popover.on, vm.createDisplayListener());
-
- scope.$watch('popover.text', vm.refresh);
-
- if (scope.popover.click) {
- icon.addEventListener('click', scope.popover.click);
- }
- };
-
- vm.createDismissListener = () => event => {
- event.stopPropagation();
-
- if (vm.isClickWithinPopover(event, popover)) {
- return;
- }
-
- vm.dismiss();
-
- if (scope.popover.on === 'mouseenter') {
- icon.removeEventListener('mouseleave', vm.dismissListener);
- } else {
- window.addEventListener(scope.popover.on, vm.dismissListener);
- }
-
- window.removeEventListener('resize', vm.dismissListener);
- };
-
- vm.dismiss = (refresh) => {
- if (!refresh && scope.popover.resetOnExit) {
- scope.popover.text = scope.originalText;
- scope.popover.title = scope.originalTitle;
- }
-
- vm.open = false;
-
- popover.style.visibility = 'hidden';
- popover.style.opacity = 0;
- };
-
- vm.isClickWithinPopover = (event, popoverEl) => {
- const box = popoverEl.getBoundingClientRect();
-
- const x = event.clientX;
- const y = event.clientY;
-
- if ((x <= box.right && x >= box.left) && (y >= box.top && y <= box.bottom)) {
- return true;
- }
-
- return false;
- };
-
- vm.createDisplayListener = () => event => {
- if (vm.open) {
- return;
- }
-
- event.stopPropagation();
-
- vm.display();
-
- vm.dismissListener = vm.createDismissListener(event);
-
- if (scope.popover.on === 'mouseenter') {
- icon.addEventListener('mouseleave', vm.dismissListener);
- } else {
- window.addEventListener(scope.popover.on, vm.dismissListener);
- }
-
- window.addEventListener('resize', vm.dismissListener);
- };
-
- vm.refresh = () => {
- if (!vm.open) {
- return;
- }
-
- vm.dismiss(true);
- window.setTimeout(vm.display, DEFAULT_REFRESH_DELAY);
- };
-
- vm.getPositions = () => {
- const arrow = popover.getElementsByClassName('at-Popover-arrow')[0];
-
- arrow.style.lineHeight = `${DEFAULT_ARROW_HEIGHT}px`;
- arrow.children[0].style.lineHeight = `${scope.popover.arrowHeight}px`;
-
- const data = {
- arrow,
- icon: icon.getBoundingClientRect(),
- popover: popover.getBoundingClientRect(),
- windowHeight: window.innerHeight
- };
-
- data.cx = Math.floor(data.icon.left + (data.icon.width / 2));
- data.cy = Math.floor(data.icon.top + (data.icon.height / 2));
- data.rightBoundary = Math.floor(data.icon.right);
-
- return data;
- };
-
- vm.display = () => {
- vm.open = true;
-
- const positions = vm.getPositions();
-
- popover.style.visibility = 'visible';
- popover.style.opacity = 1;
-
- if (scope.popover.position === 'right') {
- vm.displayRight(positions);
- } else if (scope.popover.position === 'top') {
- vm.displayTop(positions);
- }
- };
-
- vm.displayRight = (pos) => {
- const arrowHeight = pos.arrow.offsetHeight;
- const arrowLeft = pos.rightBoundary + DEFAULT_PADDING;
- const popoverLeft = arrowLeft + DEFAULT_PADDING - 1;
-
- let popoverTop;
- if (pos.cy < (pos.popover.height / 2)) {
- popoverTop = DEFAULT_PADDING;
- } else {
- popoverTop = Math.floor((pos.cy - pos.popover.height / 2));
- }
-
- const arrowTop = Math.floor(popoverTop + (pos.popover.height / 2) - (arrowHeight / 2));
-
- pos.arrow.style.top = `${arrowTop}px`;
- pos.arrow.style.left = `${arrowLeft}px`;
-
- popover.style.top = `${popoverTop}px`;
- popover.style.left = `${popoverLeft}px`;
- };
-
- vm.displayTop = (pos) => {
- const arrowTop = pos.icon.top - pos.icon.height - DEFAULT_PADDING;
- const arrowLeft = Math.floor(pos.icon.right - pos.icon.width - (pos.arrow.style.width / 2));
-
- const popoverTop = pos.icon.top - pos.popover.height - pos.icon.height - 5;
- const popoverLeft = Math.floor(pos.cx - (pos.popover.width / 2));
-
- pos.arrow.style.top = `${arrowTop}px`;
- pos.arrow.style.left = `${arrowLeft}px`;
-
- popover.style.top = `${popoverTop}px`;
- popover.style.left = `${popoverLeft}px`;
- };
-}
-
-function atPopover () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- require: ['atPopover'],
- templateUrl,
- controller: AtPopoverController,
- controllerAs: 'vm',
- link: atPopoverLink,
- scope: {
- state: '='
- }
- };
-}
-
-export default atPopover;
diff --git a/awx/ui/client/lib/components/popover/popover.partial.html b/awx/ui/client/lib/components/popover/popover.partial.html
deleted file mode 100644
index 974575f68f..0000000000
--- a/awx/ui/client/lib/components/popover/popover.partial.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
{{ popover.title | translate }}
-
{{ popover.text | translate }}
-
-
-
diff --git a/awx/ui/client/lib/components/relaunchButton/_index.less b/awx/ui/client/lib/components/relaunchButton/_index.less
deleted file mode 100644
index d9ccc1f67f..0000000000
--- a/awx/ui/client/lib/components/relaunchButton/_index.less
+++ /dev/null
@@ -1,39 +0,0 @@
-.at-Relaunch {
- margin-left: 15px;
-
- &--button {
- font-size: 16px;
- height: 30px;
- min-width: 30px;
- color: #646972;
- background-color: inherit;
- border: none;
- border-radius: 4px;
- }
- &--button:hover {
- background-color: @at-blue;
- color: white;
- }
- &--dropdownTitle {
- color: #707070;
- font-size: 12px;
- font-weight: bold;
- text-transform: uppercase;
- padding: 3px 10px;
- }
- &--dropdownOptions {
- i {
- padding-right: 5px;
- }
- a:hover {
- cursor: pointer;
- }
- }
-}
-
-.open {
- .at-Relaunch--button {
- background-color: @at-blue;
- color: white;
- }
-}
diff --git a/awx/ui/client/lib/components/relaunchButton/relaunchButton.component.js b/awx/ui/client/lib/components/relaunchButton/relaunchButton.component.js
deleted file mode 100644
index 7b68d427ac..0000000000
--- a/awx/ui/client/lib/components/relaunchButton/relaunchButton.component.js
+++ /dev/null
@@ -1,295 +0,0 @@
-import templateUrl from './relaunchButton.partial.html';
-
-const atRelaunch = {
- templateUrl,
- bindings: {
- job: '<'
- },
- controller: ['ProcessErrors', 'AdhocRun', 'ComponentsStrings',
- 'ProjectModel', 'InventorySourceModel', 'WorkflowJobModel', 'Alert',
- 'AdHocCommandModel', 'JobModel', 'JobTemplateModel', 'PromptService',
- '$state', '$q', '$scope', atRelaunchCtrl
- ],
- controllerAs: 'vm'
-};
-
-function atRelaunchCtrl (
- ProcessErrors, AdhocRun, strings,
- Project, InventorySource, WorkflowJob, Alert,
- AdHocCommand, Job, JobTemplate, PromptService,
- $state, $q, $scope
-) {
- const vm = this;
- vm.strings = strings;
- const jobObj = new Job();
- const jobTemplate = new JobTemplate();
-
- const transitionOptions = { reload: true };
-
- if ($state.includes('output')) {
- transitionOptions.inherit = false;
- transitionOptions.location = 'replace';
- }
-
- const updateTooltip = () => {
- if (vm.job.type === 'job' && vm.job.status === 'failed') {
- vm.tooltip = strings.get('relaunch.HOSTS');
- } else {
- vm.tooltip = strings.get('relaunch.DEFAULT');
- }
- };
-
- const checkRelaunchPlaybook = (option) => {
- jobObj.getRelaunch({
- id: vm.job.id
- }).then((getRelaunchRes) => {
- if (
- getRelaunchRes.data.passwords_needed_to_start &&
- getRelaunchRes.data.passwords_needed_to_start.length > 0
- ) {
- const jobPromises = [
- jobObj.request('get', vm.job.id),
- jobTemplate.optionsLaunch(vm.job.unified_job_template),
- jobObj.getCredentials(vm.job.id)
- ];
-
- $q.all(jobPromises)
- .then(([jobRes, launchOptions, jobCreds]) => {
- const populatedJob = jobRes.data;
- const jobTypeChoices = _.get(
- launchOptions,
- 'data.actions.POST.job_type.choices',
- []
- ).map(c => ({ label: c[1], value: c[0] }));
- const verbosityChoices = _.get(
- launchOptions,
- 'data.actions.POST.verbosity.choices',
- []
- ).map(c => ({ label: c[1], value: c[0] }));
- const verbosity = _.find(
- verbosityChoices,
- item => item.value === populatedJob.verbosity
- );
- const jobType = _.find(
- jobTypeChoices,
- item => item.value === populatedJob.job_type
- );
-
- vm.promptData = {
- launchConf: {
- passwords_needed_to_start:
- getRelaunchRes.data.passwords_needed_to_start
- },
- launchOptions: launchOptions.data,
- job: vm.job.id,
- relaunchHostType: option ? (option.value) : null,
- prompts: {
- credentials: {
- value: populatedJob.summary_fields.credentials ?
- _.merge(
- jobCreds.data.results,
- populatedJob.summary_fields.credentials
- ) : []
- },
- variables: {
- value: populatedJob.extra_vars
- },
- inventory: {
- value: populatedJob.summary_fields.inventory || null
- },
- verbosity: {
- value: verbosity,
- choices: verbosityChoices
- },
- jobType: {
- value: jobType,
- choices: jobTypeChoices
- },
- limit: {
- value: populatedJob.limit
- },
- tags: {
- value: populatedJob.job_tags
- },
- skipTags: {
- value: populatedJob.skip_tags
- },
- diffMode: {
- value: populatedJob.diff_mode
- },
- scmBranch: {
- value: populatedJob.scm_branch
- }
- },
- triggerModalOpen: true
- };
- });
- } else {
- const launchParams = {
- id: vm.job.id,
- };
-
- if (_.has(option, 'value')) {
- launchParams.relaunchData = {
- hosts: option.value
- };
- }
-
- jobObj.postRelaunch(launchParams)
- .then((launchRes) => {
- if (!$state.is('jobs')) {
- const relaunchType = launchRes.data.type === 'job' ? 'playbook' : launchRes.data.type;
- $state.go('output', { id: launchRes.data.id, type: relaunchType }, transitionOptions);
- }
- }).catch(({ data, status, config }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- });
- }
- });
- };
-
- vm.$onInit = () => {
- vm.showRelaunch = vm.job.type !== 'system_job' && vm.job.summary_fields.user_capabilities.start;
-
- vm.icon = 'icon-launch';
- vm.dropdownTitle = strings.get('relaunch.DROPDOWN_TITLE');
- vm.dropdownOptions = [
- {
- name: strings.get('relaunch.ALL'),
- icon: 'icon-host-all',
- value: 'all'
- },
- {
- name: strings.get('relaunch.FAILED'),
- icon: 'icon-host-failed',
- value: 'failed'
- }
- ];
-
- updateTooltip();
-
- $scope.$watch('vm.job.status', () => {
- updateTooltip();
- });
- };
-
- vm.relaunchJob = () => {
- if (vm.job.type === 'inventory_update') {
- const inventorySource = new InventorySource();
-
- inventorySource.getUpdate(vm.job.inventory_source)
- .then((getUpdateRes) => {
- if (getUpdateRes.data.can_update) {
- inventorySource.postUpdate(vm.job.inventory_source)
- .then((postUpdateRes) => {
- if (!$state.is('jobs')) {
- $state.go('output', { id: postUpdateRes.data.id, type: 'inventory' }, transitionOptions);
- }
- }).catch(({ data, status, config }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- });
- } else {
- Alert(
- 'Permission Denied', 'You do not have permission to sync this inventory source. Please contact your system administrator.',
- 'alert-danger'
- );
- }
- });
- } else if (vm.job.type === 'project_update') {
- const project = new Project();
-
- project.getUpdate(vm.job.project)
- .then((getUpdateRes) => {
- if (getUpdateRes.data.can_update) {
- project.postUpdate(vm.job.project)
- .then((postUpdateRes) => {
- if (!$state.is('jobs')) {
- $state.go('output', { id: postUpdateRes.data.id, type: 'project' }, transitionOptions);
- }
- }).catch(({ data, status, config }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- });
- } else {
- Alert(
- 'Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
- 'alert-danger'
- );
- }
- });
- } else if (vm.job.type === 'workflow_job') {
- const workflowJob = new WorkflowJob();
-
- workflowJob.postRelaunch({
- id: vm.job.id
- }).then((launchRes) => {
- if (!$state.is('jobs')) {
- $state.go('workflowResults', { id: launchRes.data.id }, transitionOptions);
- }
- }).catch(({ data, status, config }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- });
- } else if (vm.job.type === 'ad_hoc_command') {
- const adHocCommand = new AdHocCommand();
-
- adHocCommand.getRelaunch({
- id: vm.job.id
- }).then((getRelaunchRes) => {
- if (
- getRelaunchRes.data.passwords_needed_to_start &&
- getRelaunchRes.data.passwords_needed_to_start.length > 0
- ) {
- AdhocRun({ scope: $scope, project_id: vm.job.id, relaunch: true });
- } else {
- adHocCommand.postRelaunch({
- id: vm.job.id
- }).then((launchRes) => {
- if (!$state.is('jobs')) {
- $state.go('output', { id: launchRes.data.id, type: 'command' }, transitionOptions);
- }
- }).catch(({ data, status, config }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', { path: `${config.url}`, status })
- });
- });
- }
- });
- } else if (vm.job.type === 'job') {
- checkRelaunchPlaybook();
- }
- };
-
- vm.relaunchOn = (option) => {
- checkRelaunchPlaybook(option);
- };
-
- vm.relaunchJobWithPassword = () => {
- jobObj.postRelaunch({
- id: vm.promptData.job,
- relaunchData: PromptService.bundlePromptDataForRelaunch(vm.promptData)
- }).then((launchRes) => {
- if (!$state.is('jobs')) {
- $state.go('output', { id: launchRes.data.job, type: 'playbook' }, transitionOptions);
- }
- }).catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: `Error relaunching job. POST returned status: ${status}`
- });
- });
- };
-}
-
-export default atRelaunch;
diff --git a/awx/ui/client/lib/components/relaunchButton/relaunchButton.partial.html b/awx/ui/client/lib/components/relaunchButton/relaunchButton.partial.html
deleted file mode 100644
index eaf6fce323..0000000000
--- a/awx/ui/client/lib/components/relaunchButton/relaunchButton.partial.html
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/switch/_index.less b/awx/ui/client/lib/components/switch/_index.less
deleted file mode 100644
index f1fa1197c5..0000000000
--- a/awx/ui/client/lib/components/switch/_index.less
+++ /dev/null
@@ -1,85 +0,0 @@
-.atSwitch-listTableCell {
- display: flex;
- align-items: center;
- height: 100%;
- justify-content: flex-end;
- padding-right: 0px;
-}
-
-.atSwitch-outer {
- position: relative;
- display: inline-block;
- width: 40px;
- height: 26px;
- cursor: pointer;
-
- .fa {
- display: none;
- }
-}
-
-.atSwitch-on {
- .atSwitch-slider {
- background-color: @default-link;
- }
-
- .atSwitch-slider:before {
- -webkit-transform: translateX(16px);
- -ms-transform: translateX(16px);
- transform: translateX(16px);
- }
-
- .fa {
- display: block;
- position: absolute;
- top: 7px;
- left: 4px;
- color: @default-bg;
- font-size: 12px;
- }
-}
-
-.atSwitch-disabled {
- cursor: not-allowed;
-
- .atSwitch-inner {
- pointer-events: none;
- }
-
- .atSwitch-slider {
- background-color: @default-icon;
- }
-
- .atSwitch-slider:before {
- background-color: @d2grey;
- }
-
- .fa {
- color: @d2grey;
- }
-}
-
-.atSwitch-slider {
- position: absolute;
- border-radius: 34px;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: @d2grey;
- -webkit-transition: .4s;
- transition: .4s;
-}
-
-.atSwitch-slider:before {
- position: absolute;
- content: "";
- height: 16px;
- width: 16px;
- left: 4px;
- bottom: 5px;
- background-color: @default-bg;
- -webkit-transition: .4s;
- transition: .4s;
- border-radius: 50%;
-}
diff --git a/awx/ui/client/lib/components/switch/switch.directive.js b/awx/ui/client/lib/components/switch/switch.directive.js
deleted file mode 100644
index cf33d29f55..0000000000
--- a/awx/ui/client/lib/components/switch/switch.directive.js
+++ /dev/null
@@ -1,22 +0,0 @@
-const templateUrl = require('~components/switch/switch.partial.html');
-
-function atSwitch () {
- return {
- restrict: 'E',
- replace: true,
- templateUrl,
- scope: {
- hide: '=',
- onToggle: '&',
- switchOn: '=',
- switchDisabled: '=',
- tooltip: '=',
- tooltipString: '@',
- tooltipPlacement: '@',
- tooltipContainer: '@',
- tooltipWatch: '='
- },
- };
-}
-
-export default atSwitch;
diff --git a/awx/ui/client/lib/components/switch/switch.partial.html b/awx/ui/client/lib/components/switch/switch.partial.html
deleted file mode 100644
index d1f1614767..0000000000
--- a/awx/ui/client/lib/components/switch/switch.partial.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/awx/ui/client/lib/components/syntax-highlight/index.js b/awx/ui/client/lib/components/syntax-highlight/index.js
deleted file mode 100644
index 4936e5ff81..0000000000
--- a/awx/ui/client/lib/components/syntax-highlight/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import syntaxHighlight from './syntax-highlight.directive';
-
-const MODULE_NAME = 'at.syntax.highlight';
-
-angular.module(MODULE_NAME, [])
- .directive('atSyntaxHighlight', syntaxHighlight);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/lib/components/syntax-highlight/syntax-highlight.directive.js b/awx/ui/client/lib/components/syntax-highlight/syntax-highlight.directive.js
deleted file mode 100644
index 8ef0be94e0..0000000000
--- a/awx/ui/client/lib/components/syntax-highlight/syntax-highlight.directive.js
+++ /dev/null
@@ -1,98 +0,0 @@
-const templateUrl = require('~components/syntax-highlight/syntax-highlight.partial.html');
-
-function atSyntaxHighlightController ($scope, AngularCodeMirror) {
- const vm = this;
- const varName = `${$scope.name}_codemirror`;
-
- function init () {
- if ($scope.disabled === 'true') {
- $scope.disabled = true;
- } else if ($scope.disabled === 'false') {
- $scope.disabled = false;
- }
- $scope.value = $scope.value || $scope.default;
-
- initCodeMirror();
-
- $scope.$watch(varName, () => {
- $scope.value = $scope[varName];
- if ($scope.oneLine && $scope.value && $scope.value.includes('\n')) {
- $scope.hasNewlineError = true;
- } else {
- $scope.hasNewlineError = false;
- }
- });
- }
-
- function initCodeMirror () {
- $scope.varName = varName;
- $scope[varName] = $scope.value;
- const codeMirror = AngularCodeMirror(!!$scope.disabled);
- codeMirror.addModes({
- jinja2: {
- mode: $scope.mode,
- matchBrackets: true,
- autoCloseBrackets: true,
- styleActiveLine: true,
- lineNumbers: true,
- gutters: ['CodeMirror-lint-markers'],
- lint: true,
- scrollbarStyle: null,
- }
- });
- if (document.querySelector(`.ng-hide #${$scope.name}_codemirror`)) {
- return;
- }
- codeMirror.showTextArea({
- scope: $scope,
- model: varName,
- element: `${$scope.name}_codemirror`,
- lineNumbers: true,
- mode: $scope.mode,
- });
- }
-
- vm.name = $scope.name;
- vm.rows = $scope.rows || 6;
- if ($scope.init) {
- $scope.init = init;
- }
- angular.element(document).ready(() => {
- init();
- });
- $scope.$on('reset-code-mirror', () => {
- setImmediate(initCodeMirror);
- });
-}
-
-atSyntaxHighlightController.$inject = [
- '$scope',
- 'AngularCodeMirror'
-];
-
-function atCodeMirrorTextarea () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- controller: atSyntaxHighlightController,
- controllerAs: 'vm',
- scope: {
- disabled: '@',
- label: '@',
- labelClass: '@',
- tooltip: '@',
- tooltipPlacement: '@',
- value: '=',
- name: '@',
- init: '=',
- default: '@',
- rows: '@',
- oneLine: '@',
- mode: '@',
- }
- };
-}
-
-export default atCodeMirrorTextarea;
diff --git a/awx/ui/client/lib/components/syntax-highlight/syntax-highlight.partial.html b/awx/ui/client/lib/components/syntax-highlight/syntax-highlight.partial.html
deleted file mode 100644
index 595021035a..0000000000
--- a/awx/ui/client/lib/components/syntax-highlight/syntax-highlight.partial.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
- {{ label || vm.strings.get('code_mirror.label.VARIABLES') }}
-
-
-
-
-
-
-
-
New lines are not supported in this field
-
diff --git a/awx/ui/client/lib/components/tabs/_index.less b/awx/ui/client/lib/components/tabs/_index.less
deleted file mode 100644
index 80b9eec5c6..0000000000
--- a/awx/ui/client/lib/components/tabs/_index.less
+++ /dev/null
@@ -1,28 +0,0 @@
-.at-Tab {
- margin: 0 @at-margin-item-column 0 0;
- font-size: @at-font-size-body;
- line-height: 1;
-}
-
-.at-Tab--active {
- &, &:hover, &:active, &:focus {
- color: @at-color-tab-text-default-active;
- background-color: @at-color-tab-default-active;
- border-color: @at-color-tab-border-default-active;
- cursor: default;
- }
-}
-
-.at-Tab--disabled {
- &, &:hover, &:active, &:focus {
- background-color: @at-color-tab-default-disabled;
- color: @at-color-tab-text-default-disabled;
- border-color: @at-color-tab-border-default-disabled;
- opacity: 0.65;
- cursor: not-allowed;
- }
-}
-
-.at-TabGroup--padBelow {
- margin-bottom: 20px;
-}
diff --git a/awx/ui/client/lib/components/tabs/group.directive.js b/awx/ui/client/lib/components/tabs/group.directive.js
deleted file mode 100644
index d3c55a295f..0000000000
--- a/awx/ui/client/lib/components/tabs/group.directive.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const templateUrl = require('~components/tabs/group.partial.html');
-
-function AtTabGroupController () {
- const vm = this;
-
- vm.tabs = [];
-
- vm.register = tab => {
- tab.active = true;
-
- vm.tabs.push(tab);
- };
-
- vm.clearActive = () => {
- vm.tabs.forEach((tab) => {
- tab.state._active = false;
- });
- };
-}
-
-function atTabGroup () {
- return {
- restrict: 'E',
- replace: true,
- require: 'atTabGroup',
- transclude: true,
- templateUrl,
- controller: AtTabGroupController,
- controllerAs: 'vm',
- scope: {
- state: '='
- }
- };
-}
-
-export default atTabGroup;
diff --git a/awx/ui/client/lib/components/tabs/group.partial.html b/awx/ui/client/lib/components/tabs/group.partial.html
deleted file mode 100644
index 325fb36cc5..0000000000
--- a/awx/ui/client/lib/components/tabs/group.partial.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/awx/ui/client/lib/components/tabs/tab.directive.js b/awx/ui/client/lib/components/tabs/tab.directive.js
deleted file mode 100644
index 85dc5f4d2c..0000000000
--- a/awx/ui/client/lib/components/tabs/tab.directive.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const templateUrl = require('~components/tabs/tab.partial.html');
-
-function atTabLink (scope, el, attrs, controllers) {
- const groupController = controllers[0];
- const tabController = controllers[1];
-
- tabController.init(scope, groupController);
-}
-
-function AtTabController ($state) {
- const vm = this;
-
- let scope;
- let group;
-
- vm.init = (_scope_, _group_) => {
- scope = _scope_;
- group = _group_;
-
- group.register(scope);
- };
-
- vm.handleClick = () => {
- if (scope.state._disabled || scope.state._active) {
- return;
- }
- if (scope.state._go) {
- $state.go(scope.state._go, scope.state._params, { reload: true });
- return;
- }
- group.clearActive();
- scope.state._active = true;
- if (scope.state._onClickActivate) {
- scope.state._onClickActivate();
- }
- };
-}
-
-AtTabController.$inject = ['$state'];
-
-function atTab () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- require: ['^^atTabGroup', 'atTab'],
- templateUrl,
- controller: AtTabController,
- controllerAs: 'vm',
- link: atTabLink,
- scope: {
- state: '='
- }
- };
-}
-
-export default atTab;
diff --git a/awx/ui/client/lib/components/tabs/tab.partial.html b/awx/ui/client/lib/components/tabs/tab.partial.html
deleted file mode 100644
index 5b77e02841..0000000000
--- a/awx/ui/client/lib/components/tabs/tab.partial.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
diff --git a/awx/ui/client/lib/components/tag/_index.less b/awx/ui/client/lib/components/tag/_index.less
deleted file mode 100644
index 486b304337..0000000000
--- a/awx/ui/client/lib/components/tag/_index.less
+++ /dev/null
@@ -1,85 +0,0 @@
-.TagComponent {
- color: @at-white;
- cursor: default;
- background: @at-blue;
- border-radius: @at-space;
- font-size: 12px;
- display: flex;
- flex-direction: row;
- align-content: center;
- min-height: @at-space-4x;
- overflow: hidden;
- max-width: 200px;
- margin: @at-space 0;
-
- &:last-of-type {
- margin-right: 20px;
- }
-}
-
-.TagComponent-name {
- color: @at-white;
- margin: 2px @at-space-2x;
- align-self: center;
- /* fallback for FF < 68 which doesn't support `break-word` */
- word-break: break-all;
- word-break: break-word;
-
- &:hover,
- &:focus {
- color: @at-white;
- }
-}
-
-.TagComponent-icon {
- .at-mixin-VerticallyCenter();
- line-height: 20px;
- margin-left: @at-space-2x;
-
- &--cloud:before,
- &--aws:before,
- &--tower:before,
- &--azure_rm:before,
- {
- content: '\f0c2';
- }
-
- &--insights:before {
- content: '\f129';
- }
-
- &--net:before {
- content: '\f0e8';
- }
-
- &--scm:before {
- content: '\f126';
- }
-
- &--ssh:before {
- content: '\f084';
- }
-
- &--vault:before {
- content: '\f187';
- }
-
- &--external:before {
- content: '\f14c'
- }
-
- &--kubernetes:before, &--kubernetes_bearer_token:before {
- content: '\f0c2';
- }
-}
-
-.TagComponent-button {
- padding: 0 @at-space;
- .at-mixin-VerticallyCenter();
-}
-
-.TagComponent-button:hover {
- cursor: pointer;
- border-color: @at-color-error;
- background-color: @at-color-error;
-}
diff --git a/awx/ui/client/lib/components/tag/tag.directive.js b/awx/ui/client/lib/components/tag/tag.directive.js
deleted file mode 100644
index f18ae9dce9..0000000000
--- a/awx/ui/client/lib/components/tag/tag.directive.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const templateUrl = require('~components/tag/tag.partial.html');
-
-function atTag () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- scope: {
- tag: '=',
- icon: '@?',
- link: '@?',
- removeTag: '&?',
- },
- };
-}
-
-export default atTag;
diff --git a/awx/ui/client/lib/components/tag/tag.partial.html b/awx/ui/client/lib/components/tag/tag.partial.html
deleted file mode 100644
index f16da4da42..0000000000
--- a/awx/ui/client/lib/components/tag/tag.partial.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/toggle-tag/_index.less b/awx/ui/client/lib/components/toggle-tag/_index.less
deleted file mode 100644
index 18639c5648..0000000000
--- a/awx/ui/client/lib/components/toggle-tag/_index.less
+++ /dev/null
@@ -1,19 +0,0 @@
-.ToggleComponent-wrapper {
- line-height: initial;
-}
-
-.ToggleComponent-container {
- display: flex;
- flex-wrap: wrap;
-}
-
-.ToggleComponent-button {
- border: none;
- background: transparent;
- color: @at-blue;
- font-size: @at-font-size;
-
- &:hover {
- color: @at-blue-hover;
- }
-}
\ No newline at end of file
diff --git a/awx/ui/client/lib/components/toggle-tag/constants.js b/awx/ui/client/lib/components/toggle-tag/constants.js
deleted file mode 100644
index f3a4951c9c..0000000000
--- a/awx/ui/client/lib/components/toggle-tag/constants.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const TRUNCATE_LENGTH = 5;
-export const IS_TRUNCATED = true;
diff --git a/awx/ui/client/lib/components/toggle-tag/toggle-tag.directive.js b/awx/ui/client/lib/components/toggle-tag/toggle-tag.directive.js
deleted file mode 100644
index 4fec4cd794..0000000000
--- a/awx/ui/client/lib/components/toggle-tag/toggle-tag.directive.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { IS_TRUNCATED, TRUNCATE_LENGTH } from './constants';
-
-const templateUrl = require('~components/toggle-tag/toggle-tag.partial.html');
-
-function controller (strings) {
- const vm = this;
- vm.truncatedLength = TRUNCATE_LENGTH;
- vm.isTruncated = IS_TRUNCATED;
- vm.strings = strings;
-
- vm.toggle = () => {
- vm.isTruncated = !vm.isTruncated;
- };
-}
-
-controller.$inject = ['ComponentsStrings'];
-
-function atToggleTag () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- controller,
- controllerAs: 'vm',
- templateUrl,
- scope: {
- tags: '=',
- },
- };
-}
-
-export default atToggleTag;
diff --git a/awx/ui/client/lib/components/toggle-tag/toggle-tag.partial.html b/awx/ui/client/lib/components/toggle-tag/toggle-tag.partial.html
deleted file mode 100644
index fada04154e..0000000000
--- a/awx/ui/client/lib/components/toggle-tag/toggle-tag.partial.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
{{:: vm.strings.get('toggle.VIEW_MORE') }}
-
-
-
-
{{:: vm.strings.get('toggle.VIEW_LESS') }}
-
-
-
-
diff --git a/awx/ui/client/lib/components/truncate/_index.less b/awx/ui/client/lib/components/truncate/_index.less
deleted file mode 100644
index b4e4cb9dd5..0000000000
--- a/awx/ui/client/lib/components/truncate/_index.less
+++ /dev/null
@@ -1,35 +0,0 @@
-.at-Truncate {
- display: inline-block;
-
- .at-Truncate-text {
- font-family: monospace, Courier, "Courier New", "Open Sans", sans-serif;
- }
-
- .at-Truncate-tag {
- display: inherit;
- }
-
- .at-Truncate-copy {
- color: @at-gray-b7;
- cursor: pointer;
- margin: 0 20px 0 0;
- display: inherit;
-
- i:hover {
- color: @at-blue;
- }
- }
-
- .at-Truncate-textarea {
- background: transparent;
- border: none;
- box-shadow: none;
- height: 2em;
- left: 0px;
- outline: none;
- padding: 0px;
- position: fixed;
- top: 0px;
- width: 2em;
- }
-}
diff --git a/awx/ui/client/lib/components/truncate/truncate.directive.js b/awx/ui/client/lib/components/truncate/truncate.directive.js
deleted file mode 100644
index 8cc3df8bef..0000000000
--- a/awx/ui/client/lib/components/truncate/truncate.directive.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const templateUrl = require('~components/truncate/truncate.partial.html');
-
-function atTruncateLink (scope, el, attr, ctrl) {
- const truncateController = ctrl;
- const { string } = attr;
- const { maxlength } = attr;
-
- truncateController.init(el, string, maxlength);
-}
-
-function AtTruncateController (strings) {
- const vm = this;
- let el;
- let string;
- let maxlength;
- vm.strings = strings;
-
- vm.init = (_el_, _string_, _maxlength_) => {
- el = _el_;
- string = _string_;
- maxlength = _maxlength_;
- vm.truncatedString = string.substring(0, maxlength);
- };
-
- vm.copyToClipboard = () => {
- vm.tooltip.popover.text = vm.strings.get('truncate.COPIED');
-
- const textarea = el[0].getElementsByClassName('at-Truncate-textarea')[0];
- textarea.value = string;
- textarea.select();
-
- document.execCommand('copy');
- };
-
- vm.tooltip = {
- popover: {
- text: vm.strings.get('truncate.DEFAULT'),
- on: 'mouseover',
- position: 'top',
- icon: 'fa fa-clone',
- resetOnExit: true,
- click: vm.copyToClipboard
- }
- };
-}
-
-AtTruncateController.$inject = ['ComponentsStrings'];
-
-function atTruncate () {
- return {
- restrict: 'E',
- replace: true,
- transclude: true,
- templateUrl,
- controller: AtTruncateController,
- controllerAs: 'vm',
- link: atTruncateLink,
- scope: {
- state: '=',
- maxLength: '@',
- string: '@'
- }
- };
-}
-
-export default atTruncate;
diff --git a/awx/ui/client/lib/components/truncate/truncate.partial.html b/awx/ui/client/lib/components/truncate/truncate.partial.html
deleted file mode 100644
index aa329908eb..0000000000
--- a/awx/ui/client/lib/components/truncate/truncate.partial.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
- {{vm.truncatedString}}
-
-
-
-
diff --git a/awx/ui/client/lib/components/utility/_index.less b/awx/ui/client/lib/components/utility/_index.less
deleted file mode 100644
index f9851bef2b..0000000000
--- a/awx/ui/client/lib/components/utility/_index.less
+++ /dev/null
@@ -1,5 +0,0 @@
-.at-Divider {
- clear: both;
- margin: 0;
- padding: 0;
-}
diff --git a/awx/ui/client/lib/components/utility/divider.directive.js b/awx/ui/client/lib/components/utility/divider.directive.js
deleted file mode 100644
index 8aa71fad50..0000000000
--- a/awx/ui/client/lib/components/utility/divider.directive.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const templateUrl = require('~components/utility/divider.partial.html');
-
-function atPanelBody () {
- return {
- restrict: 'E',
- replace: true,
- templateUrl,
- scope: false
- };
-}
-
-export default atPanelBody;
diff --git a/awx/ui/client/lib/components/utility/divider.partial.html b/awx/ui/client/lib/components/utility/divider.partial.html
deleted file mode 100644
index 514695d55c..0000000000
--- a/awx/ui/client/lib/components/utility/divider.partial.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/awx/ui/client/lib/models/AdHocCommand.js b/awx/ui/client/lib/models/AdHocCommand.js
deleted file mode 100644
index 9f259a929a..0000000000
--- a/awx/ui/client/lib/models/AdHocCommand.js
+++ /dev/null
@@ -1,44 +0,0 @@
-let $http;
-let BaseModel;
-
-function getRelaunch (params) {
- const req = {
- method: 'GET',
- url: `${this.path}${params.id}/relaunch/`
- };
-
- return $http(req);
-}
-
-function postRelaunch (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/relaunch/`
- };
-
- return $http(req);
-}
-
-function AdHocCommandModel (method, resource, config) {
- BaseModel.call(this, 'ad_hoc_commands');
-
- this.Constructor = AdHocCommandModel;
- this.postRelaunch = postRelaunch.bind(this);
- this.getRelaunch = getRelaunch.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function AdHocCommandModelLoader (_$http_, _BaseModel_) {
- $http = _$http_;
- BaseModel = _BaseModel_;
-
- return AdHocCommandModel;
-}
-
-AdHocCommandModelLoader.$inject = [
- '$http',
- 'BaseModel',
-];
-
-export default AdHocCommandModelLoader;
diff --git a/awx/ui/client/lib/models/Application.js b/awx/ui/client/lib/models/Application.js
deleted file mode 100644
index 2a364eb9e7..0000000000
--- a/awx/ui/client/lib/models/Application.js
+++ /dev/null
@@ -1,80 +0,0 @@
-let Base;
-
-function createFormSchema (method, config) {
- function mungeSelectFromOptions (configObj, value) {
- configObj.choices = [[null, '']].concat(configObj.choices);
- configObj._data = configObj.choices;
- configObj._exp = 'choice[1] for choice in state._data';
- configObj._format = 'selectFromOptions';
-
- configObj._data.forEach((val, i) => {
- if (val[0] === value) {
- configObj._value = configObj._data[i];
- }
- });
-
- return configObj;
- }
-
- if (!config) {
- config = method;
- method = 'GET';
- }
-
- const schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`));
-
- if (config && config.omit) {
- config.omit.forEach(key => delete schema[key]);
- }
-
- Object.keys(schema).forEach(key => {
- schema[key].id = key;
-
- if (this.has(key) && schema[key].type !== 'choice') {
- schema[key]._value = this.get(key);
- }
-
- if (schema[key].type === 'choice') {
- schema[key] = mungeSelectFromOptions(schema[key], this.get(key));
- }
- });
-
- // necessary because authorization_grant_type is not changeable on update
- if (method === 'put') {
- schema.authorization_grant_type = mungeSelectFromOptions(Object.assign({}, this
- .options('actions.GET.authorization_grant_type')), this
- .get('authorization_grant_type'));
-
- schema.authorization_grant_type._required = false;
- schema.authorization_grant_type._disabled = true;
- }
-
- return schema;
-}
-
-function setDependentResources () {
- this.dependentResources = [];
-}
-
-function ApplicationModel (method, resource, config) {
- // TODO: change to applications
- Base.call(this, 'applications');
-
- this.Constructor = ApplicationModel;
- this.createFormSchema = createFormSchema.bind(this);
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function ApplicationModelLoader (BaseModel) {
- Base = BaseModel;
-
- return ApplicationModel;
-}
-
-ApplicationModelLoader.$inject = [
- 'BaseModel',
-];
-
-export default ApplicationModelLoader;
diff --git a/awx/ui/client/lib/models/Base.js b/awx/ui/client/lib/models/Base.js
deleted file mode 100644
index e5425a3335..0000000000
--- a/awx/ui/client/lib/models/Base.js
+++ /dev/null
@@ -1,738 +0,0 @@
-let $http;
-let $q;
-let cache;
-let strings;
-
-function request (method, resource, config) {
- let req = this.parseRequestConfig(method, resource, config);
-
- if (Array.isArray(req.method)) {
- const promises = req.method.map((_method, i) => {
- const _resource = Array.isArray(req.resource) ? req.resource[i] : req.resource;
-
- req = this.parseRequestConfig(_method, _resource, config);
-
- if (this.isCacheable(req)) {
- return this.requestWithCache(req);
- }
-
- return this.request(req);
- });
-
- return $q.all(promises);
- }
-
- if (this.isCacheable(req)) {
- return this.requestWithCache(req);
- }
-
- return this.http[req.method](req);
-}
-
-function requestWithCache (config) {
- const key = cache.createKey(config.method, this.path, config.resource);
-
- return cache.get(key)
- .then(data => {
- if (data) {
- this.model[config.method.toUpperCase()] = data;
-
- return data;
- }
-
- return this.http[config.method](config)
- .then(res => {
- cache.put(key, res.data);
-
- return res;
- });
- });
-}
-
-/**
- * Intended to be useful in searching and filtering results using params
- * supported by the API.
- *
- * @arg {Object} params - An object of keys and values to to format and
- * to the URL as a query string. Refer to the API documentation for the
- * resource in use for specifics.
- * @arg {Object} config - Configuration specific to the UI to accommodate
- * common use cases.
- *
- * @yields {boolean} - Indicating a match has been found. If so, the results
- * are set on the model.
- */
-function search (params = {}, config = {}, headers = {}) {
- const req = {
- method: 'GET',
- url: this.path,
- headers
- };
-
- if (typeof params === 'string') {
- req.url = '?params';
- } else if (Array.isArray(params)) {
- req.url += `?${params.join('&')}`;
- } else {
- req.params = params;
- }
-
- return $http(req)
- .then(({ data }) => {
- if (!data.count) {
- return false;
- }
-
- if (config.unique) {
- if (data.count !== 1) {
- return false;
- }
-
- [this.model.GET] = data.results;
- } else {
- this.model.GET = data;
- }
-
- return true;
- });
-}
-
-function httpGet (config = {}) {
- const req = {
- method: 'GET',
- url: this.path
- };
-
- if (config.params) {
- req.params = config.params;
-
- if (config.params.page_size) {
- this.page.size = config.params.page_size;
- this.page.current = 1;
-
- if (config.pageCache) {
- this.page.cachedPages = this.page.cachedPages || {};
- this.page.cache = this.page.cache || {};
- this.page.limit = config.pageLimit || false;
-
- if (!_.has(this.page.cachedPages, 'root')) {
- this.page.cachedPages.root = [];
- }
-
- if (!_.has(this.page.cache, 'root')) {
- this.page.cache.root = {};
- }
- }
- }
- }
-
- if (typeof config.resource === 'object') {
- this.model.GET = config.resource;
-
- return $q.resolve();
- } else if (config.resource) {
- req.url = `${this.path}${config.resource}/`;
- }
-
- return $http(req)
- .then(res => {
- this.model.GET = res.data;
-
- if (config.pageCache) {
- this.page.cache.root[this.page.current] = res.data.results;
- this.page.cachedPages.root.push(this.page.current);
- this.page.count = res.data.count;
- this.page.last = Math.ceil(res.data.count / this.page.size);
- }
-
- return res;
- });
-}
-
-function httpPost (config = {}) {
- const req = {
- method: 'POST',
- url: this.path,
- data: config.data,
- };
-
- if (config.url) {
- req.url = `${this.path}${config.url}`;
- }
-
- if (!('replace' in config)) {
- config.replace = true;
- }
-
- return $http(req)
- .then(res => {
- if (config.replace) {
- this.model.GET = res.data;
- }
- return res;
- });
-}
-
-function httpPatch (config = {}) {
- const req = {
- method: 'PUT',
- url: `${this.path}${this.get('id')}/`,
- data: config.changes
- };
-
- return $http(req);
-}
-
-function httpPut (config = {}) {
- const model = _.merge(this.get(), config.data);
-
- const req = {
- method: 'PUT',
- url: `${this.path}${this.get('id')}/`,
- data: model
- };
-
- return $http(req);
-}
-
-function httpOptions (config = {}) {
- const req = {
- method: 'OPTIONS',
- url: this.path
- };
-
- if (config.resource) {
- req.url = `${this.path}${config.resource}/`;
- }
-
- return $http(req)
- .then(res => {
- this.model.OPTIONS = res.data;
-
- return res;
- });
-}
-
-function httpDelete (config = {}) {
- const req = {
- method: 'DELETE',
- url: this.path
- };
-
- if (config.resource) {
- req.url = `${this.path}${config.resource}/`;
- }
-
- return $http(req);
-}
-
-function options (keys) {
- return this.find('options', keys);
-}
-
-function get (keys) {
- return this.find('get', keys);
-}
-
-function unset (method, keys) {
- if (!keys) {
- keys = method;
- method = 'GET';
- }
-
- method = method.toUpperCase();
- keys = keys.split('.');
-
- if (!keys.length) {
- delete this.model[method];
- } else if (keys.length === 1) {
- delete this.model[method][keys[0]];
- } else {
- const property = keys.splice(-1);
- keys = keys.join('.');
-
- const model = this.find(method, keys);
- delete model[property];
- }
-}
-
-function set (method, keys, value) {
- if (!value) {
- value = keys;
- keys = method;
- method = 'GET';
- }
-
- keys = keys.split('.');
-
- if (keys.length === 1) {
- this.model[keys[0]] = value;
- } else {
- const property = keys.splice(-1);
- keys = keys.join('.');
-
- const model = this.find(method, keys);
-
- model[property] = value;
- }
-}
-
-function match (method, key, value) {
- if (!value) {
- value = key;
- key = method;
- method = 'GET';
- }
-
- const model = this.model[method.toUpperCase()];
-
- if (!model) {
- return null;
- }
-
- if (!model.results) {
- if (model[key] === value) {
- return model;
- }
-
- return null;
- }
-
- const result = model.results.filter(object => object[key] === value);
-
- return result.length === 0 ? null : result[0];
-}
-
-function find (method, keys) {
- let value = this.model[method.toUpperCase()];
-
- if (!keys) {
- return value;
- }
-
- try {
- keys = keys.split('.');
-
- keys.forEach(key => {
- const bracketIndex = key.indexOf('[');
- const hasArray = bracketIndex !== -1;
-
- if (!hasArray) {
- value = value[key];
- return;
- }
-
- if (bracketIndex === 0) {
- value = value[Number(key.substring(1, key.length - 1))];
- return;
- }
-
- const prop = key.substring(0, bracketIndex);
- const index = Number(key.substring(bracketIndex + 1, key.length - 1));
-
- value = value[prop][index];
- });
- } catch (err) {
- return undefined;
- }
-
- return value;
-}
-
-function has (method, keys) {
- if (!keys) {
- keys = method;
- method = 'GET';
- }
-
- method = method.toUpperCase();
-
- let value;
- switch (method) {
- case 'OPTIONS':
- value = this.options(keys);
- break;
- default:
- value = this.get(keys);
- }
-
- return value !== undefined && value !== null;
-}
-
-function extend (method, related, config = {}) {
- const req = this.parseRequestConfig(method.toUpperCase(), config);
-
- if (_.get(config, 'params.page_size')) {
- this.page.size = config.params.page_size;
- this.page.current = 1;
-
- if (config.pageCache) {
- this.page.cachedPages = this.page.cachedPages || {};
- this.page.cache = this.page.cache || {};
- this.page.limit = config.pageLimit || false;
-
- if (!_.has(this.page.cachedPages, `related.${related}`)) {
- _.set(this.page.cachedPages, `related.${related}`, []);
- }
-
- if (!_.has(this.page.cache, `related.${related}`)) {
- _.set(this.page.cache, `related.${related}`, []);
- }
- }
- }
-
- if (this.has(req.method, `related.${related}`)) {
- req.url = this.get(`related.${related}`);
-
- Object.assign(req, config);
-
- return $http(req)
- .then(({ data }) => {
- this.set(req.method, `related.${related}`, data);
-
- if (config.pageCache) {
- this.page.cache.related[related][this.page.current] = data.results;
- this.page.cachedPages.related[related].push(this.page.current);
- this.page.count = data.count;
- this.page.last = Math.ceil(data.count / this.page.size);
- }
-
- return this;
- });
- }
-
- return Promise.reject(new Error(`No related property, ${related}, exists`));
-}
-
-function updateCount (count) {
- this.page.count = count;
- this.page.last = Math.ceil(count / this.page.size);
-
- return this.page.last;
-}
-
-function goToPage (config) {
- const params = config.params || {};
- const { page } = config;
-
- let url;
- let key;
- let pageNumber;
- let pageCache;
- let pagesInCache;
-
- if (config.related) {
- url = `${this.endpoint}${config.related}/`;
- key = `related.${config.related}`;
- } else {
- url = this.endpoint;
- key = 'root';
- }
-
- params.page_size = this.page.size;
-
- if (page === 'next') {
- pageNumber = this.page.current + 1;
- } else if (page === 'previous') {
- pageNumber = this.page.current - 1;
- } else if (page === 'first') {
- pageNumber = 1;
- } else if (page === 'last') {
- pageNumber = this.page.last;
- } else {
- pageNumber = page;
- }
-
- if (pageNumber < 1 || pageNumber > this.page.last) {
- return Promise.resolve(null);
- }
-
- this.page.current = pageNumber;
-
- if (this.page.cache) {
- pageCache = _.get(this.page.cache, key);
- pagesInCache = _.get(this.page.cachedPages, key);
-
- if (_.has(pageCache, pageNumber)) {
- return Promise.resolve({
- results: pageCache[pageNumber],
- page: pageNumber
- });
- }
- }
-
- params.page_size = this.page.size;
- params.page = pageNumber;
-
- const req = {
- method: 'GET',
- url,
- params
- };
-
- return $http(req)
- .then(({ data }) => {
- if (pageCache) {
- pageCache[pageNumber] = data.results;
- pagesInCache.push(pageNumber);
-
- if (pagesInCache.length > this.page.limit) {
- const pageToDelete = pagesInCache.shift();
-
- delete pageCache[pageToDelete];
- }
- }
-
- return {
- results: data.results,
- page: pageNumber
- };
- });
-}
-
-function next (config = {}) {
- config.page = 'next';
-
- return this.goToPage(config);
-}
-
-function prev (config = {}) {
- config.page = 'previous';
-
- return this.goToPage(config);
-}
-
-function normalizePath (resource) {
- const version = '/api/v2/';
-
- return `${version}${resource}/`;
-}
-
-function isEditable () {
- let canEdit = this.get('summary_fields.user_capabilities.edit');
-
- if (canEdit === undefined) {
- canEdit = true;
- }
-
- if (canEdit) {
- return true;
- }
-
- if (this.has('options', 'actions.PUT')) {
- return true;
- }
-
- return false;
-}
-
-function isCreatable () {
- if (this.has('options', 'actions.POST')) {
- return true;
- }
-
- return false;
-}
-
-function isCacheable () {
- if (this.settings.cache === true) {
- return true;
- }
-
- return false;
-}
-
-function graft (id) {
- let item = this.get('results').filter(result => result.id === id);
-
- item = item ? item[0] : undefined;
-
- if (!item) {
- return undefined;
- }
-
- return new this.Constructor('get', item, true);
-}
-
-function getDependentResourceCounts (id) {
- this.setDependentResources(id);
-
- const promises = [];
-
- this.dependentResources.forEach(resource => {
- promises.push(resource.model.request('get', { params: resource.params })
- .then(res => ({
- label: resource.model.label,
- count: res.data.count
- })));
- });
-
- return Promise.all(promises);
-}
-
-function copy () {
- if (!this.has('POST', 'related.copy')) {
- return Promise.reject(new Error('No related property, copy, exists'));
- }
-
- const date = new Date();
- const name = `${this.get('name')}@${date.toLocaleTimeString()}`;
-
- const url = `${this.path}${this.get('id')}/copy/`;
-
- const req = {
- url,
- method: 'POST',
- data: { name }
- };
-
- return $http(req).then(res => res.data);
-}
-
-/**
- * `create` is called on instantiation of every model. Models can be
- * instantiated empty or with `GET` and/or `OPTIONS` requests that yield data.
- * If model data already exists a new instance can be created (see: `graft`)
- * with existing data.
- *
- * @arg {string=} method - Populate the model with `GET` or `OPTIONS` data.
- * @arg {(string|Object)=} resource - An `id` reference to a particular
- * resource or an existing model's data.
- * @arg {config=} config - Create a new instance from existing model data.
- *
- * @returns {(Object|Promise)} - Returns a reference to the model instance
- * if an empty instance or graft is created. Otherwise, a promise yielding
- * a model instance is returned.
- */
-function create (method, resource, config) {
- const req = this.parseRequestConfig(method, resource, config);
-
- if (!req || !req.method) {
- return this;
- }
-
- if (req.resource) {
- this.setEndpoint(req.resource);
- }
-
- this.promise = this.request(req);
-
- if (req.graft) {
- return this;
- }
-
- return this.promise
- .then(() => this);
-}
-
-function setEndpoint (resource) {
- if (Array.isArray(resource)) {
- this.endpoint = `${this.path}${resource[0]}/`;
- } else {
- this.endpoint = `${this.path}${resource}/`;
- }
-}
-
-function parseRequestConfig (method, resource, config) {
- if (!method) {
- return null;
- }
-
- let req = {};
-
- if (Array.isArray(method)) {
- if (Array.isArray(resource)) {
- req.resource = resource;
- } else if (resource === null) {
- req.resource = undefined;
- } else if (typeof resource === 'object') {
- req = resource;
- }
-
- req.method = method;
- } else if (typeof method === 'string') {
- if (resource === null) {
- req.resource = undefined;
- } else if (typeof resource === 'object') {
- req = resource;
- } else {
- req.resource = resource;
- }
-
- req.method = method;
- } else if (typeof method === 'object') {
- req = method;
- } else {
- req = config;
- req.method = method;
- req.resource = resource === null ? undefined : resource;
- }
-
- return req;
-}
-
-/**
- * Base functionality for API interaction.
- *
- * @arg {string} resource - The API resource for the model extending BaseModel to
- * use.
- * @arg {Object=} settings - Configuration applied to all instances of the
- * extending model.
- * @arg {boolean=} settings.cache - Cache the model data.
- *
- */
-function BaseModel (resource, settings) {
- this.create = create;
- this.find = find;
- this.get = get;
- this.goToPage = goToPage;
- this.graft = graft;
- this.has = has;
- this.isEditable = isEditable;
- this.isCacheable = isCacheable;
- this.isCreatable = isCreatable;
- this.match = match;
- this.next = next;
- this.normalizePath = normalizePath;
- this.options = options;
- this.parseRequestConfig = parseRequestConfig;
- this.prev = prev;
- this.request = request;
- this.requestWithCache = requestWithCache;
- this.search = search;
- this.set = set;
- this.setEndpoint = setEndpoint;
- this.unset = unset;
- this.extend = extend;
- this.copy = copy;
- this.getDependentResourceCounts = getDependentResourceCounts;
- this.updateCount = updateCount;
-
- this.http = {
- get: httpGet.bind(this),
- options: httpOptions.bind(this),
- patch: httpPatch.bind(this),
- post: httpPost.bind(this),
- put: httpPut.bind(this),
- delete: httpDelete.bind(this)
- };
-
- this.page = {};
- this.model = {};
- this.path = this.normalizePath(resource);
- this.label = strings.get(`${resource}.LABEL`);
- this.settings = settings || {};
-}
-
-function BaseModelLoader (_$http_, _$q_, _cache_, ModelsStrings) {
- $http = _$http_;
- $q = _$q_;
- cache = _cache_;
- strings = ModelsStrings;
-
- return BaseModel;
-}
-
-BaseModelLoader.$inject = ['$http', '$q', 'CacheService', 'ModelsStrings'];
-
-export default BaseModelLoader;
diff --git a/awx/ui/client/lib/models/Config.js b/awx/ui/client/lib/models/Config.js
deleted file mode 100644
index 9f2e3ab87a..0000000000
--- a/awx/ui/client/lib/models/Config.js
+++ /dev/null
@@ -1,39 +0,0 @@
-let $log;
-let Base;
-
-function getTruncatedVersion () {
- let version;
-
- try {
- [version] = this.get('version').split('-');
- } catch (err) {
- $log.error(err);
- }
-
- return version;
-}
-
-function isOpen () {
- return this.get('license_info.license_type') === 'open';
-}
-
-function ConfigModel (method, resource, config) {
- Base.call(this, 'config', { cache: true });
-
- this.Constructor = ConfigModel;
- this.getTruncatedVersion = getTruncatedVersion;
- this.isOpen = isOpen;
-
- return this.create(method, resource, config);
-}
-
-function ConfigModelLoader (BaseModel, _$log_) {
- Base = BaseModel;
- $log = _$log_;
-
- return ConfigModel;
-}
-
-ConfigModelLoader.$inject = ['BaseModel', '$log'];
-
-export default ConfigModelLoader;
diff --git a/awx/ui/client/lib/models/Credential.js b/awx/ui/client/lib/models/Credential.js
deleted file mode 100644
index 6fbce5e141..0000000000
--- a/awx/ui/client/lib/models/Credential.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/* eslint camelcase: 0 */
-const ENCRYPTED_VALUE = '$encrypted$';
-
-let Base;
-let Project;
-let JobTemplate;
-let Inventory;
-let InventorySource;
-
-function createFormSchema (method, config) {
- if (!config) {
- config = method;
- method = 'GET';
- }
-
- const schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`));
-
- if (config && config.omit) {
- config.omit.forEach(key => delete schema[key]);
- }
-
- Object.keys(schema).forEach(key => {
- schema[key].id = key;
-
- if (this.has(key)) {
- schema[key]._value = this.get(key);
- }
- });
-
- // Custom credentials can have input fields named 'name', 'organization',
- // 'description', etc. Underscore these variables to make collisions
- // less likely to occur.
- schema._name = schema.name;
- schema._organization = schema.organization;
- schema._description = schema.description;
- delete schema.name;
- delete schema.organization;
- delete schema.description;
-
- return schema;
-}
-
-function assignInputGroupValues (apiConfig, credentialType, sourceCredentials) {
- let inputs = credentialType.get('inputs.fields');
-
- if (!inputs) {
- return [];
- }
-
- if (this.has('credential_type')) {
- if (credentialType.get('id') !== this.get('credential_type')) {
- inputs.forEach(field => {
- field.tagMode = this.isEditable() && credentialType.get('kind') !== 'external';
- });
- return inputs;
- }
- }
-
- inputs = inputs.map(input => {
- const value = this.get(`inputs.${input.id}`);
-
- input._value = value;
- input._encrypted = value === ENCRYPTED_VALUE;
-
- return input;
- });
-
- if (credentialType.get('namespace') === 'ssh') {
- const become = inputs.find((field) => field.id === 'become_method');
- become._isDynamic = true;
- become._choices = Array.from(apiConfig.become_methods, method => method[0]);
- // Add the value to the choices if it doesn't exist in the preset list
- if (become._value && become._value !== '') {
- const optionMatches = become._choices
- .findIndex((option) => option === become._value);
- if (optionMatches === -1) {
- become._choices.push(become._value);
- }
- }
- }
-
- const linkedFieldNames = (this.get('related.input_sources.results') || [])
- .map(({ input_field_name }) => input_field_name);
-
- inputs = inputs.map((field) => {
- field.tagMode = this.isEditable() && credentialType.get('kind') !== 'external';
- if (linkedFieldNames.includes(field.id)) {
- field.tagMode = true;
- field.asTag = true;
- const { summary_fields } = this.get('related.input_sources.results')
- .find(({ input_field_name }) => input_field_name === field.id);
- field._tagValue = summary_fields.source_credential.name;
-
- const { source_credential: { id } } = summary_fields;
- const src = sourceCredentials.data.results.find(obj => obj.id === id);
- const canRemove = _.get(src, ['summary_fields', 'user_capabilities', 'delete'], false);
-
- if (!canRemove) {
- field._disabled = true;
- }
- }
-
- return field;
- });
-
- return inputs;
-}
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new Project(),
- params: {
- credential: id
- }
- },
- {
- model: new JobTemplate(),
- params: {
- credentials__id: id,
- ask_credential_on_launch: false
- }
- },
- {
- model: new Inventory(),
- params: {
- insights_credential: id
- }
- },
- {
- model: new InventorySource(),
- params: {
- credentials__id: id
- }
- }
- ];
-}
-
-function CredentialModel (method, resource, config) {
- Base.call(this, 'credentials');
-
- this.Constructor = CredentialModel;
- this.createFormSchema = createFormSchema.bind(this);
- this.assignInputGroupValues = assignInputGroupValues.bind(this);
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function CredentialModelLoader (
- BaseModel,
- ProjectModel,
- JobTemplateModel,
- InventoryModel,
- InventorySourceModel
-) {
- Base = BaseModel;
- Project = ProjectModel;
- JobTemplate = JobTemplateModel;
- Inventory = InventoryModel;
- InventorySource = InventorySourceModel;
-
- return CredentialModel;
-}
-
-CredentialModelLoader.$inject = [
- 'BaseModel',
- 'ProjectModel',
- 'JobTemplateModel',
- 'InventoryModel',
- 'InventorySourceModel'
-];
-
-export default CredentialModelLoader;
diff --git a/awx/ui/client/lib/models/CredentialType.js b/awx/ui/client/lib/models/CredentialType.js
deleted file mode 100644
index 38c44cd845..0000000000
--- a/awx/ui/client/lib/models/CredentialType.js
+++ /dev/null
@@ -1,68 +0,0 @@
-let Base;
-let Credential;
-
-function categorizeByKind () {
- const group = {};
-
- this.get('results').forEach(result => {
- group[result.kind] = group[result.kind] || [];
- group[result.kind].push(result);
- });
-
- return Object.keys(group).map(category => ({
- data: group[category],
- category
- }));
-}
-
-function mergeInputProperties (key = 'fields') {
- if (!this.has(`inputs.${key}`)) {
- return undefined;
- }
-
- const required = this.get('inputs.required');
-
- return this.get(`inputs.${key}`).forEach((field, i) => {
- if (!required || required.indexOf(field.id) === -1) {
- this.set(`inputs.${key}[${i}].required`, false);
- } else {
- this.set(`inputs.${key}[${i}].required`, true);
- }
- });
-}
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new Credential(),
- params: {
- credential_type: id
- }
- }
- ];
-}
-
-function CredentialTypeModel (method, resource, config) {
- Base.call(this, 'credential_types');
-
- this.Constructor = CredentialTypeModel;
- this.categorizeByKind = categorizeByKind.bind(this);
- this.mergeInputProperties = mergeInputProperties.bind(this);
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function CredentialTypeModelLoader (BaseModel, CredentialModel) {
- Base = BaseModel;
- Credential = CredentialModel;
-
- return CredentialTypeModel;
-}
-
-CredentialTypeModelLoader.$inject = [
- 'BaseModel',
- 'CredentialModel'
-];
-
-export default CredentialTypeModelLoader;
diff --git a/awx/ui/client/lib/models/Instance.js b/awx/ui/client/lib/models/Instance.js
deleted file mode 100644
index 09b7df0547..0000000000
--- a/awx/ui/client/lib/models/Instance.js
+++ /dev/null
@@ -1,47 +0,0 @@
-let Base;
-
-function createFormSchema (method, config) {
- if (!config) {
- config = method;
- method = 'GET';
- }
-
- const schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`));
-
- if (config && config.omit) {
- config.omit.forEach(key => delete schema[key]);
- }
-
- Object.keys(schema).forEach(key => {
- schema[key].id = key;
-
- if (this.has(key)) {
- schema[key]._value = this.get(key);
- }
- });
-
- return schema;
-}
-
-function InstanceModel (method, resource, config) {
- // Base takes two args: resource and settings
- // resource is the string endpoint
- Base.call(this, 'instances');
-
- this.Constructor = InstanceModel;
- this.createFormSchema = createFormSchema.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function InstanceModelLoader (BaseModel) {
- Base = BaseModel;
-
- return InstanceModel;
-}
-
-InstanceModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default InstanceModelLoader;
diff --git a/awx/ui/client/lib/models/InstanceGroup.js b/awx/ui/client/lib/models/InstanceGroup.js
deleted file mode 100644
index cc82432c42..0000000000
--- a/awx/ui/client/lib/models/InstanceGroup.js
+++ /dev/null
@@ -1,47 +0,0 @@
-let Base;
-
-function createFormSchema (method, config) {
- if (!config) {
- config = method;
- method = 'GET';
- }
-
- const schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`));
-
- if (config && config.omit) {
- config.omit.forEach(key => delete schema[key]);
- }
-
- Object.keys(schema).forEach(key => {
- schema[key].id = key;
-
- if (this.has(key)) {
- schema[key]._value = this.get(key);
- }
- });
-
- return schema;
-}
-
-function InstanceGroupModel (method, resource, config) {
- // Base takes two args: resource and settings
- // resource is the string endpoint
- Base.call(this, 'instance_groups');
-
- this.Constructor = InstanceGroupModel;
- this.createFormSchema = createFormSchema.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function InstanceGroupModelLoader (BaseModel) {
- Base = BaseModel;
-
- return InstanceGroupModel;
-}
-
-InstanceGroupModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default InstanceGroupModelLoader;
diff --git a/awx/ui/client/lib/models/Inventory.js b/awx/ui/client/lib/models/Inventory.js
deleted file mode 100644
index 828dac1055..0000000000
--- a/awx/ui/client/lib/models/Inventory.js
+++ /dev/null
@@ -1,45 +0,0 @@
-let Base;
-let JobTemplate;
-let WorkflowJobTemplate;
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new JobTemplate(),
- params: {
- inventory: id
- }
- },
- {
- model: new WorkflowJobTemplate(),
- params: {
- inventory: id
- }
- }
- ];
-}
-
-function InventoryModel (method, resource, config) {
- Base.call(this, 'inventories');
-
- this.Constructor = InventoryModel;
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function InventoryModelLoader (BaseModel, JobTemplateModel, WorkflowJobTemplateModel) {
- Base = BaseModel;
- JobTemplate = JobTemplateModel;
- WorkflowJobTemplate = WorkflowJobTemplateModel;
-
- return InventoryModel;
-}
-
-InventoryModelLoader.$inject = [
- 'BaseModel',
- 'JobTemplateModel',
- 'WorkflowJobTemplateModel',
-];
-
-export default InventoryModelLoader;
diff --git a/awx/ui/client/lib/models/InventoryScript.js b/awx/ui/client/lib/models/InventoryScript.js
deleted file mode 100644
index 1b759410ab..0000000000
--- a/awx/ui/client/lib/models/InventoryScript.js
+++ /dev/null
@@ -1,36 +0,0 @@
-let Base;
-let InventorySource;
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new InventorySource(),
- params: {
- source_script: id
- }
- }
- ];
-}
-
-function InventoryScriptModel (method, resource, config) {
- Base.call(this, 'inventory_scripts');
-
- this.Constructor = InventoryScriptModel;
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function InventoryScriptModelLoader (BaseModel, InventorySourceModel) {
- Base = BaseModel;
- InventorySource = InventorySourceModel;
-
- return InventoryScriptModel;
-}
-
-InventoryScriptModelLoader.$inject = [
- 'BaseModel',
- 'InventorySourceModel'
-];
-
-export default InventoryScriptModelLoader;
diff --git a/awx/ui/client/lib/models/InventorySource.js b/awx/ui/client/lib/models/InventorySource.js
deleted file mode 100644
index 0d68a11780..0000000000
--- a/awx/ui/client/lib/models/InventorySource.js
+++ /dev/null
@@ -1,63 +0,0 @@
-let Base;
-let WorkflowJobTemplateNode;
-let $http;
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new WorkflowJobTemplateNode(),
- params: {
- unified_job_template: id
- }
- }
- ];
-}
-
-function getUpdate (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/update/`
- };
-
- return $http(req);
-}
-
-function postUpdate (id) {
- const req = {
- method: 'POST',
- url: `${this.path}${id}/update/`
- };
-
- return $http(req);
-}
-
-function InventorySourceModel (method, resource, config) {
- Base.call(this, 'inventory_sources');
-
- this.Constructor = InventorySourceModel;
- this.setDependentResources = setDependentResources.bind(this);
- this.getUpdate = getUpdate.bind(this);
- this.postUpdate = postUpdate.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function InventorySourceModelLoader (
- BaseModel,
- WorkflowJobTemplateNodeModel,
- _$http_
-) {
- Base = BaseModel;
- WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
- $http = _$http_;
-
- return InventorySourceModel;
-}
-
-InventorySourceModelLoader.$inject = [
- 'BaseModel',
- 'WorkflowJobTemplateNodeModel',
- '$http'
-];
-
-export default InventorySourceModelLoader;
diff --git a/awx/ui/client/lib/models/InventoryUpdate.js b/awx/ui/client/lib/models/InventoryUpdate.js
deleted file mode 100644
index 37951911d7..0000000000
--- a/awx/ui/client/lib/models/InventoryUpdate.js
+++ /dev/null
@@ -1,21 +0,0 @@
-let BaseModel;
-
-function InventoryUpdateModel (method, resource, config) {
- BaseModel.call(this, 'inventory_updates');
-
- this.Constructor = InventoryUpdateModel;
-
- return this.create(method, resource, config);
-}
-
-function InventoryUpdateModelLoader (_BaseModel_) {
- BaseModel = _BaseModel_;
-
- return InventoryUpdateModel;
-}
-
-InventoryUpdateModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default InventoryUpdateModelLoader;
diff --git a/awx/ui/client/lib/models/Job.js b/awx/ui/client/lib/models/Job.js
deleted file mode 100644
index 7e2f017826..0000000000
--- a/awx/ui/client/lib/models/Job.js
+++ /dev/null
@@ -1,59 +0,0 @@
-let $http;
-let BaseModel;
-
-function getRelaunch (params) {
- const req = {
- method: 'GET',
- url: `${this.path}${params.id}/relaunch/`
- };
-
- return $http(req);
-}
-
-function postRelaunch (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/relaunch/`
- };
-
- if (params.relaunchData) {
- req.data = params.relaunchData;
- }
-
- return $http(req);
-}
-
-function getCredentials (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/credentials/`
- };
-
- return $http(req);
-}
-
-function JobModel (method, resource, config) {
- BaseModel.call(this, 'jobs');
-
- this.Constructor = JobModel;
-
- this.postRelaunch = postRelaunch.bind(this);
- this.getRelaunch = getRelaunch.bind(this);
- this.getCredentials = getCredentials.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function JobModelLoader (_$http_, _BaseModel_) {
- $http = _$http_;
- BaseModel = _BaseModel_;
-
- return JobModel;
-}
-
-JobModelLoader.$inject = [
- '$http',
- 'BaseModel',
-];
-
-export default JobModelLoader;
diff --git a/awx/ui/client/lib/models/JobEvent.js b/awx/ui/client/lib/models/JobEvent.js
deleted file mode 100644
index 1c71ba9c54..0000000000
--- a/awx/ui/client/lib/models/JobEvent.js
+++ /dev/null
@@ -1,19 +0,0 @@
-let BaseModel;
-
-function JobEventModel (method, resource, config) {
- BaseModel.call(this, 'job_events');
-
- this.Constructor = JobEventModel;
-
- return this.create(method, resource, config);
-}
-
-function JobEventModelLoader (_BaseModel_) {
- BaseModel = _BaseModel_;
-
- return JobEventModel;
-}
-
-JobEventModel.$inject = ['BaseModel'];
-
-export default JobEventModelLoader;
diff --git a/awx/ui/client/lib/models/JobTemplate.js b/awx/ui/client/lib/models/JobTemplate.js
deleted file mode 100644
index b5a0dae16e..0000000000
--- a/awx/ui/client/lib/models/JobTemplate.js
+++ /dev/null
@@ -1,120 +0,0 @@
-let Base;
-let WorkflowJobTemplateNode;
-let $http;
-
-function optionsLaunch (id) {
- const req = {
- method: 'OPTIONS',
- url: `${this.path}${id}/launch/`
- };
-
- return $http(req);
-}
-
-function getLaunch (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/launch/`
- };
-
- return $http(req)
- .then(res => {
- this.model.launch.GET = res.data;
-
- return res;
- });
-}
-
-function postLaunch (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/launch/`
- };
-
- if (params.launchData) {
- req.data = params.launchData;
- }
-
- return $http(req);
-}
-
-function getSurveyQuestions (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/survey_spec/`
- };
-
- return $http(req);
-}
-
-function getLaunchConf () {
- // this method is just a pass-through to the underlying launch GET data
- // we use it to make the access patterns consistent across both types of
- // templates
- return this.model.launch.GET;
-}
-
-function canLaunchWithoutPrompt () {
- const launchData = this.getLaunchConf();
-
- return (
- launchData.can_start_without_user_input &&
- !launchData.ask_inventory_on_launch &&
- !launchData.ask_credential_on_launch &&
- !launchData.ask_verbosity_on_launch &&
- !launchData.ask_job_type_on_launch &&
- !launchData.ask_limit_on_launch &&
- !launchData.ask_tags_on_launch &&
- !launchData.ask_skip_tags_on_launch &&
- !launchData.ask_variables_on_launch &&
- !launchData.ask_diff_mode_on_launch &&
- !launchData.ask_scm_branch_on_launch &&
- !launchData.survey_enabled &&
- launchData.variables_needed_to_start.length === 0
- );
-}
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new WorkflowJobTemplateNode(),
- params: {
- unified_job_template: id
- }
- }
- ];
-}
-
-function JobTemplateModel (method, resource, config) {
- Base.call(this, 'job_templates');
-
- this.Constructor = JobTemplateModel;
- this.setDependentResources = setDependentResources.bind(this);
- this.optionsLaunch = optionsLaunch.bind(this);
- this.getLaunch = getLaunch.bind(this);
- this.postLaunch = postLaunch.bind(this);
- this.getSurveyQuestions = getSurveyQuestions.bind(this);
- this.getLaunchConf = getLaunchConf.bind(this);
- this.canLaunchWithoutPrompt = canLaunchWithoutPrompt.bind(this);
-
- this.model.launch = {};
-
- return this.create(method, resource, config);
-}
-
-function JobTemplateModelLoader (BaseModel, WorkflowJobTemplateNodeModel, _$http_) {
- Base = BaseModel;
- WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
- $http = _$http_;
-
- return JobTemplateModel;
-}
-
-JobTemplateModelLoader.$inject = [
- 'BaseModel',
- 'WorkflowJobTemplateNodeModel',
- '$http',
- '$state'
-];
-
-export default JobTemplateModelLoader;
diff --git a/awx/ui/client/lib/models/Me.js b/awx/ui/client/lib/models/Me.js
deleted file mode 100644
index 221a29da34..0000000000
--- a/awx/ui/client/lib/models/Me.js
+++ /dev/null
@@ -1,27 +0,0 @@
-let Base;
-
-function MeModel (method, resource, config) {
- Base.call(this, 'me');
-
- this.Constructor = MeModel;
-
- return this.create(method, resource, config)
- .then(() => {
- if (this.has('results')) {
- _.merge(this.model.GET, this.get('results[0]'));
- this.unset('results');
- }
-
- return this;
- });
-}
-
-function MeModelLoader (BaseModel) {
- Base = BaseModel;
-
- return MeModel;
-}
-
-MeModelLoader.$inject = ['BaseModel'];
-
-export default MeModelLoader;
diff --git a/awx/ui/client/lib/models/NotificationTemplate.js b/awx/ui/client/lib/models/NotificationTemplate.js
deleted file mode 100644
index 6418a7184d..0000000000
--- a/awx/ui/client/lib/models/NotificationTemplate.js
+++ /dev/null
@@ -1,21 +0,0 @@
-let Base;
-
-function NotificationTemplateModel (method, resource, config) {
- Base.call(this, 'notification_templates');
-
- this.Constructor = NotificationTemplateModel;
-
- return this.create(method, resource, config);
-}
-
-function NotificationTemplateModelLoader (BaseModel) {
- Base = BaseModel;
-
- return NotificationTemplateModel;
-}
-
-NotificationTemplateModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default NotificationTemplateModelLoader;
diff --git a/awx/ui/client/lib/models/Organization.js b/awx/ui/client/lib/models/Organization.js
deleted file mode 100644
index 6209889fba..0000000000
--- a/awx/ui/client/lib/models/Organization.js
+++ /dev/null
@@ -1,36 +0,0 @@
-let Base;
-let Credential;
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new Credential(),
- params: {
- organization: id
- }
- }
- ];
-}
-
-function OrganizationModel (method, resource, config) {
- Base.call(this, 'organizations');
-
- this.Constructor = OrganizationModel;
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function OrganizationModelLoader (BaseModel, CredentialModel) {
- Base = BaseModel;
- Credential = CredentialModel;
-
- return OrganizationModel;
-}
-
-OrganizationModelLoader.$inject = [
- 'BaseModel',
- 'CredentialModel'
-];
-
-export default OrganizationModelLoader;
diff --git a/awx/ui/client/lib/models/Project.js b/awx/ui/client/lib/models/Project.js
deleted file mode 100644
index 02606c3dcd..0000000000
--- a/awx/ui/client/lib/models/Project.js
+++ /dev/null
@@ -1,83 +0,0 @@
-let Base;
-let JobTemplate;
-let WorkflowJobTemplateNode;
-let InventorySource;
-let $http;
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new JobTemplate(),
- params: {
- project: id
- }
- },
- {
- model: new WorkflowJobTemplateNode(),
- params: {
- unified_job_template: id
- }
- },
- {
- model: new InventorySource(),
- params: {
- source_project: id
- }
- }
- ];
-}
-
-function getUpdate (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/update/`
- };
-
- return $http(req);
-}
-
-function postUpdate (id) {
- const req = {
- method: 'POST',
- url: `${this.path}${id}/update/`
- };
-
- return $http(req);
-}
-
-function ProjectModel (method, resource, config) {
- Base.call(this, 'projects');
-
- this.Constructor = ProjectModel;
- this.setDependentResources = setDependentResources.bind(this);
- this.getUpdate = getUpdate.bind(this);
- this.postUpdate = postUpdate.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function ProjectModelLoader (
- BaseModel,
- JobTemplateModel,
- WorkflowJobTemplateNodeModel,
- InventorySourceModel,
- _$http_
-) {
- Base = BaseModel;
- JobTemplate = JobTemplateModel;
- WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
- InventorySource = InventorySourceModel;
- $http = _$http_;
-
- return ProjectModel;
-}
-
-ProjectModelLoader.$inject = [
- 'BaseModel',
- 'JobTemplateModel',
- 'WorkflowJobTemplateNodeModel',
- 'InventorySourceModel',
- '$http'
-];
-
-export default ProjectModelLoader;
diff --git a/awx/ui/client/lib/models/ProjectUpdate.js b/awx/ui/client/lib/models/ProjectUpdate.js
deleted file mode 100644
index a8b1ae1fe9..0000000000
--- a/awx/ui/client/lib/models/ProjectUpdate.js
+++ /dev/null
@@ -1,21 +0,0 @@
-let BaseModel;
-
-function ProjectUpdateModel (method, resource, config) {
- BaseModel.call(this, 'project_updates');
-
- this.Constructor = ProjectUpdateModel;
-
- return this.create(method, resource, config);
-}
-
-function ProjectUpdateModelLoader (_BaseModel_) {
- BaseModel = _BaseModel_;
-
- return ProjectUpdateModel;
-}
-
-ProjectUpdateModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default ProjectUpdateModelLoader;
diff --git a/awx/ui/client/lib/models/Schedule.js b/awx/ui/client/lib/models/Schedule.js
deleted file mode 100644
index b6bd3cf60f..0000000000
--- a/awx/ui/client/lib/models/Schedule.js
+++ /dev/null
@@ -1,38 +0,0 @@
-let Base;
-let $http;
-
-function postCredential (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/credentials/`
- };
-
- if (params.data) {
- req.data = params.data;
- }
-
- return $http(req);
-}
-
-function ScheduleModel (method, resource, config) {
- Base.call(this, 'schedules');
-
- this.Constructor = ScheduleModel;
- this.postCredential = postCredential.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function ScheduleModelLoader (BaseModel, _$http_) {
- Base = BaseModel;
- $http = _$http_;
-
- return ScheduleModel;
-}
-
-ScheduleModelLoader.$inject = [
- 'BaseModel',
- '$http'
-];
-
-export default ScheduleModelLoader;
diff --git a/awx/ui/client/lib/models/SystemJob.js b/awx/ui/client/lib/models/SystemJob.js
deleted file mode 100644
index cc092ff8f4..0000000000
--- a/awx/ui/client/lib/models/SystemJob.js
+++ /dev/null
@@ -1,19 +0,0 @@
-let BaseModel;
-
-function SystemJobModel (method, resource, config) {
- BaseModel.call(this, 'system_jobs');
-
- this.Constructor = SystemJobModel;
-
- return this.create(method, resource, config);
-}
-
-function SystemJobModelLoader (_BaseModel_) {
- BaseModel = _BaseModel_;
-
- return SystemJobModel;
-}
-
-SystemJobModelLoader.$inject = ['BaseModel'];
-
-export default SystemJobModelLoader;
diff --git a/awx/ui/client/lib/models/Token.js b/awx/ui/client/lib/models/Token.js
deleted file mode 100644
index c4dfaf1937..0000000000
--- a/awx/ui/client/lib/models/Token.js
+++ /dev/null
@@ -1,26 +0,0 @@
-let Base;
-
-function setDependentResources () {
- this.dependentResources = [];
-}
-
-function TokenModel (method, resource, config) {
- Base.call(this, 'tokens');
-
- this.Constructor = TokenModel;
- this.setDependentResources = setDependentResources.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function TokenModelLoader (BaseModel) {
- Base = BaseModel;
-
- return TokenModel;
-}
-
-TokenModelLoader.$inject = [
- 'BaseModel',
-];
-
-export default TokenModelLoader;
diff --git a/awx/ui/client/lib/models/UnifiedJob.js b/awx/ui/client/lib/models/UnifiedJob.js
deleted file mode 100644
index 13078f8fa2..0000000000
--- a/awx/ui/client/lib/models/UnifiedJob.js
+++ /dev/null
@@ -1,21 +0,0 @@
-let Base;
-
-function UnifiedJobModel (method, resource, config) {
- Base.call(this, 'unified_jobs');
-
- this.Constructor = UnifiedJobModel;
-
- return this.create(method, resource, config);
-}
-
-function UnifiedJobModelLoader (BaseModel) {
- Base = BaseModel;
-
- return UnifiedJobModel;
-}
-
-UnifiedJobModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default UnifiedJobModelLoader;
diff --git a/awx/ui/client/lib/models/UnifiedJobTemplate.js b/awx/ui/client/lib/models/UnifiedJobTemplate.js
deleted file mode 100644
index fb1e241fd3..0000000000
--- a/awx/ui/client/lib/models/UnifiedJobTemplate.js
+++ /dev/null
@@ -1,111 +0,0 @@
-let BaseModel;
-let WorkflowJobTemplateNode;
-let $http;
-
-function optionsLaunch (id) {
- const req = {
- method: 'OPTIONS',
- url: `${this.path}${id}/launch/`
- };
-
- return $http(req);
-}
-
-function getLaunch (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/launch/`
- };
-
- return $http(req)
- .then(res => {
- this.model.launch.GET = res.data;
-
- return res;
- });
-}
-
-function postLaunch (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/launch/`
- };
-
- if (params.launchData) {
- req.data = params.launchData;
- }
-
- return $http(req);
-}
-
-function getSurveyQuestions (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/survey_spec/`
- };
-
- return $http(req);
-}
-
-function canLaunchWithoutPrompt () {
- const launchData = this.model.launch.GET;
-
- return (
- launchData.can_start_without_user_input &&
- !launchData.ask_inventory_on_launch &&
- !launchData.ask_credential_on_launch &&
- !launchData.ask_verbosity_on_launch &&
- !launchData.ask_job_type_on_launch &&
- !launchData.ask_limit_on_launch &&
- !launchData.ask_tags_on_launch &&
- !launchData.ask_skip_tags_on_launch &&
- !launchData.ask_variables_on_launch &&
- !launchData.ask_diff_mode_on_launch &&
- !launchData.ask_scm_branch_on_launch &&
- !launchData.survey_enabled
- );
-}
-
-function setDependentResources (id) {
- this.dependentResources = [
- {
- model: new WorkflowJobTemplateNode(),
- params: {
- unified_job_template: id
- }
- }
- ];
-}
-
-function UnifiedJobTemplateModel (method, resource, graft) {
- BaseModel.call(this, 'unified_job_templates');
-
- this.Constructor = UnifiedJobTemplateModel;
- this.setDependentResources = setDependentResources.bind(this);
- this.optionsLaunch = optionsLaunch.bind(this);
- this.getLaunch = getLaunch.bind(this);
- this.postLaunch = postLaunch.bind(this);
- this.getSurveyQuestions = getSurveyQuestions.bind(this);
- this.canLaunchWithoutPrompt = canLaunchWithoutPrompt.bind(this);
-
- this.model.launch = {};
-
- return this.create(method, resource, graft);
-}
-
-function UnifiedJobTemplateModelLoader (_BaseModel_, WorkflowJobTemplateNodeModel, _$http_) {
- BaseModel = _BaseModel_;
- WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
- $http = _$http_;
-
- return UnifiedJobTemplateModel;
-}
-
-UnifiedJobTemplateModelLoader.$inject = [
- 'BaseModel',
- 'WorkflowJobTemplateNodeModel',
- '$http',
- '$state'
-];
-
-export default UnifiedJobTemplateModelLoader;
diff --git a/awx/ui/client/lib/models/User.js b/awx/ui/client/lib/models/User.js
deleted file mode 100644
index da521255cb..0000000000
--- a/awx/ui/client/lib/models/User.js
+++ /dev/null
@@ -1,40 +0,0 @@
-let Base;
-let $http;
-
-function postAuthorizedTokens (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/authorized_tokens/`
- };
-
- if (params.payload) {
- req.data = params.payload;
- }
-
- return $http(req);
-}
-
-function UserModel (method, resource, config) {
- Base.call(this, 'users');
-
- this.Constructor = UserModel;
- this.postAuthorizedTokens = postAuthorizedTokens.bind(this);
-
- this.model.launch = {};
-
- return this.create(method, resource, config);
-}
-
-function UserModelLoader (BaseModel, _$http_) {
- Base = BaseModel;
- $http = _$http_;
-
- return UserModel;
-}
-
-UserModelLoader.$inject = [
- 'BaseModel',
- '$http'
-];
-
-export default UserModelLoader;
diff --git a/awx/ui/client/lib/models/WorkflowJob.js b/awx/ui/client/lib/models/WorkflowJob.js
deleted file mode 100644
index 02ea3582cc..0000000000
--- a/awx/ui/client/lib/models/WorkflowJob.js
+++ /dev/null
@@ -1,34 +0,0 @@
-let Base;
-let $http;
-
-function postRelaunch (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/relaunch/`
- };
-
- return $http(req);
-}
-
-function WorkflowJobModel (method, resource, config) {
- Base.call(this, 'workflow_jobs');
-
- this.Constructor = WorkflowJobModel;
- this.postRelaunch = postRelaunch.bind(this);
-
- return this.create(method, resource, config);
-}
-
-function WorkflowJobModelLoader (BaseModel, _$http_) {
- Base = BaseModel;
- $http = _$http_;
-
- return WorkflowJobModel;
-}
-
-WorkflowJobModelLoader.$inject = [
- 'BaseModel',
- '$http'
-];
-
-export default WorkflowJobModelLoader;
diff --git a/awx/ui/client/lib/models/WorkflowJobTemplate.js b/awx/ui/client/lib/models/WorkflowJobTemplate.js
deleted file mode 100644
index 06d9e9decc..0000000000
--- a/awx/ui/client/lib/models/WorkflowJobTemplate.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/* eslint camelcase: 0 */
-let Base;
-let $http;
-
-function optionsLaunch (id) {
- const req = {
- method: 'OPTIONS',
- url: `${this.path}${id}/launch/`
- };
-
- return $http(req);
-}
-
-function getLaunch (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/launch/`
- };
-
- return $http(req)
- .then(res => {
- this.model.launch.GET = res.data;
-
- return res;
- });
-}
-
-function postLaunch (params) {
- const req = {
- method: 'POST',
- url: `${this.path}${params.id}/launch/`
- };
-
- if (params.launchData) {
- req.data = params.launchData;
- }
-
- return $http(req);
-}
-
-function getSurveyQuestions (id) {
- const req = {
- method: 'GET',
- url: `${this.path}${id}/survey_spec/`
- };
-
- return $http(req);
-}
-
-function getLaunchConf () {
- return this.model.launch.GET;
-}
-
-function canLaunchWithoutPrompt () {
- const launchData = this.getLaunchConf();
-
- return (
- launchData.can_start_without_user_input &&
- !launchData.ask_inventory_on_launch &&
- !launchData.ask_variables_on_launch &&
- !launchData.ask_limit_on_launch &&
- !launchData.ask_scm_branch_on_launch &&
- !launchData.survey_enabled &&
- launchData.variables_needed_to_start.length === 0
- );
-}
-
-function WorkflowJobTemplateModel (method, resource, config) {
- Base.call(this, 'workflow_job_templates');
-
- this.Constructor = WorkflowJobTemplateModel;
- this.optionsLaunch = optionsLaunch.bind(this);
- this.getLaunch = getLaunch.bind(this);
- this.postLaunch = postLaunch.bind(this);
- this.getSurveyQuestions = getSurveyQuestions.bind(this);
- this.getLaunchConf = getLaunchConf.bind(this);
- this.canLaunchWithoutPrompt = canLaunchWithoutPrompt.bind(this);
-
- this.model.launch = {};
-
- return this.create(method, resource, config);
-}
-
-function WorkflowJobTemplateModelLoader (BaseModel, _$http_) {
- Base = BaseModel;
- $http = _$http_;
-
- return WorkflowJobTemplateModel;
-}
-
-WorkflowJobTemplateModelLoader.$inject = [
- 'BaseModel',
- '$http',
-];
-
-export default WorkflowJobTemplateModelLoader;
diff --git a/awx/ui/client/lib/models/WorkflowJobTemplateNode.js b/awx/ui/client/lib/models/WorkflowJobTemplateNode.js
deleted file mode 100644
index c08cbd2e8c..0000000000
--- a/awx/ui/client/lib/models/WorkflowJobTemplateNode.js
+++ /dev/null
@@ -1,21 +0,0 @@
-let Base;
-
-function WorkflowJobTemplateNodeModel (method, resource, config) {
- Base.call(this, 'workflow_job_template_nodes');
-
- this.Constructor = WorkflowJobTemplateNodeModel;
-
- return this.create(method, resource, config);
-}
-
-function WorkflowJobTemplateNodeModelLoader (BaseModel) {
- Base = BaseModel;
-
- return WorkflowJobTemplateNodeModel;
-}
-
-WorkflowJobTemplateNodeModelLoader.$inject = [
- 'BaseModel'
-];
-
-export default WorkflowJobTemplateNodeModelLoader;
diff --git a/awx/ui/client/lib/models/index.js b/awx/ui/client/lib/models/index.js
deleted file mode 100644
index 6d8cc142e9..0000000000
--- a/awx/ui/client/lib/models/index.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import atLibServices from '~services';
-
-import AdHocCommand from '~models/AdHocCommand';
-import Application from '~models/Application';
-import Base from '~models/Base';
-import Config from '~models/Config';
-import Credential from '~models/Credential';
-import CredentialType from '~models/CredentialType';
-import Instance from '~models/Instance';
-import InstanceGroup from '~models/InstanceGroup';
-import Inventory from '~models/Inventory';
-import InventoryScript from '~models/InventoryScript';
-import InventorySource from '~models/InventorySource';
-import InventoryUpdate from '~models/InventoryUpdate';
-import Job from '~models/Job';
-import JobEvent from '~models/JobEvent';
-import JobTemplate from '~models/JobTemplate';
-import Me from '~models/Me';
-import NotificationTemplate from '~models/NotificationTemplate';
-import Organization from '~models/Organization';
-import Project from '~models/Project';
-import ProjectUpdate from '~models/ProjectUpdate';
-import Schedule from '~models/Schedule';
-import SystemJob from '~models/SystemJob';
-import Token from '~models/Token';
-import UnifiedJob from '~models/UnifiedJob';
-import UnifiedJobTemplate from '~models/UnifiedJobTemplate';
-import User from '~models/User';
-import WorkflowJob from '~models/WorkflowJob';
-import WorkflowJobTemplate from '~models/WorkflowJobTemplate';
-import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode';
-
-import ModelsStrings from '~models/models.strings';
-
-const MODULE_NAME = 'at.lib.models';
-
-angular
- .module(MODULE_NAME, [
- atLibServices
- ])
- .service('AdHocCommandModel', AdHocCommand)
- .service('ApplicationModel', Application)
- .service('BaseModel', Base)
- .service('ConfigModel', Config)
- .service('CredentialModel', Credential)
- .service('CredentialTypeModel', CredentialType)
- .service('InstanceGroupModel', InstanceGroup)
- .service('InstanceModel', Instance)
- .service('InventoryModel', Inventory)
- .service('InventoryScriptModel', InventoryScript)
- .service('InventorySourceModel', InventorySource)
- .service('InventoryUpdateModel', InventoryUpdate)
- .service('JobEventModel', JobEvent)
- .service('JobModel', Job)
- .service('JobTemplateModel', JobTemplate)
- .service('MeModel', Me)
- .service('ModelsStrings', ModelsStrings)
- .service('NotificationTemplate', NotificationTemplate)
- .service('OrganizationModel', Organization)
- .service('ProjectModel', Project)
- .service('ProjectUpdateModel', ProjectUpdate)
- .service('ScheduleModel', Schedule)
- .service('SystemJobModel', SystemJob)
- .service('TokenModel', Token)
- .service('UnifiedJobModel', UnifiedJob)
- .service('UnifiedJobTemplateModel', UnifiedJobTemplate)
- .service('UserModel', User)
- .service('WorkflowJobModel', WorkflowJob)
- .service('WorkflowJobTemplateModel', WorkflowJobTemplate)
- .service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/lib/models/models.strings.js b/awx/ui/client/lib/models/models.strings.js
deleted file mode 100644
index c9385e3db5..0000000000
--- a/awx/ui/client/lib/models/models.strings.js
+++ /dev/null
@@ -1,56 +0,0 @@
-function ModelsStrings (BaseString) {
- BaseString.call(this, 'models');
-
- const { t } = this;
- const ns = this.models;
-
- ns.credentials = {
- LABEL: t.s('Credentials')
- };
-
- ns.credential_types = {
- LABEL: t.s('Credential Types')
- };
-
- ns.inventories = {
- LABEL: t.s('Inventories')
- };
-
- ns.inventory_scripts = {
- LABEL: t.s('Inventory Scripts')
-
- };
-
- ns.inventory_sources = {
- LABEL: t.s('Inventory Sources')
-
- };
-
- ns.job_templates = {
- LABEL: t.s('Job Templates')
-
- };
-
- ns.organizations = {
- LABEL: t.s('Organizations')
-
- };
-
- ns.projects = {
- LABEL: t.s('Projects')
-
- };
-
- ns.workflow_job_templates = {
- LABEL: t.s('Workflow Job Templates')
- };
-
- ns.workflow_job_template_nodes = {
- LABEL: t.s('Workflow Job Template Nodes')
-
- };
-}
-
-ModelsStrings.$inject = ['BaseStringService'];
-
-export default ModelsStrings;
diff --git a/awx/ui/client/lib/services/app.strings.js b/awx/ui/client/lib/services/app.strings.js
deleted file mode 100644
index a844897308..0000000000
--- a/awx/ui/client/lib/services/app.strings.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * This service is used to access the app-wide strings defined in BaseStringService.
- */
-function AppStrings (BaseString) {
- BaseString.call(this, 'app');
-}
-
-AppStrings.$inject = ['BaseStringService'];
-
-export default AppStrings;
diff --git a/awx/ui/client/lib/services/base-string.service.js b/awx/ui/client/lib/services/base-string.service.js
deleted file mode 100644
index 86119d5e12..0000000000
--- a/awx/ui/client/lib/services/base-string.service.js
+++ /dev/null
@@ -1,203 +0,0 @@
-import defaults from '~assets/default.strings.json';
-
-let i18n;
-let $filter;
-
-function BaseStringService (namespace) {
- const ERROR_NO_NAMESPACE = 'BaseString cannot be extended without providing a namespace';
-
- if (!namespace) {
- throw new Error(ERROR_NO_NAMESPACE);
- }
-
- this[namespace] = {};
- this.t = {};
-
- /**
- * To translate a singular string by itself or a string with context data, use `translate`.
- * For brevity, this is renamed as `t.s` (as in "translate singular"). `t.s` serves a dual
- * purpose -- it's to mark strings for translation so they appear in the `.pot` file after
- * the grunt-angular-gettext task is run AND it's used to fetch the translated string at
- * runtime.
- *
- * NOTE: View ui/src/i18n.js for where these i18n methods are defined. i18n is a wrapper around
- * the library angular-gettext.
- *
- * @arg {string} string - The string to be translated
- * @arg {object=} context - A data object used to populate dynamic context data in a string.
- *
- * @returns {string} The translated string or the original string in the even the translation
- * does not exist.
- */
- this.t.s = i18n.translate;
-
- /**
- * To translate a plural string use `t.p`. The `count` supplied will determine whether the
- * singular or plural string is returned.
- *
- * @arg {number} count - The count of the plural object
- * @arg {string} singular - The singular version of the string to be translated
- * @arg {string} plural - The plural version of the string to be translated
- * @arg {object=} context - A data object used to populate dynamic context data in a string.
- *
- * @returns {string} The translated string or the original string in the even the translation
- * does not exist.
- */
- this.t.p = i18n.translatePlural;
-
- const { t } = this;
-
- /*
- * These strings are globally relevant and configured to give priority to values in
- * default.strings.json and fall back to defaults defined inline.
- */
- this.BRAND_NAME = defaults.BRAND_NAME || 'AWX';
- this.PENDO_API_KEY = defaults.PENDO_API_KEY || '';
-
- /*
- * Globally relevant strings should be defined here to avoid duplication of content across the
- * the project.
- */
- this.CANCEL = t.s('CANCEL');
- this.CLOSE = t.s('CLOSE');
- this.SAVE = t.s('SAVE');
- this.SELECT = t.s('SELECT');
- this.OK = t.s('OK');
- this.RUN = t.s('RUN');
- this.NEXT = t.s('NEXT');
- this.SHOW = t.s('SHOW');
- this.HIDE = t.s('HIDE');
- this.ON = t.s('ON');
- this.OFF = t.s('OFF');
- this.YAML = t.s('YAML');
- this.JSON = t.s('JSON');
- this.DELETE = t.s('DELETE');
- this.COPY = t.s('COPY');
- this.YES = t.s('YES');
- this.CLOSE = t.s('CLOSE');
- this.TEST = t.s('TEST');
- this.REMOVE = t.s('REMOVE');
- this.SUCCESSFUL_CREATION = resource => t.s('{{ resource }} successfully created', { resource: $filter('sanitize')(resource) });
-
- this.logos = {
- AWX_LOGO: t.s('Ansible AWX Logo'),
- TOWER_LOGO: t.s('Ansible Tower Logo'),
- CUSTOM_LOGO: t.s('Custom Logo')
- };
-
- this.deleteResource = {
- HEADER: t.s('Delete'),
- USED_BY: resourceType => t.s('The {{ resourceType }} is currently being used by other resources.', { resourceType }),
- UNAVAILABLE: resourceType => t.s('Deleting this {{ resourceType }} will make the following resources unavailable.', { resourceType }),
- CONFIRM: resourceType => t.s('Are you sure you want to delete this {{ resourceType }}?', { resourceType })
- };
-
- this.removeTeamAccess = {
- HEADER: t.s('Team access removal'),
- ACTION_TEXT: t.s('REMOVE TEAM ACCESS'),
- CONFIRM: (role, name) => t.s('Please confirm that you would like to remove {{ role }} access from the team {{ name }}. This will affect all members of the team. If you would like to only remove access for this particular user, please remove them from the team.', { role, name }),
- };
-
- this.removeUserAccess = {
- HEADER: t.s('Role access removal'),
- ACTION_TEXT: t.s('REMOVE ACCESS'),
- CONFIRM: (role, name) => t.s('Please confirm that you would like to remove {{ role }} access from {{ name }}.', { role, name }),
- };
-
- this.cancelJob = {
- HEADER: t.s('Cancel'),
- SUBMIT_REQUEST: t.s('Are you sure you want to submit the request to cancel this job?'),
- CANCEL_JOB: t.s('Cancel Job'),
- RETURN: t.s('Return')
- };
-
- this.error = {
- HEADER: t.s('Error!'),
- CALL: ({ path, action, status }) => t.s('Call to {{ path }} failed. {{ action }} returned status: {{ status }}.', { path, action, status }),
- };
-
- this.listActions = {
- COPY: resourceType => t.s('Copy {{resourceType}}', { resourceType }),
- DELETE: resourceType => t.s('Delete the {{resourceType}}', { resourceType }),
- CANCEL: resourceType => t.s('Cancel the {{resourceType}}', { resourceType })
- };
-
- this.sort = {
- NAME_ASCENDING: t.s('Name (Ascending)'),
- NAME_DESCENDING: t.s('Name (Descending)'),
- CREATED_ASCENDING: t.s('Created (Ascending)'),
- CREATED_DESCENDING: t.s('Created (Descending)'),
- MODIFIED_ASCENDING: t.s('Modified (Ascending)'),
- MODIFIED_DESCENDING: t.s('Modified (Descending)'),
- EXPIRES_ASCENDING: t.s('Expires (Ascending)'),
- EXPIRES_DESCENDING: t.s('Expires (Descending)'),
- LAST_JOB_RUN_ASCENDING: t.s('Last Run (Ascending)'),
- LAST_JOB_RUN_DESCENDING: t.s('Last Run (Descending)'),
- LAST_USED_ASCENDING: t.s('Last Used (Ascending)'),
- LAST_USED_DESCENDING: t.s('Last Used (Descending)'),
- USERNAME_ASCENDING: t.s('Username (Ascending)'),
- USERNAME_DESCENDING: t.s('Username (Descending)'),
- START_TIME_ASCENDING: t.s('Start Time (Ascending)'),
- START_TIME_DESCENDING: t.s('Start Time (Descending)'),
- FINISH_TIME_ASCENDING: t.s('Finish Time (Ascending)'),
- FINISH_TIME_DESCENDING: t.s('Finish Time (Descending)'),
- UUID_ASCENDING: t.s('UUID (Ascending)'),
- UUID_DESCENDING: t.s('UUID (Descending)'),
- LAUNCHED_BY_ASCENDING: t.s('Launched By (Ascending)'),
- LAUNCHED_BY_DESCENDING: t.s('Launched By (Descending)'),
- INVENTORY_ASCENDING: t.s('Inventory (Ascending)'),
- INVENTORY_DESCENDING: t.s('Inventory (Descending)'),
- PROJECT_ASCENDING: t.s('Project (Ascending)'),
- PROJECT_DESCENDING: t.s('Project (Descending)'),
- ORGANIZATION_ASCENDING: t.s('Organization (Ascending)'),
- ORGANIZATION_DESCENDING: t.s('Organization (Descending)'),
- CAPACITY_ASCENDING: t.s('Capacity (Ascending)'),
- CAPACITY_DESCENDING: t.s('Capacity (Descending)')
- };
-
- this.ALERT = ({ header, body }) => t.s('{{ header }} {{ body }}', { header, body });
-
- /**
- * This getter searches the extending class' namespace first for a match then falls back to
- * the more globally relevant strings defined here. Strings with with dots as delimeters are
- * supported to give flexibility to extending classes to nest strings as necessary.
- *
- *
- * The `t.s` and `t.p` calls should only be used where strings are defined in
- * .strings.js` files. To use translated strings elsewhere, access them through this
- * common interface.
- *
- * @arg {string} name - The property name of the string (e.g. 'CANCEL')
- * @arg {number=} count - A count of objects referenced in your plural string
- * @arg {object=} context - An object containing data to use in the interpolation of the string
- */
- this.get = (name, ...args) => {
- const keys = name.split('.');
- let value;
-
- keys.forEach(key => {
- if (!value) {
- value = this[namespace][key] || this[key];
- } else {
- value = value[key];
- }
- });
-
- if (!value || typeof value === 'string') {
- return value;
- }
-
- return value(...args);
- };
-}
-
-function BaseStringServiceLoader (_i18n_, _$filter_) {
- i18n = _i18n_;
- $filter = _$filter_;
-
- return BaseStringService;
-}
-
-BaseStringServiceLoader.$inject = ['i18n', '$filter'];
-
-export default BaseStringServiceLoader;
diff --git a/awx/ui/client/lib/services/cache.service.js b/awx/ui/client/lib/services/cache.service.js
deleted file mode 100644
index 783b0e0d4c..0000000000
--- a/awx/ui/client/lib/services/cache.service.js
+++ /dev/null
@@ -1,32 +0,0 @@
-function CacheService ($cacheFactory, $q) {
- const cache = $cacheFactory('api');
-
- this.put = (key, data) => cache.put(key, data);
- this.get = (key) => $q.resolve(cache.get(key));
-
- this.remove = (key) => {
- if (!key) {
- return cache.removeAll();
- }
-
- return cache.remove(key);
- };
-
- this.createKey = (method, path, resource) => {
- let key = `${method.toUpperCase()}.${path}`;
-
- if (resource) {
- if (resource.id) {
- key += `${resource.id}/`;
- } else if (Number(resource)) {
- key += `${resource}/`;
- }
- }
-
- return key;
- };
-}
-
-CacheService.$inject = ['$cacheFactory', '$q'];
-
-export default CacheService;
diff --git a/awx/ui/client/lib/services/event.service.js b/awx/ui/client/lib/services/event.service.js
deleted file mode 100644
index d7b7a40538..0000000000
--- a/awx/ui/client/lib/services/event.service.js
+++ /dev/null
@@ -1,37 +0,0 @@
-function EventService () {
- this.addListeners = list => {
- const listeners = [];
-
- list.forEach(args => listeners.push(this.addListener(...args)));
-
- return listeners;
- };
-
- this.addListener = (el, name, fn) => {
- const listener = {
- fn,
- name,
- el
- };
-
- if (Array.isArray(name)) {
- name.forEach(e => listener.el.addEventListener(e, listener.fn));
- } else {
- listener.el.addEventListener(listener.name, listener.fn);
- }
-
- return listener;
- };
-
- this.remove = listeners => {
- listeners.forEach(listener => {
- if (Array.isArray(listener.name)) {
- listener.name.forEach(name => listener.el.removeEventListener(name, listener.fn));
- } else {
- listener.el.removeEventListener(listener.name, listener.fn);
- }
- });
- };
-}
-
-export default EventService;
diff --git a/awx/ui/client/lib/services/index.js b/awx/ui/client/lib/services/index.js
deleted file mode 100644
index 39ed1d8299..0000000000
--- a/awx/ui/client/lib/services/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import AppStrings from '~services/app.strings';
-import BaseStringService from '~services/base-string.service';
-import CacheService from '~services/cache.service';
-import EventService from '~services/event.service';
-
-const MODULE_NAME = 'at.lib.services';
-
-angular
- .module(MODULE_NAME, [
- 'I18N'
- ])
- .service('AppStrings', AppStrings)
- .service('BaseStringService', BaseStringService)
- .service('CacheService', CacheService)
- .service('EventService', EventService);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/lib/theme/_global.less b/awx/ui/client/lib/theme/_global.less
deleted file mode 100644
index 01690ab2dd..0000000000
--- a/awx/ui/client/lib/theme/_global.less
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * For styles that are used in more than one place throughout the application.
- *
- * 1. Buttons
- *
- */
-
-// 1. Buttons -------------------------------------------------------------------------------------
-
-.at-Button--success {
- .at-mixin-Button();
- .at-mixin-ButtonColor('at-color-success', 'at-color-default');
-
- &[disabled] {
- background: @at-color-disabled;
- border-color: @at-color-disabled;
- }
-}
-
-.at-Button--add {
- &:extend(.at-Button--success all);
- &:before {
- content: "+";
- font-size: 20px;
- }
- border: none;
- display: inline-flex;
- margin-left: @at-space-4x;
-
- &[aria-expanded="true"] {
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- }
-}
-
-.at-Button--info {
- .at-mixin-Button();
- .at-mixin-ButtonColor('at-color-info', 'at-color-default');
-}
-
-.at-Button--error {
- .at-mixin-Button();
- .at-mixin-ButtonColor('at-color-error', 'at-color-default');
-}
-
-.at-ButtonHollow--default {
- .at-mixin-Button();
- .at-mixin-ButtonHollow(
- 'at-color-default',
- 'at-color-button-border-default',
- 'at-color-button-text-default'
- );
-}
-
-.at-ButtonIcon {
- padding: 4px @at-padding-button-horizontal;
- font-size: @at-font-size-body;
-}
-
-.at-ButtonIcon-noborder {
- padding: 4px @at-padding-button-horizontal;
- font-size: @at-font-size-body;
- .at-mixin-Button();
- .at-mixin-ButtonHollow(
- 'at-color-default',
- 'at-color-default',
- 'at-color-button-text-default'
- );
-}
-
-.at-Button--expand {
- width: 100%;
-}
diff --git a/awx/ui/client/lib/theme/_mixins.less b/awx/ui/client/lib/theme/_mixins.less
deleted file mode 100644
index 3c3f0c66a5..0000000000
--- a/awx/ui/client/lib/theme/_mixins.less
+++ /dev/null
@@ -1,117 +0,0 @@
-.at-mixin-Placeholder (@color) {
- &:-moz-placeholder {
- color: @color;
- }
- &:-ms-input-placeholder {
- color: @color;
- }
- &::-webkit-input-placeholder {
- color: @color;
- }
-}
-
-.at-mixin-Heading (@size) {
- color: @at-color-body-text;
- font-size: @size;
- font-weight: @at-font-weight-heading;
- line-height: @at-line-height-short;
- text-transform: uppercase;
- margin: 0;
- padding: 0;
-}
-
-.at-mixin-Border (@color: @at-border-default-color) {
- border-width: @at-border-default-width;
- border-style: @at-border-default-style;
- border-color: @color
-}
-
-.at-mixin-Button () {
- border-radius: @at-border-radius;
- height: @at-height-input;
- padding: @at-padding-button-vertical @at-padding-button-horizontal;
- font-size: @at-font-size-body;
- line-height: 1;
-}
-
-.at-mixin-InputButton () {
- height: @at-height-button;
- padding: 0 @at-padding-button-horizontal;
-
- &, &:active, &:hover, &:focus {
- color: @at-color-button-text-default;
- border-color: @at-color-input-border;
- background-color: @at-color-input-button;
- cursor: pointer;
- }
-
- &:hover {
- background-color: @at-color-input-button-hover;
- }
-}
-
-.at-mixin-ButtonColor (@background, @color, @hover: '@{background}-hover') {
- background-color: @@background;
- border-color: @@background;
-
- &, &:hover, &:focus {
- color: @@color;
- }
-
- &:hover, &:focus {
- background-color: @@hover;
- border-color: @@hover;
- }
-
- &[disabled] {
- background-color: fade(@@background, 60%);
- }
-}
-
-.at-mixin-ButtonHollow (@bg, @border, @text) {
- @hover: '@{bg}-hover';
-
- background-color: @@bg;
- color: @@text;
- border-color: @@border;
-
- &:hover, &:active {
- color: @@text;
- background-color: @@hover;
- box-shadow: none;
- }
-
- &:focus {
- color: @@text;
- background-color: @@hover;
- border-color: @@border;
- cursor: default;
- }
-
- &[disabled] {
- opacity: 0.65;
- }
-}
-
-.at-mixin-ButtonIcon () {
- line-height: @at-line-height-short;
-
- & > i {
- cursor: pointer;
- transition: color @at-transition-icon-button;
- }
-
- & > i:hover {
- color: @at-color-icon-hover
- }
-}
-
-.at-mixin-FontFixedWidth () {
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
-}
-
-.at-mixin-VerticallyCenter () {
- display: flex;
- flex-direction: column;
- justify-content: center;
-}
\ No newline at end of file
diff --git a/awx/ui/client/lib/theme/_resets.less b/awx/ui/client/lib/theme/_resets.less
deleted file mode 100644
index e7070fa42d..0000000000
--- a/awx/ui/client/lib/theme/_resets.less
+++ /dev/null
@@ -1,5 +0,0 @@
-// TODO (remove override on cleanup):
-
-.at-Panel-heading:hover {
- cursor: default;
-}
diff --git a/awx/ui/client/lib/theme/_utility.less b/awx/ui/client/lib/theme/_utility.less
deleted file mode 100644
index b3663b74a3..0000000000
--- a/awx/ui/client/lib/theme/_utility.less
+++ /dev/null
@@ -1,30 +0,0 @@
-.at-u-noSpace {
- margin: 0;
- padding: 0;
-}
-
-.at-u-flat {
- padding-top: 0;
- padding-bottom: 0;
- margin-top: 0;
- margin-bottom: 0;
-}
-
-.at-u-thin {
- padding-left: 0;
- padding-right: 0;
- margin-left: 0;
- margin-right: 0;
-}
-
-.at-u-clear {
- clear: both;
-}
-
-.at-u-noBorder {
- border: none;
-}
-
-.at-u-floatRight {
- float: right
-}
diff --git a/awx/ui/client/lib/theme/_variables.less b/awx/ui/client/lib/theme/_variables.less
deleted file mode 100644
index 157adf6cb0..0000000000
--- a/awx/ui/client/lib/theme/_variables.less
+++ /dev/null
@@ -1,335 +0,0 @@
-/**
- * All base variables used. These should only be referenced by the contextual variables defined
- * below. In development, unless you are intentionally making a fundamental change, these variables
- * should not be modified, removed, or added to.
- *
- * These variables should not be used directly in development of components or features. If an
- * alias doesn't exist for the context you're working within, check with UX to create a new alias
- * or to define a more applicable alias.
- *
- * The goal is for UX to define the contexts for the contextual variables, so it's easy to make
- * modifications like, "Change heading text to be smaller" or "Make all warnings a lighter shade
- * of orange"
- *
- * 1. Colors
- * 2. Typography
- * 3. Layout
- * 4. Breakpoints
- *
- */
-
-// 1. Colors --------------------------------------------------------------------------------------
-
-@at-gray-fc: #fcfcfc;
-@at-gray-fa: #fafafa;
-@at-gray-f2: #f2f2f2;
-@at-gray-f6: #f6f6f6;
-@at-gray-eb: #ebebeb;
-@at-gray-e1: #e1e1e1;
-@at-gray-d7: #d7d7d7;
-@at-gray-b7: #b7b7b7;
-@at-gray-a9: #a9a9a9;
-@at-gray-646972: #646972;
-@at-gray-76: #767676;
-@at-gray-60: #606060;
-@at-gray-70: #707070;
-@at-gray-48: #484848;
-@at-gray-161b1f: #161b1f;
-
-@at-white: #ffffff;
-@at-white-hover: #f2f2f2;
-
-@at-blue: #337ab7;
-@at-blue-hover: #286090;
-
-@at-green: #5cb85c;
-@at-green-hover: #449d44;
-
-@at-orange: #f0ad4e;
-@at-orange-hover: #ec971f;
-
-@at-red: #d9534f;
-@at-red-hover: #c9302c;
-
-@at-red-bright: #ff0000;
-@at-red-bright-hover: #d81f1f;
-
-// 2. Typography ----------------------------------------------------------------------------------
-
-@at-font-size: 12px;
-@at-font-size-2x: 13px;
-@at-font-size-3x: 14px;
-@at-font-size-4x: 16px;
-@at-font-size-5x: 20px;
-
-@at-font-weight: 400;
-@at-font-weight-2x: 700;
-
-// 3. Layout --------------------------------------------------------------------------------------
-
-@at-space: 5px;
-@at-space-2x: 10px;
-@at-space-3x: 15px;
-@at-space-4x: 20px;
-@at-space-5x: 25px;
-@at-space-10x: 50px;
-
-// 4. Breakpoints ---------------------------------------------------------------------------------
-
-@at-breakpoint-sm: 700px;
-
-/**
- * All variables used in the UI. Use these variables directly during the development of components
- * and features. Be sure the context of the variable name applies to the work that's being done.
- * For example, it wouldn't make sense to use `@at-input-height` to describe the height of a
- * button. Either add an alias if it makes sense to use the same base variable, or add a new
- * base variable to reference.
- *
- * Keep in mind the goal is to be able to modify an item by referencing its context instead of
- * an arbitrary variable name. For example, tt should be a simple change when an ask comes in to
- * "increase the height of inputs"
- *
- * 1. Colors
- * 2. Typography
- * 3. Layout
- * 4. Buttons
- * 5. Misc
- * 6. Breakpoints
- *
- */
-
-// 1. Colors --------------------------------------------------------------------------------------
-
-@at-color-default: @at-white;
-@at-color-default-hover: @at-white-hover;
-
-@at-color-unreachable: @at-red-bright;
-@at-color-unreachable-hover: @at-red-bright-hover;
-
-@at-color-error: @at-red;
-@at-color-error-hover: @at-red-hover;
-
-@at-color-warning: @at-orange;
-@at-color-warning-hover: @at-orange-hover;
-
-@at-color-info: @at-blue;
-@at-color-info-hover: @at-blue-hover;
-
-@at-color-success: @at-green;
-@at-color-success-hover: @at-green-hover;
-
-@at-color-disabled: @at-gray-b7;
-
-@at-color-body-background-dark: @at-gray-70;
-@at-color-body-background-light: @at-gray-eb;
-@at-color-body-text-dark: @at-white;
-@at-color-body-background: @at-gray-fc;
-@at-color-body-text: @at-gray-70;
-
-@at-color-button-border-default: @at-gray-b7;
-@at-color-button-text-default: @at-gray-70;
-
-@at-color-tab-default-active: @at-gray-646972;
-@at-color-tab-border-default-active: @at-gray-646972;
-@at-color-tab-text-default-active: @at-white;
-
-@at-color-tab-default-disabled: @at-white;
-@at-color-tab-border-default-disabled: @at-gray-b7;
-@at-color-tab-text-default-disabled: @at-gray-70;
-
-@at-color-form-label: @at-gray-70;
-
-@at-color-input-background: @at-gray-fc;
-@at-color-input-border: @at-gray-b7;
-@at-color-input-button: @at-white;
-@at-color-input-button-hover: @at-gray-f2;
-@at-color-input-disabled: @at-gray-eb;
-@at-color-input-readonly: @at-color-input-background;
-
-@at-color-input-error: @at-color-error;
-@at-color-input-focus: @at-color-info;
-@at-color-input-hint: @at-gray-646972;
-@at-color-input-icon: @at-gray-b7;
-@at-color-input-placeholder: @at-gray-646972;
-@at-color-input-text: @at-gray-161b1f;
-@at-color-input-slider-thumb: @at-blue;
-@at-color-input-slider-track: @at-gray-b7;
-
-@at-color-icon-dismiss: @at-gray-d7;
-@at-color-icon-popover: @at-gray-646972;
-@at-color-icon-hover: @at-gray-646972;
-
-@at-color-panel-heading: @at-gray-70;
-@at-color-panel-border: @at-gray-b7;
-
-@at-color-search-key-active: @at-blue;
-
-@at-color-table-header-background: @at-gray-eb;
-@at-color-line-separator: @at-gray-e1;
-
-@at-color-top-nav-background: @at-white;
-@at-color-top-nav-border-bottom: @at-gray-b7;
-@at-color-top-nav-item-text: @at-gray-70;
-@at-color-top-nav-item-icon: @at-gray-646972;
-@at-color-top-nav-item-icon-socket-outline: @at-white;
-@at-color-top-nav-item-background-hover: @at-gray-fa;
-@at-color-side-nav-background: @at-gray-48;
-@at-color-side-nav-content: @at-white;
-@at-color-side-nav-item-background-hover: @at-gray-76;
-@at-color-side-nav-item-border-hover: @at-white;
-@at-color-side-nav-item-icon: @at-white;
-@at-color-side-nav-item-spacer: @at-gray-d7;
-@at-color-side-nav-space-collapsed-border: @at-gray-b7;
-
-@at-color-list-empty-border: @at-gray-d7;
-@at-color-list-empty-background: @at-gray-f6;
-@at-color-list-empty: @at-gray-646972;
-@at-color-list-border: @at-gray-b7;
-@at-color-list-row-item-tag-background: @at-gray-eb;
-@at-color-list-row-item-tag: @at-gray-60;
-@at-color-list-row-item-label: @at-gray-646972;
-@at-color-list-row-action-background: @at-white;
-@at-color-list-row-action-icon: @at-gray-646972;
-@at-color-list-row-action-hover: @at-blue;
-@at-color-list-row-action-hover-danger: @at-red;
-@at-color-list-row-action-icon-hover: @at-white;
-@at-color-list-row-item-tag-primary-background: @at-blue;
-@at-color-list-row-item-tag-primary: @at-white;
-
-// 2. Typography ----------------------------------------------------------------------------------
-
-@at-font-size-body: @at-font-size-3x;
-@at-font-size-button: @at-font-size;
-@at-font-size-breadcrumb: @at-font-size-3x;
-@at-font-size-form-label: @at-font-size-2x;
-@at-font-size-help-text: @at-font-size;
-@at-font-size-icon: @at-font-size-4x;
-@at-font-size-input: @at-font-size-3x;
-@at-font-size-panel-heading: @at-font-size-3x;
-@at-font-size-panel-inset-heading: @at-font-size-2x;
-@at-font-size-modal-heading: @at-font-size-3x;
-@at-font-size-modal-dismiss: @at-font-size-3x;
-@at-font-size-navigation: @at-font-size-3x;
-@at-font-size-table-heading: @at-font-size-3x;
-@at-font-size-menu-icon: @at-font-size-5x;
-@at-font-size-side-nav-icon: 19px;
-@at-font-size-side-nav-space: 11px;
-@at-font-size-list-row-item-tag: 10px;
-@at-font-size-list-row-action: 19px;
-@at-font-size-list-row-action-icon: 19px;
-@at-font-size-jumbotron-heading: 24px;
-@at-font-size-jumbotron-text: @at-font-size-4x;
-
-@at-font-weight-body: @at-font-weight;
-@at-font-weight-heading: @at-font-weight-2x;
-
-// 3. Layout --------------------------------------------------------------------------------------
-
-@at-padding-button-horizontal: @at-space-2x;
-@at-padding-button-vertical: @at-space;
-@at-padding-inset: @at-space-3x;
-@at-padding-panel: @at-space-4x;
-@at-padding-popover: @at-space-2x;
-@at-padding-well: @at-space-2x;
-@at-padding-input: @at-space-2x;
-@at-padding-top-nav-item-sides: @at-space-4x;
-@at-padding-side-nav-item-icon: @at-space-3x;
-@at-padding-side-nav-item-icon: 10px 15px;
-@at-padding-side-nav-item-spacer: 10px 10px 25px 15px;
-@at-padding-bottom-side-nav-toggle-mobile: 15px;
-@at-padding-top-side-nav-toggle: 5px;
-@at-padding-left-side-nav-toggle-icon: 15px;
-@at-padding-left-side-nav-item-icon: 10px;
-@at-padding-left-side-nav-item-icon-expanded: 15px;
-@at-padding-left-side-nav-item-icon-no-tooltip: 18px;
-@at-padding-between-side-nav-icon-text: @at-space-3x;
-@at-padding-list-empty: @at-space-2x;
-@at-padding-list-row-item-tag: 3px 9px;
-@at-padding-list-row-action: 7px;
-@at-padding-list-row: 10px 20px 10px 10px;
-@at-padding-bottom-instances-wrap: 30px;
-
-@at-margin-input-message: @at-space;
-@at-margin-item-column: @at-space-3x;
-@at-margin-panel: @at-space-4x;
-@at-margin-panel-inset: @at-space-3x;
-@at-margin-popover: @at-space-2x;
-@at-margin-tag: @at-space-2x;
-@at-margin-form-label: @at-space;
-@at-margin-form-label-hint: @at-space-2x;
-@at-margin-top-nav-item-between-icon-and-name: @at-space-2x;
-@at-margin-top-nav-item-icon-socket-top-makeup: -3px;
-@at-margin-side-nav-space-collapsed: 5px 0;
-
-@at-margin-top-search-key: @at-space-2x;
-
-@at-margin-top-list: @at-space-4x;
-@at-margin-bottom-list-toolbar: @at-space-4x;
-@at-margin-above-list-toolbar: @at-space-4x;
-@at-margin-left-toolbar-action: @at-space-4x;
-@at-margin-left-toolbar-carat: @at-space;
-@at-margin-bottom-list-header: @at-space;
-@at-margin-left-list-row-item-tag: @at-space-2x;
-@at-margin-top-list-row-item-tag: 2.25px;
-@at-margin-left-list-row-action: @at-space-4x;
-@at-margin-right-list-row-item-tag-icon: 8px;
-@at-margin-left-list-row-item-tag-container: -10px;
-@at-margin-list-row-action-mobile: 10px;
-@at-margin-right-list-row-item-status: @at-space-2x;
-@at-margin-right-list-row-item-inline: @at-space-4x;
-@at-margin-right-list-row-item-inline-label: @at-space-2x;
-
-@at-height-divider: @at-margin-panel;
-@at-height-input: 30px;
-@at-height-textarea: 144px;
-@at-height-button: 30px;
-@at-height-tab: 30px;
-@at-height-top-nav: 60px;
-@at-height-top-nav-item-icon: 21px;
-@at-height-top-nav-item-icon-socket: 18px;
-@at-height-side-nav-item-icon: 19px;
-@at-height-side-nav-spacer: 20px;
-@at-height-top-side-nav-makeup: 55px;
-@at-height-list-empty: 200px;
-@at-height-toolbar-action: 30px;
-@at-height-list-row-item: 27px;
-@at-height-list-row-action: 30px;
-@at-height-side-nav-toggle-mobile: 40px;
-
-@at-width-input-button-sm: 72px;
-@at-width-input-button-md: 84px;
-@at-width-collapsed-side-nav: 55px;
-@at-width-expanded-side-nav: 190px;
-@at-width-list-row-item-label: 120px;
-@at-width-list-row-action: 30px;
-@at-width-side-nav-toggle-mobile: 50px;
-
-@at-line-height-list-row-item-header: @at-space-3x;
-@at-line-height-list-row-item-labels: 17px;
-
-// 4. Transitions ---------------------------------------------------------------------------------
-
-@at-transition-icon-button: 0.2s;
-
-// 5. Misc ----------------------------------------------------------------------------------------
-
-@at-border-radius: 5px;
-@at-border-default-style: solid;
-@at-border-default-width: 1px;
-@at-border-default-color: @at-gray-b7;
-@at-border-style-list-active-indicator: 5px solid @at-color-info;
-@at-popover-maxwidth: 320px;
-@at-line-height-short: 0.9;
-@at-line-height-tall: 2;
-@at-line-height: 24px;
-@at-highlight-left-border-size: 5px;
-@at-highlight-left-border-margin-makeup: -5px;
-@at-z-index-nav: 1040;
-@at-z-index-side-nav: 1030;
-@at-line-height-list-row-item-tag: 14px;
-
-// 6. Breakpoints ---------------------------------------------------------------------------------
-
-@at-breakpoint-mobile-layout: @at-breakpoint-sm;
-@at-breakpoint-compact-list: @at-breakpoint-sm;
-@at-breakpoint-instances-wrap: 1036px;
diff --git a/awx/ui/client/lib/theme/index.less b/awx/ui/client/lib/theme/index.less
deleted file mode 100644
index c7baad45e4..0000000000
--- a/awx/ui/client/lib/theme/index.less
+++ /dev/null
@@ -1,160 +0,0 @@
-// Dependency Variables
-@import '../../../node_modules/components-font-awesome/less/variables';
-
-// App-specific Legacy Variables
-@import '../../src/shared/branding/colors.default.less';
-@import '../../src/shared/branding/colors';
-
-/**
- * Override Variables
- *
- * NOTE: Used in conditional build scenarios and will need to persist after any refactoring effort.
- */
-@import '../../assets/variables';
-
-/**
- * Legacy Styles
- *
- * NOTE: Styles below are a mix of 3rd-party dependencies and in-house code. For the 3rd-party
- * stuff, we'd be better off managing them via npm where possible.
- */
-@import '../../legacy/styles/fonts';
-@import '../../legacy/styles/animations';
-@import '../../legacy/styles/jquery-ui-overrides';
-@import '../../legacy/styles/codemirror';
-@import '../../legacy/styles/angular-scheduler';
-@import '../../legacy/styles/log-viewer';
-@import '../../legacy/styles/event-viewer';
-@import '../../legacy/styles/job-details';
-@import '../../legacy/styles/jobs';
-@import '../../legacy/styles/inventory-edit';
-@import '../../legacy/styles/stdout';
-@import '../../legacy/styles/lists';
-@import '../../legacy/styles/forms';
-@import '../../legacy/styles/dashboard';
-@import '../../legacy/styles/survey-maker';
-@import '../../legacy/styles/text-label';
-@import '../../legacy/styles/bootstrap-datepicker';
-@import '../../legacy/styles/ansible-ui';
-@import '../../legacy/styles/bootstrap-custom-overrides';
-
-// Legacy Utilities
-@import '../../src/shared/utilities/alerts';
-@import '../../src/shared/utilities/hidden';
-@import '../../src/shared/utilities/icons';
-@import '../../src/shared/utilities/layer';
-@import '../../src/shared/utilities/truncated-text';
-@import '../../src/shared/utilities/unbold';
-@import '../../src/shared/utilities/wordwrap';
-
-// Legacy Layout
-@import '../../src/shared/layouts/one-plus-one';
-@import '../../src/shared/layouts/one-plus-two';
-
-/**
- * Legacy Features
- *
- * NOTE: "dot" namespacing interferes with Less' ability to infer the .less suffix, so it's
- * explicitly added to the import statements below.
- */
-@import '../../src/about/about.block.less';
-@import '../../src/access/rbac-role-column/roleList.block.less';
-@import '../../src/access/add-rbac.block.less';
-@import '../../src/activity-stream/streamDetailModal/streamDetailModal.block.less';
-@import '../../src/activity-stream/activitystream.block.less';
-@import '../../src/bread-crumb/bread-crumb.block.less';
-@import '../../src/configuration/settings.block.less';
-@import '../../src/credentials/ownerList.block.less';
-@import '../../src/home/dashboard/counts/dashboard-counts.block.less';
-@import '../../src/home/dashboard/graphs/dashboard-graphs.block.less';
-@import '../../src/home/dashboard/lists/dashboard-list.block.less';
-@import '../../src/home/dashboard/dashboard.block.less';
-@import '../../src/instance-groups/capacity-bar/capacity-bar.block.less';
-@import '../../src/instance-groups/capacity-adjuster/capacity-adjuster.block.less';
-@import '../../src/instance-groups/instance-group.block.less';
-@import '../../src/instance-groups/instances/instance-modal.block.less';
-@import '../../src/inventories-hosts/inventories/insights/insights.block.less';
-@import '../../src/inventories-hosts/inventories/list/host-summary-popover/host-summary-popover.block.less';
-@import '../../src/inventories-hosts/inventories/related/hosts/related-groups-labels/relatedGroupsLabelsList.block.less';
-@import '../../src/inventories-hosts/inventories/inventories.block.less';
-@import '../../src/inventories-hosts/shared/associate-groups/associate-groups.block.less';
-@import '../../src/inventories-hosts/shared/associate-hosts/associate-hosts.block.less';
-@import '../../src/license/license.block.less';
-@import '../../src/login/loginModal/thirdPartySignOn/thirdPartySignOn.block.less';
-@import '../../src/login/loginModal/loginModal.block.less';
-@import '../../src/login/loginModal/loginModalNotice.block.less';
-@import '../../src/management-jobs/card/mgmtcards.block.less';
-@import '../../src/notifications/notifications.block.less';
-@import '../../src/organizations/linkout/addUsers/addUsers.block.less';
-@import '../../src/organizations/orgcards.block.less';
-@import '../../src/scheduler/repeatFrequencyOptions.block.less';
-@import '../../src/scheduler/schedulerForm.block.less';
-@import '../../src/scheduler/schedulerDatePicker.block.less';
-@import '../../src/scheduler/schedulerFormDetail.block.less';
-@import '../../src/scheduler/schedulertime.block.less';
-@import '../../src/scheduler/spinnerInput.block.less';
-@import '../../src/shared/container/container.block.less';
-@import '../../src/shared/detail-nav/detail-nav.block.less';
-@import '../../src/shared/icon/icon.block.less';
-@import '../../src/shared/instance-groups-multiselect/instance-groups.block.less';
-@import '../../src/shared/lookup/lookup-modal.block.less';
-@import '../../src/shared/modal/modal';
-@import '../../src/shared/multi-select-preview/multi-select-preview.block.less';
-@import '../../src/shared/paginate/paginate.block.less';
-@import '../../src/shared/prompt/prompt';
-@import '../../src/shared/smart-search/smart-search.block.less';
-@import '../../src/shared/button.block.less';
-@import '../../src/shared/download-standard-out.block.less';
-@import '../../src/shared/media-object.block.less';
-@import '../../src/shared/text-label';
-@import '../../src/shared/upgrade/upgrade.block.less';
-@import '../../src/smart-status/smart-status.block.less';
-@import '../../src/workflow-results/standard-out.block.less';
-@import '../../src/templates/prompt/prompt.block.less';
-@import '../../src/templates/job_templates/multi-credential/multi-credential.block.less';
-@import '../../src/templates/job_templates/webhook-credential/webhook-credential.block.less';
-@import '../../src/templates/labels/labelsList.block.less';
-@import '../../src/templates/survey-maker/survey-maker.block.less';
-@import '../../src/templates/survey-maker/survey-maker.block.less';
-@import '../../src/templates/survey-maker/shared/survey-controls.block.less';
-@import '../../src/templates/survey-maker/survey-maker.block.less';
-@import '../../src/templates/workflows/workflow.block.less';
-@import '../../src/templates/workflows/workflow-chart/workflow-chart.block.less';
-@import '../../src/templates/workflows/workflow-controls/workflow-controls.block.less';
-@import '../../src/templates/workflows/workflow-maker/workflow-maker.block.less';
-@import '../../src/tooltip/tooltip.block.less';
-@import '../../src/workflow-results/workflow-status-bar/workflow-status-bar.block.less';
-@import '../../src/workflow-results/workflow-results.block.less';
-
-/**
- * App-wide style
- *
- * NOTE: Variables, mixins, and classes below are useful in more than one place across the
- * application. When working with Less, if the need for a variable, mixin, class, etc exists in
- * more than one location, take a moment to move it to this more general location for easy reuse
- * and to avoid duplication.
- */
-@import '_variables';
-@import '_mixins';
-@import '_utility';
-@import '_global';
-
-/**
- * Component and Feature style
- *
- * NOTE: These index files are aggregation points for components and features. To view the more
- * granular imports, view the contents of these files. Variables, classes, etc defined within
- * these specific files ought to have no use elsewhere. As we shift to leverage components, very
- * few feature-specific styles will exist.
- */
-@import '../components/_index';
-@import '../../features/_index';
-
-/*
- * Resets
- *
- * NOTE: In some cases, the legacy classes override dependency styles explicitly. In those cases,
- * it's necessary to override the overrides. This particular file will only be relevant during
- * the transition.
- */
-@import '_resets';
diff --git a/awx/ui/client/src/about/about.block.less b/awx/ui/client/src/about/about.block.less
deleted file mode 100644
index 3b9a0ad00a..0000000000
--- a/awx/ui/client/src/about/about.block.less
+++ /dev/null
@@ -1,60 +0,0 @@
-/** @define About */
-.About-ansibleVersion,
-.About-cowsayCode {
- font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
-}
-
-.About-cowsayContainer {
- width: 340px;
- margin: 0 auto;
-}
-.About-cowsayCode {
- background-color: @default-bg;
- padding-left: 30px;
- border-style: none;
- max-width: 340px;
- padding-left: 30px;
-}
-.About-modalHeader {
- border: none;
- padding-bottom: 0px;
-}
-.About-modalDialog {
- max-width: 500px;
-}
-
-.About-modalBody {
- padding-top: 0px;
- padding-bottom: 0px;
-}
-
-.About-brandImg {
- float: @about-modal-float;
- width: @about-modal-width;
- padding-top: @about-modal-padding-top;
- margin-top: @about-modal-margin-top;
- margin-left: @about-modal-margin-left;
-}
-
-.About-close {
- position: absolute;
- top: 15px;
- right: 15px;
- z-index: 10;
-}
-
-.About-modalFooter {
- clear: both;
-}
-
-.About-footerText {
- text-align: right;
- color: @default-interface-txt;
- margin: 0;
- font-size: 12px;
- padding-top: 10px;
-}
-
-.About-ansibleVersion {
- color: @default-data-txt;
-}
diff --git a/awx/ui/client/src/about/about.controller.js b/awx/ui/client/src/about/about.controller.js
deleted file mode 100644
index e2ef6e776a..0000000000
--- a/awx/ui/client/src/about/about.controller.js
+++ /dev/null
@@ -1,32 +0,0 @@
-export default ['$rootScope', '$scope', '$location', 'ConfigService', 'lastPath',
- ($rootScope, $scope, $location, ConfigService, lastPath) => {
-
- ConfigService.getConfig()
- .then(function(config){
- $scope.version = config.version.split('-')[0];
- $scope.ansible_version = config.ansible_version;
- $scope.subscription = config.license_info.subscription_name;
- $scope.speechBubble = createSpeechBubble($rootScope.BRAND_NAME, config.version);
- $scope.currentYear = new Date().getFullYear();
- $('#about-modal').modal('show');
- });
-
- $('#about-modal').on('hidden.bs.modal', () => $location.url(lastPath));
-
- function createSpeechBubble (brand, version) {
- let text = `${brand} ${version}`;
- let top = '';
- let bottom = '';
-
- for (let i = 0; i < text.length; i++) {
- top += '_';
- bottom += '-';
- }
-
- top = ` __${top}__ \n`;
- text = `< ${text} >\n`;
- bottom = ` --${bottom}-- `;
-
- return top + text + bottom;
- }
-}];
diff --git a/awx/ui/client/src/about/about.partial.html b/awx/ui/client/src/about/about.partial.html
deleted file mode 100644
index 2be5f6234b..0000000000
--- a/awx/ui/client/src/about/about.partial.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-{{ speechBubble }}
- \ ^__^
- \ (oo)\_______
- (__) A )\/\
- ||----w |
- || ||
-
-
-
-
-
-
diff --git a/awx/ui/client/src/about/about.route.js b/awx/ui/client/src/about/about.route.js
deleted file mode 100644
index e8fb6b0d10..0000000000
--- a/awx/ui/client/src/about/about.route.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import {templateUrl} from '../shared/template-url/template-url.factory';
-import controller from './about.controller';
-import { N_ } from '../i18n';
-
-export default {
- name: 'about',
- route: '/about',
- controller: controller,
- ncyBreadcrumb: {
- label: N_("ABOUT")
- },
- resolve: {
- lastPath: function($location) {
- return $location.url();
- }
- },
- onExit: function(){
- // hacky way to handle user browsing away via URL bar
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- },
- templateUrl: templateUrl('about/about')
-};
diff --git a/awx/ui/client/src/about/main.js b/awx/ui/client/src/about/main.js
deleted file mode 100644
index 8ef9d54b63..0000000000
--- a/awx/ui/client/src/about/main.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- import controller from './about.controller';
- import route from './about.route';
-
- export default
- angular.module('about', [])
- .controller('about', controller)
- .run(['$stateExtender', function($stateExtender){
- $stateExtender.addState(route);
- }]);
diff --git a/awx/ui/client/src/access/add-rbac-resource/main.js b/awx/ui/client/src/access/add-rbac-resource/main.js
deleted file mode 100644
index 346e6106c6..0000000000
--- a/awx/ui/client/src/access/add-rbac-resource/main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import addRbacResourceDirective from './rbac-resource.directive';
-import rbacMultiselect from '../rbac-multiselect/main';
-
-export default
- angular.module('AddRbacResourceModule', [rbacMultiselect.name])
- .directive('addRbacResource', addRbacResourceDirective);
diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js
deleted file mode 100644
index 97b00e1e7f..0000000000
--- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js
+++ /dev/null
@@ -1,153 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/**
- * @ngdoc function
- * @name controllers.function:Access
- * @description
- * Controller for handling permissions adding
- */
-
-export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', 'Wait', 'ProcessErrors', function(rootScope, scope, GetBasePath, Rest, $q, Wait, ProcessErrors) {
-
- init();
-
- function init(){
-
- let resources = ['users', 'teams'];
-
- scope.allSelected = {};
- _.each(resources, (type) => scope.allSelected[type] = {});
-
- // the object permissions are being added to
- scope.object = scope.resourceData.data;
- // array for all possible roles for the object
- scope.roles = angular.copy(scope.object.summary_fields.object_roles);
-
- scope.appStrings = rootScope.appStrings;
-
- const objectType = _.get(scope, ['object', 'type']);
- const teamRoles = _.get(scope, ['object', 'summary_fields', 'object_roles'], {});
-
- if (objectType === 'organization') {
- // some organization object_roles aren't allowed for teams
- delete teamRoles.admin_role;
- delete teamRoles.member_role;
- }
-
- scope.teamRoles = teamRoles;
-
- // TODO: get working with api
- // array w roles and descriptions for key
- scope.roleKey = Object
- .keys(scope.object.summary_fields.object_roles)
- .map(function(key) {
- return {
- name: scope.object.summary_fields
- .object_roles[key].name,
- description: scope.object.summary_fields
- .object_roles[key].description
- };
- });
-
- scope.showKeyPane = false;
-
- scope.tab = {
- users: true,
- teams: false,
- };
-
- // pop/push into unified collection of selected users & teams
- scope.$on("selectedOrDeselected", function(e, value) {
- let resourceType = scope.currentTab(),
- item = value.value;
-
- function buildName(user) {
- return (user.first_name &&
- user.last_name) ?
- user.first_name + " " +
- user.last_name :
- user.username;
- }
-
- if (value.isSelected) {
- if (item.type === 'user') {
- item.name = buildName(item);
- }
- scope.allSelected[resourceType][item.id] = item;
- scope.allSelected[resourceType][item.id].roles = [];
- } else {
- delete scope.allSelected[resourceType][item.id];
- }
- });
-
- }
-
- scope.currentTab = function(){
- return _.findKey(scope.tab, (tab) => tab);
- };
-
- scope.removeObject = function(obj){
- let resourceType = scope.currentTab();
- delete scope.allSelected[resourceType][obj.id];
- obj.isSelected = false;
- };
-
- scope.toggleKeyPane = function() {
- scope.showKeyPane = !scope.showKeyPane;
- };
-
- scope.hasSelectedRows = function(){
- return _.some(scope.allSelected, (type) => Object.keys(type).length > 0);
- };
-
- scope.selectTab = function(selected){
- _.each(scope.tab, (value, key, collection) => {
- collection[key] = (selected === key);
- });
- };
-
- // post roles to api
- scope.updatePermissions = function() {
- Wait('start');
-
- let requests = [];
-
- _.forEach(scope.allSelected, (selectedValues) => {
- _.forEach(selectedValues, (selectedValue) => {
- var url = GetBasePath(selectedValue.type + "s") + selectedValue.id +
- "/roles/";
-
- if (scope.onlyMemberRole === 'true') {
- Rest.setUrl(url);
- requests.push(Rest.post({ "id": scope.roles.member_role.id }));
- } else {
- (selectedValue.roles || [])
- .map(function(role) {
- Rest.setUrl(url);
- requests.push(Rest.post({ "id": role.value || role.id }));
- });
- }
- });
- });
-
- $q.all(requests)
- .then(function() {
- Wait('stop');
- rootScope.$broadcast("refreshList", "permission");
- scope.closeModal();
- }, function(error) {
- Wait('stop');
- rootScope.$broadcast("refreshList", "permission");
- scope.closeModal();
- ProcessErrors(null, error.data, error.status, null, {
- hdr: 'Error!',
- msg: 'Failed to post role(s): POST returned status' +
- error.status
- });
- });
- };
-}];
diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js
deleted file mode 100644
index 6993fee15a..0000000000
--- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-import controller from './rbac-resource.controller';
-
-/* jshint unused: vars */
-export default ['templateUrl', '$state',
- 'addPermissionsUsersList', 'addPermissionsTeamsList',
- function(templateUrl, $state, usersList, teamsList) {
- return {
- restrict: 'E',
- scope: {
- defaultParams: '=?',
- usersDataset: '=',
- teamsDataset: '=',
- resourceData: '=',
- withoutTeamPermissions: '@',
- onlyMemberRole: '@',
- queryPrefix: '@',
- title: '@'
- },
- controller: controller,
- templateUrl: templateUrl('access/add-rbac-resource/rbac-resource'),
- link: function(scope, element, attrs) {
- scope.selectTab('users');
- $('#add-permissions-modal').modal('show');
-
- scope.closeModal = function() {
- $state.go('^', null, {reload: true});
- };
-
- window.scrollTo(0, 0);
- }
- };
- }
-];
diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html
deleted file mode 100644
index b243ceb750..0000000000
--- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
-
-
-
-
- 1
-
-
- Please select Users / Teams from the lists below.
-
-
- Please select Users from the list below.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
-
Please assign roles to the selected users/teams
-
- Key
-
-
-
-
-
- {{ key.name }}
-
-
- {{ key.description || "No description provided" }}
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/access/add-rbac-user-team/main.js b/awx/ui/client/src/access/add-rbac-user-team/main.js
deleted file mode 100644
index 94a1fa7c60..0000000000
--- a/awx/ui/client/src/access/add-rbac-user-team/main.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import addRbacUserTeamDirective from './rbac-user-team.directive';
-import rbacSelectedList from './rbac-selected-list.directive';
-
-export default
- angular.module('AddRbacUserTeamModule', [])
- .directive('addRbacUserTeam', addRbacUserTeamDirective)
- .directive('rbacSelectedList', rbacSelectedList);
\ No newline at end of file
diff --git a/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js b/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js
deleted file mode 100644
index bc8828e77c..0000000000
--- a/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js
+++ /dev/null
@@ -1,207 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/* jshint unused: vars */
-export default ['$compile', 'i18n', 'generateList',
- 'ProjectList', 'TemplateList', 'InventoryList', 'CredentialList',
- 'OrganizationList', '$window',
- function($compile, i18n, generateList,
- ProjectList, TemplateList, InventoryList, CredentialList,
- OrganizationList, $window) {
- return {
- restrict: 'E',
- scope: {
- resourceType: "=",
- collection: "=",
- selected: "="
- },
- link: function(scope, element, attrs) {
- let listMap, list, list_html;
-
- listMap = {
- projects: ProjectList,
- job_templates: TemplateList,
- workflow_templates: TemplateList,
- inventories: InventoryList,
- credentials: CredentialList,
- organizations: OrganizationList
- };
-
- list = _.cloneDeep(listMap[scope.resourceType]);
-
- delete list.actions;
- delete list.layoutClass;
-
- list.listTitleBadge = false;
-
- switch(scope.resourceType){
- case 'projects':
- list.fields = {
- name: list.fields.name,
- scm_type: list.fields.scm_type
- };
- delete list.staticColumns;
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/projects/{{project.id}}";
- list.fields.name.columnClass = 'col-sm-5';
- list.fields.scm_type.columnClass = 'col-sm-5';
- break;
- case 'inventories':
- list.fields = {
- name: list.fields.name,
- organization: list.fields.organization
- };
- delete list.staticColumns;
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = '{{inventory.linkToDetails}}';
- list.fields.name.columnClass = 'col-sm-5';
- list.fields.organization.columnClass = 'col-sm-5';
- break;
- case 'job_templates':
- list.name = 'job_templates';
- list.iterator = 'job_template';
- list.fields = {
- name: list.fields.name
- };
- list.fields.name.columnClass = 'col-sm-10';
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/templates/job_template/{{job_template.id}}";
- break;
- case 'workflow_templates':
- list.name = 'workflow_job_templates';
- list.iterator = 'workflow_job_template';
- list.fields = {
- name: list.fields.name
- };
- list.fields.name.columnClass = 'col-sm-10';
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/templates/workflow_job_template/{{workflow_template.id}}";
- break;
- case 'credentials':
- list.fields = {
- name: list.fields.name
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/credentials/{{credential.id}}";
- list.fields.name.columnClass = 'col-sm-10';
- break;
- case 'organizations':
- list.fields = {
- name: list.fields.name
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/organizations/{{organization.id}}";
- list.fields.name.columnClass = 'col-sm-10';
- break;
- }
-
- list.fieldActions = {
- columnClass: 'col-sm-2',
- remove: {
- ngClick: `removeSelection(${list.iterator}, resourceType)`,
- iconClass: 'fa fa-times-circle',
- awToolTip: i18n._(`Remove ${list.iterator.replace(/_/g, ' ')}`),
- label: i18n._('Remove'),
- class: 'btn-sm'
- }
- };
-
- list.fields = _.each(list.fields, (field) => field.nosort = true);
-
- list_html = generateList.build({
- mode: 'edit',
- list: list,
- related: false,
- title: false,
- showSearch: false,
- showEmptyPanel: false,
- paginate: false
- });
-
- scope.list = list;
-
- scope.$watchCollection('collection', function(selected){
- scope[`${list.iterator}_dataset`] = scope.collection;
- scope[list.name] = _.values(scope.collection);
- });
-
- scope.$watch(list.name, function(){
- if(scope.list.name === 'inventories') {
- if (scope[list.name] !== undefined) {
- scope[list.name].forEach(function(item, item_idx) {
- var itm = scope[list.name][item_idx];
-
- if(itm.kind && itm.kind === "smart") {
- itm.linkToDetails = `#/inventories/smart/${itm.id}`;
- }
- else {
- itm.linkToDetails = `#/inventories/inventory/${itm.id}`;
- }
-
- });
- }
- }
- });
-
- scope.removeSelection = function(resource, type){
- let multiselect_scope, deselectedIdx;
-
- delete scope.collection[resource.id];
- delete scope.selected[type][resource.id];
-
- $('.tooltip').each(function() {
- $(this).remove();
- });
-
- // a quick & dirty hack
- // section 1 and section 2 elements produce sibling scopes
- // This means events propogated from section 2 are not received in section 1
- // The following code directly accesses the right scope by list table id
- multiselect_scope = angular.element('#AddPermissions-body').find(`#${type}_table`).scope();
- deselectedIdx = _.findIndex(multiselect_scope[type], {id: resource.id});
- multiselect_scope[type][deselectedIdx].isSelected = false;
- };
-
- scope.linkoutResource = function(type, resource) {
-
- let url;
-
- switch(type){
- case 'project':
- url = "/#/projects/" + resource.id;
- break;
- case 'inventory':
- url = resource.kind && resource.kind === "smart" ? "/#/inventories/smart/" + resource.id : "/#/inventories/inventory/" + resource.id;
- break;
- case 'job_template':
- url = "/#/templates/job_template/" + resource.id;
- break;
- case 'workflow_job_template':
- url = "/#/templates/workflow_job_template/" + resource.id;
- break;
- case 'user':
- url = "/#/users/" + resource.id;
- break;
- case 'team':
- url = "/#/teams/" + resource.id;
- break;
- case 'organization':
- url = "/#/organizations/" + resource.id;
- break;
- case 'credential':
- url = "/#/credentials/" + resource.id;
- break;
- }
-
- $window.open(url,'_blank');
- };
-
- element.append(list_html);
- $compile(element.contents())(scope);
- }
- };
- }
-];
diff --git a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.controller.js b/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.controller.js
deleted file mode 100644
index dfffc7cfcd..0000000000
--- a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.controller.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/**
- * @ngdoc function
- * @name controllers.function:Access
- * @description
- * Controller for handling permissions adding
- */
-
-export default ['$scope', '$state', 'i18n', 'CreateSelect2', 'Rest', '$q', 'Wait', 'ProcessErrors', '$rootScope',
-function(scope, $state, i18n, CreateSelect2, Rest, $q, Wait, ProcessErrors, rootScope) {
-
- init();
-
- function init(){
-
- scope.appStrings = rootScope.appStrings;
-
- let resources = ['job_templates', 'workflow_templates', 'projects', 'inventories', 'credentials', 'organizations'];
-
- // data model:
- // selected - keyed by type of resource
- // selected[type] - keyed by each resource object's id
- // selected[type][id] === { roles: [ ... ], ... }
-
- // collection of resources selected in section 1
- scope.allSelected = {};
- _.each(resources, (type) => scope.allSelected[type] = {});
-
- // collection of assignable roles per type of resource
- scope.keys = {};
- _.each(resources, (type) => scope.keys[type] = {});
-
- // collection of currently-selected role to assign in section 2
- scope.roleSelection = {};
- _.each(resources, (type) => scope.roleSelection[type] = null);
-
- // tracks currently-selected tabs, initialized with the job templates tab open
- scope.tab = {
- job_templates: true,
- workflow_templates: false,
- projects: false,
- inventories: false,
- credentials: false,
- organizations: false
- };
-
- // initializes select2 per select field
- // html snippet:
- /*
-
-
-
-
- */
- _.each(resources, (type) => buildSelect2(type));
-
- function buildSelect2(type){
- CreateSelect2({
- element: `#${type}-role-select`,
- multiple: false,
- placeholder: i18n._('Select a role')
- });
- }
-
- scope.showKeyPane = false;
-
- // the user or team being assigned permissions
- scope.owner = scope.resolve.resourceData.data;
- }
-
- // aggregate name/descriptions for each available role, based on resource type
- // reasoning:
- function aggregateKey(item, type) {
- const ownerType = _.get(scope, ['owner', 'type']);
- const { object_roles } = item.summary_fields;
-
- if (ownerType === 'team' && type === 'organizations') {
- // some organization object_roles aren't allowed for teams
- delete object_roles.admin_role;
- delete object_roles.member_role;
- }
-
- _.merge(scope.keys[type], object_roles);
- }
-
- scope.closeModal = function() {
- $state.go('^', null, {reload: true});
- };
-
- scope.currentTab = function(){
- return _.findKey(scope.tab, (tab) => tab);
- };
-
- scope.toggleKeyPane = function() {
- scope.showKeyPane = !scope.showKeyPane;
- };
-
- scope.showSection2Container = function(){
- return _.some(scope.allSelected, (type) => Object.keys(type).length > 0);
- };
-
- scope.showSection2Tab = function(tab){
- return Object.keys(scope.allSelected[tab]).length > 0;
- };
-
- scope.saveEnabled = function(){
- let missingRole = false;
- let resourceSelected = false;
- _.forOwn(scope.allSelected, function(value, key) {
- if(Object.keys(value).length > 0) {
- // A resource from this tab has been selected
- resourceSelected = true;
- if(!scope.roleSelection[key]) {
- missingRole = true;
- }
- }
- });
- return resourceSelected && !missingRole;
- };
-
- // handle form tab changes
- scope.selectTab = function(selected){
- _.each(scope.tab, (value, key, collection) => {
- collection[key] = (selected === key);
- });
- };
-
- // pop/push into unified collection of selected resourcesf
- scope.$on("selectedOrDeselected", function(e, value) {
- let resourceType = scope.currentTab(),
- item = value.value;
-
- if (value.isSelected) {
- scope.allSelected[resourceType][item.id] = item;
- scope.allSelected[resourceType][item.id].roles = [];
- aggregateKey(item, resourceType);
- } else {
- delete scope.allSelected[resourceType][item.id];
- }
- });
-
- // post roles to api
- scope.saveForm = function() {
- //Wait('start');
-
- // builds an array of role entities to apply to current user or team
- let roles = _(scope.allSelected).map( (resources, type) => {
- return _.map(resources, (resource) => {
- return resource.summary_fields.object_roles[scope.roleSelection[type]];
- });
- }).flattenDeep().value();
-
- Rest.setUrl(scope.owner.related.roles);
-
- $q.all( _.map(roles, (entity) => Rest.post({id: entity.id})) )
- .then( () =>{
- Wait('stop');
- scope.closeModal();
- }, (error) => {
- scope.closeModal();
- ProcessErrors(null, error.data, error.status, null, {
- hdr: 'Error!',
- msg: 'Failed to post role(s): POST returned status' +
- error.status
- });
- });
- };
-}];
diff --git a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.directive.js b/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.directive.js
deleted file mode 100644
index ea4aafd2f3..0000000000
--- a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.directive.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-import controller from './rbac-user-team.controller';
-
-/* jshint unused: vars */
-export default ['templateUrl',
- function(templateUrl) {
- return {
- restrict: 'E',
- scope: {
- resolve: "=",
- title: "@",
- },
- controller: controller,
- templateUrl: templateUrl('access/add-rbac-user-team/rbac-user-team'),
- link: function(scope, element, attrs) {
- scope.selectTab('job_templates');
- $('#add-permissions-modal').modal('show');
- window.scrollTo(0, 0);
- }
- };
- }
-];
diff --git a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html b/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html
deleted file mode 100644
index 610db8bb81..0000000000
--- a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html
+++ /dev/null
@@ -1,203 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- 1
-
-
- Please select resources from the lists below.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Please assign roles to the selected resources
-
-
-
-
-
-
-
- {{ key.name }}
-
-
- {{ key.description || "No description provided" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/access/add-rbac.block.less b/awx/ui/client/src/access/add-rbac.block.less
deleted file mode 100644
index 1f9ea39ea2..0000000000
--- a/awx/ui/client/src/access/add-rbac.block.less
+++ /dev/null
@@ -1,231 +0,0 @@
-/** @define AddPermissions */
-
-.AddPermissions-backDrop {
- width: 100vw;
- height: 100vh;
- position: fixed;
- top: 0;
- left: 0;
- z-index: 1041;
- opacity: 0.2;
- transition: 0.5s opacity;
- background: @login-backdrop;
-}
-
-.AddPermissions-dialog {
- margin: 30px auto;
- margin-top: 95px;
-}
-
-.AddPermissions-content {
- max-width: 750px;
- margin: 0 auto;
- border: 0;
- box-shadow: none;
- background-color: @login-bg;
- border-radius: 4px;
- transition: opacity 0.5s;
- z-index: 1042;
- position: relative;
- opacity: 1;
-}
-
-.AddPermissions-content--userTeam {
- max-width: 820px;
-}
-
-.AddPermissions-header {
- padding: 20px;
- padding-bottom: 10px;
- padding-top: 15px;
-}
-
-.AddPermissions-body {
- padding: 0px 20px;
-}
-
-.AddPermissions-body .List-well {
- margin-top: 0;
-}
-
-.AddPermissions-footer {
- display: flex;
- flex-wrap: wrap-reverse;
- align-items: center;
- padding: 20px;
- padding-bottom: 0px;
- padding-top: 20px;
-}
-
-.AddPermissions-list {
- margin-bottom: 20px;
-}
-
-.AddPermissions-list .List-searchRow {
- height: 0px;
-}
-
-.AddPermissions-list .List-searchWidget {
- height: 66px;
-}
-
-.AddPermissions-list .List-tableHeader:last-child {
- border-top-right-radius: 5px;
-}
-
-.AddPermissions-list select-all {
- display: none;
-}
-
-.AddPermissions-title {
- margin-top: 5px;
- margin-bottom: 20px;
-}
-
-.AddPermissions-buttons {
- margin-left: auto;
- margin-bottom: 20px;
-}
-
-.AddPermissions-directions {
- margin-top: 10px;
- margin-bottom: 20px;
- color: @default-interface-txt;
- display: flex;
- align-items: center;
-}
-
-.AddPermissions-directionNumber {
- font-size: 14px;
- font-weight: bold;
- border-radius: 50%;
- background-color: @default-list-header-bg;
- padding: 1px 8px;
- margin-right: 10px;
- width: 23px;
- height: 23px;
-}
-
-.AddPermissions-separator {
- margin-top: 20px 0px;
- width: 100%;
- border-bottom: 1px solid @d7grey;
-}
-
-.AddPermissions-roleRow {
- display: flex;
- margin-bottom: 10px;
- align-items: center;
-}
-
-.AddPermissions-roleName {
- width: 30%;
- padding-right: 10px;
- display: flex;
- align-items: center;
-}
-
-.AddPermissions-roleNameVal {
- font-size: 14px;
- max-width: ~"calc(100% - 46px)";
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
-}
-
-.AddPermissions-roleSelect {
- width: ~"calc(70% - 40px)";
- margin-right: 20px;
-}
-
-.AddPermissions-roleSelect .Form-dropDown {
- height: inherit !important;
-}
-
-.AddPermissions-roleRemove {
- border-radius: 50%;
- padding: 1px 0;
- line-height: 11px;
- color: @default-icon;
- background-color: @default-tertiary-bg;
- border: 0;
- height: 23px;
- width: 23px;
-}
-
-.AddPermissions-roleRemove:hover {
- background-color: @default-err;
- color: @default-bg;
-}
-
-.AddPermissions-selectHide {
- display: none;
-}
-
-.AddPermissions .select2-search__field {
- text-transform: uppercase;
-}
-
-.AddPermissions-keyToggle {
- margin-left: auto;
- text-transform: uppercase;
- background-color: @default-bg;
- border-radius: 5px;
- color: @default-interface-txt;
- border: 1px solid @d7grey;
- cursor: pointer;
- width: 70px;
- height: 34px;
- line-height: 20px;
-}
-
-.AddPermissions-keyToggle:hover {
- background-color: @default-tertiary-bg;
-}
-
-.AddPermissions-keyToggle.is-active {
- background-color: @default-link;
- border-color: @default-link;
- color: @default-bg;
- &:hover{
- background-color: @default-link-hov;
- }
-}
-
-.AddPermissions-keyPane {
- margin: 20px 0;
- font-size: 12px;
- width: 100%;
- padding: 20px;
- margin-bottom: 15px;
- border-radius: 4px;
- border: 1px solid @login-notice-border;
- background-color: @login-notice-bg;
- color: @login-notice-text;
-}
-
-.AddPermissions-keyRow {
- display: flex;
- flex-direction: column;
- margin-bottom: 15px;
-}
-
-.AddPermissions-keyName {
- flex: 1 0 auto;
- text-transform: uppercase;
- font-weight: bold;
- padding-bottom: 3px;
-}
-
-.AddPermissions-keyDescription {
- flex: 1 0 auto;
-}
-
-.AddPermissions-roleSet {
- display: flex;
-
- .AddPermissions-roleSet-dropdown {
- flex: 1;
- margin-right: 20px;
- }
-}
\ No newline at end of file
diff --git a/awx/ui/client/src/access/main.js b/awx/ui/client/src/access/main.js
deleted file mode 100644
index 1da571b524..0000000000
--- a/awx/ui/client/src/access/main.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import roleList from './rbac-role-column/roleList.directive';
-import addRbacResource from './add-rbac-resource/main';
-import addRbacUserTeam from './add-rbac-user-team/main';
-import permissionsList from './permissions-list.controller';
-
-export default
- angular.module('RbacModule', [
- addRbacResource.name,
- addRbacUserTeam.name
- ])
- .controller('PermissionsList', permissionsList)
- .directive('roleList', roleList);
diff --git a/awx/ui/client/src/access/permissions-list.controller.js b/awx/ui/client/src/access/permissions-list.controller.js
deleted file mode 100644
index ee0caaebcc..0000000000
--- a/awx/ui/client/src/access/permissions-list.controller.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['$scope', 'ListDefinition', 'Dataset', 'Wait', 'Rest', 'ProcessErrors', 'Prompt', '$state', '$filter', 'i18n',
- function($scope, list, Dataset, Wait, Rest, ProcessErrors, Prompt, $state, $filter, i18n) {
- init();
-
- function init() {
- $scope.list = list;
- $scope[`${list.iterator}_dataset`] = Dataset.data;
- $scope[`${list.iterator}s`] = $scope[`${list.iterator}_dataset`].results;
- }
-
- let reloadAfterDelete = () => {
- let reloadListStateParams = null;
-
- if($scope.permissions.length === 1 && $state.params.permission_search && _.has($state, 'params.permission_search.page') && parseInt($state.params.permission_search.page).toString() !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.permission_search.page = (parseInt(reloadListStateParams.permission_search.page)-1).toString();
- }
-
- $state.go('.', reloadListStateParams, {reload: true});
- };
-
- $scope.deletePermissionFromUser = function(userId, userName, roleName, roleType, url) {
-
- var action = function() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- Rest.setUrl(url);
- Rest.post({ "disassociate": true, "id": Number(userId) })
- .then(() => {
- Wait('stop');
- reloadAfterDelete();
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Could not disassociate user from role. Call to ' + url + ' failed. DELETE returned status: ' + status
- });
- });
- };
-
- Prompt({
- hdr: `Remove role`,
- body: `
-
- Confirm the removal of the ${$filter('sanitize')(roleType)}
- ${roleName}
- role associated with ${$filter('sanitize')(userName)}.
-
- `,
- action: action,
- actionText: i18n._('REMOVE')
- });
- };
-
- $scope.deletePermissionFromTeam = function(teamId, teamName, roleName, roleType, url) {
-
- var action = function() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- Rest.setUrl(url);
- Rest.post({ "disassociate": true, "id": teamId })
- .then(() => {
- Wait('stop');
- reloadAfterDelete();
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Could not disassociate team from role. Call to ' + url + ' failed. DELETE returned status: ' + status
- });
- });
- };
-
- Prompt({
- hdr: `Remove role`,
- body: `
-
- Confirm the removal of the ${$filter('sanitize')(roleType)}
- ${roleName}
- role associated with the ${$filter('sanitize')(teamName)} team.
-
- `,
- action: action,
- actionText: i18n._('REMOVE')
- });
- };
- }
-];
diff --git a/awx/ui/client/src/access/rbac-multiselect/main.js b/awx/ui/client/src/access/rbac-multiselect/main.js
deleted file mode 100644
index c5bc4f030f..0000000000
--- a/awx/ui/client/src/access/rbac-multiselect/main.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import rbacMultiselectList from './rbac-multiselect-list.directive';
-import rbacMultiselectRole from './rbac-multiselect-role.directive';
-import teamsList from './permissionsTeams.list';
-import usersList from './permissionsUsers.list';
-
-export default
- angular.module('rbacMultiselectModule', [])
- .directive('rbacMultiselectList', rbacMultiselectList)
- .directive('rbacMultiselectRole', rbacMultiselectRole)
- .factory('addPermissionsTeamsList', teamsList)
- .factory('addPermissionsUsersList', usersList);
diff --git a/awx/ui/client/src/access/rbac-multiselect/permissionsTeams.list.js b/awx/ui/client/src/access/rbac-multiselect/permissionsTeams.list.js
deleted file mode 100644
index 11950e0fcf..0000000000
--- a/awx/ui/client/src/access/rbac-multiselect/permissionsTeams.list.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
- export default ['i18n', function(i18n) {
- return {
- name: 'teams',
- iterator: 'team',
- listTitleBadge: false,
- multiSelect: true,
- multiSelectExtended: true,
- index: false,
- hover: true,
- emptyListText : i18n._('No Teams exist'),
- fields: {
- name: {
- key: true,
- label: i18n._('name')
- },
- organization: {
- label: i18n._('organization'),
- ngBind: 'team.summary_fields.organization.name',
- sourceModel: 'organization',
- sourceField: 'name',
- searchable: true
- }
- }
-
- };
-}];
diff --git a/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js b/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js
deleted file mode 100644
index 1e5a8193c3..0000000000
--- a/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
- export default ['i18n', function(i18n) {
- return {
- name: 'users',
- iterator: 'user',
- title: false,
- listTitleBadge: false,
- multiSelect: true,
- multiSelectExtended: true,
- index: false,
- hover: true,
- emptyListText: i18n._('No Users to add'),
- disableRow: "{{ objectType === 'organization' && user.summary_fields.user_capabilities.edit === false }}",
- disableRowValue: "objectType === 'organization' && user.summary_fields.user_capabilities.edit === false",
- disableTooltip: {
- placement: 'top',
- tipWatch: 'user.tooltip'
- },
- fields: {
- first_name: {
- label: i18n._('First Name'),
- columnClass: 'd-none d-sm-flex col-md-3 col-sm-3'
- },
- last_name: {
- label: i18n._('Last Name'),
- columnClass: 'd-none d-sm-flex col-md-3 col-sm-3'
- },
- username: {
- key: true,
- label: i18n._('Username'),
- columnClass: 'col-md-5 col-sm-5 col-xs-11'
- },
- },
-
- };
-}];
diff --git a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js b/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js
deleted file mode 100644
index 2a7e5ac212..0000000000
--- a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js
+++ /dev/null
@@ -1,277 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/* jshint unused: vars */
-export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateList', 'ProjectList',
- 'InventoryList', 'CredentialList', '$compile', 'generateList',
- 'OrganizationList', '$window', 'i18n',
- function(addPermissionsTeamsList, addPermissionsUsersList, TemplateList, ProjectList,
- InventoryList, CredentialList, $compile, generateList,
- OrganizationList, $window, i18n) {
- return {
- restrict: 'E',
- scope: {
- allSelected: '=',
- view: '@',
- dataset: '=',
- defaultParams: '=?',
- objectType: '=',
- queryPrefix: '@'
- },
- template: "
",
- link: function(scope, element, attrs, ctrl) {
- let listMap, list, list_html;
-
- listMap = {
- Teams: addPermissionsTeamsList,
- Users: addPermissionsUsersList,
- Projects: ProjectList,
- JobTemplates: TemplateList,
- WorkflowTemplates: TemplateList,
- Inventories: InventoryList,
- Credentials: CredentialList,
- Organizations: OrganizationList
- };
- list = _.cloneDeep(listMap[scope.view]);
- if (scope.queryPrefix) {
- list.iterator = scope.queryPrefix;
- }
- list.multiSelect = true;
- list.multiSelectExtended = true;
- list.listTitleBadge = false;
- list.layoutClass = 'List-staticColumnLayout--statusOrCheckbox';
- delete list.actions;
- delete list.fieldActions;
-
- switch(scope.view){
-
- case 'Projects':
- list.fields = {
- name: list.fields.name,
- scm_type: list.fields.scm_type
- };
- delete list.staticColumns;
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/projects/{{project.id}}";
- list.fields.name.columnClass = 'col-sm-6';
- list.fields.scm_type.columnClass = 'col-sm-6';
- break;
-
- case 'Inventories':
- list.fields = {
- name: list.fields.name,
- organization: list.fields.organization
- };
- delete list.staticColumns;
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = '{{inventory.linkToDetails}}';
- list.fields.name.columnClass = 'col-sm-6';
- list.fields.organization.columnClass = 'col-sm-6';
- delete list.disableRow;
- break;
-
- case 'JobTemplates':
- list.name = 'job_templates';
- list.iterator = 'job_template';
- list.basePath = 'job_templates';
- list.fields = {
- name: list.fields.name
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/templates/job_template/{{job_template.id}}";
- list.fields.name.columnClass = 'col-sm-12';
- break;
-
- case 'WorkflowTemplates':
- list.name = 'workflow_templates';
- list.iterator = 'workflow_template';
- list.basePath = 'workflow_job_templates';
- list.fields = {
- name: list.fields.name
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/templates/workflow_job_template/{{workflow_template.id}}";
- list.fields.name.columnClass = 'col-sm-12';
- break;
- case 'Users':
- if (!scope.queryPrefix) {
- list.querySet = { order_by: 'username', page_size: '5' };
- }
- list.fields = {
- username: list.fields.username,
- first_name: list.fields.first_name,
- last_name: list.fields.last_name
- };
- delete list.fields.username.ngClick;
- list.fields.username.ngHref = "#/users/{{" + list.iterator + ".id}}";
- list.fields.username.columnClass = 'col-sm-4 col-xs-11';
- list.fields.first_name.columnClass = 'd-none d-sm-flex col-sm-4';
- list.fields.last_name.columnClass = 'd-none d-sm-flex col-sm-4';
- break;
- case 'Teams':
- list.fields = {
- name: list.fields.name,
- organization: list.fields.organization,
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/teams/{{team.id}}";
- list.fields.name.columnClass = 'col-sm-6';
- list.fields.organization.columnClass = 'col-sm-6';
- break;
- case 'Organizations':
- list.fields = {
- name: list.fields.name
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/organizations/{{organization.id}}";
- list.fields.name.columnClass = 'col-sm-12';
- break;
- case 'Credentials':
- list.fields = {
- name: list.fields.name
- };
- delete list.fields.name.ngClick;
- list.fields.name.ngHref = "#/credentials/{{credential.id}}";
- list.fields.name.columnClass = 'col-sm-12';
- break;
- default:
- list.fields = {
- name: list.fields.name,
- description: list.fields.description
- };
- list.fields.name.columnClass = 'col-sm-6';
- list.fields.description.columnClass = 'col-sm-6';
- }
-
- list_html = generateList.build({
- mode: 'edit',
- list: list,
- related: false,
- title: false,
- hideViewPerPage: true
- });
-
- scope.list = list;
- scope[`${list.iterator}_dataset`] = scope.dataset.data;
-
- if (scope.defaultParams) {
- scope[`${list.iterator}_default_params`] = scope.defaultParams;
- }
-
- scope[`${list.name}`] = scope[`${list.iterator}_dataset`].results;
-
- scope.$watch(list.name, function(){
- _.forEach(scope[`${list.name}`], isSelected);
- optionsRequestDataProcessing();
- });
-
- scope.$on(`${list.iterator}_options`, function(event, data){
- scope.options = data.data.actions.GET;
- optionsRequestDataProcessing();
- });
-
- // iterate over the list and add fields like type label, after the
- // OPTIONS request returns, or the list is sorted/paginated/searched
- function optionsRequestDataProcessing(){
- if(scope.list.name === 'users'){
- if (scope[list.name] !== undefined) {
- scope[`${list.iterator}_queryset`] = list.querySet;
- scope[list.name].forEach(function(item, item_idx) {
- var itm = scope[list.name][item_idx];
- if(itm.summary_fields.user_capabilities.edit){
- // undefined doesn't render the tooltip,
- // which is intended here.
- itm.tooltip = undefined;
- }
- else if(scope.objectType === 'organization' && !itm.summary_fields.user_capabilities.edit){
- itm.tooltip = i18n._('You do not have permission to manage this user');
- }
- });
- }
- }
- if(scope.list.name === 'projects'){
- if (scope[list.name] !== undefined) {
- scope[list.name].forEach(function(item, item_idx) {
- var itm = scope[list.name][item_idx];
-
- // Set the item type label
- if (list.fields.scm_type && scope.options &&
- scope.options.hasOwnProperty('scm_type')) {
- scope.options.scm_type.choices.forEach(function(choice) {
- if (choice[0] === item.scm_type) {
- itm.type_label = choice[1];
- }
- });
- }
-
- });
- }
- }
- else if(scope.list.name === 'inventories') {
- if (scope[list.name] !== undefined) {
- scope[list.name].forEach(function(item, item_idx) {
- var itm = scope[list.name][item_idx];
-
- if(itm.kind && itm.kind === "smart") {
- itm.linkToDetails = `#/inventories/smart/${itm.id}`;
- }
- else {
- itm.linkToDetails = `#/inventories/inventory/${itm.id}`;
- }
- });
- }
- }
- }
-
- function isSelected(item){
- _.forEach(scope.allSelected[list.name], (selectedRow) => {
- if(selectedRow.id === item.id) {
- item.isSelected = true;
- }
- });
- return item;
- }
-
- element.append(list_html);
- $compile(element.contents())(scope);
-
- scope.linkoutResource = function(type, resource) {
-
- let url;
-
- switch(type){
- case 'project':
- url = "/#/projects/" + resource.id;
- break;
- case 'inventory':
- url = resource.kind && resource.kind === "smart" ? "/#/inventories/smart/" + resource.id : "/#/inventories/inventory/" + resource.id;
- break;
- case 'job_template':
- url = "/#/templates/job_template/" + resource.id;
- break;
- case 'workflow_job_template':
- url = "/#/templates/workflow_job_template/" + resource.id;
- break;
- case 'user':
- url = "/#/users/" + resource.id;
- break;
- case 'team':
- url = "/#/teams/" + resource.id;
- break;
- case 'organization':
- url = "/#/organizations/" + resource.id;
- break;
- case 'credential':
- url = "/#/credentials/" + resource.id;
- break;
- }
-
- $window.open(url,'_blank');
- };
- }
- };
-
-}];
diff --git a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-role.directive.js b/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-role.directive.js
deleted file mode 100644
index 11f40109e7..0000000000
--- a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-role.directive.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/* jshint unused: vars */
-export default
- [
- 'CreateSelect2',
- 'i18n',
- function(CreateSelect2, i18n) {
- return {
- restrict: 'E',
- scope: {
- roles: '=',
- model: '='
- },
- template: '
',
- link: function(scope, element, attrs, ctrl) {
- CreateSelect2({
- element: '.roleSelect2',
- multiple: true,
- placeholder: i18n._('Select roles')
- });
- }
- };
- }
- ];
diff --git a/awx/ui/client/src/access/rbac-role-column/roleList.block.less b/awx/ui/client/src/access/rbac-role-column/roleList.block.less
deleted file mode 100644
index 00766d9df7..0000000000
--- a/awx/ui/client/src/access/rbac-role-column/roleList.block.less
+++ /dev/null
@@ -1,79 +0,0 @@
-/** @define RoleList */
-
-.RoleList {
- display: flex;
- flex-wrap: wrap;
- align-items: flex-start;
-}
-
-.RoleList-tagContainer {
- display: flex;
- max-width: 100%;
-}
-
-.RoleList-tag {
- border-radius: 5px;
- padding: 2px 10px;
- margin: 4px 0px;
- font-size: 12px;
- color: @default-bg;
- text-transform: uppercase;
- background-color: @default-link;
- margin-right: 5px;
- max-width: 100%;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
-
- .fa-users {
- margin-left: 0.5em;
- }
-}
-
-.RoleList-tag--deletable {
- margin-right: 0px;
- border-top-left-radius: 0px;
- border-bottom-left-radius: 0px;
- border-right: 0;
- max-width: ~"calc(100% - 23px)";
- margin-right: 5px;
-}
-
-.RoleList-deleteContainer {
- background-color: @default-link;
- border-top-left-radius: 5px;
- border-bottom-left-radius: 5px;
- color: @default-bg;
- padding: 0 5px;
- margin: 4px 0px;
- align-items: center;
- display: flex;
- cursor: pointer;
-}
-
-.RoleList-tag--team {
- cursor: default;
-}
-
-.RoleList-tagDelete {
- font-size: 13px;
- color: @default-bg;
-}
-
-.RoleList-name {
- flex: initial;
- max-width: 100%;
-}
-
-.RoleList-tag--deletable > .RoleList-name {
- max-width: ~"calc(100% - 23px)";
-}
-
-.RoleList-deleteContainer:hover, {
- border-color: @default-err;
- background-color: @default-err;
-}
-
-.RoleList-deleteContainer:hover > .RoleList-tagDelete {
- color: @default-bg;
-}
diff --git a/awx/ui/client/src/access/rbac-role-column/roleList.directive.js b/awx/ui/client/src/access/rbac-role-column/roleList.directive.js
deleted file mode 100644
index 3dd3ee0790..0000000000
--- a/awx/ui/client/src/access/rbac-role-column/roleList.directive.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/* jshint unused: vars */
-export default
- [ 'templateUrl', 'Wait', 'GetBasePath', 'Rest', '$state', 'ProcessErrors', 'Prompt', '$filter', '$rootScope', 'i18n', 'AppStrings',
- function(templateUrl, Wait, GetBasePath, Rest, $state, ProcessErrors, Prompt, $filter, $rootScope, i18n, strings) {
- return {
- restrict: 'E',
- scope: {
- 'deleteTarget': '='
- },
- templateUrl: templateUrl('access/rbac-role-column/roleList'),
- link: function(scope, element, attrs) {
- // given a list of roles (things like "project
- // auditor") which are pulled from two different
- // places in summary fields, and creates a
- // concatenated/sorted list
- scope.access_list = []
- .concat(scope.deleteTarget.summary_fields
- .direct_access.map((i) => {
- i.role.explicit = true;
- return i.role;
- }))
- .concat(scope.deleteTarget.summary_fields
- .indirect_access.map((i) => {
- // Indirect access roles describe the role on another object that
- // gives the user access to this object, so we must introspect them.
- //
- // If the user has indirect admin access, they are system admin, org admin,
- // or a
_admin. Return the role name directly.
- // Similarly, if they are an auditor, return that instead of a read role.
- if (i.descendant_roles.includes('admin_role') || i.role.name.includes('Auditor')) {
- i.role.explicit = false;
- i.role.parent_role_name = i.role.name;
- return i.role;
- }
- // Handle more complex cases
- // This includes roles team<->team roles, and roles an org admin
- // inherits from teams in their organization.
- //
- // For these, we want to describe the actual permissions for the
- // object we are retrieving the access_list for, so replace
- // the role name with the descendant_roles.
- let indirect_roles = [];
- i.descendant_roles.forEach((descendant_role) => {
- let r = _.cloneDeep(i.role);
- r.parent_role_name = r.name;
- r.name = descendant_role.replace('_role','');
- r.explicit = false;
- // Do not include the read role unless it is the only descendant role.
- if (r.name !== 'read' || i.descendant_roles.length === 1) {
- indirect_roles.push(r);
- }
- });
- return indirect_roles;
- }))
- .flat()
- .filter((role) => {
- return Boolean(attrs.teamRoleList) === Boolean(role.team_id);
- })
- .sort((a, b) => {
- if (a.name
- .toLowerCase() > b.name
- .toLowerCase()) {
- return 1;
- } else {
- return -1;
- }
- });
-
- scope.deletePermission = function(user, accessListEntry) {
- let entry = accessListEntry;
-
- let action = function() {
- $('#prompt-modal').modal('hide');
- Wait('start');
-
- let url;
- if (entry.team_id) {
- url = GetBasePath("teams") + entry.team_id + "/roles/";
- } else {
- url = GetBasePath("users") + user.id + "/roles/";
- }
-
- Rest.setUrl(url);
- Rest.post({ "disassociate": true, "id": entry.id })
- .then(() => {
- Wait('stop');
- $state.go('.', null, { reload: true });
- })
- .catch(({data, status}) => {
- ProcessErrors($rootScope, data, status, null, {
- hdr: 'Error!',
- msg: 'Failed to remove access. Call to ' + url + ' failed. DELETE returned status: ' + status
- });
- });
- };
-
- if (accessListEntry.team_id) {
- Prompt({
- hdr: strings.get('removeTeamAccess.HEADER'),
- body: `${strings.get('removeTeamAccess.CONFIRM', entry.name, $filter('sanitize')(entry.team_name))}
`,
- action: action,
- actionText: strings.get('removeTeamAccess.ACTION_TEXT'),
- });
- } else {
- Prompt({
- hdr: strings.get('removeUserAccess.HEADER'),
- body: `${strings.get('removeUserAccess.CONFIRM', entry.name, $filter('sanitize')(user.username))}
`,
- action: action,
- actionText: strings.get('removeUserAccess.ACTION_TEXT'),
- });
- }
- };
- }
- };
- }
- ];
diff --git a/awx/ui/client/src/access/rbac-role-column/roleList.partial.html b/awx/ui/client/src/access/rbac-role-column/roleList.partial.html
deleted file mode 100644
index 587dff8763..0000000000
--- a/awx/ui/client/src/access/rbac-role-column/roleList.partial.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
- {{ entry.name }}
-
-
-
-
- {{ entry.name }}
-
-
-
- {{ entry.name }}
-
-
-
diff --git a/awx/ui/client/src/activity-stream/activity-detail.form.js b/awx/ui/client/src/activity-stream/activity-detail.form.js
deleted file mode 100644
index 50ac02a570..0000000000
--- a/awx/ui/client/src/activity-stream/activity-detail.form.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc overview
- * @name forms
- * @description These are all the controllers that are used throughout the application
- *
-*/
-/**
- * @ngdoc function
- * @name forms.function:ActivityDetail
- * @description This form is for activity detail modal that can be shown on most pages.
-*/
-
-export default ['i18n', function(i18n) {
- return {
-
- name: 'activity',
- editTitle: i18n._('ACTIVITY DETAIL'),
- well: false,
- 'class': 'horizontal-narrow',
- formFieldSize: 'col-lg-10',
- formLabelSize: 'col-lg-2',
-
- fields: {
- user: {
- label: i18n._("Initiated by"),
- type: 'text',
- readonly: true
- },
- operation: {
- label: i18n._('Action'),
- type: 'text',
- readonly: true
- },
- changes: {
- label: i18n._('Changes'),
- type: 'textarea',
- class: 'Form-textAreaLabel',
- ngHide: "!changes || changes =='' || changes == 'null'",
- readonly: true
- }
- }
-
- };}];
diff --git a/awx/ui/client/src/activity-stream/activitystream.block.less b/awx/ui/client/src/activity-stream/activitystream.block.less
deleted file mode 100644
index 2f49163095..0000000000
--- a/awx/ui/client/src/activity-stream/activitystream.block.less
+++ /dev/null
@@ -1,9 +0,0 @@
-.ActivityStream-refreshButton{
- height: 30px;
- padding-top: 0px;
- padding-bottom: 0px;
-}
-
-.ActivityStream-eventColumnHeader:hover{
- cursor: auto;
-}
diff --git a/awx/ui/client/src/activity-stream/activitystream.controller.js b/awx/ui/client/src/activity-stream/activitystream.controller.js
deleted file mode 100644
index febc257786..0000000000
--- a/awx/ui/client/src/activity-stream/activitystream.controller.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/**
- * @ngdoc function
- * @name controllers.function:Activity Stream
- * @description This controller controls the activity stream.
- */
-export default ['$scope', '$state', 'subTitle', 'GetTargetTitle',
- 'StreamList', 'Dataset', '$rootScope', 'ShowDetail', 'BuildDescription',
- function activityStreamController($scope, $state, subTitle, GetTargetTitle,
- list, Dataset, $rootScope, ShowDetail, BuildDescription) {
-
- // search init
- $scope.list = list;
- $scope[`${list.iterator}_dataset`] = Dataset.data;
- $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
-
- // subTitle is passed in via a resolve on the route. If there is no subtitle
- // generated in the resolve then we go get the targets generic title.
-
- // Get the streams sub-title based on the target. This scope variable is leveraged
- // when we define the activity stream list. Specifically it is included in the list
- // title.
- $scope.streamSubTitle = subTitle ? subTitle : GetTargetTitle($state.params.target);
-
- $rootScope.flashMessage = null;
-
- $scope.refreshStream = function () {
- $state.go('.', null, {reload: true});
- };
-
- $scope.showDetail = function (id) {
- ShowDetail({
- scope: $scope,
- activity_id: id
- });
- };
-
- if($scope.activities && $scope.activities.length > 0) {
- buildUserAndDescription();
- }
-
- $scope.$watch('activities', function(){
- // Watch for future update to scope.activities (like page change, column sort, search, etc)
- buildUserAndDescription();
- });
-
- function buildUserAndDescription(){
- $scope.activities.forEach(function(activity, i) {
- // build activity.user
- if ($scope.activities[i].summary_fields.actor) {
- if ($scope.activities[i].summary_fields.actor.id) {
- $scope.activities[i].user = "" +
- $scope.activities[i].summary_fields.actor.username + " ";
- } else {
- $scope.activities[i].user = $scope.activities[i].summary_fields.actor.username + ' (deleted)';
- }
- } else {
- $scope.activities[i].user = 'system';
- }
- // build description column / action text
- BuildDescription($scope.activities[i]);
-
- });
- }
-
- const route = _.find($state.$current.path, (step) => {
- return step.params.hasOwnProperty('activity_search');
- });
- let defaultParams = angular.copy(route.params.activity_search.config.value);
-
- defaultParams.or__object1__in = $state.params.activity_search.or__object1__in ? $state.params.activity_search.or__object1__in : defaultParams.or__object1__in;
- defaultParams.or__object2__in = $state.params.activity_search.or__object2__in ? $state.params.activity_search.or__object2__in : defaultParams.or__object2__in;
-
- $scope[`${list.iterator}_default_params`] = defaultParams;
- }
-];
diff --git a/awx/ui/client/src/activity-stream/activitystream.route.js b/awx/ui/client/src/activity-stream/activitystream.route.js
deleted file mode 100644
index feb3676c25..0000000000
--- a/awx/ui/client/src/activity-stream/activitystream.route.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- import { N_ } from '../i18n';
-
-export default {
- name: 'activityStream',
- route: '/activity_stream?target&id',
- searchPrefix: 'activity',
- data: {
- activityStream: true
- },
- params: {
- activity_search: {
- value: {
- // default params will not generate search tags
- order_by: '-timestamp',
- or__object1__in: null,
- or__object2__in: null
- },
- dynamic: true
- }
- },
- ncyBreadcrumb: {
- label: N_("ACTIVITY STREAM")
- },
- onExit: function() {
- $('#stream-detail-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- },
- views: {
- '@': {
- controller: 'activityStreamController',
- templateProvider: function(StreamList, generateList) {
- let html = generateList.build({
- list: StreamList,
- mode: 'edit'
- });
- html = generateList.wrapPanel(html);
- return html;
- }
- }
- },
- resolve: {
- Dataset: ['StreamList', 'QuerySet', '$stateParams', 'GetBasePath',
- function(list, qs, $stateParams, GetBasePath) {
- let path = GetBasePath(list.basePath) || GetBasePath(list.name);
- let stateParams = $stateParams[`${list.iterator}_search`];
- // Sending or__object1__in=null will result in an api error response so lets strip
- // these out. This should only be null when hitting the All Activity page.
- if(stateParams.or__object1__in && stateParams.or__object1__in === null) {
- delete stateParams.or__object1__in;
- }
- if(stateParams.or__object2__in && stateParams.or__object2__in === null) {
- delete stateParams.or__object2__in;
- }
- return qs.search(path, stateParams);
- }
- ],
- subTitle: ['$stateParams', 'Rest', 'ModelToBasePathKey', '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.
- if ($stateParams.target && $stateParams.id) {
- var target = $stateParams.target;
- var id = $stateParams.id;
-
- var url = getBasePath(ModelToBasePathKey(target)) + id + '/';
- rest.setUrl(url);
- return rest.get()
- .then(function(data) {
- // Return the name or the username depending on which is available.
- return (data.data.name || data.data.username);
- }).catch(function(response) {
- ProcessErrors(null, response.data, response.status, null, {
- hdr: 'Error!',
- msg: 'Failed to get title info. GET returned status: ' +
- response.status
- });
- });
- } else {
- return null;
- }
- }
- ]
- }
-};
diff --git a/awx/ui/client/src/activity-stream/factories/build-anchor.factory.js b/awx/ui/client/src/activity-stream/factories/build-anchor.factory.js
deleted file mode 100644
index 7081d24db4..0000000000
--- a/awx/ui/client/src/activity-stream/factories/build-anchor.factory.js
+++ /dev/null
@@ -1,123 +0,0 @@
-export default function BuildAnchor($log, $filter) {
- // Returns a full resource_name HTML string if link can be derived from supplied context
- // returns name of resource if activity stream object doesn't contain enough data to build a UI url
- // arguments are: a summary_field object, a resource type, an activity stream object
- return function (obj, resource, activity) {
- var url = '/#/';
- // try/except pattern asserts that:
- // if we encounter a case where a UI url can't or shouldn't be generated, just supply the name of the resource
- try {
- // catch-all case to avoid generating urls if a resource has been deleted
- // if a resource still exists, it'll be serialized in the activity's summary_fields
- if (!activity.summary_fields[resource]){
- throw {name : 'ResourceDeleted', message: 'The referenced resource no longer exists'};
- }
- let name;
- switch (resource) {
- case 'custom_inventory_script':
- url += 'inventory_scripts/' + obj.id + '/';
- break;
- case 'group':
- if (activity.operation === 'create' || activity.operation === 'delete'){
- // the API formats the changes.inventory field as str 'myInventoryName-PrimaryKey'
- var inventory_id = _.last(activity.changes.inventory.split('-'));
- url += 'inventories/inventory/' + inventory_id + '/groups/edit/' + activity.changes.id;
- }
- else {
- url += 'inventories/inventory/' + activity.summary_fields.inventory[0].id + '/groups/edit/' + (activity.changes.id || activity.changes.object1_pk);
- }
- break;
- case 'host':
- url += 'hosts/' + obj.id;
- break;
- case 'job':
- url += 'jobs/' + obj.id;
- break;
- case 'inventory':
- url += obj.kind && obj.kind === "smart" ? 'inventories/smart/' + obj.id + '/' : 'inventories/inventory/' + obj.id + '/';
- break;
- case 'schedule':
- // schedule urls depend on the resource they're associated with
- if (activity.summary_fields.job_template){
- url += 'templates/job_template/' + activity.summary_fields.job_template[0].id + '/schedules/' + obj.id;
- }
- else if (activity.summary_fields.project){
- url += 'projects/' + activity.summary_fields.project[0].id + '/schedules/' + obj.id;
- }
- else if (activity.summary_fields.system_job_template){
- url += 'management_jobs/management_jobs/' + activity.summary_fields.system_job_template[0].id + '/schedules/edit/' + obj.id;
- }
- // urls for inventory sync schedules currently depend on having an inventory id and group id
- else {
- throw {name : 'NotImplementedError', message : 'activity.summary_fields to build this url not implemented yet'};
- }
- break;
- case 'setting':
- if (activity.summary_fields.setting[0].category === 'jobs' ||
- activity.summary_fields.setting[0].category === 'ui') {
- url += `settings/${activity.summary_fields.setting[0].category}`;
- }
- else if (activity.summary_fields.setting[0].category === 'system' ||
- activity.summary_fields.setting[0].category === 'logging') {
- url += `settings/system`;
- }
- else {
- url += `settings/auth`;
- }
- break;
- case 'notification_template':
- url += `notification_templates/${obj.id}`;
- break;
- case 'role':
- throw {name : 'NotImplementedError', message : 'role object management is not consolidated to a single UI view'};
- case 'job_template':
- url += `templates/job_template/${obj.id}`;
- break;
- case 'workflow_job_template':
- url += `templates/workflow_job_template/${obj.id}`;
- break;
- case 'workflow_job_template_node':
- url += `templates/workflow_job_template/${activity.summary_fields.workflow_job_template[0].id}`;
- name = activity.summary_fields.workflow_job_template[0].name;
- break;
- case 'workflow_job':
- url += `workflows/${obj.id}`;
- break;
- case 'label':
- url = null;
- break;
- case 'inventory_source':
- const inventoryId = _.get(obj, 'inventory', '').split('-').reverse()[0];
- url += `inventories/inventory/${inventoryId}/inventory_sources/edit/${obj.id}`;
- break;
- case 'o_auth2_application':
- url += `applications/${obj.id}`;
- break;
- case 'workflow_approval':
- url += `workflows/${activity.summary_fields.workflow_job[0].id}`;
- name = activity.summary_fields.workflow_job[0].name + ' | ' + activity.summary_fields.workflow_approval[0].name;
- break;
- case 'workflow_approval_template':
- url += `templates/workflow_job_template/${activity.summary_fields.workflow_job_template[0].id}/workflow-maker`;
- name = activity.summary_fields.workflow_job_template[0].name + ' | ' + activity.summary_fields.workflow_approval_template[0].name;
- break;
- default:
- url += resource + 's/' + obj.id + '/';
- }
-
- name = $filter('sanitize')(name || obj.name || obj.username);
-
- if (url) {
- return ` ${name} `;
- }
-
- return ` ${name} `;
- }
- catch(err){
- $log.debug(err);
- return ' ' + $filter('sanitize')(obj.name || obj.username || '') + ' ';
- }
- };
-}
-
- BuildAnchor.$inject = ['$log', '$filter'];
diff --git a/awx/ui/client/src/activity-stream/factories/build-description.factory.js b/awx/ui/client/src/activity-stream/factories/build-description.factory.js
deleted file mode 100644
index 4e25e21b48..0000000000
--- a/awx/ui/client/src/activity-stream/factories/build-description.factory.js
+++ /dev/null
@@ -1,162 +0,0 @@
-export default function BuildDescription(BuildAnchor, $log, i18n) {
- return function (activity) {
-
- var pastTense = function(operation){
- return (/e$/.test(activity.operation)) ? operation + 'd ' : operation + 'ed ';
- };
- // convenience method to see if dis+association operation involves 2 groups
- // the group cases are slightly different because groups can be dis+associated into each other
- var isGroupRelationship = function(activity){
- return activity.object1 === 'group' && activity.object2 === 'group' && activity.summary_fields.group.length > 1;
- };
-
- // Activity stream objects will outlive the resources they reference
- // in that case, summary_fields will not be available - show generic error text instead
- try {
- activity.description = pastTense(activity.operation);
- switch(activity.object_association){
- // explicit role dis+associations
- case 'role':
- var object1 = activity.object1;
- var object2 = activity.object2;
-
- // if object1 winds up being the role's resource, we need to swap the objects
- // in order to make the sentence make sense.
- if (activity.object_type === object1) {
- object1 = activity.object2;
- object2 = activity.object1;
- }
-
- // object1 field is resource targeted by the dis+association
- // object2 field is the resource the role is inherited from
- // summary_field.role[0] contains ref info about the role
- switch(activity.operation){
- // expected outcome: "disassociated role_name from "
- case 'disassociate':
- if (isGroupRelationship(activity)){
- activity.description += BuildAnchor(activity.summary_fields.group[1], object2, activity) + activity.summary_fields.role[0].role_field +
- ' from ' + BuildAnchor(activity.summary_fields.group[0], object1, activity);
- }
- else{
- activity.description += BuildAnchor(activity.summary_fields[object2][0], object2, activity) + activity.summary_fields.role[0].role_field +
- ' from ' + BuildAnchor(activity.summary_fields[object1][0], object1, activity);
- }
- break;
- // expected outcome: "associated role_name to "
- case 'associate':
- if (isGroupRelationship(activity)){
- activity.description += BuildAnchor(activity.summary_fields.group[1], object2, activity) + activity.summary_fields.role[0].role_field +
- ' to ' + BuildAnchor(activity.summary_fields.group[0], object1, activity);
- }
- else{
- activity.description += BuildAnchor(activity.summary_fields[object2][0], object2, activity) + activity.summary_fields.role[0].role_field +
- ' to ' + BuildAnchor(activity.summary_fields[object1][0], object1, activity);
- }
- break;
- }
- break;
- // inherited role dis+associations (logic identical to case 'role')
- case 'parents':
- // object1 field is resource targeted by the dis+association
- // object2 field is the resource the role is inherited from
- // summary_field.role[0] contains ref info about the role
- switch(activity.operation){
- // expected outcome: "disassociated role_name from "
- case 'disassociate':
- if (isGroupRelationship(activity)){
- activity.description += activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) +
- 'from ' + activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
- }
- else{
- activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
- ' from ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
- }
- break;
- // expected outcome: "associated role_name to "
- case 'associate':
- if (isGroupRelationship(activity)){
- activity.description += activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity) +
- 'to ' + activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity);
- }
- else{
- activity.description += BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) + activity.summary_fields.role[0].role_field +
- ' to ' + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
- }
- break;
- }
- break;
- // CRUD operations / resource on resource dis+associations
- default:
- switch(activity.operation){
- // expected outcome: "disassociated from "
- case 'disassociate' :
- if (isGroupRelationship(activity)){
- activity.description += activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity) +
- 'from ' + activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity);
- }
- else {
- if (activity.object1 === 'workflow_job_template_node' && activity.object2 === 'workflow_job_template_node') {
- activity.description += 'two nodes on workflow' + BuildAnchor(activity.summary_fields[activity.object1[0]], activity.object1, activity);
- } else {
- activity.description += activity.object2 + BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity) +
- 'from ' + activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
- }
- }
- break;
- // expected outcome "associated to "
- case 'associate':
- // groups are the only resource that can be associated/disassociated into each other
- if (isGroupRelationship(activity)){
- activity.description += activity.object1 + BuildAnchor(activity.summary_fields.group[0], activity.object1, activity) +
- 'to ' + activity.object2 + BuildAnchor(activity.summary_fields.group[1], activity.object2, activity);
- }
- else {
- if (activity.object1 === 'workflow_job_template_node' && activity.object2 === 'workflow_job_template_node') {
- activity.description += 'two nodes on workflow' + BuildAnchor(activity.summary_fields[activity.object1[0]], activity.object1, activity);
- } else {
- activity.description += activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity) +
- 'to ' + activity.object2 + BuildAnchor(activity.summary_fields[activity.object2][0], activity.object2, activity);
- }
- }
- break;
- case 'delete':
- activity.description += activity.object1 + BuildAnchor(activity.changes, activity.object1, activity);
- break;
- // expected outcome: "operation "
- case 'update':
- if (activity.object1 === 'workflow_approval' &&
- _.has(activity, 'changes.status') &&
- activity.changes.status.length === 2
- ) {
- let operationText = '';
- if (activity.changes.status[1] === 'successful') {
- operationText = i18n._('approved');
- } else if (activity.changes.status[1] === 'failed') {
- if (activity.changes.timed_out && activity.changes.timed_out[1] === true) {
- operationText = i18n._('timed out');
- } else {
- operationText = i18n._('denied');
- }
- } else {
- operationText = i18n._('updated');
- }
- activity.description = `${operationText} ${activity.object1} ${BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity)}`;
- } else {
- activity.description += activity.object1 + BuildAnchor(activity.summary_fields[activity.object1][0], activity.object1, activity);
- }
- break;
- case 'create':
- activity.description += activity.object1 + BuildAnchor(activity.changes, activity.object1, activity);
- break;
- }
- break;
- }
- }
- catch(err){
- $log.debug(err);
- activity.description = i18n._('Event summary not available');
- }
- };
- }
-
-BuildDescription.$inject = ['BuildAnchor', '$log', 'i18n'];
diff --git a/awx/ui/client/src/activity-stream/factories/show-detail.factory.js b/awx/ui/client/src/activity-stream/factories/show-detail.factory.js
deleted file mode 100644
index b2d328aa79..0000000000
--- a/awx/ui/client/src/activity-stream/factories/show-detail.factory.js
+++ /dev/null
@@ -1,47 +0,0 @@
-export default
- function ShowDetail($filter, Find, ParseTypeChange, ParseVariableString) {
- return function (params, scope) {
-
- var activity_id = params.activity_id,
- activity = Find({ list: params.scope.activities, key: 'id', val: activity_id }),
- element;
-
- if (activity) {
-
- // Grab our element out of the dom
- element = angular.element(document.getElementById('stream-detail-modal'));
-
- // Grab the modal's scope so that we can set a few variables
- scope = element.scope();
-
- scope.changes = activity.changes;
- scope.user = ((activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system') +
- ' on ' + $filter('longDate')(activity.timestamp);
- scope.operation = activity.description;
- scope.settingCategory = _.get(activity, 'summary_fields.setting[0].category');
- scope.settingName = _.get(activity, 'summary_fields.setting[0].name');
- scope.header = "Event " + activity.id;
-
- scope.variables = ParseVariableString(scope.changes);
- scope.parseType = 'json';
- ParseTypeChange({ scope: scope,
- field_id: 'activity-stream-changes',
- readOnly: true });
- scope.parseTypeChange('parseType', 'variables');
-
- // Open the modal
- $('#stream-detail-modal').modal({
- show: true,
- backdrop: 'static',
- keyboard: true
- });
-
- if (!scope.$$phase) {
- scope.$digest();
- }
- }
-
- };
- }
-
- ShowDetail.$inject = ['$filter', 'Find', 'ParseTypeChange', 'ParseVariableString'];
diff --git a/awx/ui/client/src/activity-stream/get-target-title.factory.js b/awx/ui/client/src/activity-stream/get-target-title.factory.js
deleted file mode 100644
index d895daa988..0000000000
--- a/awx/ui/client/src/activity-stream/get-target-title.factory.js
+++ /dev/null
@@ -1,59 +0,0 @@
-export default function GetTargetTitle(i18n) {
- return function (target) {
-
- var rtnTitle = i18n._('ALL ACTIVITY');
-
- switch(target) {
- case 'project':
- rtnTitle = i18n._('PROJECTS');
- break;
- case 'credential_type':
- rtnTitle = i18n._('CREDENTIAL TYPES');
- break;
- case 'inventory':
- rtnTitle = i18n._('INVENTORIES');
- break;
- case 'credential':
- rtnTitle = i18n._('CREDENTIALS');
- break;
- case 'user':
- rtnTitle = i18n._('USERS');
- break;
- case 'team':
- rtnTitle = i18n._('TEAMS');
- break;
- case 'notification_template':
- rtnTitle = i18n._('NOTIFICATION TEMPLATES');
- break;
- case 'organization':
- rtnTitle = i18n._('ORGANIZATIONS');
- break;
- case 'job':
- rtnTitle = i18n._('JOBS');
- break;
- case 'custom_inventory_script':
- rtnTitle = i18n._('INVENTORY SCRIPTS');
- break;
- case 'schedule':
- rtnTitle = i18n._('SCHEDULES');
- break;
- case 'host':
- rtnTitle = i18n._('HOSTS');
- break;
- case 'template':
- rtnTitle = i18n._('TEMPLATES');
- break;
- case 'o_auth2_application':
- rtnTitle = i18n._('APPLICATIONS');
- break;
- case 'o_auth2_access_token':
- rtnTitle = i18n._('TOKENS');
- break;
- }
-
- return rtnTitle;
-
- };
-}
-
-GetTargetTitle.$inject = ['i18n'];
diff --git a/awx/ui/client/src/activity-stream/main.js b/awx/ui/client/src/activity-stream/main.js
deleted file mode 100644
index 383bab8d11..0000000000
--- a/awx/ui/client/src/activity-stream/main.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import activityStreamRoute from './activitystream.route';
-import activityStreamController from './activitystream.controller';
-import streamDropdownNav from './streamDropdownNav/stream-dropdown-nav.directive';
-import streamDetailModal from './streamDetailModal/main';
-import BuildAnchor from './factories/build-anchor.factory';
-import BuildDescription from './factories/build-description.factory';
-import ShowDetail from './factories/show-detail.factory';
-import GetTargetTitle from './get-target-title.factory';
-import ModelToBasePathKey from './model-to-base-path-key.factory';
-import ActivityDetailForm from './activity-detail.form';
-import StreamList from './streams.list';
-
-export default angular.module('activityStream', [streamDetailModal.name])
- .controller('activityStreamController', activityStreamController)
- .directive('streamDropdownNav', streamDropdownNav)
- .factory('BuildAnchor', BuildAnchor)
- .factory('BuildDescription', BuildDescription)
- .factory('ShowDetail', ShowDetail)
- .factory('GetTargetTitle', GetTargetTitle)
- .factory('ModelToBasePathKey', ModelToBasePathKey)
- .factory('ActivityDetailForm', ActivityDetailForm)
- .factory('StreamList', StreamList)
- .run(['$stateExtender', function($stateExtender) {
- $stateExtender.addState(activityStreamRoute);
- }]);
diff --git a/awx/ui/client/src/activity-stream/model-to-base-path-key.factory.js b/awx/ui/client/src/activity-stream/model-to-base-path-key.factory.js
deleted file mode 100644
index 2ce145c4dc..0000000000
--- a/awx/ui/client/src/activity-stream/model-to-base-path-key.factory.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc function
- * @name helpers.function:ApiModel
- * @description Helper functions to convert singular/plural versions of our models to the opposite
-*/
-
-export default function ModelToBasePathKey() {
- return function(model) {
- // This function takes in the singular model string and returns the key needed
- // to get the base path from $rootScope/local storage.
-
- var basePathKey;
-
- switch(model) {
- case 'o_auth2_application':
- basePathKey = 'applications';
- break;
- case 'project':
- basePathKey = 'projects';
- break;
- case 'credential_type':
- basePathKey = 'credential_types';
- break;
- case 'inventory':
- basePathKey = 'inventory';
- break;
- case 'job_template':
- basePathKey = 'job_templates';
- break;
- case 'credential':
- basePathKey = 'credentials';
- break;
- case 'user':
- basePathKey = 'users';
- break;
- case 'team':
- basePathKey = 'teams';
- break;
- case 'notification_template':
- basePathKey = 'notification_templates';
- break;
- case 'organization':
- basePathKey = 'organizations';
- break;
- case 'management_job':
- basePathKey = 'management_jobs';
- break;
- case 'custom_inventory_script':
- basePathKey = 'inventory_scripts';
- break;
- case 'workflow_job_template':
- basePathKey = 'workflow_job_templates';
- break;
- case 'host':
- basePathKey = 'hosts';
- break;
- }
-
- return basePathKey;
- };
-}
diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/main.js b/awx/ui/client/src/activity-stream/streamDetailModal/main.js
deleted file mode 100644
index 03533073aa..0000000000
--- a/awx/ui/client/src/activity-stream/streamDetailModal/main.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*************************************************
- * 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
deleted file mode 100644
index 3cd0ae8e18..0000000000
--- a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less
+++ /dev/null
@@ -1,39 +0,0 @@
-.StreamDetail-actionButton {
- padding: 4px 25px!important;
-}
-
-.StreamDetail-inlineRow {
- margin-bottom: 20px;
- display: flex;
-}
-
-.StreamDetail-rowTitle {
- color: @default-interface-txt;
- font-size: 12px;
-}
-
-.StreamDetail-inlineRowTitle {
- flex: 0 0 125px;
-}
-
-.StreamDetail-inlineRowData {
- flex: 1 0;
-}
-
-.StreamDetail-changesRowTitle {
- margin-bottom: 5px;
-}
-
-.StreamDetail-actions{
- word-break: break-all;
-}
-
-.StreamDetail-changes {
- border: none;
- background-color: @default-no-items-bord;
- margin-bottom: 0;
- max-height: 200px;
- overflow: scroll;
- overflow-x: auto;
- 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
deleted file mode 100644
index e144663f96..0000000000
--- a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.directive.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*************************************************
- * 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
deleted file mode 100644
index d81edd99d7..0000000000
--- a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
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
deleted file mode 100644
index 3dbf3a0d14..0000000000
--- a/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.directive.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['templateUrl', 'i18n', function(templateUrl, i18n) {
- return {
- restrict: 'E',
- scope: true,
- replace: true,
- templateUrl: templateUrl('activity-stream/streamDropdownNav/stream-dropdown-nav'),
- controller: ['$scope', '$state', '$stateParams','CreateSelect2', function($scope, $state, $stateParams, CreateSelect2) {
-
- if($state.params && $state.params.target) {
- $scope.streamTarget = ($state.params.target === 'job_template' || $state.params.target === 'workflow_job_template') ? 'template' : $state.params.target;
- }
- else {
- $scope.streamTarget = 'dashboard';
- }
-
- $scope.options = [
- {label: i18n._('All Activity'), value: 'dashboard'},
- {label: i18n._('Applications'), value: 'o_auth2_application'},
- {label: i18n._('Tokens'), value: 'o_auth2_access_token'},
- {label: i18n._('Credentials'), value: 'credential'},
- {label: i18n._('Hosts'), value: 'host'},
- {label: i18n._('Inventories'), value: 'inventory'},
- {label: i18n._('Inventory Scripts'), value: 'custom_inventory_script'},
- {label: i18n._('Jobs'), value: 'job'},
- {label: i18n._('Notification Templates'), value: 'notification_template'},
- {label: i18n._('Organizations'), value: 'organization'},
- {label: i18n._('Projects'), value: 'project'},
- {label: i18n._('Credential Types'), value: 'credential_type'},
- {label: i18n._('Schedules'), value: 'schedule'},
- {label: i18n._('Teams'), value: 'team'},
- {label: i18n._('Templates'), value: 'template'},
- {label: i18n._('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', {target: null, activity_search: {page_size:"20", order_by: '-timestamp'}});
- }
- else {
- let search = {
- or__object1__in: $scope.streamTarget,
- or__object2__in: $scope.streamTarget,
- page_size: '20',
- order_by: '-timestamp'
- };
-
- if ($scope.streamTarget && $scope.streamTarget === 'template') {
- search.or__object1__in = 'job_template,workflow_job_template';
- search.or__object2__in = 'job_template,workflow_job_template';
- }
-
- if ($scope.streamTarget && $scope.streamTarget === 'job') {
- search.or__object1__in = 'job,workflow_approval';
- search.or__object2__in = 'job,workflow_approval';
- }
-
- // Attach the taget to the query parameters
- $state.go('activityStream', {target: $scope.streamTarget, id: null, activity_search: search});
- }
-
- };
- }],
- };
-}];
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
deleted file mode 100644
index d70b0ce2f8..0000000000
--- a/awx/ui/client/src/activity-stream/streamDropdownNav/stream-dropdown-nav.partial.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/awx/ui/client/src/activity-stream/streams.list.js b/awx/ui/client/src/activity-stream/streams.list.js
deleted file mode 100644
index 0105f1899e..0000000000
--- a/awx/ui/client/src/activity-stream/streams.list.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
-export default ['i18n', function(i18n) {
- return {
-
- name: 'activities',
- iterator: 'activity',
- basePath: 'activity_stream',
- editTitle: i18n._('ACTIVITY STREAM'),
- listTitle: i18n._('ACTIVITY STREAM') + '
{{streamSubTitle}}',
- listTitleBadge: false,
- emptyListText: i18n._('There are no events to display at this time'),
- selectInstructions: '',
- index: false,
- hover: true,
- toolbarAuxAction: " ",
-
- fields: {
- timestamp: {
- label: i18n._('Time'),
- key: true,
- desc: true,
- noLink: true,
- filter: "longDate",
- columnClass: 'col-lg-3 col-md-2 col-sm-3 col-xs-3'
- },
- user: {
- label: i18n._('Initiated by'),
- ngBindHtml: 'activity.user', // @todo punch monkey
- sourceModel: 'actor',
- sourceField: 'username',
- columnClass: 'col-lg-3 col-md-3 col-sm-3 col-xs-3'
- },
- description: {
- label: i18n._('Event'),
- ngBindHtml: 'activity.description', // @todo punch monkey
- nosort: true,
- columnClass: 'ActivityStream-eventColumnHeader col-lg-5 col-md-6 col-sm-4 col-xs-4'
- }
- },
-
- actions: {
- refresh: {
- mode: 'all',
- id: 'activity-stream-refresh-btn',
- awToolTip: i18n._("Refresh the page"),
- ngClick: "refreshStream()",
- actionClass: 'btn List-buttonDefault ActivityStream-refreshButton',
- buttonContent: i18n._('REFRESH')
- }
- },
-
- fieldActions: {
-
- columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2',
-
- view: {
- label: i18n._('View'),
- ngClick: "showDetail(activity.id)",
- icon: 'fa-zoom-in',
- "class": 'btn-default btn-xs',
- awToolTip: i18n._('View event details'),
- dataPlacement: 'top'
- }
- }
-
- };}];
diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js
deleted file mode 100644
index fe420ace1d..0000000000
--- a/awx/ui/client/src/app.js
+++ /dev/null
@@ -1,451 +0,0 @@
-// Configuration dependencies
-global.$AnsibleConfig = null;
-// Provided via Webpack DefinePlugin in webpack.config.js
-global.$ENV = {};
-
-global.$ConfigResponse = {};
-
-var urlPrefix;
-
-if ($basePath) {
- urlPrefix = `${$basePath}`;
-}
-
-import start from './app.start';
-import inventoriesHosts from './inventories-hosts/main';
-import inventoryScripts from './inventory-scripts/main';
-import credentials from './credentials/main';
-import credentialTypes from './credential-types/main';
-import organizations from './organizations/main';
-import managementJobs from './management-jobs/main';
-import workflowResults from './workflow-results/main';
-import jobSubmission from './job-submission/main';
-import notifications from './notifications/main';
-import about from './about/main';
-import license from './license/main';
-import breadCrumb from './bread-crumb/main';
-import browserData from './browser-data/main';
-import configuration from './configuration/main';
-import home from './home/main';
-import login from './login/main';
-import activityStream from './activity-stream/main';
-import Templates from './templates/main';
-import teams from './teams/main';
-import users from './users/main';
-import projects from './projects/main';
-import RestServices from './rest/main';
-import access from './access/main';
-import scheduler from './scheduler/main';
-import instanceGroups from './instance-groups/main';
-import shared from './shared/main';
-
-import atFeatures from '~features';
-import atLibComponents from '~components';
-import atLibModels from '~models';
-import atLibServices from '~services';
-
-start.bootstrap(() => {
- angular.bootstrap(document.body, ['awApp']);
-});
-
-angular
- .module('awApp', [
- 'I18N',
- 'AngularCodeMirrorModule',
- 'angular-duration-format',
- 'angularMoment',
- 'AngularScheduler',
- 'dndLists',
- 'ncy-angular-breadcrumb',
- 'ngSanitize',
- 'ngCookies',
- 'ngToast',
- 'gettext',
- 'Timezones',
- 'lrInfiniteScroll',
- shared.name,
- about.name,
- access.name,
- license.name,
- RestServices.name,
- browserData.name,
- configuration.name,
- inventoriesHosts.name,
- inventoryScripts.name,
- credentials.name,
- credentialTypes.name,
- organizations.name,
- managementJobs.name,
- breadCrumb.name,
- home.name,
- login.name,
- activityStream.name,
- workflowResults.name,
- jobSubmission.name,
- notifications.name,
- Templates.name,
- teams.name,
- users.name,
- projects.name,
- scheduler.name,
-
- 'Utilities',
- 'templates',
- 'PromptDialog',
- 'AWDirectives',
-
- instanceGroups,
- atFeatures,
- atLibComponents,
- atLibModels,
- atLibServices
- ])
- .constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/')
- .constant('AngularScheduler.useTimezone', true)
- .constant('AngularScheduler.showUTCField', true)
- .constant('$timezones.definitions.location', urlPrefix + 'lib/angular-tz-extensions/tz/data')
- .config(['$locationProvider', function($locationProvider) {
- $locationProvider.hashPrefix('');
- }])
- .config(['$logProvider', function($logProvider) {
- window.debug = function(){
- $logProvider.debugEnabled(!$logProvider.debugEnabled());
- return $logProvider.debugEnabled();
- };
- window.debug(false);
- }])
- .config(['ngToastProvider', function(ngToastProvider) {
- ngToastProvider.configure({
- animation: 'slide',
- dismissOnTimeout: false,
- dismissButton: true,
- timeout: 4000
- });
- }])
- .config(['$breadcrumbProvider', 'QuerySetProvider',
- '$urlServiceProvider',
- function($breadcrumbProvider, QuerySet,
- $urlServiceProvider) {
- $urlServiceProvider.config.strictMode(false);
- $breadcrumbProvider.setOptions({
- templateUrl: urlPrefix + 'partials/breadcrumb.html'
- });
-
- // route to the details pane of /job/:id/host-event/:eventId if no other child specified
- $urlServiceProvider.rules.when('/jobs/*/host-event/*', '/jobs/*/host-event/*/details');
- $urlServiceProvider.rules.otherwise('/home');
-
- $urlServiceProvider.config.type('queryset', {
- // encoding
- // from {operator__key1__comparator=value, ... }
- // to "_search=operator:key:compator=value& ... "
- encode: function(item) {
- return QuerySet.$get().encodeArr(item);
- },
- // decoding
- // from "_search=operator:key:compator=value& ... "
- // to {operator__key1__comparator=value, ... }
- decode: function(item) {
- return QuerySet.$get().decodeArr(item);
- },
- // directionality - are we encoding or decoding?
- is: function(item) {
- // true: encode to uri
- // false: decode to $stateParam
- return angular.isObject(item);
- }
- });
-
-
- // Handy hook for debugging register/deregister of lazyLoad'd states
- // $stateProvider.stateRegistry.onStatesChanged((event, states) =>{
- // console.log(event, states)
- // })
- }
- ])
- .run(['$q', '$cookies', '$rootScope', '$log', '$stateParams',
- 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer',
- 'LoadConfig', 'Store', 'pendoService', 'Rest',
- '$state', 'GetBasePath', 'ConfigService', 'ProcessErrors',
- 'SocketService', 'AppStrings', '$transitions', 'i18n',
- function($q, $cookies, $rootScope, $log, $stateParams,
- CheckLicense, $location, Authorization, LoadBasePaths, Timer,
- LoadConfig, Store, pendoService, Rest,
- $state, GetBasePath, ConfigService, ProcessErrors,
- SocketService, AppStrings, $transitions, i18n) {
-
- $rootScope.$state = $state;
- $rootScope.$state.matches = function(stateName) {
- return $state.current.name.search(stateName) > 0;
- };
- $rootScope.$stateParams = $stateParams;
-
- $state.defaultErrorHandler(function(error) {
- $log.debug(`$state.defaultErrorHandler: ${error}`);
- });
-
- $rootScope.refresh = function() {
- $state.go('.', null, {reload: true});
- };
-
- $rootScope.refreshJobs = function(){
- $state.go('.', null, {reload: true});
- };
-
- $rootScope.breadcrumb = {};
- $rootScope.BRAND_NAME = AppStrings.get('BRAND_NAME');
- $rootScope.tabTitle = `Ansible ${$rootScope.BRAND_NAME}`;
- $rootScope.appStrings = AppStrings;
- $rootScope.$watch('$state.current.ncyBreadcrumbLabel', function(title) {
- title = (title) ? "| " + title : "";
- document.title = `Ansible ${$rootScope.BRAND_NAME} ${title}`;
- });
-
- $rootScope.$on('ws-approval', () => {
- fetchApprovalsCount();
- });
-
- function activateTab() {
- // Make the correct tab active
- var base = $location.path().replace(/^\//, '').split('/')[0];
-
- if (base === '') {
- base = 'home';
- } else {
- //base.replace(/\_/g, ' ');
- base = (base === 'job_events' || base === 'job_host_summaries') ? 'jobs' : base;
- }
- }
-
- function fetchApprovalsCount() {
- Rest.setUrl(`${GetBasePath('workflow_approvals')}?status=pending&page_size=1`);
- Rest.get()
- .then(({data}) => {
- $rootScope.pendingApprovalCount = data.count;
- })
- .catch(({data, status}) => {
- ProcessErrors({}, data, status, null, {
- hdr: i18n._('Error!'),
- msg: i18n._('Failed to get workflow jobs pending approval. GET returned status: ') + status
- });
- });
- }
-
- if ($rootScope.removeConfigReady) {
- $rootScope.removeConfigReady();
- }
- $rootScope.removeConfigReady = $rootScope.$on('ConfigReady', function(evt) {
- var list, id;
- // initially set row edit indicator for crud pages
- if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
- list = $location.$$path.split("/")[3];
- id = $location.$$path.split("/")[4];
- $rootScope.listBeingEdited = list;
- $rootScope.rowBeingEdited = id;
- $rootScope.initialIndicatorLoad = true;
- } else if ($location.$$path.split("/")[2]) {
- list = $location.$$path.split("/")[1];
- id = $location.$$path.split("/")[2];
- $rootScope.listBeingEdited = list;
- $rootScope.rowBeingEdited = id;
- }
-
- LoadBasePaths();
-
- $rootScope.crumbCache = [];
-
- $transitions.onStart({}, function(trans) {
- $rootScope.flashMessage = null;
-
- $('#form-modal2 .modal-body').empty();
-
- $('.tooltip').each(function() {
- $(this).remove();
- });
-
- $('.popover').each(function() {
- $(this).remove();
- });
-
- if (trans.to().name !== "templates.editWorkflowJobTemplate.workflowMaker" &&
- trans.to().name !== "templates.editWorkflowJobTemplate.workflowMaker.inventory" &&
- trans.to().name !== "templates.editWorkflowJobTemplate.workflowMaker.credential") {
- $('.ui-dialog-content').each(function() {
- $(this).dialog('close');
- });
- }
-
- try {
- $('#help-modal').dialog('close');
- } catch (e) {
- // ignore
- }
-
- // On each navigation request, check that the user is logged in
- if (!/^\/(login|logout)/.test($location.path())) {
- // capture most recent URL, excluding login/logout
- $rootScope.lastPath = $location.path();
- $rootScope.enteredPath = $location.path();
- $cookies.put('lastPath', $location.path());
- }
-
- if (Authorization.isUserLoggedIn() === false) {
- if (trans.to().name !== "signIn") {
- $state.go('signIn');
- }
- } else if ($rootScope && $rootScope.sessionTimer && $rootScope.sessionTimer.isExpired()) {
- // gets here on timeout
- if (trans.to().name !== "signIn") {
- $state.go('signIn');
- }
- } else {
- if ($rootScope.current_user === undefined || $rootScope.current_user === null) {
- Authorization.restoreUserInfo(); //user must have hit browser refresh
- }
- if (trans.to().name && (trans.to().name !== "signIn" && trans.to().name !== "signOut" && trans.to().name !== "license")) {
- ConfigService.getConfig().then(function() {
- // if not headed to /login or /logout, then check the license
- CheckLicense.test(evt);
- });
- }
- }
- activateTab();
- });
-
- $transitions.onSuccess({}, function(trans) {
- if(trans.to() === trans.from()) {
- // check to see if something other than a search param has changed
- let toParamsWithoutSearchKeys = {};
- let fromParamsWithoutSearchKeys = {};
- for (let key in trans.params('to')) {
- if (trans.params('to').hasOwnProperty(key) && !/_search/.test(key)) {
- toParamsWithoutSearchKeys[key] = trans.params('to')[key];
- }
- }
- for (let key in trans.params('from')) {
- if (trans.params('from').hasOwnProperty(key) && !/_search/.test(key)) {
- fromParamsWithoutSearchKeys[key] = trans.params('from')[key];
- }
- }
-
- if(!_.isEqual(toParamsWithoutSearchKeys, fromParamsWithoutSearchKeys)) {
- document.body.scrollTop = document.documentElement.scrollTop = 0;
- }
- }
- else {
- document.body.scrollTop = document.documentElement.scrollTop = 0;
- }
-
- if (trans.from().name === 'license' && trans.params('to').hasOwnProperty('licenseMissing')) {
- $rootScope.licenseMissing = trans.params('to').licenseMissing;
- }
- var list, id;
- // broadcast event change if editing crud object
- if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
- list = $location.$$path.split("/")[3];
- 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]) {
- list = $location.$$path.split("/")[1];
- id = $location.$$path.split("/")[2];
-
- delete $rootScope.listBeingEdited;
- delete $rootScope.rowBeingEdited;
-
- $rootScope.$broadcast("EditIndicatorChange", list, id);
- } else if ($rootScope.addedAnItem) {
- delete $rootScope.addedAnItem;
- $rootScope.$broadcast("RemoveIndicator");
- } else {
- $rootScope.$broadcast("RemoveIndicator");
- }
-
- if(_.includes(trans.from().name, 'output') && trans.to().name === 'jobs'){
- $state.reload();
- }
- });
-
- if (!Authorization.isUserLoggedIn()) {
- // User not authenticated, redirect to login page
- if (!/^\/(login|logout)/.test($location.path())) {
- $rootScope.preAuthUrl = $location.path();
- }
- $location.path('/login');
- } else {
- var lastUser = $cookies.getObject('current_user'),
- timestammp = Store('sessionTime');
- if (lastUser && lastUser.id && timestammp && timestammp[lastUser.id] && timestammp[lastUser.id].loggedIn) {
- var stime = timestammp[lastUser.id].time,
- now = new Date().getTime();
- if ((stime - now) <= 0) {
- if (global.$AnsibleConfig.login_redirect_override) {
- window.location.replace(global.$AnsibleConfig.login_redirect_override);
- } else {
- $location.path('/login');
- }
- }
- }
- // If browser refresh, set the user_is_superuser value
- $rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
- $rootScope.user_is_system_auditor = Authorization.getUserInfo('is_system_auditor');
-
- // state the user refreshes we want to open the socket, except if the user is on the login page, which should happen after the user logs in (see the AuthService module for that call to OpenSocket)
- if (!_.includes($location.$$url, '/login')) {
- ConfigService.getConfig().then(function() {
- Timer.init().then(function(timer) {
- $rootScope.sessionTimer = timer;
- SocketService.init();
- pendoService.issuePendoIdentity();
- CheckLicense.test();
- if ($location.$$path === "/home" && $state.current && $state.current.name === "") {
- $state.go('dashboard');
- } else if ($location.$$path === "/portal" && $state.current && $state.current.name === "") {
- $state.go('portalMode');
- }
- });
- });
- fetchApprovalsCount();
- }
- }
-
- activateTab();
-
- $rootScope.viewCurrentUser = function() {
- $location.path('/users/' + $rootScope.current_user.id);
- };
-
- $rootScope.viewLicense = function() {
- $location.path('/license');
- };
- $rootScope.toggleTab = function(e, tab, tabs) {
- e.preventDefault();
- $('#' + tabs + ' #' + tab).tab('show');
- };
-
- }); // end of 'ConfigReady'
-
-
- if (!$AnsibleConfig) {
- // create a promise that will resolve state $AnsibleConfig is loaded
- $rootScope.loginConfig = $q.defer();
- }
- if (!$rootScope.basePathsLoaded) {
- // create a promise that will resolve when base paths are loaded
- $rootScope.basePathsLoaded = $q.defer();
- }
- $rootScope.licenseMissing = true;
- //the authorization controller redirects to the home page automatcially if there is no last path defined. in order to override
- // this, set the last path to /portal for instances where portal is visited for the first time.
- $rootScope.lastPath = ($location.path() === "/portal") ? 'portal' : undefined;
-
- LoadConfig();
- }
- ]);
diff --git a/awx/ui/client/src/app.start.js b/awx/ui/client/src/app.start.js
deleted file mode 100644
index d0f738c340..0000000000
--- a/awx/ui/client/src/app.start.js
+++ /dev/null
@@ -1,108 +0,0 @@
-const SUPPORTED_LOCALES = ['en', 'es', 'fr', 'ja', 'nl', 'zh'];
-const DEFAULT_LOCALE = 'en';
-const BASE_PATH = global.$basePath ? `${global.$basePath}languages/` : '/static/languages/';
-
-/**
- * The Angular app is manually initialized in order to complete some
- * asynchronous work up front. This function returns a callback so app.js can
- * call `angular.bootstrap` when the work is complete.
- *
- * @argument {function} - Callback.
- */
-function bootstrap (callback) {
- fetchLocaleStrings((locale) => {
- if (locale) {
- angular.module('I18N').constant('LOCALE', locale);
- }
-
- fetchConfig(() => {
- angular.element(document).ready(() => callback());
- });
- });
-}
-
-/**
- * GET the localized JSON strings file or fall back to the default language
- * if the locale isn't supported or if the request fails.
- *
- * @argument {function} - Callback.
- *
- * @returns {object=} - Locale data if it exists.
- */
-function fetchLocaleStrings (callback) {
- const code = getNormalizedLocaleCode();
-
- if (isDefaultLocale(code) || !isSupportedLocale(code)) {
- callback({ code });
-
- return;
- }
-
- const request = $.ajax(`${BASE_PATH}${code}.json`);
-
- request.done(res => {
- if (res[code]) {
- callback({ code, strings: res[code] });
- } else {
- callback({ code: DEFAULT_LOCALE });
- }
- });
-
- request.fail(() => callback({ code: DEFAULT_LOCALE }));
-}
-
-function fetchConfig (callback) {
- const request = $.ajax('/api/');
-
- request.done(res => {
- global.$ConfigResponse = res;
- if (res.login_redirect_override) {
- if (!document.cookie.split(';').filter((item) => item.includes('userLoggedIn=true')).length && !window.location.href.includes('/#/login')) {
- window.location.replace(res.login_redirect_override);
- } else {
- callback();
- }
- } else {
- callback();
- }
- });
-
- request.fail(() => callback());
-}
-
-/**
- * Grabs the language off of navigator for browser compatibility.
- * If the language isn't set, then it falls back to the DEFAULT_LOCALE. The
- * locale code is normalized to be lowercase and 2 characters in length.
- */
-function getNormalizedLocaleCode () {
- let code;
-
- if (navigator.languages && navigator.languages[0]) {
- [code] = navigator.languages;
- } else if (navigator.language) {
- code = navigator.language;
- } else {
- code = navigator.userLanguage;
- }
-
- try {
- code = code.split('-')[0].toLowerCase();
- } catch (error) {
- code = DEFAULT_LOCALE;
- }
-
- return code.substring(0, 2);
-}
-
-function isSupportedLocale (code) {
- return SUPPORTED_LOCALES.includes(code);
-}
-
-function isDefaultLocale (code) {
- return code === DEFAULT_LOCALE;
-}
-
-export default {
- bootstrap
-};
diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.block.less b/awx/ui/client/src/bread-crumb/bread-crumb.block.less
deleted file mode 100644
index 5b7190fb28..0000000000
--- a/awx/ui/client/src/bread-crumb/bread-crumb.block.less
+++ /dev/null
@@ -1,105 +0,0 @@
-/** @define BreadCrumb */
-
-.BreadCrumb {
- padding: 0;
- display: flex;
- background-color: @bc-bg;
- width: 100%;
- z-index: 1039;
- margin-top: 60px;
- height: 40px;
- border-bottom: 1px solid @bc-border;
-}
-.BreadCrumb.is-loggedOut {
- opacity: 0;
-}
-.BreadCrumb-menuLinkHolder {
- display: flex;
- margin-left: auto;
-}
-.BreadCrumb-menuLink {
- width: 58px;
- color: @bc-link-icon;
- flex: initial;
- display: flex;
- align-items: center;
- padding: 0 19px;
- cursor: pointer;
-}
-.BreadCrumb-menuLink:hover {
- color: @bc-link-icon-focus;
-}
-.BreadCrumb-menuLink {
- .BreadCrumb-menuLinkImage.fa-refresh {
- &:hover {
- color: @default-link;
- }
- }
-}
-.BreadCrumb-menuLinkImage {
- font-size: 18px;
- color: @bc-link-icon;
- flex: initial;
-
- &:hover {
- color: @default-link-hov;
- }
-}
-.BreadCrumb-menuLink.BreadCrumb-menuLinkActive {
- color: @bc-link-icon-focus;
-
- .BreadCrumb-menuLinkImage {
- color: @bc-link-icon-focus;
-
- &:hover {
- color: @default-link-hov
- }
- }
-}
-.BreadCrumb-list {
- padding: 0px 20px;
- list-style: none;
- background-color: @default-bg;
- border-radius: 4px;
- line-height: 40px;
-}
-
-.BreadCrumb-item {
- display: inline-block;
- color: @default-interface-txt;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- vertical-align: bottom;
-}
-
-.BreadCrumb-invItem {
- max-width: 400px;
-}
-
-.BreadCrumb-item + .BreadCrumb-item:before {
- content: "/";
- padding: 0 5px;
- color: @default-icon;
-}
-
-@breadcrumb-breakpoint: 900px;
-@breakpoint-sm: 700px;
-
-@media screen and (max-width: @breadcrumb-breakpoint) {
- .BreadCrumb-menuLinkImage {
- font-size: 24px;
- }
- .BreadCrumb-menuLink {
- width: 67px;
- padding: 0 21px;
- }
-}
-
-@media screen and (max-width: @breakpoint-sm) {
- .BreadCrumb {
- position: fixed;
- z-index: 2;
- }
-}
\ No newline at end of file
diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.directive.js b/awx/ui/client/src/bread-crumb/bread-crumb.directive.js
deleted file mode 100644
index 47c1b82e61..0000000000
--- a/awx/ui/client/src/bread-crumb/bread-crumb.directive.js
+++ /dev/null
@@ -1,134 +0,0 @@
-export default
- ['templateUrl', '$state', '$rootScope', 'Store', 'Empty', '$window', 'BreadCrumbService', 'i18n', '$transitions',
- function(templateUrl, $state, $rootScope, Store, Empty, $window, BreadCrumbService, i18n, $transitions) {
- return {
- restrict: 'E',
- templateUrl: templateUrl('bread-crumb/bread-crumb'),
- link: function(scope) {
-
- var streamConfig = {}, originalRoute;
-
- let init = function() {
-
- scope.showActivityStreamButton = false;
- scope.showRefreshButton = false;
- scope.alwaysShowRefreshButton = false;
- scope.loadingLicense = true;
-
- $transitions.onSuccess({}, function updateActivityStreamButton(trans) {
- if(trans.from() && !Empty(trans.from().name)) {
- // Go ahead and attach the from params to the state object so that it can all be stored together
-
- trans.from().fromParams = trans.params('from') ? trans.params('from') : {};
- // Store the state that we're coming from in local storage to be accessed when navigating away from the
- // activity stream
- //Store('previous_state', fromState);
- }
-
- streamConfig = (trans.to() && trans.to().data) ? trans.to().data : {};
-
- if(streamConfig && streamConfig.activityStream) {
- scope.loadingLicense = false;
- scope.activityStreamActive = (trans.to().name === 'activityStream') ? true : false;
- scope.activityStreamTooltip = (trans.to().name === 'activityStream') ? i18n._('Hide Activity Stream') : i18n._('View Activity Stream');
- scope.showActivityStreamButton = true;
- }
- else {
- scope.showActivityStreamButton = false;
- }
-
- scope.showRefreshButton = (streamConfig && streamConfig.refreshButton) ? true : false;
- scope.alwaysShowRefreshButton = (streamConfig && streamConfig.alwaysShowRefreshButton) ? true: false;
- });
-
- scope.loadingLicense = false;
- scope.activityStreamActive = ($state.current.name === 'activityStream') ? true : false;
- scope.activityStreamTooltip = ($state.current.name === 'activityStream') ? 'Hide Activity Stream' : 'View Activity Stream';
- scope.showActivityStreamButton = ((streamConfig && streamConfig.activityStream) || $state.current.name ==='activityStream') ? true : false;
-
- function onResize(){
- BreadCrumbService.truncateCrumbs();
- }
-
- function cleanUp() {
- angular.element($window).off('resize', onResize);
- }
-
- angular.element($window).on('resize', onResize);
- scope.$on('$destroy', cleanUp);
- };
-
- init();
-
- scope.refresh = function() {
- $state.go($state.current, {}, {reload: true});
- };
-
- scope.toggleActivityStream = function() {
-
- // If the user is not already on the activity stream then they want to navigate to it
- if(!scope.activityStreamActive) {
- var stateGoParams = {};
-
- if(streamConfig && streamConfig.activityStream) {
- if(streamConfig.activityStreamTarget) {
- stateGoParams.target = streamConfig.activityStreamTarget;
- let isTemplateTarget = _.includes(['template', 'job_template', 'workflow_job_template'], streamConfig.activityStreamTarget);
- stateGoParams.activity_search = {
- or__object1__in: streamConfig.activityStreamTarget,
- or__object2__in: streamConfig.activityStreamTarget,
- order_by: '-timestamp',
- page_size: '20',
- };
-
- if (isTemplateTarget) {
- stateGoParams.activity_search.or__object1__in = 'job_template,workflow_job_template';
- stateGoParams.activity_search.or__object2__in = 'job_template,workflow_job_template';
- }
-
- if (streamConfig.activityStreamTarget === 'job') {
- stateGoParams.activity_search.or__object1__in = 'job,workflow_approval';
- stateGoParams.activity_search.or__object2__in = 'job,workflow_approval';
- }
-
- if (streamConfig.activityStreamTarget && streamConfig.activityStreamId && !streamConfig.noActivityStreamID) {
- stateGoParams.activity_search[streamConfig.activityStreamTarget] = $state.params[streamConfig.activityStreamId];
- }
- }
- else {
- stateGoParams.activity_search = {
- order_by: '-timestamp',
- page_size: '20',
- };
- }
- if(streamConfig.activityStreamId && !streamConfig.noActivityStreamID) {
- stateGoParams.id = $state.params[streamConfig.activityStreamId];
- }
- if(stateGoParams.target === "custom_inventory_script"){
- if ($state.params.inventory_script_id !== undefined) {
- stateGoParams.activity_search[streamConfig.activityStreamTarget] = $state.params.inventory_script_id;
- stateGoParams.id = $state.params.inventory_script_id;
- }
- }
-
- }
- originalRoute = $state.current;
- $state.go('activityStream', stateGoParams);
- }
- // The user is navigating away from the activity stream - take them back from whence they came
- else {
- if(originalRoute) {
- $state.go(originalRoute.name, originalRoute.fromParams);
- }
- else {
- // If for some reason something went wrong (like local storage was wiped, etc) take the
- // user back to the dashboard
- $state.go('dashboard');
- }
-
- }
-
- };
- }
- };
- }];
diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.partial.html b/awx/ui/client/src/bread-crumb/bread-crumb.partial.html
deleted file mode 100644
index 606eec8b04..0000000000
--- a/awx/ui/client/src/bread-crumb/bread-crumb.partial.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.service.js b/awx/ui/client/src/bread-crumb/bread-crumb.service.js
deleted file mode 100644
index eb7a8f81e5..0000000000
--- a/awx/ui/client/src/bread-crumb/bread-crumb.service.js
+++ /dev/null
@@ -1,80 +0,0 @@
-export default
- [function(){
- return {
- truncateCrumbs: function(){
- let breadCrumbBarWidth = $('#bread_crumb').outerWidth();
- let menuLinkWidth = $('.BreadCrumb-menuLinkHolder').outerWidth();
- let availableWidth = breadCrumbBarWidth - menuLinkWidth;
- let $breadcrumbClone = $('.BreadCrumb-list').clone().appendTo('#bread_crumb_width_checker');
- let $breadcrumbCloneItems = $breadcrumbClone.find('.BreadCrumb-item');
- // 40px for the padding on the breadcrumb bar and a few extra pixels for rounding
- let breadcrumbBarPadding = 45;
- let expandedBreadcrumbWidth = breadcrumbBarPadding;
- let crumbs = [];
- $breadcrumbCloneItems.css('max-width', 'none');
- $breadcrumbCloneItems.each(function(index, item){
- let crumbWidth = $(item).outerWidth();
- expandedBreadcrumbWidth += crumbWidth;
- crumbs.push({
- index: index,
- origWidth: crumbWidth
- });
- });
- // Remove the clone from the dom
- $breadcrumbClone.remove();
- if(expandedBreadcrumbWidth > availableWidth) {
- let widthToTrim = expandedBreadcrumbWidth - availableWidth;
- // Sort the crumbs from biggest to smallest
- let sortedCrumbs = _.orderBy(crumbs, ["origWidth"], ["desc"]);
- let maxWidth;
- for(let i=0; i widthToTrim) {
- // If we trim down the biggest (i+1) crumbs equally then we can make it fit
- maxWidth = maxWidth - (widthToTrim/potentialCrumbsToTrim);
- break;
- }
- else {
- // Trim this biggest crumb down to the next biggest
- widthToTrim = widthToTrim - (sortedCrumbs[i].origWidth - sortedCrumbs[i+1].origWidth);
- maxWidth = sortedCrumbs[i].origWidth;
- }
- }
- else {
- // This is the biggest crumb
- if(sortedCrumbs[i].origWidth - widthToTrim > sortedCrumbs[i+1].origWidth) {
- maxWidth = sortedCrumbs[i].origWidth - widthToTrim;
- break;
- }
- else {
- // Trim this biggest crumb down to the next biggest
- widthToTrim = widthToTrim - (sortedCrumbs[i].origWidth - sortedCrumbs[i+1].origWidth);
- maxWidth = sortedCrumbs[i+1].origWidth;
- }
- }
- }
- else {
- // This is the smallest crumb
- if(sortedCrumbs[i-1]) {
- // We've gotten all the way down to the smallest crumb without being able to reasonably trim
- // the previous crumbs. Go ahead and trim all of them equally.
- maxWidth = (availableWidth-breadcrumbBarPadding)/(i+1);
- }
- else {
- // There's only one breadcrumb so trim this one down
- maxWidth = sortedCrumbs[i].origWidth - widthToTrim;
- }
- }
- }
- $('.BreadCrumb-item').css('max-width', maxWidth);
- }
- else {
- $('.BreadCrumb-item').css('max-width', 'none');
- }
- }
- };
- }];
diff --git a/awx/ui/client/src/bread-crumb/main.js b/awx/ui/client/src/bread-crumb/main.js
deleted file mode 100644
index 6369beda61..0000000000
--- a/awx/ui/client/src/bread-crumb/main.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import breadCrumb from './bread-crumb.directive';
-import breadCrumbService from './bread-crumb.service';
-
-export default
- angular.module('breadCrumb', [])
- .service('BreadCrumbService', breadCrumbService)
- .directive('breadCrumb', breadCrumb);
diff --git a/awx/ui/client/src/browser-data/browser-data.factory.js b/awx/ui/client/src/browser-data/browser-data.factory.js
deleted file mode 100644
index 3b6c4f535f..0000000000
--- a/awx/ui/client/src/browser-data/browser-data.factory.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
- export default ['$window', function($window) {
- var ua = $window.navigator.userAgent,
- browserName;
-
- var browser =
- { userAgent: ua,
- platform: $window.navigator.platform,
- name: "Unknown Browser"
- };
-
- if (ua.search("MSIE") >= 0) {
- browserName = "Internet Explorer";
- }
- else if (navigator.userAgent.search("Chrome") >= 0 && navigator.userAgent.search("OPR") < 0) {
- browserName = "Chrome";
- }
- else if (navigator.userAgent.search("Firefox") >= 0) {
- browserName = "Firefox";
- }
- else if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0 && navigator.userAgent.search("OPR") < 0) {
- browserName = "Safari";
- }
- else if (navigator.userAgent.search("OPR") >= 0) {
- browserName = "Opera";
- }
-
- browser.name = browserName;
- return browser;
-}];
diff --git a/awx/ui/client/src/browser-data/main.js b/awx/ui/client/src/browser-data/main.js
deleted file mode 100644
index 038bcf036c..0000000000
--- a/awx/ui/client/src/browser-data/main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
- import getBrowserData from './browser-data.factory';
-import ngApp from './ng-app.directive';
-
-export default
- angular.module('browserData', [])
- .directive('ngApp', ngApp)
- .factory('browserData', getBrowserData);
diff --git a/awx/ui/client/src/browser-data/ng-app.directive.js b/awx/ui/client/src/browser-data/ng-app.directive.js
deleted file mode 100644
index 84d0cf8def..0000000000
--- a/awx/ui/client/src/browser-data/ng-app.directive.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/* jshint unused: vars */
-
-export default ['browserData', function(browserData) {
- return {
- link: function(scope, element, attrs) {
- element
- .attr('data-browser', browserData.userAgent)
- .attr('data-platform', browserData.platform);
- }
- };
-}];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js b/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js
deleted file mode 100644
index d916e3a53a..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js
+++ /dev/null
@@ -1,397 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default [
- '$scope',
- '$rootScope',
- '$stateParams',
- 'SettingsUtils',
- 'CreateSelect2',
- 'GenerateForm',
- 'i18n',
- 'ParseTypeChange',
- function (
- $scope,
- $rootScope,
- $stateParams,
- SettingsUtils,
- CreateSelect2,
- GenerateForm,
- i18n,
- ParseTypeChange
- ) {
- const authVm = this;
- const generator = GenerateForm;
- const formTracker = $scope.$parent.vm.formTracker; // track the current active form
-
- authVm.activeAuthForm = 'azure';
- authVm.activeTab = 'azure';
- authVm.ldapDropdownValue = '';
- authVm.githubDropdownValue = 'github';
-
- let codeInputInitialized = false;
-
- const formDefs = $scope.$parent.formDefs;
-
- // Default active authform
- if ($stateParams.form === 'auth') {
- formTracker.setCurrentAuth(authVm.activeAuthForm);
- }
-
- authVm.activeForm = function(tab) {
- if(!_.get($scope.$parent, [formTracker.currentFormName(), '$dirty'])) {
- authVm.activeTab = tab;
- authVm.activeAuthForm = getActiveAuthForm(tab);
- formTracker.setCurrentAuth(authVm.activeAuthForm);
- startCodeMirrors();
- } else {
- var msg = i18n._('You have unsaved changes. Would you like to proceed without saving?');
- var title = i18n._('Warning: Unsaved Changes');
- var buttons = [{
- label: i18n._('Discard changes'),
- "class": "btn Form-cancelButton",
- "id": "formmodal-cancel-button",
- onClick: function() {
- $scope.$parent.vm.populateFromApi();
- $scope.$parent[formTracker.currentFormName()].$setPristine();
- authVm.activeTab = tab;
- authVm.activeAuthForm = getActiveAuthForm(tab);
- formTracker.setCurrentAuth(authVm.activeAuthForm);
- $('#FormModal-dialog').dialog('close');
- }
- }, {
- label: i18n._('Save changes'),
- onClick: function() {
- $scope.$parent.vm.formSave()
- .then(function() {
- $scope.$parent[formTracker.currentFormName()].$setPristine();
- $scope.$parent.vm.populateFromApi();
- authVm.activeTab = tab;
- authVm.activeAuthForm = getActiveAuthForm(tab);
- formTracker.setCurrentAuth(authVm.activeAuthForm);
- $('#FormModal-dialog').dialog('close');
- }).catch(() => {
- event.preventDefault();
- $('#FormModal-dialog').dialog('close');
- });
- },
- "class": "btn btn-primary",
- "id": "formmodal-save-button"
- }];
- $scope.$parent.vm.triggerModal(msg, title, buttons);
- }
- formTracker.setCurrentAuth(authVm.activeAuthForm);
- authVm.ldapSelected = (authVm.activeAuthForm.indexOf('ldap') !== -1);
- };
-
- authVm.dropdownOptions = [
- {label: i18n._('Azure AD'), value: 'azure'},
- {label: i18n._('GitHub'), value: 'github'},
- {label: i18n._('Google OAuth2'), value: 'google_oauth'},
- {label: i18n._('LDAP'), value: 'ldap'},
- {label: i18n._('RADIUS'), value: 'radius'},
- {label: i18n._('SAML'), value: 'saml'},
- {label: i18n._('TACACS+'), value: 'tacacs'}
- ];
-
- authVm.ldapDropdownOptions = [
- {label: i18n._('Default'), value: ''},
- {label: i18n._('LDAP 1 (Optional)'), value: '1'},
- {label: i18n._('LDAP 2 (Optional)'), value: '2'},
- {label: i18n._('LDAP 3 (Optional)'), value: '3'},
- {label: i18n._('LDAP 4 (Optional)'), value: '4'},
- {label: i18n._('LDAP 5 (Optional)'), value: '5'},
- ];
-
- authVm.githubDropdownOptions = [
- {label: i18n._('GitHub (Default)'), value: 'github'},
- {label: i18n._('GitHub Org'), value: 'github_org'},
- {label: i18n._('GitHub Team'), value: 'github_team'},
- ];
-
- CreateSelect2({
- element: '#configure-dropdown-nav',
- multiple: false,
- });
-
- CreateSelect2({
- element: '#configure-ldap-dropdown',
- multiple: false,
- });
-
- CreateSelect2({
- element: '#configure-github-dropdown',
- multiple: false,
- });
-
- var authForms = [
- {
- formDef: formDefs.azure,
- id: 'auth-azure-form',
- name: 'azure'
- },
- {
- formDef: formDefs.github,
- id: 'auth-github-form',
- name: 'github'
- },
- {
- formDef: formDefs.github_org,
- id: 'auth-github-org-form',
- name: 'github_org'
- },
- {
- formDef: formDefs.github_team,
- id: 'auth-github-team-form',
- name: 'github_team'
- },
- {
- formDef: formDefs.google_oauth,
- id: 'auth-google-form',
- name: 'google_oauth'
- },
- {
- formDef: formDefs.radius,
- id: 'auth-radius-form',
- name: 'radius'
- },
- {
- formDef: formDefs.tacacs,
- id: 'auth-tacacs-form',
- name: 'tacacs'
- },
- {
- formDef: formDefs.saml,
- id: 'auth-saml-form',
- name: 'saml'
- },
- {
- formDef: formDefs.ldap,
- id: 'auth-ldap-form',
- name: 'ldap'
- },
- {
- formDef: formDefs.ldap1,
- id: 'auth-ldap1-form',
- name: 'ldap1'
- },
- {
- formDef: formDefs.ldap2,
- id: 'auth-ldap2-form',
- name: 'ldap2'
- },
- {
- formDef: formDefs.ldap3,
- id: 'auth-ldap3-form',
- name: 'ldap3'
- },
- {
- formDef: formDefs.ldap4,
- id: 'auth-ldap4-form',
- name: 'ldap4'
- },
- {
- formDef: formDefs.ldap5,
- id: 'auth-ldap5-form',
- name: 'ldap5'
- }
- ];
- var forms = _.map(authForms, 'formDef');
- _.each(forms, function(form) {
- var keys = _.keys(form.fields);
- _.each(keys, function(key) {
- if($scope.configDataResolve[key].type === 'choice') {
- // Create options for dropdowns
- var optionsGroup = key + '_options';
- $scope.$parent.$parent[optionsGroup] = [];
- _.each($scope.configDataResolve[key].choices, function(choice){
- $scope.$parent.$parent[optionsGroup].push({
- name: choice[0],
- label: choice[1],
- value: choice[0]
- });
- });
- }
- addFieldInfo(form, key);
- });
- // Disable the save button for system auditors
- form.buttons.save.disabled = $rootScope.user_is_system_auditor;
- });
-
- $scope.$parent.$parent.parseType = 'json';
-
- _.each(authForms, function(form) {
- // Generate the forms
- generator.inject(form.formDef, {
- id: form.id,
- mode: 'edit',
- scope: $scope.$parent.$parent,
- related: true,
- noPanel: true
- });
- });
-
- function startCodeMirrors (key) {
- var form = _.find(authForms, f => f.name === $scope.authVm.activeAuthForm);
-
- if(!key){
- // Attach codemirror to fields that need it
- _.each(form.formDef.fields, function(field) {
- // Codemirror balks at empty values so give it one
- if($scope.$parent.$parent[field.name] === null && field.codeMirror) {
- $scope.$parent.$parent[field.name] = '{}';
- }
- if(field.codeMirror) {
- createIt(field.name);
- }
- });
- }
- else if(key){
- createIt(key);
- }
-
- function createIt(name){
- ParseTypeChange({
- scope: $scope.$parent.$parent,
- variable: name,
- parse_variable: 'parseType',
- field_id: form.formDef.name + '_' + name,
- readOnly: $scope.configDataResolve[name] && $scope.configDataResolve[name].disabled ? true : false
- });
- $scope.parseTypeChange('parseType', name);
- }
- }
-
- function addFieldInfo(form, key) {
- _.extend(form.fields[key], {
- awPopOver: ($scope.configDataResolve[key].defined_in_file) ?
- null: $scope.configDataResolve[key].help_text,
- label: $scope.configDataResolve[key].label,
- name: key,
- toggleSource: key,
- dataPlacement: 'top',
- placeholder: SettingsUtils.formatPlaceholder($scope.configDataResolve[key].placeholder, key) || null,
- dataTitle: $scope.configDataResolve[key].label,
- required: $scope.configDataResolve[key].required,
- ngDisabled: $rootScope.user_is_system_auditor,
- disabled: $scope.configDataResolve[key].disabled || null,
- readonly: $scope.configDataResolve[key].readonly || null,
- definedInFile: $scope.configDataResolve[key].defined_in_file || null
- });
- }
-
- // Flag to avoid re-rendering and breaking Select2 dropdowns on tab switching
- var dropdownRendered = false;
-
- function populateLDAPGroupType(flag, index = null){
- let groupPropName;
- let groupOptionsPropName;
- let selectElementId;
-
- if (index) {
- groupPropName = `AUTH_LDAP_${index}_GROUP_TYPE`;
- groupOptionsPropName = `${groupPropName}_options`;
- selectElementId = `#configuration_ldap${index}_template_${groupPropName}`;
- } else {
- groupPropName = 'AUTH_LDAP_GROUP_TYPE';
- groupOptionsPropName = `${groupPropName}_options`;
- selectElementId = `#configuration_ldap_template_${groupPropName}`;
- }
-
- if($scope.$parent[groupPropName] !== null) {
- $scope.$parent.$parent[groupPropName] = _.find($scope[groupOptionsPropName], { value: $scope.$parent[groupPropName] });
- }
-
- if(flag !== undefined){
- dropdownRendered = flag;
- }
-
- if(!dropdownRendered) {
- dropdownRendered = true;
- CreateSelect2({
- element: selectElementId,
- multiple: false,
- placeholder: i18n._('Select group types'),
- });
- }
- }
-
- function populateTacacsProtocol(flag){
- if($scope.$parent.TACACSPLUS_AUTH_PROTOCOL !== null) {
- $scope.$parent.$parent.TACACSPLUS_AUTH_PROTOCOL = _.find($scope.$parent.TACACSPLUS_AUTH_PROTOCOL_options, { value: $scope.$parent.TACACSPLUS_AUTH_PROTOCOL });
- }
-
- if(flag !== undefined){
- dropdownRendered = flag;
- }
-
- if(!dropdownRendered) {
- dropdownRendered = true;
- CreateSelect2({
- element: '#configuration_tacacs_template_TACACSPLUS_AUTH_PROTOCOL',
- multiple: false,
- placeholder: i18n._('Select group types'),
- });
- }
- }
-
- $scope.$on('AUTH_LDAP_GROUP_TYPE_populated', (e, data, flag) => populateLDAPGroupType(flag));
- $scope.$on('AUTH_LDAP_1_GROUP_TYPE_populated', (e, data, flag) => populateLDAPGroupType(flag, 1));
- $scope.$on('AUTH_LDAP_2_GROUP_TYPE_populated', (e, data, flag) => populateLDAPGroupType(flag, 2));
- $scope.$on('AUTH_LDAP_3_GROUP_TYPE_populated', (e, data, flag) => populateLDAPGroupType(flag, 3));
- $scope.$on('AUTH_LDAP_4_GROUP_TYPE_populated', (e, data, flag) => populateLDAPGroupType(flag, 4));
- $scope.$on('AUTH_LDAP_5_GROUP_TYPE_populated', (e, data, flag) => populateLDAPGroupType(flag, 5));
-
- $scope.$on('$locationChangeStart', (event, url) => {
- let parts = url.split('/');
- let tab = parts[parts.length - 1];
-
- if (tab === 'auth') {
- startCodeMirrors();
- codeInputInitialized = true;
- }
- });
-
- $scope.$on('populated', function() {
- let tab = $stateParams.form;
-
- if (tab === 'auth') {
- startCodeMirrors();
- codeInputInitialized = true;
- }
-
- populateLDAPGroupType(false);
- populateLDAPGroupType(false, 1);
- populateLDAPGroupType(false, 2);
- populateLDAPGroupType(false, 3);
- populateLDAPGroupType(false, 4);
- populateLDAPGroupType(false, 5);
-
- populateTacacsProtocol(false);
- });
-
- $scope.$on('codeMirror_populated', function() {
- let tab = $stateParams.form;
- if (tab === 'auth') {
- startCodeMirrors();
- codeInputInitialized = true;
- }
- });
-
- function getActiveAuthForm (tab) {
- if (tab === 'ldap') {
- return `ldap${authVm.ldapDropdownValue}`;
- } else if (tab === 'github') {
- return authVm.githubDropdownValue;
- }
- return tab;
- }
-
- angular.extend(authVm, {
- authForms: authForms,
- });
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.partial.html b/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.partial.html
deleted file mode 100644
index 5154285c80..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.partial.html
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-azure.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-azure.form.js
deleted file mode 100644
index e4e8a99ba2..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-azure.form.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default ['i18n', function(i18n) {
- return {
- name: 'configuration_azure_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- SOCIAL_AUTH_AZUREAD_OAUTH2_CALLBACK_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_CALLBACK_URL'
- },
- SOCIAL_AUTH_AZUREAD_OAUTH2_KEY: {
- type: 'text',
- reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_KEY'
- },
- SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET'
- },
- SOCIAL_AUTH_AZUREAD_OAUTH2_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_ORGANIZATION_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_AZUREAD_OAUTH2_TEAM_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_TEAM_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github-org.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github-org.form.js
deleted file mode 100644
index 5087081254..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github-org.form.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'configuration_github_org_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- SOCIAL_AUTH_GITHUB_ORG_CALLBACK_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_CALLBACK_URL'
- },
- SOCIAL_AUTH_GITHUB_ORG_KEY: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_ORG_KEY'
- },
- SOCIAL_AUTH_GITHUB_ORG_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'SOCIAL_AUTH_GITHUB_ORG_SECRET'
- },
- SOCIAL_AUTH_GITHUB_ORG_NAME: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_ORG_NAME'
- },
- SOCIAL_AUTH_GITHUB_ORG_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GITHUB_ORG_ORGANIZATION_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_GITHUB_ORG_TEAM_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GITHUB_ORG_TEAM_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github-team.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github-team.form.js
deleted file mode 100644
index 01fab7193d..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github-team.form.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'configuration_github_team_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- SOCIAL_AUTH_GITHUB_TEAM_CALLBACK_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_CALLBACK_URL'
- },
- SOCIAL_AUTH_GITHUB_TEAM_KEY: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_KEY'
- },
- SOCIAL_AUTH_GITHUB_TEAM_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_SECRET'
- },
- SOCIAL_AUTH_GITHUB_TEAM_ID: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_ID'
- },
- SOCIAL_AUTH_GITHUB_TEAM_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_ORGANIZATION_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_GITHUB_TEAM_TEAM_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_TEAM_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github.form.js
deleted file mode 100644
index 2f13957cb4..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-github.form.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'configuration_github_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- SOCIAL_AUTH_GITHUB_CALLBACK_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_CALLBACK_URL'
- },
- SOCIAL_AUTH_GITHUB_KEY: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GITHUB_KEY'
- },
- SOCIAL_AUTH_GITHUB_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'SOCIAL_AUTH_GITHUB_SECRET'
- },
- SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_GITHUB_TEAM_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GITHUB_TEAM_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-google-oauth2.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-google-oauth2.form.js
deleted file mode 100644
index 31986685ea..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-google-oauth2.form.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'configuration_google_oauth_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL'
- },
- SOCIAL_AUTH_GOOGLE_OAUTH2_KEY: {
- type: 'text',
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY'
- },
- SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET'
- },
- SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS',
- rows: 6
- },
- SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- SOCIAL_AUTH_GOOGLE_OAUTH2_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_ORGANIZATION_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_GOOGLE_OAUTH2_TEAM_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_TEAM_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap.form.js
deleted file mode 100644
index 3f483b70a3..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap.form.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_ldap_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- AUTH_LDAP_SERVER_URI: {
- type: 'text',
- reset: 'AUTH_LDAP_SERVER_URI'
- },
- AUTH_LDAP_BIND_DN: {
- type: 'text',
- reset: 'AUTH_LDAP_BIND_DN'
- },
- AUTH_LDAP_BIND_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- },
- AUTH_LDAP_USER_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_USER_SEARCH'
- },
- AUTH_LDAP_GROUP_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_GROUP_SEARCH'
- },
- AUTH_LDAP_USER_DN_TEMPLATE: {
- type: 'text',
- reset: 'AUTH_LDAP_USER_DN_TEMPLATE'
- },
- AUTH_LDAP_USER_ATTR_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_USER_ATTR_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_GROUP_TYPE: {
- type: 'select',
- reset: 'AUTH_LDAP_GROUP_TYPE',
- ngOptions: 'group.label for group in AUTH_LDAP_GROUP_TYPE_options track by group.value',
- },
- AUTH_LDAP_GROUP_TYPE_PARAMS: {
- type: 'textarea',
- reset: 'AUTH_LDAP_GROUP_TYPE_PARAMS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_REQUIRE_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_REQUIRE_GROUP'
- },
- AUTH_LDAP_DENY_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_DENY_GROUP'
- },
- AUTH_LDAP_START_TLS: {
- type: 'toggleSwitch'
- },
- AUTH_LDAP_USER_FLAGS_BY_GROUP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_USER_FLAGS_BY_GROUP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_ORGANIZATION_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_TEAM_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_TEAM_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "configuration_ldap_template_form.$invalid || configuration_ldap_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap1.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap1.form.js
deleted file mode 100644
index e89ae9c59a..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap1.form.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_ldap1_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- AUTH_LDAP_1_SERVER_URI: {
- type: 'text',
- reset: 'AUTH_LDAP_1_SERVER_URI'
- },
- AUTH_LDAP_1_BIND_DN: {
- type: 'text',
- reset: 'AUTH_LDAP_1_BIND_DN'
- },
- AUTH_LDAP_1_BIND_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- },
- AUTH_LDAP_1_USER_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_1_USER_SEARCH'
- },
- AUTH_LDAP_1_GROUP_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_1_GROUP_SEARCH'
- },
- AUTH_LDAP_1_USER_DN_TEMPLATE: {
- type: 'text',
- reset: 'AUTH_LDAP_1_USER_DN_TEMPLATE'
- },
- AUTH_LDAP_1_USER_ATTR_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_1_USER_ATTR_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_1_GROUP_TYPE: {
- type: 'select',
- reset: 'AUTH_LDAP_1_GROUP_TYPE',
- ngOptions: 'group.label for group in AUTH_LDAP_1_GROUP_TYPE_options track by group.value',
- },
- AUTH_LDAP_1_GROUP_TYPE_PARAMS: {
- type: 'textarea',
- reset: 'AUTH_LDAP_1_GROUP_TYPE_PARAMS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_1_REQUIRE_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_1_REQUIRE_GROUP'
- },
- AUTH_LDAP_1_DENY_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_1_DENY_GROUP'
- },
- AUTH_LDAP_1_START_TLS: {
- type: 'toggleSwitch'
- },
- AUTH_LDAP_1_USER_FLAGS_BY_GROUP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_1_USER_FLAGS_BY_GROUP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_1_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_1_ORGANIZATION_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_1_TEAM_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_1_TEAM_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "configuration_ldap1_template_form.$invalid || configuration_ldap1_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap2.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap2.form.js
deleted file mode 100644
index ee1b2a8751..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap2.form.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_ldap2_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- AUTH_LDAP_2_SERVER_URI: {
- type: 'text',
- reset: 'AUTH_LDAP_2_SERVER_URI'
- },
- AUTH_LDAP_2_BIND_DN: {
- type: 'text',
- reset: 'AUTH_LDAP_2_BIND_DN'
- },
- AUTH_LDAP_2_BIND_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- },
- AUTH_LDAP_2_USER_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_2_USER_SEARCH'
- },
- AUTH_LDAP_2_GROUP_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_2_GROUP_SEARCH'
- },
- AUTH_LDAP_2_USER_DN_TEMPLATE: {
- type: 'text',
- reset: 'AUTH_LDAP_2_USER_DN_TEMPLATE'
- },
- AUTH_LDAP_2_USER_ATTR_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_2_USER_ATTR_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_2_GROUP_TYPE: {
- type: 'select',
- reset: 'AUTH_LDAP_2_GROUP_TYPE',
- ngOptions: 'group.label for group in AUTH_LDAP_2_GROUP_TYPE_options track by group.value',
- },
- AUTH_LDAP_2_GROUP_TYPE_PARAMS: {
- type: 'textarea',
- reset: 'AUTH_LDAP_2_GROUP_TYPE_PARAMS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_2_REQUIRE_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_2_REQUIRE_GROUP'
- },
- AUTH_LDAP_2_DENY_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_2_DENY_GROUP'
- },
- AUTH_LDAP_2_START_TLS: {
- type: 'toggleSwitch'
- },
- AUTH_LDAP_2_USER_FLAGS_BY_GROUP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_2_USER_FLAGS_BY_GROUP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_2_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_2_ORGANIZATION_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_2_TEAM_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_2_TEAM_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "configuration_ldap2_template_form.$invalid || configuration_ldap2_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap3.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap3.form.js
deleted file mode 100644
index 029974500f..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap3.form.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_ldap3_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- AUTH_LDAP_3_SERVER_URI: {
- type: 'text',
- reset: 'AUTH_LDAP_3_SERVER_URI'
- },
- AUTH_LDAP_3_BIND_DN: {
- type: 'text',
- reset: 'AUTH_LDAP_3_BIND_DN'
- },
- AUTH_LDAP_3_BIND_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- },
- AUTH_LDAP_3_USER_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_3_USER_SEARCH'
- },
- AUTH_LDAP_3_GROUP_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_3_GROUP_SEARCH'
- },
- AUTH_LDAP_3_USER_DN_TEMPLATE: {
- type: 'text',
- reset: 'AUTH_LDAP_3_USER_DN_TEMPLATE'
- },
- AUTH_LDAP_3_USER_ATTR_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_3_USER_ATTR_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_3_GROUP_TYPE: {
- type: 'select',
- reset: 'AUTH_LDAP_3_GROUP_TYPE',
- ngOptions: 'group.label for group in AUTH_LDAP_3_GROUP_TYPE_options track by group.value',
- },
- AUTH_LDAP_3_GROUP_TYPE_PARAMS: {
- type: 'textarea',
- reset: 'AUTH_LDAP_3_GROUP_TYPE_PARAMS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_3_REQUIRE_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_3_REQUIRE_GROUP'
- },
- AUTH_LDAP_3_DENY_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_3_DENY_GROUP'
- },
- AUTH_LDAP_3_START_TLS: {
- type: 'toggleSwitch'
- },
- AUTH_LDAP_3_USER_FLAGS_BY_GROUP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_3_USER_FLAGS_BY_GROUP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_3_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_3_ORGANIZATION_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_3_TEAM_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_3_TEAM_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "!ldap_auth || configuration_ldap3_template_form.$invalid || configuration_ldap3_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap4.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap4.form.js
deleted file mode 100644
index fa8195c5dc..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap4.form.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_ldap4_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- AUTH_LDAP_4_SERVER_URI: {
- type: 'text',
- reset: 'AUTH_LDAP_4_SERVER_URI'
- },
- AUTH_LDAP_4_BIND_DN: {
- type: 'text',
- reset: 'AUTH_LDAP_4_BIND_DN'
- },
- AUTH_LDAP_4_BIND_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- },
- AUTH_LDAP_4_USER_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_4_USER_SEARCH'
- },
- AUTH_LDAP_4_GROUP_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_4_GROUP_SEARCH'
- },
- AUTH_LDAP_4_USER_DN_TEMPLATE: {
- type: 'text',
- reset: 'AUTH_LDAP_4_USER_DN_TEMPLATE'
- },
- AUTH_LDAP_4_USER_ATTR_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_4_USER_ATTR_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_4_GROUP_TYPE: {
- type: 'select',
- reset: 'AUTH_LDAP_4_GROUP_TYPE',
- ngOptions: 'group.label for group in AUTH_LDAP_4_GROUP_TYPE_options track by group.value',
- },
- AUTH_LDAP_4_GROUP_TYPE_PARAMS: {
- type: 'textarea',
- reset: 'AUTH_LDAP_4_GROUP_TYPE_PARAMS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_4_REQUIRE_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_4_REQUIRE_GROUP'
- },
- AUTH_LDAP_4_DENY_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_4_DENY_GROUP'
- },
- AUTH_LDAP_4_START_TLS: {
- type: 'toggleSwitch'
- },
- AUTH_LDAP_4_USER_FLAGS_BY_GROUP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_4_USER_FLAGS_BY_GROUP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_4_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_4_ORGANIZATION_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_4_TEAM_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_4_TEAM_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "!ldap_auth || configuration_ldap4_template_form.$invalid || configuration_ldap4_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap5.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap5.form.js
deleted file mode 100644
index 9fe6dbb796..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-ldap5.form.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************
- * Copyright (c) 2018 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_ldap5_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- AUTH_LDAP_5_SERVER_URI: {
- type: 'text',
- reset: 'AUTH_LDAP_5_SERVER_URI'
- },
- AUTH_LDAP_5_BIND_DN: {
- type: 'text',
- reset: 'AUTH_LDAP_5_BIND_DN'
- },
- AUTH_LDAP_5_BIND_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- },
- AUTH_LDAP_5_USER_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_5_USER_SEARCH'
- },
- AUTH_LDAP_5_GROUP_SEARCH: {
- type: 'textarea',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- reset: 'AUTH_LDAP_5_GROUP_SEARCH'
- },
- AUTH_LDAP_5_USER_DN_TEMPLATE: {
- type: 'text',
- reset: 'AUTH_LDAP_5_USER_DN_TEMPLATE'
- },
- AUTH_LDAP_5_USER_ATTR_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_5_USER_ATTR_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_5_GROUP_TYPE: {
- type: 'select',
- reset: 'AUTH_LDAP_5_GROUP_TYPE',
- ngOptions: 'group.label for group in AUTH_LDAP_5_GROUP_TYPE_options track by group.value',
- },
- AUTH_LDAP_5_GROUP_TYPE_PARAMS: {
- type: 'textarea',
- reset: 'AUTH_LDAP_5_GROUP_TYPE_PARAMS',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_5_REQUIRE_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_5_REQUIRE_GROUP'
- },
- AUTH_LDAP_5_DENY_GROUP: {
- type: 'text',
- reset: 'AUTH_LDAP_5_DENY_GROUP'
- },
- AUTH_LDAP_5_START_TLS: {
- type: 'toggleSwitch'
- },
- AUTH_LDAP_5_USER_FLAGS_BY_GROUP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_5_USER_FLAGS_BY_GROUP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_5_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_5_ORGANIZATION_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- AUTH_LDAP_5_TEAM_MAP: {
- type: 'textarea',
- reset: 'AUTH_LDAP_5_TEAM_MAP',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "!ldap_auth || configuration_ldap5_template_form.$invalid || configuration_ldap5_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-radius.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-radius.form.js
deleted file mode 100644
index 568c3b45ca..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-radius.form.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_radius_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- RADIUS_SERVER: {
- type: 'text',
- reset: 'RADIUS_SERVER'
- },
- RADIUS_PORT: {
- type: 'text',
- reset: 'RADIUS_PORT'
- },
- RADIUS_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'RADIUS_SECRET'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "configuration_radius_template_form.$invalid || configuration_radius_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-saml.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-saml.form.js
deleted file mode 100644
index 7062b9dc6a..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-saml.form.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'configuration_saml_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- SOCIAL_AUTH_SAML_CALLBACK_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_SAML_CALLBACK_URL'
- },
- SOCIAL_AUTH_SAML_METADATA_URL: {
- type: 'text',
- reset: 'SOCIAL_AUTH_SAML_METADATA_URL'
- },
- SOCIAL_AUTH_SAML_SP_ENTITY_ID: {
- type: 'text',
- reset: 'SOCIAL_AUTH_SAML_SP_ENTITY_ID'
- },
- SOCIAL_AUTH_SAML_SP_PUBLIC_CERT: {
- type: 'textarea',
- rows: 6,
- elementClass: 'Form-monospace',
- reset: 'SOCIAL_AUTH_SAML_SP_PUBLIC_CERT'
- },
- SOCIAL_AUTH_SAML_SP_PRIVATE_KEY: {
- type: 'textarea',
- rows: 6,
- elementClass: 'Form-monospace',
- hasShowInputButton: true,
- reset: 'SOCIAL_AUTH_SAML_SP_PRIVATE_KEY'
- },
- SOCIAL_AUTH_SAML_ORG_INFO: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_ORG_INFO',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_TECHNICAL_CONTACT: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_TECHNICAL_CONTACT',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_SUPPORT_CONTACT: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_SUPPORT_CONTACT',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_ENABLED_IDPS: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_ENABLED_IDPS',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_ORGANIZATION_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_ORGANIZATION_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_ORGANIZATION_ATTR: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_ORGANIZATION_ATTR',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_TEAM_MAP: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_TEAM_MAP',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_TEAM_ATTR: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_TEAM_ATTR',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- SOCIAL_AUTH_SAML_SECURITY_CONFIG: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_SECURITY_CONFIG',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- SOCIAL_AUTH_SAML_SP_EXTRA: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_SP_EXTRA',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- SOCIAL_AUTH_SAML_EXTRA_DATA: {
- type: 'textarea',
- reset: 'SOCIAL_AUTH_SAML_EXTRA_DATA',
- codeMirror: true,
- rows: 6,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- },
- },
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "configuration_saml_template_form.$invalid || configuration_saml_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-tacacs.form.js b/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-tacacs.form.js
deleted file mode 100644
index f1fef03147..0000000000
--- a/awx/ui/client/src/configuration/forms/auth-form/sub-forms/auth-tacacs.form.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- // editTitle: 'Authorization Configuration',
- name: 'configuration_tacacs_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- TACACSPLUS_HOST: {
- type: 'text',
- reset: 'TACACSPLUS_HOST'
- },
- TACACSPLUS_PORT: {
- type: 'text',
- reset: 'TACACSPLUS_PORT'
- },
- TACACSPLUS_SECRET: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'TACACSPLUS_SECRET'
- },
- TACACSPLUS_SESSION_TIMEOUT: {
- type: 'number',
- integer: true,
- spinner: true,
- min: 0,
- reset: 'TACACSPLUS_SESSION_TIMEOUT'
- },
- TACACSPLUS_AUTH_PROTOCOL: {
- type: 'select',
- reset: 'TACACSPLUS_AUTH_PROTOCOL',
- ngOptions: 'protocol.label for protocol in TACACSPLUS_AUTH_PROTOCOL_options track by protocol.value',
-
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: "configuration_tacacs_template_form.$invalid || configuration_tacacs_template_form.$pending"
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.controller.js b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.controller.js
deleted file mode 100644
index 256f11214b..0000000000
--- a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.controller.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default [
- '$scope',
- '$rootScope',
- '$stateParams',
- 'ConfigurationJobsForm',
- 'CreateSelect2',
- 'GenerateForm',
- 'ParseTypeChange',
- 'i18n',
- function(
- $scope,
- $rootScope,
- $stateParams,
- ConfigurationJobsForm,
- CreateSelect2,
- GenerateForm,
- ParseTypeChange,
- i18n
- ) {
- const generator = GenerateForm;
- var form = ConfigurationJobsForm;
- const formTracker = $scope.$parent.vm.formTracker;
-
- if ($stateParams.form === 'jobs') {
- formTracker.setCurrentAuth('jobs');
- }
-
- let tab;
- let codeInputInitialized = false;
-
- $scope.$parent.$parent.AD_HOC_COMMANDS_options = [];
- _.each($scope.$parent.configDataResolve.AD_HOC_COMMANDS.default, function (command) {
- $scope.$parent.$parent.AD_HOC_COMMANDS_options.push({
- name: command,
- label: command,
- value: command
- });
- });
-
- // Disable the save button for system auditors
- form.buttons.save.disabled = $rootScope.user_is_system_auditor;
-
- var keys = _.keys(form.fields);
- _.each(keys, function(key) {
- addFieldInfo(form, key);
- });
-
- function addFieldInfo(form, key) {
- _.extend(form.fields[key], {
- awPopOver: ($scope.$parent.configDataResolve[key].defined_in_file) ?
- null: $scope.$parent.configDataResolve[key].help_text,
- label: $scope.$parent.configDataResolve[key].label,
- name: key,
- toggleSource: key,
- dataPlacement: 'top',
- dataTitle: $scope.$parent.configDataResolve[key].label,
- required: $scope.$parent.configDataResolve[key].required,
- ngDisabled: $rootScope.user_is_system_auditor,
- disabled: $scope.$parent.configDataResolve[key].disabled || null,
- readonly: $scope.$parent.configDataResolve[key].readonly || null,
- definedInFile: $scope.$parent.configDataResolve[key].defined_in_file || null
- });
- }
-
- generator.inject(form, {
- id: 'configure-jobs-form',
- mode: 'edit',
- scope: $scope.$parent.$parent,
- related: false,
- noPanel: true
- });
-
- $scope.$parent.$parent.parseType = 'json';
-
- function initializeCodeInput () {
- let name = 'AWX_TASK_ENV';
-
- ParseTypeChange({
- scope: $scope.$parent.$parent,
- variable: name,
- parse_variable: 'parseType',
- field_id: `configuration_jobs_template_${name}`
- });
-
- $scope.parseTypeChange('parseType', name);
- }
-
- function loadAdHocCommands () {
- $scope.$parent.$parent.AD_HOC_COMMANDS_values = $scope.$parent.$parent.AD_HOC_COMMANDS.map(value => value);
- $scope.$parent.$parent.AD_HOC_COMMANDS = $scope.$parent.$parent.AD_HOC_COMMANDS.map(value => ({
- value,
- name: value,
- label: value
- }));
-
- $scope.$parent.$parent.AD_HOC_COMMANDS_options = $scope.$parent.$parent.AD_HOC_COMMANDS.map(tag => tag);
- CreateSelect2({
- element: '#configuration_jobs_template_AD_HOC_COMMANDS',
- multiple: true,
- addNew: true,
- placeholder: i18n._('Select commands')
- });
-
- }
-
- function revertAdHocCommands () {
- $scope.$parent.$parent.AD_HOC_COMMANDS = $scope.$parent.configDataResolve.AD_HOC_COMMANDS.default.map(value => ({
- value,
- name: value,
- label: value
- }));
-
- $('.select2-selection__choice').each(function(i, element){
- if(!_.includes($scope.$parent.configDataResolve.AD_HOC_COMMANDS.default, element.title)){
- $(`#configuration_jobs_template_AD_HOC_COMMANDS option[value='${element.title}']`).remove();
- element.remove();
- }
- });
-
- $scope.$parent.$parent.AD_HOC_COMMANDS_options = $scope.$parent.$parent.AD_HOC_COMMANDS.map(tag => tag);
- $scope.$parent.$parent.AD_HOC_COMMANDS_values = $scope.$parent.$parent.AD_HOC_COMMANDS.map(tag => tag.value);
- CreateSelect2({
- element: '#configuration_jobs_template_AD_HOC_COMMANDS',
- multiple: true,
- addNew: true,
- placeholder: i18n._('Select commands'),
- options: $scope.$parent.$parent.AD_HOC_COMMANDS_options
- });
- }
-
- // Managing the state of select2's tags since the behavior is unpredictable otherwise.
- let commandsElement = $('#configuration_jobs_template_AD_HOC_COMMANDS');
-
- commandsElement.on('select2:select', event => {
- let command = event.params.data.text;
- let commands = $scope.$parent.$parent.AD_HOC_COMMANDS_values;
-
- commands.push(command);
- });
-
- commandsElement.on('select2:unselect', event => {
- let command = event.params.data.text;
- let commands = $scope.$parent.$parent.AD_HOC_COMMANDS_values;
-
- $scope.$parent.$parent.AD_HOC_COMMANDS_values = commands.filter(value => value !== command);
- });
-
- $scope.$on('AD_HOC_COMMANDS_reverted', () => revertAdHocCommands());
-
- /*
- * Necessary to listen for revert clicks and relaunch the codemirror instance.
- */
- $scope.$on('codeMirror_populated', () => {
- if (tab === 'jobs') {
- initializeCodeInput();
- }
- });
-
- /*
- * This event is fired if the user navigates directly to this tab, where the
- * $locationChangeStart does not. Watching this and location ensure proper display on
- * direct load of this tab or if the user comes from a different tab.
- */
- $scope.$on('populated', () => {
- tab = $stateParams.form;
- if (tab === 'jobs') {
- initializeCodeInput();
- codeInputInitialized = true;
- }
-
- loadAdHocCommands();
- });
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js
deleted file mode 100644
index 0cf4def48d..0000000000
--- a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- showHeader: false,
- name: 'configuration_jobs_template',
- showActions: true,
- fields: {
- AD_HOC_COMMANDS: {
- type: 'select',
- ngOptions: 'command.label for command in AD_HOC_COMMANDS_options track by command.value',
- reset: 'AD_HOC_COMMANDS',
- multiSelect: true
- },
- AWX_PROOT_BASE_PATH: {
- type: 'text',
- reset: 'AWX_PROOT_BASE_PATH',
- },
- SCHEDULE_MAX_JOBS: {
- type: 'number',
- reset: 'SCHEDULE_MAX_JOBS'
- },
- AWX_PROOT_SHOW_PATHS: {
- type: 'textarea',
- reset: 'AWX_PROOT_SHOW_PATHS',
- rows: 6
- },
- AWX_ANSIBLE_CALLBACK_PLUGINS: {
- type: 'textarea',
- reset: 'AWX_ANSIBLE_CALLBACK_PLUGINS',
- rows: 6
- },
- AWX_PROOT_HIDE_PATHS: {
- type: 'textarea',
- reset: 'AWX_PROOT_HIDE_PATHS',
- rows: 6
- },
- AWX_PROOT_ENABLED: {
- type: 'toggleSwitch',
- },
- DEFAULT_JOB_TIMEOUT: {
- type: 'text',
- reset: 'DEFAULT_JOB_TIMEOUT',
- },
- DEFAULT_INVENTORY_UPDATE_TIMEOUT: {
- type: 'text',
- reset: 'DEFAULT_INVENTORY_UPDATE_TIMEOUT',
- },
- DEFAULT_PROJECT_UPDATE_TIMEOUT: {
- type: 'text',
- reset: 'DEFAULT_PROJECT_UPDATE_TIMEOUT',
- },
- ANSIBLE_FACT_CACHE_TIMEOUT: {
- type: 'text',
- reset: 'ANSIBLE_FACT_CACHE_TIMEOUT',
- },
- MAX_FORKS: {
- type: 'text',
- reset: 'MAX_FORKS',
- },
- PROJECT_UPDATE_VVV: {
- type: 'toggleSwitch',
- },
- GALAXY_IGNORE_CERTS: {
- type: 'toggleSwitch',
- },
- AWX_ROLES_ENABLED: {
- type: 'toggleSwitch',
- },
- AWX_COLLECTIONS_ENABLED: {
- type: 'toggleSwitch',
- },
- AWX_SHOW_PLAYBOOK_LINKS: {
- type: 'toggleSwitch',
- },
- AWX_TASK_ENV: {
- type: 'textarea',
- reset: 'AWX_TASK_ENV',
- rows: 6,
- codeMirror: true,
- class: 'Form-textAreaLabel Form-formGroup--fullWidth'
- },
- AWX_ISOLATED_HOST_KEY_CHECKING: {
- type: 'toggleSwitch',
- },
- AWX_ISOLATED_CHECK_INTERVAL: {
- type: 'text',
- reset: 'AWX_ISOLATED_CHECK_INTERVAL'
- },
- AWX_ISOLATED_LAUNCH_TIMEOUT: {
- type: 'text',
- reset: 'AWX_ISOLATED_LAUNCH_TIMEOUT'
- },
- AWX_ISOLATED_CONNECTION_TIMEOUT: {
- type: 'text',
- reset: 'AWX_ISOLATED_CONNECTION_TIMEOUT'
- },
- AWX_RESOURCE_PROFILING_ENABLED: {
- type: 'toggleSwitch',
- }
- },
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}];
diff --git a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.partial.html b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.partial.html
deleted file mode 100644
index 165a551cbd..0000000000
--- a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.partial.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
diff --git a/awx/ui/client/src/configuration/forms/settings-form.controller.js b/awx/ui/client/src/configuration/forms/settings-form.controller.js
deleted file mode 100644
index e78d08baaa..0000000000
--- a/awx/ui/client/src/configuration/forms/settings-form.controller.js
+++ /dev/null
@@ -1,635 +0,0 @@
-import defaultStrings from '~assets/default.strings.json';
-
-export default [
- '$scope', '$rootScope', '$state', '$stateParams', '$q',
- 'SettingsService', 'SettingsUtils', 'CreateDialog', 'i18n', 'ProcessErrors', 'Store',
- 'Wait', 'configDataResolve', 'ToJSON', 'ConfigService',
- //Form definitions
- 'configurationAzureForm',
- 'configurationGithubForm',
- 'configurationGithubOrgForm',
- 'configurationGithubTeamForm',
- 'configurationGoogleForm',
- 'configurationLdapForm',
- 'configurationLdap1Form',
- 'configurationLdap2Form',
- 'configurationLdap3Form',
- 'configurationLdap4Form',
- 'configurationLdap5Form',
- 'configurationRadiusForm',
- 'configurationTacacsForm',
- 'configurationSamlForm',
- 'systemActivityStreamForm',
- 'systemLoggingForm',
- 'systemMiscForm',
- 'ConfigurationJobsForm',
- 'ConfigurationUiForm',
- 'ngToast',
- function(
- $scope, $rootScope, $state, $stateParams, $q,
- SettingsService, SettingsUtils, CreateDialog, i18n, ProcessErrors, Store,
- Wait, configDataResolve, ToJSON, ConfigService,
- //Form definitions
- configurationAzureForm,
- configurationGithubForm,
- configurationGithubOrgForm,
- configurationGithubTeamForm,
- configurationGoogleForm,
- configurationLdapForm,
- configurationLdap1Form,
- configurationLdap2Form,
- configurationLdap3Form,
- configurationLdap4Form,
- configurationLdap5Form,
- configurationRadiusForm,
- configurationTacacsForm,
- configurationSamlForm,
- systemActivityStreamForm,
- systemLoggingForm,
- systemMiscForm,
- ConfigurationJobsForm,
- ConfigurationUiForm,
- ngToast
- ) {
- const vm = this;
-
- vm.product = defaultStrings.BRAND_NAME;
- vm.activeTab = $stateParams.form;
-
- const formDefs = {
- 'azure': configurationAzureForm,
- 'github': configurationGithubForm,
- 'github_org': configurationGithubOrgForm,
- 'github_team': configurationGithubTeamForm,
- 'google_oauth': configurationGoogleForm,
- 'ldap': configurationLdapForm,
- 'ldap1': configurationLdap1Form,
- 'ldap2': configurationLdap2Form,
- 'ldap3': configurationLdap3Form,
- 'ldap4': configurationLdap4Form,
- 'ldap5': configurationLdap5Form,
- 'radius': configurationRadiusForm,
- 'tacacs': configurationTacacsForm,
- 'saml': configurationSamlForm,
- 'activity_stream': systemActivityStreamForm,
- 'logging': systemLoggingForm,
- 'misc': systemMiscForm,
- 'jobs': ConfigurationJobsForm,
- 'ui': ConfigurationUiForm
- };
-
- $scope.configDataResolve = configDataResolve;
- $scope.formDefs = formDefs;
-
- // check if it's auditor, show messageBar
- $scope.show_auditor_bar = false;
- if($rootScope.user_is_system_auditor && Store('show_auditor_bar') !== false) {
- $scope.show_auditor_bar = true;
- } else {
- $scope.show_auditor_bar = false;
- }
-
- var populateFromApi = function() {
- SettingsService.getCurrentValues()
- .then(function(data) {
- $scope.logAggregatorEnabled = data.LOG_AGGREGATOR_ENABLED;
- // these two values need to be unnested from the
- // OAUTH2_PROVIDER key
- data.ACCESS_TOKEN_EXPIRE_SECONDS = data
- .OAUTH2_PROVIDER.ACCESS_TOKEN_EXPIRE_SECONDS;
- data.REFRESH_TOKEN_EXPIRE_SECONDS = data
- .OAUTH2_PROVIDER.REFRESH_TOKEN_EXPIRE_SECONDS;
- data.AUTHORIZATION_CODE_EXPIRE_SECONDS = data
- .OAUTH2_PROVIDER.AUTHORIZATION_CODE_EXPIRE_SECONDS;
- var currentKeys = _.keys(data);
- $scope.requiredLogValues = {};
- $scope.originalSettings = data;
- _.each(currentKeys, function(key) {
- if(key === "LOG_AGGREGATOR_HOST") {
- $scope.requiredLogValues.LOG_AGGREGATOR_HOST = data[key];
- }
-
- if(key === "LOG_AGGREGATOR_TYPE") {
- $scope.requiredLogValues.LOG_AGGREGATOR_TYPE = data[key];
- }
-
- if (data[key] !== null && typeof data[key] === 'object') {
- if (Array.isArray(data[key])) {
- //handle arrays
- //having to do this particular check b/c
- // we want the options w/o a space, and
- // the ConfigurationUtils.arrayToList()
- // does a string.split(', ') w/ an extra space
- // behind the comma.
-
- const isLdap = (key.indexOf("AUTH_LDAP") !== -1);
- const isLdapUserSearch = isLdap && (key.indexOf("USER_SEARCH") !== -1);
- const isLdapGroupSearch = isLdap && (key.indexOf("GROUP_SEARCH") !== -1);
-
- if(key === "AD_HOC_COMMANDS"){
- $scope[key] = data[key];
- } else if (isLdapUserSearch || isLdapGroupSearch) {
- $scope[key] = JSON.stringify(data[key]);
- } else {
- $scope[key] = SettingsUtils.arrayToList(data[key], key);
- }
-
- } else {
- //handle nested objects
- if(SettingsUtils.isEmpty(data[key])) {
- $scope[key] = '{}';
- } else {
- $scope[key] = JSON.stringify(data[key]);
- }
- }
- } else {
- $scope[key] = data[key];
- }
- });
- $scope.$broadcast('populated', data);
- });
- };
-
- populateFromApi();
-
- var formTracker = {
- lastForm: '',
- currentForm: '',
- currentAuth: '',
- currentSystem: '',
- setCurrent: function(form) {
- this.lastForm = this.currentForm;
- this.currentForm = form;
- },
- getCurrent: function() {
- return this.currentForm;
- },
- currentFormName: function() {
- return 'configuration_' + this.currentForm + '_template_form';
- },
- setCurrentAuth: function(form) {
- this.currentAuth = form;
- this.setCurrent(this.currentAuth);
- },
- setCurrentSystem: function(form) {
- this.currentSystem = form;
- this.setCurrent(this.currentSystem);
- },
- };
-
- var triggerModal = function(msg, title, buttons) {
- if ($scope.removeModalReady) {
- $scope.removeModalReady();
- }
- $scope.removeModalReady = $scope.$on('ModalReady', function() {
- // $('#lookup-save-button').attr('disabled', 'disabled');
- $('#FormModal-dialog').dialog('open');
- });
-
- $('#FormModal-dialog').html(msg);
-
- CreateDialog({
- scope: $scope,
- buttons: buttons,
- width: 600,
- height: 200,
- minWidth: 500,
- title: title,
- id: 'FormModal-dialog',
- resizable: false,
- callback: 'ModalReady'
- });
- };
-
- function loginUpdate() {
- // Updates the logo and app config so that logos and info are properly shown
- // on logout after modifying.
- if($scope.CUSTOM_LOGO) {
- $rootScope.custom_logo = $scope.CUSTOM_LOGO;
- global.$AnsibleConfig.custom_logo = true;
- } else {
- $rootScope.custom_logo = '';
- global.$AnsibleConfig.custom_logo = false;
- }
-
- if($scope.CUSTOM_LOGIN_INFO) {
- $rootScope.custom_login_info = $scope.CUSTOM_LOGIN_INFO;
- global.$AnsibleConfig.custom_login_info = $scope.CUSTOM_LOGIN_INFO;
- } else {
- $rootScope.custom_login_info = '';
- global.$AnsibleConfig.custom_login_info = false;
- }
-
- Store('AnsibleConfig', global.$AnsibleConfig);
-
- $scope.$broadcast('loginUpdated');
- }
-
- $scope.resetValue = function(key) {
- Wait('start');
- var payload = {};
- if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'REFRESH_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') {
- // the reset for these two keys needs to be nested under OAUTH2_PROVIDER
- if (payload.OAUTH2_PROVIDER === undefined) {
- payload.OAUTH2_PROVIDER = {
- ACCESS_TOKEN_EXPIRE_SECONDS: $scope.ACCESS_TOKEN_EXPIRE_SECONDS,
- REFRESH_TOKEN_EXPIRE_SECONDS: $scope.REFRESH_TOKEN_EXPIRE_SECONDS,
- AUTHORIZATION_CODE_EXPIRE_SECONDS: $scope.AUTHORIZATION_CODE_EXPIRE_SECONDS
- };
- }
- payload.OAUTH2_PROVIDER[key] = $scope.configDataResolve[key].default;
- } else {
- payload[key] = $scope.configDataResolve[key].default;
- }
- SettingsService.patchConfiguration(payload)
- .then(function() {
- $scope[key] = $scope.configDataResolve[key].default;
-
- if(key === "LOG_AGGREGATOR_HOST" || key === "LOG_AGGREGATOR_TYPE") {
- $scope.requiredLogValues[key] = $scope.configDataResolve[key].default;
- }
-
- if($scope[key + '_field'].type === "select"){
- // We need to re-instantiate the Select2 element
- // after resetting the value. Example:
- $scope.$broadcast(key+'_populated', null, false);
- if(key === "AD_HOC_COMMANDS"){
- $scope.$broadcast(key+'_reverted', null, false);
- }
- }
- else if($scope[key + '_field'].reset === "CUSTOM_LOGO"){
- $scope.$broadcast(key+'_reverted');
- }
- else if($scope[key + '_field'].hasOwnProperty('codeMirror')){
- const isLdap = (key.indexOf("AUTH_LDAP") !== -1);
-
- const isLdapGroupTypeParams = isLdap && (key.indexOf("GROUP_TYPE_PARAMS") !== -1);
- const isLdapUserSearch = isLdap && (key.indexOf("USER_SEARCH") !== -1);
- const isLdapGroupSearch = isLdap && (key.indexOf("GROUP_SEARCH") !== -1);
-
- if (isLdapGroupTypeParams) {
- $scope[key] = JSON.stringify($scope.configDataResolve[key].default);
- } else if (isLdapUserSearch || isLdapGroupSearch) {
- $scope[key] = '[]';
- } else {
- $scope[key] = '{}';
- }
- $scope.$broadcast('codeMirror_populated', key);
- }
- loginUpdate();
- })
- .catch(function(data) {
- ProcessErrors($scope, data.error, data.status, formDefs[formTracker.getCurrent()],
- {
- hdr: `
- ${ i18n._('Error!')} `,
- msg: i18n._('There was an error resetting value. Returned status: ') + data.error.detail
- });
-
- })
- .finally(function() {
- Wait('stop');
- });
- };
-
- function clearApiErrors() {
- var currentForm = formDefs[formTracker.getCurrent()];
- for (var fld in currentForm.fields) {
- if (currentForm.fields[fld].sourceModel) {
- $scope[currentForm.fields[fld].sourceModel + '_' + currentForm.fields[fld].sourceField + '_api_error'] = '';
- $('[name="' + currentForm.fields[fld].sourceModel + '_' + currentForm.fields[fld].sourceField + '"]').removeClass('ng-invalid');
- } else if (currentForm.fields[fld].realName) {
- $scope[currentForm.fields[fld].realName + '_api_error'] = '';
- $('[name="' + currentForm.fields[fld].realName + '"]').removeClass('ng-invalid');
- } else {
- $scope[fld + '_api_error'] = '';
- $('[name="' + fld + '"]').removeClass('ng-invalid');
- }
- if (currentForm.fields[fld].codeMirror) {
- $('label[for="' + fld + '"] span').removeClass('error-color');
- $(`#cm-${fld}-container .CodeMirror`).removeClass('error-border');
- }
- }
- if (!$scope.$$phase) {
- $scope.$digest();
- }
- }
-
- // Some dropdowns are listed as "list" type in the API even though they're a dropdown:
- var multiselectDropdowns = ['AD_HOC_COMMANDS'];
-
- var getFormPayload = function() {
- var keys = _.keys(formDefs[formTracker.getCurrent()].fields);
- var payload = {};
- const errors = {};
-
- _.each(keys, function(key) {
- if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'REFRESH_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') {
- // These two values need to be POSTed nested under the OAUTH2_PROVIDER key
- if (payload.OAUTH2_PROVIDER === undefined) {
- payload.OAUTH2_PROVIDER = {
- ACCESS_TOKEN_EXPIRE_SECONDS: $scope.ACCESS_TOKEN_EXPIRE_SECONDS,
- REFRESH_TOKEN_EXPIRE_SECONDS: $scope.REFRESH_TOKEN_EXPIRE_SECONDS,
- AUTHORIZATION_CODE_EXPIRE_SECONDS: $scope.AUTHORIZATION_CODE_EXPIRE_SECONDS
- };
- }
- payload.OAUTH2_PROVIDER[key] = $scope[key];
- } else if($scope.configDataResolve[key].type === 'choice' || multiselectDropdowns.indexOf(key) !== -1) {
- //Parse dropdowns and dropdowns labeled as lists
- if($scope[key] === null) {
- payload[key] = null;
- } else if(!_.isEmpty($scope[`${key}_values`])) {
- if(multiselectDropdowns.indexOf(key) !== -1) {
- // Handle AD_HOC_COMMANDS
- payload[key] = $scope[`${key}_values`];
- } else {
- payload[key] = _.map($scope[key], 'value').join(',');
- }
- } else {
- if(multiselectDropdowns.indexOf(key) !== -1) {
- // Default AD_HOC_COMMANDS to an empty list
- payload[key] = $scope[key].value || [];
- } else {
- if ($scope[key]) {
- payload[key] = $scope[key].value;
- }
- }
- }
- } else if($scope.configDataResolve[key].type === 'list' && $scope[key] !== null) {
- // Parse lists
- try {
- payload[key] = SettingsUtils.listToArray($scope[key], key);
- } catch (error) {
- errors[key] = error;
- payload[key] = [];
- }
- }
- else if($scope.configDataResolve[key].type === 'nested object') {
- if(!$scope[key]) {
- payload[key] = {};
- } else {
- // payload[key] = JSON.parse($scope[key]);
- payload[key] = ToJSON($scope.parseType,
- $scope[key]);
- }
- }
- else {
- // Everything else
- if (key !== 'LOG_AGGREGATOR_TCP_TIMEOUT' ||
- ($scope.LOG_AGGREGATOR_PROTOCOL &&
- ($scope.LOG_AGGREGATOR_PROTOCOL.value === 'https' ||
- $scope.LOG_AGGREGATOR_PROTOCOL.value === 'tcp'))) {
- payload[key] = $scope[key];
- }
- }
- });
- return [payload, errors];
- };
-
- vm.formSave = function() {
- var saveDeferred = $q.defer();
- clearApiErrors();
- Wait('start');
-
- const [payload, errors] = getFormPayload();
- if (!SettingsUtils.isEmpty(errors)) {
- ProcessErrors($scope, errors, null, formDefs[formTracker.getCurrent()], {});
- return;
- }
-
- const [payloadCopy] = getFormPayload();
- SettingsService.patchConfiguration(payloadCopy)
- .then(function(data) {
- loginUpdate();
-
- $scope.requiredLogValues.LOG_AGGREGATOR_HOST = $scope.LOG_AGGREGATOR_HOST;
- $scope.requiredLogValues.LOG_AGGREGATOR_TYPE = $scope.LOG_AGGREGATOR_TYPE;
-
- saveDeferred.resolve(data);
- $scope[formTracker.currentFormName()].$setPristine();
- ngToast.success({
- timeout: 2000,
- dismissButton: false,
- dismissOnTimeout: true,
- content: ` ` +
- i18n._('Save Complete')
- });
- if(payload.PENDO_TRACKING_STATE && payload.PENDO_TRACKING_STATE !== $scope.originalSettings.PENDO_TRACKING_STATE) {
- // Refreshing the page will pull in the new config and
- // properly set pendo up/shut it off depending on the
- // action
- location.reload();
- }
- })
- .catch(function(data) {
- ProcessErrors($scope, data.data, data.status, formDefs[formTracker.getCurrent()],
- {
- hdr: `
- ${ i18n._('Error!')} `,
- msg: i18n._('Failed to save settings. Returned status: ') + data.status
- });
- saveDeferred.reject(data);
- })
- .finally(function() {
- Wait('stop');
- });
-
- return saveDeferred.promise;
- };
-
- vm.formCancel = function() {
- if ($scope[formTracker.currentFormName()].$dirty === true) {
- var msg = i18n._('You have unsaved changes. Would you like to proceed without saving?');
- var title = i18n._('Warning: Unsaved Changes');
- var buttons = [{
- label: i18n._("Discard changes"),
- "class": "btn Form-cancelButton",
- "id": "formmodal-cancel-button",
- onClick: function() {
- $('#FormModal-dialog').dialog('close');
- $state.go('settings');
- }
- }, {
- label: i18n._("Save changes"),
- onClick: function() {
- vm.formSave()
- .then(function() {
- $('#FormModal-dialog').dialog('close');
- $state.go('settings');
- });
- },
- "class": "btn btn-primary",
- "id": "formmodal-save-button"
- }];
- triggerModal(msg, title, buttons);
- } else {
- $state.go('settings');
- }
- };
-
- vm.resetAllConfirm = function() {
- var buttons = [{
- label: i18n._("Cancel"),
- "class": "btn btn-default",
- "id": "formmodal-cancel-button",
- onClick: function() {
- $('#FormModal-dialog').dialog('close');
- }
- }, {
- label: i18n._("Confirm Reset"),
- onClick: function() {
- resetAll();
- $('#FormModal-dialog').dialog('close');
- },
- "class": "btn btn-primary",
- "id": "formmodal-reset-button"
- }];
- var msg = i18n._('This will reset all configuration values to their factory defaults. Are you sure you want to proceed?');
- var title = i18n._('Confirm factory reset');
- triggerModal(msg, title, buttons);
- };
-
- vm.closeMessageBar = function() {
- var msg = 'Are you sure you want to hide the notification bar?';
- var title = 'Warning: Closing notification bar';
- var buttons = [{
- label: "Cancel",
- "class": "btn Form-cancelButton",
- "id": "formmodal-cancel-button",
- onClick: function() {
- $('#FormModal-dialog').dialog('close');
- }
- }, {
- label: "OK",
- onClick: function() {
- $('#FormModal-dialog').dialog('close');
- updateMessageBarPrefs();
- },
- "class": "btn btn-primary",
- "id": "formmodal-save-button"
- }];
- triggerModal(msg, title, buttons);
- };
-
- vm.getCurrentFormTitle = function() {
- switch($stateParams.form) {
- case 'auth':
- return 'AUTHENTICATION';
- case 'jobs':
- return 'JOBS';
- case 'system':
- return 'SYSTEM';
- case 'ui':
- return 'USER INTERFACE';
- case 'license':
- return 'LICENSE';
- }
- };
-
- $scope.toggleForm = function(key) {
- if($rootScope.user_is_system_auditor) {
- // Block system auditors from making changes
- event.preventDefault();
- return;
- }
-
- $scope[key] = !$scope[key];
- Wait('start');
- var payload = {};
- payload[key] = $scope[key];
- SettingsService.patchConfiguration(payload)
- .then(function(data) {
- //TODO consider updating form values with returned data here
- if (key === 'LOG_AGGREGATOR_ENABLED') {
- $scope.logAggregatorEnabled = data.LOG_AGGREGATOR_ENABLED;
- }
- })
- .catch(function(data) {
- //Change back on unsuccessful update
- $scope[key] = !$scope[key];
- ProcessErrors($scope, data.data, data.status, formDefs[formTracker.getCurrent()],
- {
- hdr: `
- ${ i18n._('Error!')} `,
- msg: i18n._('Failed to save toggle settings. Returned status: ') + data.status
- });
- })
- .finally(function() {
- Wait('stop');
- });
- };
-
- function resetAll () {
- var keys = _.keys(formDefs[formTracker.getCurrent()].fields);
- var payload = {};
- clearApiErrors();
- _.each(keys, function(key) {
- if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'REFRESH_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') {
- // the reset for these two keys needs to be nested under OAUTH2_PROVIDER
- if (payload.OAUTH2_PROVIDER === undefined) {
- payload.OAUTH2_PROVIDER = {
- ACCESS_TOKEN_EXPIRE_SECONDS: $scope.ACCESS_TOKEN_EXPIRE_SECONDS,
- REFRESH_TOKEN_EXPIRE_SECONDS: $scope.REFRESH_TOKEN_EXPIRE_SECONDS,
- AUTHORIZATION_CODE_EXPIRE_SECONDS: $scope.AUTHORIZATION_CODE_EXPIRE_SECONDS
- };
- }
- payload.OAUTH2_PROVIDER[key] = $scope.configDataResolve[key].default;
- } else {
- payload[key] = $scope.configDataResolve[key].default;
- }
- });
-
- Wait('start');
- SettingsService.patchConfiguration(payload)
- .then(function() {
- populateFromApi();
- $scope[formTracker.currentFormName()].$setPristine();
-
- let keys = _.keys(formDefs[formTracker.getCurrent()].fields);
- _.each(keys, function(key) {
- $scope[key] = $scope.configDataResolve[key].default;
- if($scope[key + '_field'].type === "select"){
- // We need to re-instantiate the Select2 element
- // after resetting the value. Example:
- $scope.$broadcast(key+'_populated', null, false);
- if(key === "AD_HOC_COMMANDS"){
- $scope.$broadcast(key+'_reverted', null, false);
- }
- }
- else if($scope[key + '_field'].reset === "CUSTOM_LOGO"){
- $scope.$broadcast(key+'_reverted');
- }
- else if($scope[key + '_field'].hasOwnProperty('codeMirror')){
- $scope[key] = '{}';
- $scope.$broadcast('codeMirror_populated', key);
- }
- });
-
- })
- .catch(function(data) {
- ProcessErrors($scope, data.error, data.status, formDefs[formTracker.getCurrent()],
- {
- hdr: `
- ${ i18n._('Error!')} `,
- msg: i18n._('There was an error resetting values. Returned status: ') + data.error.detail
- });
- })
- .finally(function() {
- Wait('stop');
- });
- }
-
- function updateMessageBarPrefs () {
- $scope.show_auditor_bar = false;
- Store('show_auditor_bar', $scope.show_auditor_bar);
- }
-
- angular.extend(vm, {
- formTracker: formTracker,
- getFormPayload: getFormPayload,
- populateFromApi: populateFromApi,
- triggerModal: triggerModal,
- });
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/settings-form.partial.html b/awx/ui/client/src/configuration/forms/settings-form.partial.html
deleted file mode 100644
index da1e15fdd7..0000000000
--- a/awx/ui/client/src/configuration/forms/settings-form.partial.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
- System auditors have read-only permissions in this section.
-
-
-
-
\ No newline at end of file
diff --git a/awx/ui/client/src/configuration/forms/settings-form.route.js b/awx/ui/client/src/configuration/forms/settings-form.route.js
deleted file mode 100644
index 20ca06fd7f..0000000000
--- a/awx/ui/client/src/configuration/forms/settings-form.route.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import {templateUrl} from '../../shared/template-url/template-url.factory';
-import { N_ } from '../../i18n';
-import SettingsFormController from './settings-form.controller';
-
-// Import form controllers
-import SettingsAuthController from './auth-form/configuration-auth.controller';
-import SettingsJobsController from './jobs-form/configuration-jobs.controller';
-import SettingsSystemController from './system-form/configuration-system.controller';
-import SettingsUiController from './ui-form/configuration-ui.controller';
-
-export default {
- name: 'settings.form',
- route: '/:form',
- ncyBreadcrumb: {
- label: N_("{{ vm.getCurrentFormTitle() }}")
- },
- views: {
- '@': {
- templateUrl: templateUrl('configuration/forms/settings-form'),
- controller: SettingsFormController,
- controllerAs: 'vm'
- },
- 'auth@settings.form': {
- templateUrl: templateUrl('configuration/forms/auth-form/configuration-auth'),
- controller: SettingsAuthController,
- controllerAs: 'authVm'
- },
- 'jobs@settings.form': {
- templateUrl: templateUrl('configuration/forms/jobs-form/configuration-jobs'),
- controller: SettingsJobsController,
- controllerAs: 'jobsVm'
- },
- 'system@settings.form': {
- templateUrl: templateUrl('configuration/forms/system-form/configuration-system'),
- controller: SettingsSystemController,
- controllerAs: 'systemVm'
- },
- 'ui@settings.form': {
- templateUrl: templateUrl('configuration/forms/ui-form/configuration-ui'),
- controller: SettingsUiController,
- controllerAs: 'uiVm'
- },
- 'license@settings.form': {
- templateUrl: templateUrl('license/license'),
- controller: 'licenseController'
- },
- },
- onEnter: ['$state', 'ConfigService', '$stateParams', (state, configService, stateParams) => {
- return configService.getConfig()
- .then(config => {
- if (_.get(config, 'license_info.license_type') === 'open' && stateParams.form === 'license') {
- return state.go('settings');
- }
- });
- }],
- resolve: {
- rhCreds: ['Rest', 'GetBasePath', function(Rest, GetBasePath) {
- Rest.setUrl(`${GetBasePath('settings')}system/`);
- return Rest.get()
- .then(({data}) => {
- const rhCreds = {};
- if (data.REDHAT_USERNAME && data.REDHAT_USERNAME !== "") {
- rhCreds.REDHAT_USERNAME = data.REDHAT_USERNAME;
- }
-
- if (data.REDHAT_PASSWORD && data.REDHAT_PASSWORD !== "") {
- rhCreds.REDHAT_PASSWORD = data.REDHAT_PASSWORD;
- }
-
- return rhCreds;
- }).catch(() => {
- return {};
- });
- }]
- }
-};
\ No newline at end of file
diff --git a/awx/ui/client/src/configuration/forms/system-form/configuration-system.controller.js b/awx/ui/client/src/configuration/forms/system-form/configuration-system.controller.js
deleted file mode 100644
index 14b62e2ef9..0000000000
--- a/awx/ui/client/src/configuration/forms/system-form/configuration-system.controller.js
+++ /dev/null
@@ -1,251 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default [
- '$rootScope', '$scope', '$stateParams',
- 'systemActivityStreamForm',
- 'systemLoggingForm',
- 'systemMiscForm',
- 'SettingsUtils',
- 'CreateSelect2',
- 'GenerateForm',
- 'i18n',
- 'Rest',
- 'ProcessErrors',
- 'ngToast',
- '$filter',
- function (
- $rootScope, $scope, $stateParams,
- systemActivityStreamForm,
- systemLoggingForm,
- systemMiscForm,
- SettingsUtils,
- CreateSelect2,
- GenerateForm,
- i18n,
- Rest,
- ProcessErrors,
- ngToast,
- $filter
- ) {
- var systemVm = this;
-
- var generator = GenerateForm;
- var formTracker = $scope.$parent.vm.formTracker;
- var activeSystemForm = 'misc';
-
- if ($stateParams.form === 'system') {
- formTracker.setCurrentSystem(activeSystemForm);
- }
-
- var activeForm = function (tab) {
- if (!_.get($scope.$parent, [formTracker.currentFormName(), '$dirty'])) {
- systemVm.activeSystemForm = tab;
- formTracker.setCurrentSystem(systemVm.activeSystemForm);
- } else {
- var msg = i18n._('You have unsaved changes. Would you like to proceed without saving?');
- var title = i18n._('Warning: Unsaved Changes');
- var buttons = [{
- label: i18n._('Discard changes'),
- "class": "btn Form-cancelButton",
- "id": "formmodal-cancel-button",
- onClick: function () {
- $scope.$parent.vm.populateFromApi();
- $scope.$parent[formTracker.currentFormName()].$setPristine();
- systemVm.activeSystemForm = tab;
- formTracker.setCurrentSystem(systemVm.activeSystemForm);
- $('#FormModal-dialog').dialog('close');
- }
- }, {
- label: i18n._('Save changes'),
- onClick: function () {
- $scope.$parent.vm.formSave()
- .then(function () {
- $scope.$parent[formTracker.currentFormName()].$setPristine();
- $scope.$parent.vm.populateFromApi();
- systemVm.activeSystemForm = tab;
- formTracker.setCurrentSystem(systemVm.activeSystemForm);
- $('#FormModal-dialog').dialog('close');
- });
- },
- "class": "btn btn-primary",
- "id": "formmodal-save-button"
- }];
- $scope.$parent.vm.triggerModal(msg, title, buttons);
- }
- formTracker.setCurrentSystem(systemVm.activeSystemForm);
- };
-
- var dropdownOptions = [
- { label: i18n._('Misc. System'), value: 'misc' },
- { label: i18n._('Activity Stream'), value: 'activity_stream' },
- { label: i18n._('Logging'), value: 'logging' },
- ];
-
- var systemForms = [{
- formDef: systemLoggingForm,
- id: 'system-logging-form'
- }, {
- formDef: systemActivityStreamForm,
- id: 'system-activity-stream-form'
- }, {
- formDef: systemMiscForm,
- id: 'system-misc-form'
- }];
-
- var forms = _.map(systemForms, 'formDef');
- _.each(forms, function (form) {
- var keys = _.keys(form.fields);
- _.each(keys, function (key) {
- if ($scope.configDataResolve[key].type === 'choice') {
- // Create options for dropdowns
- var optionsGroup = key + '_options';
- $scope.$parent.$parent[optionsGroup] = [];
- _.each($scope.configDataResolve[key].choices, function (choice) {
- $scope.$parent.$parent[optionsGroup].push({
- name: choice[0],
- label: choice[1],
- value: choice[0]
- });
- });
- }
- addFieldInfo(form, key);
- });
- // Disable the save button for system auditors
- form.buttons.save.disabled = $rootScope.user_is_system_auditor;
- });
-
- function addFieldInfo(form, key) {
- _.extend(form.fields[key], {
- awPopOver: ($scope.configDataResolve[key].defined_in_file) ?
- null : $scope.configDataResolve[key].help_text,
- label: $scope.configDataResolve[key].label,
- name: key,
- toggleSource: key,
- dataPlacement: 'top',
- placeholder: SettingsUtils.formatPlaceholder($scope.configDataResolve[key].placeholder, key) || null,
- dataTitle: $scope.configDataResolve[key].label,
- required: $scope.configDataResolve[key].required,
- ngDisabled: $rootScope.user_is_system_auditor,
- disabled: $scope.configDataResolve[key].disabled || null,
- readonly: $scope.configDataResolve[key].readonly || null,
- definedInFile: $scope.configDataResolve[key].defined_in_file || null
- });
- }
-
- $scope.$parent.$parent.parseType = 'json';
-
- _.each(systemForms, function (form) {
- generator.inject(form.formDef, {
- id: form.id,
- mode: 'edit',
- scope: $scope.$parent.$parent,
- related: true,
- noPanel: true
- });
- });
-
- var dropdownRendered = false;
-
- $scope.$on('populated', function () {
- populateLogAggregator(false);
- });
-
- $scope.$on('LOG_AGGREGATOR_TYPE_populated', function (e, data, flag) {
- populateLogAggregator(flag);
- });
-
- $scope.$on('LOG_AGGREGATOR_PROTOCOL_populated', function (e, data, flag) {
- populateLogAggregator(flag);
- });
-
- function populateLogAggregator(flag) {
-
- if ($scope.$parent.$parent.LOG_AGGREGATOR_TYPE !== null) {
- $scope.$parent.$parent.LOG_AGGREGATOR_TYPE = _.find($scope.$parent.$parent.LOG_AGGREGATOR_TYPE_options, { value: $scope.$parent.$parent.LOG_AGGREGATOR_TYPE });
- }
-
- if ($scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL !== null) {
- $scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL = _.find($scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL_options, { value: $scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL });
- }
-
- if ($scope.$parent.$parent.LOG_AGGREGATOR_LEVEL !== null) {
- $scope.$parent.$parent.LOG_AGGREGATOR_LEVEL = _.find($scope.$parent.$parent.LOG_AGGREGATOR_LEVEL_options, { value: $scope.$parent.$parent.LOG_AGGREGATOR_LEVEL });
- }
-
- if (flag !== undefined) {
- dropdownRendered = flag;
- }
-
- if (!dropdownRendered) {
- dropdownRendered = true;
- CreateSelect2({
- element: '#configuration_logging_template_LOG_AGGREGATOR_TYPE',
- multiple: false,
- placeholder: i18n._('Select types'),
- });
- $scope.$parent.$parent.configuration_logging_template_form.LOG_AGGREGATOR_TYPE.$setPristine();
- $scope.$parent.$parent.configuration_logging_template_form.LOG_AGGREGATOR_PROTOCOL.$setPristine();
- $scope.$parent.$parent.configuration_logging_template_form.LOG_AGGREGATOR_LEVEL.$setPristine();
- }
- }
-
- $scope.$watchGroup(['configuration_logging_template_form.$pending', 'configuration_logging_template_form.$dirty', '!logAggregatorEnabled'], (vals) => {
- if (vals.some(val => val === true)) {
- $scope.$parent.vm.disableTestButton = true;
- $scope.$parent.vm.testTooltip = i18n._('Save and enable log aggregation before testing the log aggregator.');
- } else {
- $scope.$parent.vm.disableTestButton = false;
- $scope.$parent.vm.testTooltip = i18n._('Send a test log message to the configured log aggregator.');
- }
- });
-
- $scope.$parent.vm.testLogging = function () {
- if (!$scope.$parent.vm.disableTestButton) {
- $scope.$parent.vm.disableTestButton = true;
- Rest.setUrl("/api/v2/settings/logging/test/");
- Rest.post({})
- .then(() => {
- $scope.$parent.vm.disableTestButton = false;
- ngToast.success({
- dismissButton: false,
- dismissOnTimeout: true,
- content: ` ` +
- i18n._('Log aggregator test sent successfully.')
- });
- })
- .catch(({ data, status }) => {
- $scope.$parent.vm.disableTestButton = false;
- if (status === 400 || status === 500) {
- ngToast.danger({
- dismissButton: false,
- dismissOnTimeout: true,
- content: ' ' +
- i18n._('Log aggregator test failed. Detail: ') + $filter('sanitize')(data.error),
- additionalClasses: "LogAggregator-failedNotification"
- });
- } else {
- ProcessErrors($scope, data, status, null,
- {
- hdr: i18n._('Error!'),
- msg: i18n._('There was an error testing the ' +
- 'log aggregator. Returned status: ') +
- status
- });
- }
- });
- }
- };
-
- angular.extend(systemVm, {
- activeForm: activeForm,
- activeSystemForm: activeSystemForm,
- dropdownOptions: dropdownOptions,
- systemForms: systemForms
- });
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/system-form/configuration-system.partial.html b/awx/ui/client/src/configuration/forms/system-form/configuration-system.partial.html
deleted file mode 100644
index c95aadf831..0000000000
--- a/awx/ui/client/src/configuration/forms/system-form/configuration-system.partial.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
diff --git a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-activity-stream.form.js b/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-activity-stream.form.js
deleted file mode 100644
index 2cc39299ef..0000000000
--- a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-activity-stream.form.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default ['i18n', function(i18n) {
- return {
- name: 'configuration_activity_stream_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- ACTIVITY_STREAM_ENABLED: {
- type: 'toggleSwitch',
- },
- ACTIVITY_STREAM_ENABLED_FOR_INVENTORY_SYNC: {
- type: 'toggleSwitch'
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-logging.form.js b/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-logging.form.js
deleted file mode 100644
index 9febbc4363..0000000000
--- a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-logging.form.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default ['i18n', function(i18n) {
- return {
- name: 'configuration_logging_template',
- showActions: true,
- showHeader: false,
-
- fields: {
- LOG_AGGREGATOR_HOST: {
- type: 'text',
- reset: 'LOG_AGGREGATOR_HOST'
- },
- LOG_AGGREGATOR_PORT: {
- type: 'text',
- reset: 'LOG_AGGREGATOR_PORT'
- },
- LOG_AGGREGATOR_TYPE: {
- type: 'select',
- reset: 'LOG_AGGREGATOR_TYPE',
- ngOptions: 'type.label for type in LOG_AGGREGATOR_TYPE_options track by type.value',
- },
- LOG_AGGREGATOR_USERNAME: {
- type: 'text',
- reset: 'LOG_AGGREGATOR_USERNAME'
- },
- LOG_AGGREGATOR_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'LOG_AGGREGATOR_PASSWORD'
- },
- LOG_AGGREGATOR_LOGGERS: {
- type: 'textarea',
- reset: 'LOG_AGGREGATOR_LOGGERS'
- },
- LOG_AGGREGATOR_INDIVIDUAL_FACTS: {
- type: 'toggleSwitch',
- },
- LOG_AGGREGATOR_PROTOCOL: {
- type: 'select',
- reset: 'LOG_AGGREGATOR_PROTOCOL',
- ngOptions: 'type.label for type in LOG_AGGREGATOR_PROTOCOL_options track by type.value',
- disableChooseOption: true
- },
- LOG_AGGREGATOR_TCP_TIMEOUT: {
- type: 'text',
- reset: 'LOG_AGGREGATOR_TCP_TIMEOUT',
- ngShow: 'LOG_AGGREGATOR_PROTOCOL.value === "tcp" || LOG_AGGREGATOR_PROTOCOL.value === "https"',
- awRequiredWhen: {
- reqExpression: "LOG_AGGREGATOR_PROTOCOL.value === 'tcp' || LOG_AGGREGATOR_PROTOCOL.value === 'https'",
- init: "false"
- },
- },
- LOG_AGGREGATOR_LEVEL: {
- type: 'select',
- reset: 'LOG_AGGREGATOR_LEVEL',
- ngOptions: 'type.label for type in LOG_AGGREGATOR_LEVEL_options track by type.value',
- disableChooseOption: true
- },
- LOG_AGGREGATOR_VERIFY_CERT: {
- type: 'toggleSwitch',
- ngShow: "LOG_AGGREGATOR_PROTOCOL.value === 'https'"
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- testLogging: {
- ngClass: "{'Form-button--disabled': vm.disableTestButton}",
- ngClick: 'vm.testLogging()',
- label: i18n._('Test'),
- class: 'Form-primaryButton',
- awToolTip: '{{vm.testTooltip}}',
- dataTipWatch: 'vm.testTooltip',
- dataPlacement: 'top',
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
- }
-];
diff --git a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js b/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js
deleted file mode 100644
index 911e9c26ba..0000000000
--- a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'configuration_misc_template',
- showHeader: false,
- showActions: true,
-
- fields: {
- TOWER_URL_BASE: {
- type: 'text',
- reset: 'TOWER_URL_BASE',
- },
- ORG_ADMINS_CAN_SEE_ALL_USERS: {
- type: 'toggleSwitch',
- },
- MANAGE_ORGANIZATION_AUTH: {
- type: 'toggleSwitch',
- },
- SESSION_COOKIE_AGE: {
- type: 'number',
- integer: true,
- min: 61,
- reset: 'SESSION_COOKIE_AGE',
- },
- SESSIONS_PER_USER: {
- type: 'number',
- integer: true,
- spinner: true,
- min: -1,
- reset: 'SESSIONS_PER_USER',
- },
- AUTH_BASIC_ENABLED: {
- type: 'toggleSwitch',
- },
- ALLOW_OAUTH2_FOR_EXTERNAL_USERS: {
- type: 'toggleSwitch',
- },
- LOGIN_REDIRECT_OVERRIDE: {
- type: 'text',
- reset: 'LOGIN_REDIRECT_OVERRIDE'
- },
- ACCESS_TOKEN_EXPIRE_SECONDS: {
- type: 'text',
- reset: 'ACCESS_TOKEN_EXPIRE_SECONDS'
- },
- REFRESH_TOKEN_EXPIRE_SECONDS: {
- type: 'text',
- reset: 'REFRESH_TOKEN_EXPIRE_SECONDS'
- },
- AUTHORIZATION_CODE_EXPIRE_SECONDS: {
- type: 'text',
- reset: 'AUTHORIZATION_CODE_EXPIRE_SECONDS'
- },
- REMOTE_HOST_HEADERS: {
- type: 'textarea',
- reset: 'REMOTE_HOST_HEADERS'
- },
- CUSTOM_VENV_PATHS: {
- type: 'textarea',
- reset: 'CUSTOM_VENV_PATHS'
- },
- INSIGHTS_TRACKING_STATE: {
- type: 'toggleSwitch'
- },
- REDHAT_USERNAME: {
- type: 'text',
- reset: 'REDHAT_USERNAME',
- },
- REDHAT_PASSWORD: {
- type: 'sensitive',
- hasShowInputButton: true,
- reset: 'REDHAT_PASSWORD',
- },
- AUTOMATION_ANALYTICS_URL: {
- type: 'text',
- reset: 'AUTOMATION_ANALYTICS_URL',
- },
- AUTOMATION_ANALYTICS_GATHER_INTERVAL: {
- type: 'number',
- integer: true,
- min: 1800,
- reset: 'AUTOMATION_ANALYTICS_GATHER_INTERVAL',
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.controller.js b/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.controller.js
deleted file mode 100644
index f35e8b6090..0000000000
--- a/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.controller.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default [
- '$scope',
- '$rootScope',
- 'ConfigurationUiForm',
- 'CreateSelect2',
- 'GenerateForm',
- 'i18n',
- '$stateParams',
- function(
- $scope,
- $rootScope,
- ConfigurationUiForm,
- CreateSelect2,
- GenerateForm,
- i18n,
- $stateParams
- ) {
- var generator = GenerateForm;
- var form = ConfigurationUiForm;
-
- const formTracker = $scope.$parent.vm.formTracker;
- if ($stateParams.form === 'ui') {
- formTracker.setCurrentAuth('ui');
- }
-
- var keys = _.keys(form.fields);
- _.each(keys, function(key) {
- if($scope.configDataResolve[key].type === 'choice') {
- // Create options for dropdowns
- var optionsGroup = key + '_options';
- $scope.$parent.$parent[optionsGroup] = [];
- _.each($scope.configDataResolve[key].choices, function(choice){
- $scope.$parent.$parent[optionsGroup].push({
- name: choice[0],
- label: choice[1],
- value: choice[0]
- });
- });
- }
- addFieldInfo(form, key);
- });
-
- // Disable the save button for system auditors
- form.buttons.save.disabled = $rootScope.user_is_system_auditor;
-
- function addFieldInfo(form, key) {
- _.extend(form.fields[key], {
- awPopOver: ($scope.configDataResolve[key].defined_in_file) ?
- null: $scope.configDataResolve[key].help_text,
- label: $scope.configDataResolve[key].label,
- name: key,
- toggleSource: key,
- dataPlacement: 'top',
- dataTitle: $scope.configDataResolve[key].label,
- required: $scope.configDataResolve[key].required,
- ngDisabled: $rootScope.user_is_system_auditor,
- disabled: $scope.configDataResolve[key].disabled || null,
- readonly: $scope.configDataResolve[key].readonly || null,
- definedInFile: $scope.configDataResolve[key].defined_in_file || null
- });
- }
-
- generator.inject(form, {
- id: 'configure-ui-form',
- mode: 'edit',
- scope: $scope.$parent.$parent,
- related: true,
- noPanel: true
- });
-
- // Flag to avoid re-rendering and breaking Select2 dropdowns on tab switching
- var dropdownRendered = false;
-
- function populatePendoTrackingState(flag){
- if($scope.$parent.$parent.PENDO_TRACKING_STATE !== null) {
- $scope.$parent.$parent.PENDO_TRACKING_STATE = _.find($scope.$parent.$parent.PENDO_TRACKING_STATE_options, { value: $scope.$parent.$parent.PENDO_TRACKING_STATE });
- }
-
- if(flag !== undefined){
- dropdownRendered = flag;
- }
-
- if(!dropdownRendered) {
- dropdownRendered = true;
- CreateSelect2({
- element: '#configuration_ui_template_PENDO_TRACKING_STATE',
- multiple: false,
- placeholder: i18n._('Select commands')
- });
- }
- }
-
- $scope.$on('PENDO_TRACKING_STATE_populated', function(e, data, flag) {
- populatePendoTrackingState(flag);
- });
-
- $scope.$on('populated', function(){
- populatePendoTrackingState(false);
- });
- }
- ];
diff --git a/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.form.js b/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.form.js
deleted file mode 100644
index 4bb9fd3401..0000000000
--- a/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.form.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- showHeader: false,
- name: 'configuration_ui_template',
- showActions: true,
-
- fields: {
- PENDO_TRACKING_STATE: {
- type: 'select',
- ngChange: 'changedPendo()',
- ngOptions: 'choice.label for choice in PENDO_TRACKING_STATE_options track by choice.value',
- reset: 'PENDO_TRACKING_STATE'
- },
- CUSTOM_LOGO: {
- type: 'custom',
- reset: 'CUSTOM_LOGO',
- control: ` `
- },
- CUSTOM_LOGIN_INFO: {
- type: 'textarea',
- reset: 'CUSTOM_LOGIN_INFO',
- rows: 6
- }
- },
-
- buttons: {
- reset: {
- ngShow: '!user_is_system_auditor',
- ngClick: 'vm.resetAllConfirm()',
- label: i18n._('Revert all to default'),
- class: 'Form-resetAll'
- },
- cancel: {
- ngClick: 'vm.formCancel()',
- },
- save: {
- ngClick: 'vm.formSave()',
- ngDisabled: true
- }
- }
- };
-}
-];
diff --git a/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.partial.html b/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.partial.html
deleted file mode 100644
index 82ab146e93..0000000000
--- a/awx/ui/client/src/configuration/forms/ui-form/configuration-ui.partial.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
diff --git a/awx/ui/client/src/configuration/main.js b/awx/ui/client/src/configuration/main.js
deleted file mode 100644
index 809f3312fd..0000000000
--- a/awx/ui/client/src/configuration/main.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import settingsService from './settings.service';
-import settingsUtils from './settingsUtils.service';
-
-// Import forms
-//authorization sub-forms
-import configurationAzureForm from './forms/auth-form/sub-forms/auth-azure.form.js';
-import configurationGithubForm from './forms/auth-form/sub-forms/auth-github.form.js';
-import configurationGithubOrgForm from './forms/auth-form/sub-forms/auth-github-org.form';
-import configurationGithubTeamForm from './forms/auth-form/sub-forms/auth-github-team.form';
-import configurationGoogleForm from './forms/auth-form/sub-forms/auth-google-oauth2.form';
-import configurationLdapForm from './forms/auth-form/sub-forms/auth-ldap.form.js';
-import configurationLdap1Form from './forms/auth-form/sub-forms/auth-ldap1.form.js';
-import configurationLdap2Form from './forms/auth-form/sub-forms/auth-ldap2.form.js';
-import configurationLdap3Form from './forms/auth-form/sub-forms/auth-ldap3.form.js';
-import configurationLdap4Form from './forms/auth-form/sub-forms/auth-ldap4.form.js';
-import configurationLdap5Form from './forms/auth-form/sub-forms/auth-ldap5.form.js';
-import configurationRadiusForm from './forms/auth-form/sub-forms/auth-radius.form.js';
-import configurationTacacsForm from './forms/auth-form/sub-forms/auth-tacacs.form.js';
-import configurationSamlForm from './forms/auth-form/sub-forms/auth-saml.form';
-
-//system sub-forms
-import systemActivityStreamForm from './forms/system-form/sub-forms/system-activity-stream.form.js';
-import systemLoggingForm from './forms/system-form/sub-forms/system-logging.form.js';
-import systemMiscForm from './forms/system-form/sub-forms/system-misc.form.js';
-
-import configurationJobsForm from './forms/jobs-form/configuration-jobs.form';
-import configurationUiForm from './forms/ui-form/configuration-ui.form';
-
-// Wrapper form route
-import settingsFormRoute from './forms/settings-form.route';
-
-import settingsRoute from './settings.route';
-import settingsController from './settings.controller.js';
-
-export default
-angular.module('configuration', [])
- .controller('SettingsController', settingsController)
- //auth forms
- .factory('configurationAzureForm', configurationAzureForm)
- .factory('configurationGithubForm', configurationGithubForm)
- .factory('configurationGithubOrgForm', configurationGithubOrgForm)
- .factory('configurationGithubTeamForm', configurationGithubTeamForm)
- .factory('configurationGoogleForm', configurationGoogleForm)
- .factory('configurationLdapForm', configurationLdapForm)
- .factory('configurationLdap1Form', configurationLdap1Form)
- .factory('configurationLdap2Form', configurationLdap2Form)
- .factory('configurationLdap3Form', configurationLdap3Form)
- .factory('configurationLdap4Form', configurationLdap4Form)
- .factory('configurationLdap5Form', configurationLdap5Form)
- .factory('configurationRadiusForm', configurationRadiusForm)
- .factory('configurationTacacsForm', configurationTacacsForm)
- .factory('configurationSamlForm', configurationSamlForm)
- //system forms
- .factory('systemActivityStreamForm', systemActivityStreamForm)
- .factory('systemLoggingForm', systemLoggingForm)
- .factory('systemMiscForm', systemMiscForm)
-
- //other forms
- .factory('ConfigurationJobsForm', configurationJobsForm)
- .factory('ConfigurationUiForm', configurationUiForm)
-
- //helpers and services
- .factory('SettingsUtils', settingsUtils)
- .service('SettingsService', settingsService)
- .run(['$stateExtender', function($stateExtender) {
- $stateExtender.addState(settingsFormRoute);
- $stateExtender.addState(settingsRoute);
- }]);
diff --git a/awx/ui/client/src/configuration/settings.block.less b/awx/ui/client/src/configuration/settings.block.less
deleted file mode 100644
index 33cafba674..0000000000
--- a/awx/ui/client/src/configuration/settings.block.less
+++ /dev/null
@@ -1,195 +0,0 @@
-.Form-resetValue, .Form-resetAll {
- text-transform: uppercase;
- font-weight: normal;
- cursor: pointer;
- font-size: 10px;
-}
-
-.Form-resetValue {
- float: right;
-}
-
-.Form-resetAll {
- border: none;
- padding: 0;
- background-color: @white;
- margin-right: auto;
- color: @default-link;
-
- &:hover {
- color: @default-link-hov;
- }
-}
-
-.Form-tab {
- min-width: 77px;
-}
-
-.Form-button--left {
- margin-right: auto;
- margin-left: 0;
-}
-
-.Form-nav--dropdownContainer {
- align-items: center;
- width: 100%;
- margin: 0 0 22px auto;
- display: flex;
- justify-content: flex-start;
- border-bottom: 1px solid @at-gray-b7;
- padding-bottom: 22px;
-}
-
-.Form-nav--ldapDropdownContainer {
- align-items: center;
- width: 100%;
- margin: 0 0 auto auto;
- display: flex;
-}
-
-.Form-nav--dropdown {
- width: 285px;
-}
-
-.Form-nav--dropdown .select2-container {
- margin: 0;
-}
-
-.Form-nav--dropdownLabel {
- text-transform: uppercase;
- color: @default-interface-txt;
- font-size: 14px;
- font-weight: bold;
- padding-right: 15px;
-}
-
-.Form-tabRow {
- display: flex;
-}
-
-input.Form-filePicker {
- width: 0.1px;
- height: 0.1px;
- opacity: 0;
- overflow: hidden;
- position: absolute;
- z-index: -1;
-}
-label#filePickerButton {
- cursor: pointer;
- background-color: #fff;
- color: @default-interface-txt;
- margin-bottom: 0;
-}
-input#filePickerText {
- cursor: default;
- border-radius: 0 5px 5px 0;
- background-color: #fff;
-}
-
-.Form-filePicker--selectedFile {
- margin: 12px 0;
-}
-
-.Form-filePicker--thumbnail {
- max-height: 40px;
- max-width: 40px;
-}
-
-// Messagebar for system auditor role notifications
-.Section-messageBar {
- width: 120%;
- margin-left: -20px;
- padding: 10px 10px 10px 20px;
- color: @white;
- background-color: @default-link;
-}
-
-.Section-messageBar-text {
- margin-left: @at-space-2x;
-}
-
-.Section-messageBar-warning {
- color: @at-color-warning;
-}
-
-.Section-messageBar--close {
- position: absolute;
- right: 0;
- background: none;
- border: none;
- color: @info-close;
-}
-
-.Section-messageBar--close:hover {
- color: @white;
-}
-
-//Needed to show the not-allowed cursor over a Codemirror instance
-.Form-formGroup--disabled {
- cursor: not-allowed;
- position: relative;
- display: inline-block;
-
- // Filepicker disabling
- .Form-browseButton, .Form-filePicker--textBox {
- pointer-events: none;
- cursor: not-allowed;
- }
-
- // Adding explanatory tooltips for disabled fields
- // Borrows styling from .popover
- .Form-tooltip--disabled {
- visibility: hidden;
- background-color: @default-interface-txt;
- color: @default-bg;
- text-align: center;
- border-radius: 6px;
-
- position: absolute;
- z-index: 1;
- width: 200px;
- bottom: 110%;
- left: 50%;
- margin-left: -100px;
-
- background-clip: padding-box;
- border: 1px solid rgba(0,0,0,.2);
- -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
- box-shadow: 0 5px 10px rgba(0,0,0,.2);
- white-space: normal;
-
- padding: 9px 14px;
- font-size: 12px;
- font-weight: bold;
- }
-
- &:hover .Form-tooltip--disabled {
- visibility: visible;
- }
-
- .Form-tooltip--disabled::after {
- content: " ";
- position: absolute;
- top: 100%;
- left: 50%;
- margin-left: -11px;
- border-width: 11px;
- border-style: solid;
- border-color: @default-interface-txt transparent transparent transparent;
- }
-}
-
-.LogAggregator-failedNotification{
- max-width: 500px;
- word-break: break-word;
-}
-
-hr {
- height: 1px;
-}
-
-.ConfigureTower-errorIcon{
- margin-right:5px;
- color:@red;
-}
diff --git a/awx/ui/client/src/configuration/settings.controller.js b/awx/ui/client/src/configuration/settings.controller.js
deleted file mode 100644
index 88ea0745cd..0000000000
--- a/awx/ui/client/src/configuration/settings.controller.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import defaultStrings from '~assets/default.strings.json';
-
-export default [ '$state',
- function ($state) {
- const vm = this;
-
- vm.product = defaultStrings.BRAND_NAME;
-
- vm.goToCard = (card) => {
- $state.go('settings.form', { form: card });
- };
- }
-];
diff --git a/awx/ui/client/src/configuration/settings.partial.html b/awx/ui/client/src/configuration/settings.partial.html
deleted file mode 100644
index ebfb5b5eb0..0000000000
--- a/awx/ui/client/src/configuration/settings.partial.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- Enable simplified login for your Tower applications
-
-
- Update settings pertaining to Jobs within Tower
-
-
- Define system-level features and functions
-
-
- Set preferences for data collection, logos, and logins
-
-
- View and edit your license information
-
-
\ No newline at end of file
diff --git a/awx/ui/client/src/configuration/settings.route.js b/awx/ui/client/src/configuration/settings.route.js
deleted file mode 100644
index e975a5f6ba..0000000000
--- a/awx/ui/client/src/configuration/settings.route.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { N_ } from '../i18n';
-import {templateUrl} from '../shared/template-url/template-url.factory';
-import SettingsController from './settings.controller';
-// Import form controllers
-
-export default {
- name: 'settings',
- route: '/settings',
- ncyBreadcrumb: {
- label: N_("SETTINGS")
- },
- resolve: {
- configDataResolve: ['SettingsService', function(SettingsService){
- return SettingsService.getConfigurationOptions();
- }],
- features: ['CheckLicense', '$rootScope',
- function(CheckLicense, $rootScope) {
- if($rootScope.licenseMissing === undefined){
- return CheckLicense.notify();
- }
-
- }],
- config: ['ConfigService', 'CheckLicense', '$rootScope',
- function(ConfigService, CheckLicense, $rootScope) {
- ConfigService.delete();
- return ConfigService.getConfig()
- .then(function(config){
- $rootScope.licenseMissing = (CheckLicense.valid(config.license_info) === false) ? true : false;
- return config;
- });
- }],
- },
- views: {
- '': {
- templateUrl: templateUrl('configuration/settings'),
- controller: SettingsController,
- controllerAs: 'vm'
- }
- }
-};
\ No newline at end of file
diff --git a/awx/ui/client/src/configuration/settings.service.js b/awx/ui/client/src/configuration/settings.service.js
deleted file mode 100644
index 0c74a4fe9f..0000000000
--- a/awx/ui/client/src/configuration/settings.service.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['GetBasePath', '$q', 'Rest', 'i18n',
- function(GetBasePath, $q, Rest, i18n) {
- var url = GetBasePath('settings') + 'all';
-
- return {
- getConfigurationOptions: function() {
- var deferred = $q.defer();
- var returnData = {};
-
- Rest.setUrl(url);
- Rest.options()
- .then(({data}) => {
- // Compare GET actions with PUT actions and flag discrepancies
- // for disabling in the UI
- //
- // since OAUTH2_PROVIDER returns two of the keys in a nested format,
- // we need to split those out into the root of the options payload
- // in order for them to be consumed
- var appendOauth2ProviderKeys = (optsFromAPI) => {
- var unnestOauth2ProviderKey = (key, help_text, label, parentKey) => {
- optsFromAPI[key] = _.cloneDeep(optsFromAPI[parentKey]);
- optsFromAPI[key].label = label;
- optsFromAPI[key].help_text = help_text;
- optsFromAPI[key].type = optsFromAPI[parentKey].child.type;
- optsFromAPI[key].min_value = optsFromAPI[parentKey].child.min_value;
- if (optsFromAPI[parentKey].default) {
- optsFromAPI[key].default = optsFromAPI[parentKey].default[key];
- }
- delete optsFromAPI[key].child;
- };
- if (optsFromAPI.OAUTH2_PROVIDER) {
- unnestOauth2ProviderKey('ACCESS_TOKEN_EXPIRE_SECONDS',
- i18n._('The duration (in seconds) access tokens remain valid since their creation.'),
- i18n._('Access Token Expiration'),
- 'OAUTH2_PROVIDER');
- unnestOauth2ProviderKey('REFRESH_TOKEN_EXPIRE_SECONDS',
- i18n._('The duration (in seconds) refresh tokens remain valid after the expiration of their associated access token.'),
- i18n._('Refresh Token Expiration'),
- 'OAUTH2_PROVIDER');
- unnestOauth2ProviderKey('AUTHORIZATION_CODE_EXPIRE_SECONDS',
- i18n._('The duration (in seconds) authorization codes remain valid since their creation.'),
- i18n._('Authorization Code Expiration'),
- 'OAUTH2_PROVIDER');
- }
- return optsFromAPI;
- };
- var getActions = appendOauth2ProviderKeys(data.actions.GET);
- var getKeys = _.keys(getActions);
- var putActions = data.actions.PUT ? appendOauth2ProviderKeys(data.actions.PUT) : {};
-
- _.each(getKeys, function(key) {
- if(putActions && putActions[key]) {
- returnData[key] = putActions[key];
- } else {
- returnData[key] = _.extend(getActions[key], {
- required: false,
- disabled: true
- });
- }
- });
-
- deferred.resolve(returnData);
- })
- .catch(({error}) => {
- deferred.reject(error);
- });
-
- return deferred.promise;
- },
-
- patchConfiguration: function(body) {
- var deferred = $q.defer();
-
- Rest.setUrl(url);
- Rest.patch(body)
- .then(({data}) => {
- deferred.resolve(data);
- })
- .catch((error) => {
- deferred.reject(error);
- });
-
- return deferred.promise;
- },
-
- getCurrentValues: function() {
- var deferred = $q.defer();
- Rest.setUrl(url);
- Rest.get()
- .then(({data}) => {
- deferred.resolve(data);
- })
- .catch((error) => {
- deferred.reject(error);
- });
-
- return deferred.promise;
- }
- };
- }
-];
diff --git a/awx/ui/client/src/configuration/settingsUtils.service.js b/awx/ui/client/src/configuration/settingsUtils.service.js
deleted file mode 100644
index bf6b354177..0000000000
--- a/awx/ui/client/src/configuration/settingsUtils.service.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['$q',
- function($q) {
-
- return {
- listToArray: function(input) {
- var payload;
-
- if (input.indexOf('[') !== -1) {
- payload = JSON.parse(input);
-
- if (!Array.isArray(payload)) {
- payload = [];
- }
- } else if (input.indexOf('\n') !== -1) {
- //Parse multiline input
- payload = input.replace(/^\s+|\s+$/g, "").split('\n');
- } else {
- if (input === '' || input === '{}') {
- payload = [];
- } else {
- payload = input.replace(/^\s+|\s+$/g, "")
- .split(/\s*,\s*/);
- }
- }
- return payload;
- },
-
- arrayToList: function(input) {
- var multiLineInput = false;
- _.each(input, function(statement) {
- if (statement.indexOf(',') !== -1) {
- multiLineInput = true;
- }
- });
- if (multiLineInput === false) {
- return input.join(', ');
- } else {
- return input.join('\n');
- }
- },
-
- isEmpty: function(map) {
- for (var key in map) {
- if (map.hasOwnProperty(key)) {
- return false;
- }
- }
- return true;
- },
-
- formatPlaceholder: function(input) {
- if (input !== null && typeof input === 'object') {
- if (Array.isArray(input)) {
- var multiLineInput = false;
- _.each(input, function(statement) {
- if (statement.indexOf(',') !== -1) {
- multiLineInput = true;
- }
- });
- if (multiLineInput === false) {
- return input.join(', ');
- } else {
- return input.join('\n');
- }
- } else {
- return JSON.stringify(input);
- }
- } else {
- return input;
- }
- },
-
- imageProcess: function(file) {
- var deferred = $q.defer();
- var SIZELIMIT = 1000000; // 1 MB
- var ACCEPTEDFORMATS = ['image/png', 'image/gif', 'image/jpeg']; //Basic check
-
- if(file.size < SIZELIMIT && ACCEPTEDFORMATS.indexOf(file.type) !== -1) {
- var reader = new FileReader();
- reader.readAsDataURL(file);
- reader.onload = function () {
- deferred.resolve(reader.result);
- };
- reader.onerror = function () {
- deferred.reject('File could not be parsed');
- };
- } else {
- var error = 'Error: ';
- if(file.size > SIZELIMIT) {
- error += 'Must be under ' + SIZELIMIT / 1000000 + 'MB. ';
- }
- if(ACCEPTEDFORMATS.indexOf(file.type) === -1) {
- error += 'Wrong file type - must be png, gif, or jpg.';
- }
- deferred.reject(error);
- }
- return deferred.promise;
- }
-
- };
- }
-];
diff --git a/awx/ui/client/src/credential-types/add/add.controller.js b/awx/ui/client/src/credential-types/add/add.controller.js
deleted file mode 100644
index 2d44414962..0000000000
--- a/awx/ui/client/src/credential-types/add/add.controller.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['Rest', 'Wait',
- 'CredentialTypesForm', 'ProcessErrors', 'GetBasePath',
- 'GenerateForm', '$scope', '$state', 'Alert', 'GetChoices', 'ParseTypeChange', 'ToJSON', 'CreateSelect2', 'i18n',
- function(Rest, Wait,
- CredentialTypesForm, ProcessErrors, GetBasePath,
- GenerateForm, $scope, $state, Alert, GetChoices, ParseTypeChange, ToJSON, CreateSelect2, i18n
- ) {
- var form = CredentialTypesForm,
- url = GetBasePath('credential_types');
-
- init();
-
- function init() {
-
- // for add, don't show ssh
- $scope.$on('loadCredentialKindOptions', function() {
- $scope.credential_kind_options = $scope.credential_kind_options
- .filter(val => val.value === 'net' ||
- val.value === 'cloud');
- });
-
- // Load the list of options for Kind
- $scope.$parent.optionsDefer.promise
- .then(function(options) {
- GetChoices({
- scope: $scope,
- url: url,
- field: 'kind',
- variable: 'credential_kind_options',
- options: options,
- callback: 'loadCredentialKindOptions'
- });
-
- const docs_url = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/credential_types.html#getting-started-with-credential-types';
- const docs_help_text = `${i18n._('Getting Started with Credential Types')} `;
-
- const api_inputs_help_text = _.get(options, 'actions.POST.inputs.help_text', "Specification for credential type inputs.");
- const api_injectors_help_text = _.get(options, 'actions.POST.injectors.help_text', "Specification for credential type injector.");
-
- $scope.inputs_help_text = api_inputs_help_text + docs_help_text;
- $scope.injectors_help_text = api_injectors_help_text + docs_help_text;
-
- if (!options.actions.POST) {
- $state.go("^");
- Alert('Permission Error', 'You do not have permission to add a credential type.', 'alert-info');
- }
- });
-
- // apply form definition's default field values
- GenerateForm.applyDefaults(form, $scope);
-
- // @issue @jmitchell - this setting probably collides with new RBAC can* implementation?
- $scope.canEdit = true;
-
- var callback = function() {
- // Make sure the form controller knows there was a change
- $scope[form.name + '_form'].$setDirty();
- };
- $scope.parseTypeInputs = 'yaml';
- $scope.parseTypeInjectors = 'yaml';
- ParseTypeChange({
- scope: $scope,
- field_id: 'credential_type_inputs',
- variable: 'inputs',
- onChange: callback,
- parse_variable: 'parseTypeInputs'
- });
- ParseTypeChange({
- scope: $scope,
- field_id: 'credential_type_injectors',
- variable: 'injectors',
- onChange: callback,
- parse_variable: 'parseTypeInjectors'
- });
-
- CreateSelect2({
- element: '#credential_type_kind',
- multiple: false,
- });
- }
-
- // Save
- $scope.formSave = function() {
- GenerateForm.clearApiErrors($scope);
- Wait('start');
- Rest.setUrl(url);
- var inputs = ToJSON($scope.parseTypeInputs, $scope.inputs);
- var injectors = ToJSON($scope.parseTypeInjectors, $scope.injectors);
- if (inputs === null) {
- inputs = {};
- }
- if (injectors === null) {
- injectors = {};
- }
- Rest.post({
- name: $scope.name,
- description: $scope.description,
- kind: "cloud",
- inputs: inputs,
- injectors: injectors
- })
- .then(({data}) => {
- $state.go('credentialTypes.edit', { credential_type_id: data.id }, { reload: true });
- Wait('stop');
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, form, {
- hdr: 'Error!',
- msg: 'Failed to add new credential type. PUT returned status: ' + status
- });
- });
- };
-
- $scope.formCancel = function() {
- $state.go('^');
- };
- }
-];
diff --git a/awx/ui/client/src/credential-types/add/main.js b/awx/ui/client/src/credential-types/add/main.js
deleted file mode 100644
index 9344da0e98..0000000000
--- a/awx/ui/client/src/credential-types/add/main.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import controller from './add.controller';
-
-export default
- angular.module('credentialTypesAdd', [])
- .controller('CredentialTypesAddController', controller);
diff --git a/awx/ui/client/src/credential-types/credential-types.form.js b/awx/ui/client/src/credential-types/credential-types.form.js
deleted file mode 100644
index 6f55465478..0000000000
--- a/awx/ui/client/src/credential-types/credential-types.form.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc function
- * @name forms.function:CredentialType
- * @description This form is for adding/editing a credential type
-*/
-
-export default ['i18n', function(i18n) {
- return {
-
- addTitle: i18n._('NEW CREDENTIAL TYPE'),
- editTitle: '{{ name }}',
- name: 'credential_type',
- basePath: 'credential_types',
- stateTree: 'credentialTypes',
- breadcrumbName: i18n._('CREDENTIAL TYPE'),
- showActions: true,
-
- // TODO: update fields to be the schema for credential types instead of inventory scripts
- fields: {
- name: {
- label: i18n._('Name'),
- type: 'text',
- ngDisabled: '!(credential_type.summary_fields.user_capabilities.edit || canAdd)',
- required: true,
- capitalize: false
- },
- description: {
- label: i18n._('Description'),
- type: 'text',
- ngDisabled: '!(credential_type.summary_fields.user_capabilities.edit || canAdd)'
- },
- inputs: {
- label: i18n._('Input Configuration'),
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- type: 'textarea',
- rows: 6,
- default: '---',
- showParseTypeToggle: true,
- parseTypeName: 'parseTypeInputs',
- awPopOverWatch: "inputs_help_text",
- dataTitle: i18n._('Input Configuration'),
- dataPlacement: 'right',
- dataContainer: "body",
- ngDisabled: '!(credential_type.summary_fields.user_capabilities.edit || canAdd)'
- },
- injectors: {
- label: i18n._('Injector Configuration'),
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- type: 'textarea',
- rows: 6,
- default: '---',
- showParseTypeToggle: true,
- parseTypeName: 'parseTypeInjectors',
- awPopOverWatch: "injectors_help_text",
- dataTitle: i18n._('Injector Configuration'),
- dataPlacement: 'right',
- dataContainer: "body",
- ngDisabled: '!(credential_type.summary_fields.user_capabilities.edit || canAdd)'
- },
- },
-
- buttons: { //for now always generates tags
- cancel: {
- ngClick: 'formCancel()',
- ngShow: '(credential_type.summary_fields.user_capabilities.edit || canAdd)'
- },
- close: {
- ngClick: 'formCancel()',
- ngShow: '!(credential_type.summary_fields.user_capabilities.edit || canAdd)'
- },
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: 'credential_type_form.$invalid', //Disable when $invalid, optional
- ngShow: '(credential_type.summary_fields.user_capabilities.edit || canAdd)'
- }
- }
- };
-}];
diff --git a/awx/ui/client/src/credential-types/credential-types.list.js b/awx/ui/client/src/credential-types/credential-types.list.js
deleted file mode 100644
index db6a1abde8..0000000000
--- a/awx/ui/client/src/credential-types/credential-types.list.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
-
-export default ['i18n', function(i18n){
- return {
- name: 'credential_types' ,
- listTitle: i18n._('CREDENTIAL TYPES'),
- basePath: 'credential_types',
- iterator: 'credential_type',
- index: false,
- hover: false,
- search: {
- managed_by_tower: 'false'
- },
-
- fields: {
- name: {
- key: true,
- label: i18n._('Name'),
- columnClass: 'col-md-4 col-sm-9 col-xs-9',
- modalColumnClass: 'col-sm-12',
- awToolTip: '{{credential_type.description | sanitize}}',
- dataPlacement: 'top'
- },
- kind: {
- label: i18n._('Kind'),
- ngBind: 'credential_type.kind_label',
- excludeModal: true,
- columnClass: 'd-none d-md-flex col-md-4'
- },
- },
-
- actions: {
- add: {
- mode: 'all', // One of: edit, select, all
- ngClick: 'addCredentialType()',
- awToolTip: i18n._('Create a new credential type'),
- actionClass: 'at-Button--add',
- actionId: 'button-add',
- ngShow: 'canAdd'
- }
- },
-
- fieldActions: {
-
- columnClass: 'col-md-4 col-sm-3 col-xs-3',
-
- edit: {
- ngClick: "editCredentialType(credential_type.id)",
- icon: 'fa-edit',
- label: i18n._('Edit'),
- "class": 'btn-sm',
- awToolTip: i18n._('Edit credential type'),
- dataPlacement: 'top',
- ngShow: 'credential_type.summary_fields.user_capabilities.edit'
- },
- view: {
- ngClick: "editCredentialType(credential_type.id)",
- label: i18n._('View'),
- "class": 'btn-sm',
- awToolTip: i18n._('View credential type'),
- dataPlacement: 'top',
- ngShow: '!credential_type.summary_fields.user_capabilities.edit'
- },
- "delete": {
- ngClick: "deleteCredentialType(credential_type.id, credential_type.name)",
- icon: 'fa-trash',
- label: i18n._('Delete'),
- "class": 'btn-sm',
- awToolTip: i18n._('Delete credential type'),
- dataPlacement: 'top',
- ngShow: 'credential_type.summary_fields.user_capabilities.delete'
- }
- }
- };
-}];
diff --git a/awx/ui/client/src/credential-types/credential-types.strings.js b/awx/ui/client/src/credential-types/credential-types.strings.js
deleted file mode 100644
index 037c93a0ce..0000000000
--- a/awx/ui/client/src/credential-types/credential-types.strings.js
+++ /dev/null
@@ -1,14 +0,0 @@
-function CredentialTypesStrings (BaseString) {
- BaseString.call(this, 'credential_types');
-
- let t = this.t;
- let ns = this.credential_types;
-
- ns.deleteCredentialType = {
- CREDENTIAL_TYPE_IN_USE: t.s('This credential type is currently being used by one or more credentials. Credentials that use this credential type must be deleted before the credential type can be deleted.')
- };
-}
-
-CredentialTypesStrings.$inject = ['BaseStringService'];
-
-export default CredentialTypesStrings;
diff --git a/awx/ui/client/src/credential-types/edit/edit.controller.js b/awx/ui/client/src/credential-types/edit/edit.controller.js
deleted file mode 100644
index 9437ed6065..0000000000
--- a/awx/ui/client/src/credential-types/edit/edit.controller.js
+++ /dev/null
@@ -1,199 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['Rest', 'Wait',
- 'CredentialTypesForm', 'ProcessErrors', 'GetBasePath',
- 'GenerateForm', 'resourceData',
- '$scope', '$state', 'GetChoices', 'ParseTypeChange', 'ToJSON', 'ParseVariableString', 'CreateSelect2',
- function(
- Rest, Wait, CredentialTypesForm, ProcessErrors, GetBasePath,
- GenerateForm, resourceData,
- $scope, $state, GetChoices, ParseTypeChange, ToJSON, ParseVariableString, CreateSelect2
- ) {
- var credential_typeData = resourceData.data,
- generator = GenerateForm,
- data = credential_typeData,
- id = credential_typeData.id,
- form = CredentialTypesForm,
- main = {},
- url = GetBasePath('credential_types');
-
- init();
-
- function init() {
- // Load the list of options for Kind
- $scope.$parent.optionsDefer.promise
- .then(function(options) {
- GetChoices({
- scope: $scope,
- url: url,
- field: 'kind',
- variable: 'credential_kind_options',
- options: options,
- callback: 'choicesReadyCredentialTypes'
- });
-
- const docs_url = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/credential_types.html#getting-started-with-credential-types';
- const docs_help_text = `Getting Started with Credential Types `;
-
- const api_inputs_help_text = _.get(options, 'actions.POST.inputs.help_text', "Specification for credential type inputs.");
- const api_injectors_help_text = _.get(options, 'actions.POST.injectors.help_text', "Specification for credential type injector.");
-
- $scope.inputs_help_text = api_inputs_help_text + docs_help_text;
- $scope.injectors_help_text = api_injectors_help_text + docs_help_text;
- });
- }
-
- if ($scope.removeChoicesReady) {
- $scope.removeChoicesReady();
- }
- $scope.removeChoicesReady = $scope.$on('choicesReadyCredentialTypes',
- function() {
-
- if (!resourceData.data.managed_by_tower) {
- $scope.credential_kind_options = $scope.credential_kind_options
- .filter(val => val.value === 'net' ||
- val.value === 'cloud');
- }
-
- $scope.credential_type = credential_typeData;
-
- $scope.parseTypeInputs = 'yaml';
- $scope.parseTypeInjectors = 'yaml';
-
- var callback = function() {
- // Make sure the form controller knows there was a change
- $scope[form.name + '_form'].$setDirty();
- };
-
- $scope.$watch('credential_type.summary_fields.user_capabilities.edit', function(val) {
- if (val === false) {
- $scope.canAdd = false;
- }
-
- let readOnly = !($scope.credential_type.summary_fields.user_capabilities.edit || $scope.canAdd);
-
- ParseTypeChange({
- scope: $scope,
- field_id: 'credential_type_inputs',
- variable: 'inputs',
- onChange: callback,
- parse_variable: 'parseTypeInputs',
- readOnly: readOnly
- });
- ParseTypeChange({
- scope: $scope,
- field_id: 'credential_type_injectors',
- variable: 'injectors',
- onChange: callback,
- parse_variable: 'parseTypeInjectors',
- readOnly: readOnly
- });
- });
-
- function getVars(str){
-
- // Quick function to test if the host vars are a json-object-string,
- // by testing if they can be converted to a JSON object w/o error.
- function IsJsonString(str) {
- try {
- JSON.parse(str);
- } catch (e) {
- return false;
- }
- return true;
- }
-
- if(str === ''){
- return '---';
- }
- else if(IsJsonString(str)){
- str = JSON.parse(str);
- return jsyaml.safeDump(str);
- }
- else if(!IsJsonString(str)){
- return str;
- }
- }
-
- var fld, i;
- for (fld in form.fields) {
- if (data[fld] && fld !== 'inputs' || fld !== 'injectors') {
- $scope[fld] = data[fld];
- main[fld] = data[fld];
- }
-
- if (fld === "kind") {
- // Set kind field to the correct option
- for (i = 0; i < $scope.credential_kind_options.length; i++) {
- if ($scope.kind === $scope.credential_kind_options[i].value) {
- $scope.kind = $scope.credential_kind_options[i];
- main[fld] = $scope.credential_kind_options[i];
- break;
- }
- }
- }
- }
-
- $scope.inputs = ParseVariableString(getVars(data.inputs));
- $scope.injectors = ParseVariableString(getVars(data.injectors));
-
- CreateSelect2({
- element: '#credential_type_kind',
- multiple: false,
- });
-
- // if ($scope.inputs === "{}") {
- // $scope.inputs = "---";
- // }
- //
- // if ($scope.injectors === "{}") {
- // $scope.injectors = "---";
- // }
-
- // $scope.inputs = JSON.parse($scope.inputs);
- // $scope.injectors = JSON.parse($scope.injectors);
-
- }
- );
-
- $scope.formSave = function() {
- generator.clearApiErrors($scope);
- Wait('start');
- Rest.setUrl(url + id + '/');
- var inputs = ToJSON($scope.parseTypeInputs, $scope.inputs);
- var injectors = ToJSON($scope.parseTypeInjectors, $scope.injectors);
- if (inputs === null) {
- inputs = {};
- }
- if (injectors === null) {
- injectors = {};
- }
- Rest.put({
- name: $scope.name,
- description: $scope.description,
- kind: "cloud",
- inputs: inputs,
- injectors: injectors
- })
- .then(() => {
- $state.go($state.current, null, { reload: true });
- Wait('stop');
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, form, {
- hdr: 'Error!',
- msg: 'Failed to add new credential type. PUT returned status: ' + status
- });
- });
- };
-
- $scope.formCancel = function() {
- $state.go('credentialTypes');
- };
-
- }
-];
diff --git a/awx/ui/client/src/credential-types/edit/main.js b/awx/ui/client/src/credential-types/edit/main.js
deleted file mode 100644
index 6b5695ac69..0000000000
--- a/awx/ui/client/src/credential-types/edit/main.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import controller from './edit.controller';
-
-export default
- angular.module('credentialTypesEdit', [])
- .controller('CredentialTypesEditController', controller);
diff --git a/awx/ui/client/src/credential-types/list/list.controller.js b/awx/ui/client/src/credential-types/list/list.controller.js
deleted file mode 100644
index 353cb5bd3a..0000000000
--- a/awx/ui/client/src/credential-types/list/list.controller.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['$rootScope', '$scope', 'Wait', 'CredentialTypesList',
- 'GetBasePath', 'Rest', 'ProcessErrors', 'Prompt', '$state', '$filter',
- 'Dataset', 'rbacUiControlService', 'Alert', '$q', 'CredentialTypeModel',
- 'CredentialTypesStrings', 'i18n',
- function(
- $rootScope, $scope, Wait, CredentialTypesList,
- GetBasePath, Rest, ProcessErrors, Prompt, $state, $filter,
- Dataset, rbacUiControlService, Alert, $q, CredentialType,
- CredentialTypesStrings, i18n
- ) {
- let credentialType = new CredentialType();
- var defaultUrl = GetBasePath('credential_types'),
- list = CredentialTypesList;
-
- init();
-
- function init() {
- $scope.optionsDefer = $q.defer();
-
- if (!($rootScope.user_is_superuser || $rootScope.user_is_system_auditor)) {
- $state.go("setup");
- Alert('Permission Error', 'You do not have permission to view, edit or create custom credential types.', 'alert-info');
- }
-
- $scope.canAdd = false;
-
- rbacUiControlService.canAdd("credential_types")
- .then(function(params) {
- $scope.canAdd = params.canAdd;
- $scope.options = params.options;
- $scope.optionsDefer.resolve(params.options);
- optionsRequestDataProcessing();
- });
-
- // search init
- $scope.list = list;
- $scope[`${list.iterator}_dataset`] = Dataset.data;
- $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
-
- }
-
- // @todo what is going on here, and if it needs to happen in this controller make $rootScope var name more explicit
- if ($rootScope.addedItem) {
- $scope.addedItem = $rootScope.addedItem;
- delete $rootScope.addedItem;
- }
-
- $scope.editCredentialType = function() {
- $state.go('credentialTypes.edit', {
- credential_type_id: this.credential_type.id
- });
- };
-
- $scope.deleteCredentialType = function(id, name) {
-
- var action = function() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- var url = defaultUrl + id + '/';
- credentialType.request('delete', id)
- .then(() => {
-
- let reloadListStateParams = null;
-
- if($scope.credential_types.length === 1 && $state.params.credential_type_search && _.has($state, 'params.credential_type_search.page') && $state.params.credential_type_search.page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.credential_type_search.page = (parseInt(reloadListStateParams.credential_type_search.page)-1).toString();
- }
-
- if (parseInt($state.params.credential_type_id) === id) {
- $state.go('^', reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, { reload: true });
- }
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
- });
- });
- };
-
- credentialType.getDependentResourceCounts(id)
- .then((counts) => {
- let credentialTypeInUse = false;
- let deleteModalBody = `${CredentialTypesStrings.get('deleteResource.CONFIRM', 'credential type')}
`;
-
- counts.forEach(countObj => {
- if(countObj.count && countObj.count > 0) {
- credentialTypeInUse = true;
- }
- });
-
- if (credentialTypeInUse) {
- deleteModalBody = `${CredentialTypesStrings.get('deleteCredentialType.CREDENTIAL_TYPE_IN_USE')}
`;
- }
-
- Prompt({
- hdr: i18n._('Delete') + ' ' + $filter('sanitize')(name),
- body: deleteModalBody,
- action: action,
- hideActionButton: credentialTypeInUse ? true : false,
- actionText: i18n._('DELETE')
- });
- });
- };
-
- $scope.addCredentialType = function() {
- $state.go('credentialTypes.add');
- };
-
- // iterate over the list and add fields like type label, after the
- // OPTIONS request returns, or the list is sorted/paginated/searched
- function optionsRequestDataProcessing(){
- $scope.optionsDefer.promise.then(function(options) {
- if($scope.list.name === 'credential_types'){
- if ($scope[list.name] !== undefined) {
- $scope[list.name].forEach(function(item, item_idx) {
- var itm = $scope[list.name][item_idx];
- // Set the item type label
- if (list.fields.kind && options && options.actions && options.actions.GET && options.actions.GET.kind) {
- options.actions.GET.kind.choices.forEach(function(choice) {
- if (choice[0] === item.kind) {
- itm.kind_label = choice[1];
- }
- });
- }
-
- });
- }
- }
- });
- }
-
- $scope.$watchCollection(`${$scope.list.name}`, function() {
- optionsRequestDataProcessing();
- }
- );
-
- }
-];
diff --git a/awx/ui/client/src/credential-types/list/main.js b/awx/ui/client/src/credential-types/list/main.js
deleted file mode 100644
index a029726ab5..0000000000
--- a/awx/ui/client/src/credential-types/list/main.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import CredentialTypesListController from './list.controller';
-
-export default
-angular.module('credenitalTypesList', [])
- .controller('CredentialTypesListController', CredentialTypesListController);
diff --git a/awx/ui/client/src/credential-types/main.js b/awx/ui/client/src/credential-types/main.js
deleted file mode 100644
index 0ba1ccff24..0000000000
--- a/awx/ui/client/src/credential-types/main.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import credentialTypesList from './list/main';
-import credentialTypesAdd from './add/main';
-import credentialTypesEdit from './edit/main';
-import list from './credential-types.list';
-import form from './credential-types.form';
-import { N_ } from '../i18n';
-import CredentialTypesStrings from './credential-types.strings';
-
-export default
-angular.module('credentialTypes', [
- credentialTypesList.name,
- credentialTypesAdd.name,
- credentialTypesEdit.name
- ])
- .factory('CredentialTypesList', list)
- .factory('CredentialTypesForm', form)
- .service('CredentialTypesStrings', CredentialTypesStrings)
- .config(['$stateProvider', 'stateDefinitionsProvider',
- function($stateProvider, stateDefinitionsProvider) {
- let stateDefinitions = stateDefinitionsProvider.$get();
-
- function generateStateTree() {
- let credentialTypesTree = stateDefinitions.generateTree({
- parent: 'credentialTypes',
- modes: ['add', 'edit'],
- list: 'CredentialTypesList',
- form: 'CredentialTypesForm',
- controllers: {
- list: 'CredentialTypesListController',
- add: 'CredentialTypesAddController',
- edit: 'CredentialTypesEditController'
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'credential_type'
- },
- ncyBreadcrumb: {
- label: N_('CREDENTIAL TYPES')
- }
- });
- return Promise.all([
- credentialTypesTree
- ]).then((generated) => {
- return {
- states: _.reduce(generated, (result, definition) => {
- return result.concat(definition.states);
- }, [])
- };
- });
- }
- let stateTree = {
- name: 'credentialTypes.**',
- url: '/credential_types',
- lazyLoad: () => generateStateTree()
- };
- $stateProvider.state(stateTree);
- }
- ]);
diff --git a/awx/ui/client/src/credentials/credentials.form.js b/awx/ui/client/src/credentials/credentials.form.js
deleted file mode 100644
index e58dfbcb3c..0000000000
--- a/awx/ui/client/src/credentials/credentials.form.js
+++ /dev/null
@@ -1,475 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc function
- * @name forms.function:Credentials
- * @description This form is for adding/editing a Credential
-*/
-
-export default ['i18n', function(i18n) {
- return {
-
- addTitle: i18n._('CREATE CREDENTIAL'), //Legend in add mode
- editTitle: '{{ name }}', //Legend in edit mode
- name: 'credential',
- // the top-most node of generated state tree
- stateTree: 'credentials',
- forceListeners: true,
- subFormTitles: {
- credentialSubForm: i18n._('Type Details'),
- },
-
- actions: {
-
- },
-
- fields: {
- name: {
- label: i18n._('Name'),
- type: 'text',
- required: true,
- autocomplete: false,
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- description: {
- label: i18n._('Description'),
- type: 'text',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- organization: {
- basePath: 'organizations',
- ngShow: 'canShareCredential',
- label: i18n._('Organization'),
- type: 'lookup',
- autopopulateLookup: false,
- list: 'OrganizationList',
- sourceModel: 'organization',
- sourceField: 'name',
- awPopOver: "" + i18n._("If no organization is given, the credential can only be used by the user that creates the credential. Organization admins and system administrators can assign an organization so that roles for the credential can be assigned to users and teams in that organization.") + "
",
- dataTitle: i18n._('Organization') + ' ',
- dataPlacement: 'bottom',
- dataContainer: "body",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd) || !canEditOrg',
- awLookupWhen: '(credential_obj.summary_fields.user_capabilities.edit || canAdd) && canEditOrg'
- },
- kind: {
- label: i18n._('Type'),
- excludeModal: true,
- type: 'select',
- ngOptions: 'kind.label for kind in credential_kind_options track by kind.value', // select as label for value in array 'kind.label for kind in credential_kind_options',
- ngChange: 'kindChange()',
- required: true,
- awPopOver: '\n' +
- '' + i18n._('Machine') + ' \n' +
- '' + i18n._('Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
- 'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
- 'remote hosts.') + ' ' +
- '' + i18n._('Network') + ' \n' +
- '' + i18n._('Authentication for network device access. This can include SSH keys, usernames, passwords, ' +
- 'and authorize information. Network credentials are used when submitting jobs to run playbooks against ' +
- 'network devices.') + ' ' +
- '' + i18n._('Source Control') + ' \n' +
- '' + i18n._('Used to check out and synchronize playbook repositories with a remote source control ' +
- 'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
- 'used by Projects.') + ' \n' +
- '' + i18n._('Others (Cloud Providers)') + ' \n' +
- '' + i18n._('Usernames, passwords, and access keys for authenticating to the specified cloud or infrastructure ' +
- 'provider. These are used for smart inventory sources and for cloud provisioning and deployment ' +
- 'in playbook runs.') + ' \n' +
- ' \n',
- dataTitle: i18n._('Type'),
- dataPlacement: 'right',
- dataContainer: "body",
- hasSubForm: true,
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- access_key: {
- label: i18n._('Access Key'),
- type: 'text',
- ngShow: "kind.value == 'aws'",
- awRequiredWhen: {
- reqExpression: "aws_required",
- init: false
- },
- autocomplete: false,
- apiField: 'username',
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- secret_key: {
- label: i18n._('Secret Key'),
- type: 'sensitive',
- ngShow: "kind.value == 'aws'",
- ngDisabled: "secret_key_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
- awRequiredWhen: {
- reqExpression: "aws_required",
- init: false
- },
- autocomplete: false,
- clear: false,
- hasShowInputButton: true,
- apiField: 'password',
- subForm: 'credentialSubForm'
- },
- security_token: {
- label: i18n._('STS Token'),
- type: 'sensitive',
- ngShow: "kind.value == 'aws'",
- autocomplete: false,
- apiField: 'security_token',
- awPopOver: "" + i18n._("Security Token Service (STS) is a web service that enables you to request temporary, limited-privilege credentials for AWS Identity and Access Management (IAM) users.") + "
" +
- i18n.sprintf(i18n._("To learn more about the IAM STS Token, refer to the %sAmazon documentation%s."), "
", " ") + "
",
- hasShowInputButton: true,
- dataTitle: i18n._('STS Token'),
- dataPlacement: 'right',
- dataContainer: "body",
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "host": {
- labelBind: 'hostLabel',
- type: 'text',
- ngShow: "kind.value == 'vmware' || kind.value == 'openstack' || kind.value === 'satellite6' || kind.value === 'cloudforms'",
- awPopOverWatch: "hostPopOver",
- awPopOver: i18n._("set in helpers/credentials"),
- dataTitle: i18n._('Host'),
- dataPlacement: 'right',
- dataContainer: "body",
- autocomplete: false,
- awRequiredWhen: {
- reqExpression: 'host_required',
- init: false
- },
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "subscription": {
- label: i18n._("Subscription ID"),
- type: 'text',
- ngShow: "kind.value == 'azure_rm'",
- awRequiredWhen: {
- reqExpression: 'subscription_required',
- init: false
- },
-
-
- autocomplete: false,
- awPopOver: '' + i18n._('Subscription ID is an Azure construct, which is mapped to a username.') + '
',
- dataTitle: i18n._('Subscription ID'),
- dataPlacement: 'right',
- dataContainer: "body",
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "username": {
- labelBind: 'usernameLabel',
- type: 'text',
- ngShow: "kind.value && kind.value !== 'aws' && " +
- "kind.value !== 'gce'",
- awRequiredWhen: {
- reqExpression: 'username_required',
- init: false
- },
- autocomplete: false,
- subForm: "credentialSubForm",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "email_address": {
- labelBind: 'usernameLabel',
- type: 'email',
- ngShow: "kind.value === 'gce'",
- awRequiredWhen: {
- reqExpression: 'email_required',
- init: false
- },
- autocomplete: false,
- awPopOver: '' + i18n.sprintf(i18n._('The email address assigned to the Google Compute Engine %sservice account.'), '') + '
',
- dataTitle: i18n._('Email'),
- dataPlacement: 'right',
- dataContainer: "body",
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "api_key": {
- label: i18n._('API Key'),
- type: 'sensitive',
- ngShow: "kind.value == 'rax'",
- awRequiredWhen: {
- reqExpression: "rackspace_required",
- init: false
- },
- autocomplete: false,
- hasShowInputButton: true,
- clear: false,
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "password": {
- labelBind: 'passwordLabel',
- type: 'sensitive',
- ngShow: "kind.value == 'scm' || kind.value == 'vmware' || kind.value == 'openstack'|| kind.value == 'satellite6'|| kind.value == 'cloudforms'|| kind.value == 'net' || kind.value == 'azure_rm'",
- clear: false,
- autocomplete: false,
- hasShowInputButton: true,
- awRequiredWhen: {
- reqExpression: "password_required",
- init: false
- },
- subForm: "credentialSubForm",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "ssh_password": {
- label: i18n._('Password'),
- type: 'sensitive',
- ngShow: "kind.value == 'ssh'",
- ngDisabled: "ssh_password_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
- subCheckbox: {
- variable: 'ssh_password_ask',
- text: i18n._('Ask at runtime?'),
- ngChange: 'ask(\'ssh_password\', \'undefined\')',
- ngDisabled: false,
- },
- hasShowInputButton: true,
- autocomplete: false,
- subForm: 'credentialSubForm'
- },
- "ssh_key_data": {
- labelBind: 'sshKeyDataLabel',
- type: 'textarea',
- ngShow: "kind.value == 'ssh' || kind.value == 'scm' || " +
- "kind.value == 'gce' || kind.value == 'net'",
- awRequiredWhen: {
- reqExpression: 'key_required',
- init: true
- },
- class: 'Form-textAreaLabel Form-formGroup--fullWidth',
- elementClass: 'Form-monospace',
-
-
- awDropFile: true,
- rows: 10,
- awPopOver: i18n._("SSH key description"),
- awPopOverWatch: "key_description",
- dataTitle: i18n._('Private Key'),
- dataPlacement: 'right',
- dataContainer: "body",
- subForm: "credentialSubForm",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "ssh_key_unlock": {
- label: i18n._('Private Key Passphrase'),
- type: 'sensitive',
- ngShow: "kind.value === 'ssh' || kind.value === 'scm' || kind.value === 'net'",
- ngDisabled: "keyEntered === false || ssh_key_unlock_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
- subCheckbox: {
- variable: 'ssh_key_unlock_ask',
- ngShow: "kind.value == 'ssh'",
- text: i18n._('Ask at runtime?'),
- ngChange: 'ask(\'ssh_key_unlock\', \'undefined\')',
- ngDisabled: "keyEntered === false"
- },
- hasShowInputButton: true,
- subForm: 'credentialSubForm'
- },
- "become_method": {
- label: i18n._("Privilege Escalation"),
- // hintText: "If your playbooks use privilege escalation (\"sudo: true\", \"su: true\", etc), you can specify the username to become, and the password to use here.",
- type: 'text',
- ngShow: "kind.value == 'ssh'",
- dataTitle: i18n._('Privilege Escalation'),
- awPopOver: "" + i18n.sprintf(i18n._("Specify a method for %s operations. " +
- "This is equivalent to specifying the %s parameter, where %s could be "+
- "%s"), "'become'", "--become-method=BECOME_METHOD", "BECOME_METHOD", "sudo | su | pbrun | pfexec | runas") + " " + i18n.sprintf(i18n._("(defaults to %s)"), "sudo") + "
",
- dataPlacement: 'right',
- dataContainer: "body",
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)',
- ngChange: 'becomeMethodChange()',
- },
- "become_username": {
- label: i18n._('Privilege Escalation Username'),
- type: 'text',
- ngShow: "(kind.value == 'ssh' && (become_method && become_method.value)) ",
-
-
- autocomplete: false,
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "become_password": {
- label: i18n._('Privilege Escalation Password'),
- type: 'sensitive',
- ngShow: "(kind.value == 'ssh' && (become_method && become_method.value)) ",
- ngDisabled: "become_password_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
- subCheckbox: {
- variable: 'become_password_ask',
- text: i18n._('Ask at runtime?'),
- ngChange: 'ask(\'become_password\', \'undefined\')',
- ngDisabled: false,
- },
- hasShowInputButton: true,
- autocomplete: false,
- subForm: 'credentialSubForm'
- },
- client:{
- type: 'text',
- label: i18n._('Client ID'),
- subForm: 'credentialSubForm',
- ngShow: "kind.value === 'azure_rm'",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- secret:{
- type: 'sensitive',
- hasShowInputButton: true,
- autocomplete: false,
- label: i18n._('Client Secret'),
- subForm: 'credentialSubForm',
- ngShow: "kind.value === 'azure_rm'",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- tenant: {
- type: 'text',
- label: i18n._('Tenant ID'),
- subForm: 'credentialSubForm',
- ngShow: "kind.value === 'azure_rm'",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- authorize: {
- label: i18n._('Authorize'),
- type: 'checkbox',
- ngChange: "toggleCallback('host_config_key')",
- subForm: 'credentialSubForm',
- ngShow: "kind.value === 'net'",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- authorize_password: {
- label: i18n._('Authorize Password'),
- type: 'sensitive',
- hasShowInputButton: true,
- autocomplete: false,
- subForm: 'credentialSubForm',
- ngShow: "authorize && authorize !== 'false'",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "project": {
- labelBind: 'projectLabel',
- type: 'text',
- ngShow: "kind.value == 'gce' || kind.value == 'openstack'",
- awPopOverWatch: "projectPopOver",
- awPopOver: i18n._("set in helpers/credentials"),
- dataTitle: i18n._('Project Name'),
- dataPlacement: 'right',
- dataContainer: "body",
- awRequiredWhen: {
- reqExpression: 'project_required',
- init: false
- },
- subForm: 'credentialSubForm',
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- "domain": {
- labelBind: 'domainLabel',
- type: 'text',
- ngShow: "kind.value == 'openstack'",
- awPopOver: "" + i18n._("OpenStack domains define administrative " +
- "boundaries. It is only needed for Keystone v3 authentication URLs. " +
- "Common scenarios include:") + "
" + i18n.sprintf(i18n._("v2 URLs%s - leave blank"), " ") + " " +
- "" + i18n.sprintf(i18n._("v3 default%s - set to 'default'"), " ") + " " +
- "" + i18n.sprintf(i18n._("v3 multi-domain%s - your domain name"), " ") + "
",
- dataTitle: i18n._('Domain Name'),
- dataPlacement: 'right',
- dataContainer: "body",
- ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)',
- subForm: 'credentialSubForm'
- },
- "vault_password": {
- label: i18n._("Vault Password"),
- type: 'sensitive',
- ngShow: "kind.value == 'ssh'",
- ngDisabled: "vault_password_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
- subCheckbox: {
- variable: 'vault_password_ask',
- text: i18n._('Ask at runtime?'),
- ngChange: 'ask(\'vault_password\', \'undefined\')',
- ngDisabled: false,
- },
- hasShowInputButton: true,
- autocomplete: false,
- subForm: 'credentialSubForm'
- }
- },
-
- buttons: {
- cancel: {
- ngClick: 'formCancel()',
- ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- close: {
- ngClick: 'formCancel()',
- ngShow: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- },
- save: {
- label: i18n._('Save'),
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true,
- ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)' //Disable when $pristine or $invalid, optional
- }
- },
-
- related: {
- permissions: {
- name: 'permissions',
- disabled: '(organization === undefined ? true : false)',
- // Do not transition the state if organization is undefined
- ngClick: `(organization === undefined ? true : false)||$state.go('credentials.edit.permissions')`,
- awToolTip: '{{permissionsTooltip}}',
- dataTipWatch: 'permissionsTooltip',
- awToolTipTabEnabledInEditMode: true,
- dataPlacement: 'right',
- basePath: 'api/v2/credentials/{{$stateParams.credential_id}}/access_list/',
- search: {
- order_by: 'username'
- },
- type: 'collection',
- title: i18n._('Permissions'),
- iterator: 'permission',
- index: false,
- open: false,
- actions: {
- add: {
- mode: 'all',
- ngClick: "$state.go('.add')",
- label: i18n._('Add'),
- awToolTip: i18n._('Add a permission'),
- actionClass: 'at-Button--add',
- actionId: 'button-add--permission',
- ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
- }
- },
- fields: {
- username: {
- key: true,
- label: i18n._('User'),
- linkBase: 'users',
- columnClass: 'col-sm-3 col-xs-4'
- },
- role: {
- label: i18n._('Role'),
- type: 'role',
- nosort: true,
- columnClass: 'col-sm-4 col-xs-4'
- },
- team_roles: {
- label: i18n._('Team Roles'),
- type: 'team_roles',
- nosort: true,
- columnClass: 'col-sm-5 col-xs-4'
- }
- }
- }
- }
- };}];
diff --git a/awx/ui/client/src/credentials/credentials.list.js b/awx/ui/client/src/credentials/credentials.list.js
deleted file mode 100644
index f84fbbb68f..0000000000
--- a/awx/ui/client/src/credentials/credentials.list.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
-
-
-export default ['i18n', function(i18n) {
- return {
- name: 'credentials',
- iterator: 'credential',
- selectTitle: i18n._('Add Credentials'),
- editTitle: i18n._('CREDENTIALS'),
- listTitle: i18n._('CREDENTIALS'),
- selectInstructions: "Select existing credentials by clicking each credential or checking the related checkbox. When " +
- "finished, click the blue Select button, located bottom right.
Create a brand new credential by clicking ",
- index: false,
- hover: true,
- emptyListText: i18n._('No Credentials Have Been Created'),
-
- fields: {
- name: {
- key: true,
- label: i18n._('Name'),
- columnClass: 'col-md-4 col-sm-9 col-xs-9',
- modalColumnClass: 'col-md-12',
- awToolTip: '{{credential.description | sanitize}}',
- dataPlacement: 'top'
- },
- kind: {
- label: i18n._('Kind'),
- ngBind: 'credential.kind',
- excludeModal: true,
- nosort: true,
- columnClass: 'd-none d-md-flex col-md-2'
- },
- owners: {
- label: i18n._('Owners'),
- type: 'owners',
- nosort: true,
- excludeModal: true,
- columnClass: 'd-none d-md-flex col-md-2 List-tableCell'
- }
- },
-
- actions: {
- add: {
- mode: 'all', // One of: edit, select, all
- ngClick: 'addCredential()',
- awToolTip: i18n._('Create a new credential'),
- actionClass: 'at-Button--add',
- actionId: 'button-add',
- ngShow: "true"
- }
- },
-
- fieldActions: {
-
- columnClass: 'col-md-4 col-sm-3 col-xs-3',
-
- edit: {
- ngClick: "editCredential(credential.id)",
- icon: 'fa-edit',
- label: i18n._('Edit'),
- "class": 'btn-sm',
- awToolTip: i18n._('Edit credential'),
- dataPlacement: 'top',
- ngShow: 'credential.summary_fields.user_capabilities.edit'
- },
- copy: {
- label: i18n._('Copy'),
- ngClick: 'copyCredential(credential)',
- "class": 'btn-danger btn-xs',
- awToolTip: i18n._('Copy credential'),
- dataPlacement: 'top',
- ngShow: 'credential.summary_fields.user_capabilities.copy'
- },
- view: {
- ngClick: "editCredential(credential.id)",
- label: i18n._('View'),
- "class": 'btn-sm',
- awToolTip: i18n._('View credential'),
- dataPlacement: 'top',
- ngShow: '!credential.summary_fields.user_capabilities.edit'
- },
-
- "delete": {
- ngClick: "deleteCredential(credential.id, credential.name)",
- icon: 'fa-trash',
- label: i18n._('Delete'),
- "class": 'btn-sm',
- awToolTip: i18n._('Delete credential'),
- dataPlacement: 'top',
- ngShow: 'credential.summary_fields.user_capabilities.delete'
- }
- }
- };}];
diff --git a/awx/ui/client/src/credentials/factories/become-method-change.factory.js b/awx/ui/client/src/credentials/factories/become-method-change.factory.js
deleted file mode 100644
index 2c95e12523..0000000000
--- a/awx/ui/client/src/credentials/factories/become-method-change.factory.js
+++ /dev/null
@@ -1,97 +0,0 @@
-export default
- function BecomeMethodChange(Empty, i18n) {
- return function(params) {
- var scope = params.scope;
-
- if (!Empty(scope.kind)) {
- // Apply kind specific settings
- switch (scope.kind.value) {
- case 'aws':
- scope.aws_required = true;
- break;
- case 'rax':
- scope.rackspace_required = true;
- scope.username_required = true;
- break;
- case 'ssh':
- scope.usernameLabel = i18n._('Username'); //formally 'SSH Username'
- break;
- case 'scm':
- scope.sshKeyDataLabel = i18n._('SCM Private Key');
- scope.passwordLabel = i18n._('Password');
- break;
- case 'gce':
- scope.usernameLabel = i18n._('Service Account Email Address');
- scope.sshKeyDataLabel = i18n._('RSA Private Key');
- scope.email_required = true;
- scope.key_required = true;
- scope.project_required = true;
- scope.key_description = i18n._('Paste the contents of the PEM file associated with the service account email.');
- scope.projectLabel = i18n._("Project");
- scope.project_required = false;
- scope.projectPopOver = "
" + i18n._("The Project ID is the " +
- "GCE assigned identification. It is constructed as " +
- "two words followed by a three digit number. Such " +
- "as: ") + "
adjective-noun-000
";
- break;
- case 'azure_rm':
- scope.usernameLabel = i18n._("Username");
- scope.subscription_required = true;
- scope.passwordLabel = i18n._('Password');
- scope.azure_rm_required = true;
- break;
- case 'vmware':
- scope.username_required = true;
- scope.host_required = true;
- scope.password_required = true;
- scope.hostLabel = "vCenter Host";
- scope.passwordLabel = i18n._('Password');
- scope.hostPopOver = i18n._("Enter the hostname or IP address which corresponds to your VMware vCenter.");
- break;
- case 'openstack':
- scope.hostLabel = i18n._("Host (Authentication URL)");
- scope.projectLabel = i18n._("Project (Tenant Name)");
- scope.domainLabel = i18n._("Domain Name");
- scope.password_required = true;
- scope.project_required = true;
- scope.host_required = true;
- scope.username_required = true;
- scope.projectPopOver = "" + i18n._("This is the tenant name. " +
- " This value is usually the same " +
- " as the username.") + "
";
- scope.hostPopOver = "" + i18n._("The host to authenticate with.") +
- " " + i18n.sprintf(i18n._("For example, %s"), "https://openstack.business.com/v2.0/");
- break;
- case 'satellite6':
- scope.username_required = true;
- scope.password_required = true;
- scope.passwordLabel = i18n._('Password');
- scope.host_required = true;
- scope.hostLabel = i18n._("Satellite 6 URL");
- scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL which corresponds to your %s" +
- "Red Hat Satellite 6 server. %s" +
- "For example, %s"), " ", " ", "https://satellite.example.org");
- break;
- case 'cloudforms':
- scope.username_required = true;
- scope.password_required = true;
- scope.passwordLabel = i18n._('Password');
- scope.host_required = true;
- scope.hostLabel = i18n._("CloudForms URL");
- scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL for the virtual machine which %s" +
- "corresponds to your CloudForms instance. %s" +
- "For example, %s"), " ", " ", "https://cloudforms.example.org");
- break;
- case 'net':
- scope.username_required = true;
- scope.password_required = false;
- scope.passwordLabel = i18n._('Password');
- scope.sshKeyDataLabel = i18n._('SSH Key');
- break;
- }
- }
- };
- }
-
-BecomeMethodChange.$inject =
- [ 'Empty', 'i18n' ];
diff --git a/awx/ui/client/src/credentials/factories/credential-form-save.factory.js b/awx/ui/client/src/credentials/factories/credential-form-save.factory.js
deleted file mode 100644
index 89fcba25e6..0000000000
--- a/awx/ui/client/src/credentials/factories/credential-form-save.factory.js
+++ /dev/null
@@ -1,105 +0,0 @@
-export default
- function CredentialFormSave($rootScope, $location, Rest, ProcessErrors, GetBasePath, CredentialForm, ReturnToCaller, Wait, $state, i18n) {
- return function(params) {
- var scope = params.scope,
- mode = params.mode,
- form = CredentialForm,
- data = {}, fld, url;
-
- for (fld in form.fields) {
- if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
- fld !== 'ssh_password') {
- if (fld === "organization" && !scope[fld]) {
- data.user = $rootScope.current_user.id;
- } else if (scope[fld] === null) {
- data[fld] = "";
- } else {
- data[fld] = scope[fld];
- }
- }
- }
-
- data.kind = scope.kind.value;
- if (scope.become_method === null || typeof scope.become_method === 'undefined') {
- data.become_method = "";
- data.become_username = "";
- data.become_password = "";
- } else {
- data.become_method = (scope.become_method.value) ? scope.become_method.value : "";
- }
- switch (data.kind) {
- case 'ssh':
- data.password = scope.ssh_password;
- break;
- case 'aws':
- data.username = scope.access_key;
- data.password = scope.secret_key;
- break;
- case 'rax':
- data.password = scope.api_key;
- break;
- case 'gce':
- data.username = scope.email_address;
- data.project = scope.project;
- break;
- case 'azure':
- data.username = scope.subscription;
- }
-
- Wait('start');
- if (mode === 'add') {
- url = GetBasePath("credentials");
- Rest.setUrl(url);
- Rest.post(data)
- .then(({data}) => {
- scope.addedItem = data.id;
-
- Wait('stop');
- var base = $location.path().replace(/^\//, '').split('/')[0];
- if (base === 'credentials') {
- $state.go('credentials.edit', {credential_id: data.id}, {reload: true});
- }
- else {
- ReturnToCaller(1);
- }
- })
- .catch(({data, status}) => {
- Wait('stop');
- // TODO: hopefully this conditional error handling will to away in a future versions. The reason why we cannot
- // simply pass this error to ProcessErrors is because it will actually match the form element 'ssh_key_unlock' and show
- // the error there. The ssh_key_unlock field is not shown when the kind of credential is gce/azure and as a result the
- // error is never shown. In the future, the API will hopefully either behave or respond differently.
- if(status && status === 400 && data && data.ssh_key_unlock && (scope.kind.value === 'gce' || scope.kind.value === 'azure')) {
- scope.ssh_key_data_api_error = i18n._("Encrypted credentials are not supported.");
- }
- else {
- ProcessErrors(scope, data, status, form, {
- hdr: i18n._('Error!'),
- msg: i18n._('Failed to create new Credential. POST status: ') + status
- });
- }
- });
- } else {
- url = GetBasePath('credentials') + scope.id + '/';
- Rest.setUrl(url);
- Rest.put(data)
- .then(() => {
- Wait('stop');
- $state.go($state.current, {}, {reload: true});
- })
- .catch(({data, status}) => {
- Wait('stop');
- ProcessErrors(scope, data, status, form, {
- hdr: i18n._('Error!'),
- msg: i18n._('Failed to update Credential. PUT status: ') + status
- });
- });
- }
- };
- }
-
-CredentialFormSave.$inject =
- [ '$rootScope', '$location', 'Rest',
- 'ProcessErrors', 'GetBasePath', 'CredentialForm',
- 'ReturnToCaller', 'Wait', '$state', 'i18n'
- ];
diff --git a/awx/ui/client/src/credentials/factories/kind-change.factory.js b/awx/ui/client/src/credentials/factories/kind-change.factory.js
deleted file mode 100644
index c9d324bbab..0000000000
--- a/awx/ui/client/src/credentials/factories/kind-change.factory.js
+++ /dev/null
@@ -1,170 +0,0 @@
-export default
- function KindChange(Empty, i18n) {
- return function(params) {
- var scope = params.scope,
- reset = params.reset;
-
- $('.popover').each(function() {
- // remove lingering popover
. Seems to be a bug in TB3 RC1
- $(this).remove();
- });
- $('.tooltip').each( function() {
- // close any lingering tool tipss
- $(this).hide();
- });
- // Put things in a default state
- scope.usernameLabel = i18n._('Username');
- scope.aws_required = false;
- scope.email_required = false;
- scope.rackspace_required = false;
- scope.sshKeyDataLabel = i18n._('Private Key');
- scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE)
- scope.key_required = false; // JT -- doing the same for key and project
- scope.project_required = false;
- scope.subscription_required = false;
- scope.key_description = i18n.sprintf(i18n._("Paste the contents of the SSH private key file.%s or click to close%s"), "");
- scope.host_required = false;
- scope.password_required = false;
- scope.hostLabel = '';
- scope.passwordLabel = i18n._('Password');
-
- $('.popover').each(function() {
- // remove lingering popover
. Seems to be a bug in TB3 RC1
- $(this).remove();
- });
- $('.tooltip').each( function() {
- // close any lingering tool tipss
- $(this).hide();
- });
- // Put things in a default state
- scope.usernameLabel = i18n._('Username');
- scope.aws_required = false;
- scope.email_required = false;
- scope.rackspace_required = false;
- scope.sshKeyDataLabel = i18n._('Private Key');
- scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE)
- scope.key_required = false; // JT -- doing the same for key and project
- scope.project_required = false;
- scope.domain_required = false;
- scope.subscription_required = false;
- scope.key_description = i18n._("Paste the contents of the SSH private key file.");
- scope.host_required = false;
- scope.password_required = false;
- scope.hostLabel = '';
- scope.projectLabel = '';
- scope.domainLabel = '';
- scope.project_required = false;
- scope.passwordLabel = i18n._('Password (API Key)');
- scope.projectPopOver = "
" + i18n._("The project value") + "
";
- scope.hostPopOver = "
" + i18n._("The host value") + "
";
- scope.ssh_key_data_api_error = '';
-
- if (!Empty(scope.kind)) {
- // Apply kind specific settings
- switch (scope.kind.value) {
- case 'aws':
- scope.aws_required = true;
- break;
- case 'rax':
- scope.rackspace_required = true;
- scope.username_required = true;
- break;
- case 'ssh':
- scope.usernameLabel = i18n._('Username'); //formally 'SSH Username'
- break;
- case 'scm':
- scope.sshKeyDataLabel = i18n._('SCM Private Key');
- scope.passwordLabel = i18n._('Password');
- break;
- case 'gce':
- scope.usernameLabel = i18n._('Service Account Email Address');
- scope.sshKeyDataLabel = i18n._('RSA Private Key');
- scope.email_required = true;
- scope.key_required = true;
- scope.project_required = true;
- scope.key_description = i18n._('Paste the contents of the PEM file associated with the service account email.');
- scope.projectLabel = i18n._("Project");
- scope.project_required = false;
- scope.projectPopOver = "
" + i18n._("The Project ID is the " +
- "GCE assigned identification. It is constructed as " +
- "two words followed by a three digit number. Such " +
- "as: ") + "
adjective-noun-000
";
- break;
- case 'azure_rm':
- scope.usernameLabel = i18n._("Username");
- scope.subscription_required = true;
- scope.passwordLabel = i18n._('Password');
- scope.azure_rm_required = true;
- break;
- case 'vmware':
- scope.username_required = true;
- scope.host_required = true;
- scope.password_required = true;
- scope.hostLabel = "vCenter Host";
- scope.passwordLabel = i18n._('Password');
- scope.hostPopOver = i18n._("Enter the hostname or IP address which corresponds to your VMware vCenter.");
- break;
- case 'openstack':
- scope.hostLabel = i18n._("Host (Authentication URL)");
- scope.projectLabel = i18n._("Project (Tenant Name)");
- scope.domainLabel = i18n._("Domain Name");
- scope.password_required = true;
- scope.project_required = true;
- scope.host_required = true;
- scope.username_required = true;
- scope.projectPopOver = "
" + i18n._("This is the tenant name. " +
- " This value is usually the same " +
- " as the username.") + "
";
- scope.hostPopOver = "
" + i18n._("The host to authenticate with.") +
- " " + i18n.sprintf(i18n._("For example, %s"), "https://openstack.business.com/v2.0/");
- break;
- case 'satellite6':
- scope.username_required = true;
- scope.password_required = true;
- scope.passwordLabel = i18n._('Password');
- scope.host_required = true;
- scope.hostLabel = i18n._("Satellite 6 URL");
- scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL which corresponds to your %s" +
- "Red Hat Satellite 6 server. %s" +
- "For example, %s"), " ", " ", "https://satellite.example.org");
- break;
- case 'cloudforms':
- scope.username_required = true;
- scope.password_required = true;
- scope.passwordLabel = i18n._('Password');
- scope.host_required = true;
- scope.hostLabel = i18n._("CloudForms URL");
- scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL for the virtual machine which %s" +
- "corresponds to your CloudForms instance. %s" +
- "For example, %s"), " ", " ", "https://cloudforms.example.org");
- break;
- case 'net':
- scope.username_required = true;
- scope.password_required = false;
- scope.passwordLabel = i18n._('Password');
- scope.sshKeyDataLabel = i18n._('SSH Key');
- break;
- }
- }
-
- // Reset all the field values related to Kind.
- if (reset) {
- scope.access_key = null;
- scope.secret_key = null;
- scope.api_key = null;
- scope.username = null;
- scope.password = null;
- scope.password_confirm = null;
- scope.ssh_key_data = null;
- scope.ssh_key_unlock = null;
- scope.ssh_key_unlock_confirm = null;
- scope.become_username = null;
- scope.become_password = null;
- scope.authorize = false;
- scope.authorize_password = null;
- }
- };
- }
-
-KindChange.$inject =
- [ 'Empty', 'i18n' ];
diff --git a/awx/ui/client/src/credentials/factories/owner-change.factory.js b/awx/ui/client/src/credentials/factories/owner-change.factory.js
deleted file mode 100644
index 60b77110bb..0000000000
--- a/awx/ui/client/src/credentials/factories/owner-change.factory.js
+++ /dev/null
@@ -1,18 +0,0 @@
-export default
- function OwnerChange() {
- return function(params) {
- var scope = params.scope,
- owner = scope.owner;
- if (owner === 'team') {
- scope.team_required = true;
- scope.user_required = false;
- scope.user = null;
- scope.user_username = null;
- } else {
- scope.team_required = false;
- scope.user_required = true;
- scope.team = null;
- scope.team_name = null;
- }
- };
- }
diff --git a/awx/ui/client/src/credentials/list/credentials-list.controller.js b/awx/ui/client/src/credentials/list/credentials-list.controller.js
deleted file mode 100644
index 5fedf2f711..0000000000
--- a/awx/ui/client/src/credentials/list/credentials-list.controller.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ProcessErrors', 'GetBasePath',
- 'Wait', '$state', '$filter', 'rbacUiControlService', 'Dataset', 'credentialType', 'i18n',
- 'CredentialModel', 'CredentialsStrings', 'ngToast',
- function($scope, Rest, CredentialList, Prompt,
- ProcessErrors, GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset,
- credentialType, i18n, Credential, CredentialsStrings, ngToast) {
-
- const credential = new Credential();
-
- var list = CredentialList,
- defaultUrl = GetBasePath('credentials');
-
- init();
-
- function init() {
- rbacUiControlService.canAdd('credentials')
- .then(function(params) {
- $scope.canAdd = params.canAdd;
- });
-
- $scope.$watch(list.name, assignCredentialKinds);
-
- // search init
- $scope.list = list;
- $scope[`${list.iterator}_dataset`] = Dataset.data;
- $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
-
- $scope.selected = [];
- }
-
- $scope.$on(`${list.iterator}_options`, function(event, data){
- $scope.options = data.data.actions.GET;
- });
-
- function assignCredentialKinds () {
- if (!Array.isArray($scope[list.name])) {
- return;
- }
-
- const params = $scope[list.name]
- .reduce((accumulator, credential) => {
- accumulator.push(credential.credential_type);
-
- return accumulator;
- }, [])
- .filter((id, i, array) => array.indexOf(id) === i)
- .map(id => `or__id=${id}`);
-
- credentialType.search(params)
- .then(found => {
- if (!found) {
- return;
- }
-
- $scope[list.name].forEach(credential => {
- credential.kind = credentialType.match('id', credential.credential_type).name;
- });
- });
- }
-
- $scope.copyCredential = credential => {
- Wait('start');
- new Credential('get', credential.id)
- .then(model => model.copy())
- .then((copiedCred) => {
- ngToast.success({
- content: `
-
-
-
-
-
- ${CredentialsStrings.get('SUCCESSFUL_CREATION', copiedCred.name)}
-
-
`,
- dismissButton: false,
- dismissOnTimeout: true
- });
- $state.go('.', null, { reload: true });
- })
- .catch(({ data, status }) => {
- const params = { hdr: 'Error!', msg: `Call to copy failed. Return status: ${status}` };
- ProcessErrors($scope, data, status, null, params);
- })
- .finally(() => Wait('stop'));
- };
-
- $scope.addCredential = function() {
- $state.go('credentials.add');
- };
-
- $scope.editCredential = function(id) {
- $state.go('credentials.edit', { credential_id: id });
- };
-
- $scope.deleteCredential = function(id, name) {
- var action = function() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- var url = defaultUrl + id + '/';
- credential.request('delete', id)
- .then(() => {
-
- let reloadListStateParams = null;
-
- if($scope.credentials.length === 1 && $state.params.credential_search && _.has($state, 'params.credential_search.page') && $state.params.credential_search.page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.credential_search.page = (parseInt(reloadListStateParams.credential_search.page)-1).toString();
- }
-
- if (parseInt($state.params.credential_id) === id) {
- $state.go("^", reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, {reload: true});
- }
- Wait('stop');
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
- });
- });
- };
-
- credential.getDependentResourceCounts(id)
- .then((counts) => {
- const invalidateRelatedLines = [];
- let deleteModalBody = `
${CredentialsStrings.get('deleteResource.CONFIRM', 'credential')}
`;
-
- counts.forEach(countObj => {
- if(countObj.count && countObj.count > 0) {
- invalidateRelatedLines.push(`
${countObj.label} ${countObj.count}
`);
- }
- });
-
- if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
- deleteModalBody = `
${CredentialsStrings.get('deleteResource.USED_BY', 'credential')} ${CredentialsStrings.get('deleteResource.CONFIRM', 'credential')}
`;
- invalidateRelatedLines.forEach(invalidateRelatedLine => {
- deleteModalBody += invalidateRelatedLine;
- });
- }
-
- Prompt({
- hdr: i18n._('Delete'),
- resourceName: $filter('sanitize')(name),
- body: deleteModalBody,
- action: action,
- actionText: i18n._('DELETE')
- });
- });
- };
- }
-];
diff --git a/awx/ui/client/src/credentials/main.js b/awx/ui/client/src/credentials/main.js
deleted file mode 100644
index 094e7ce568..0000000000
--- a/awx/ui/client/src/credentials/main.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import ownerList from './ownerList.directive';
-import CredentialsList from './list/credentials-list.controller';
-import BecomeMethodChange from './factories/become-method-change.factory';
-import CredentialFormSave from './factories/credential-form-save.factory';
-import KindChange from './factories/kind-change.factory';
-import OwnerChange from './factories/owner-change.factory';
-import CredentialList from './credentials.list';
-import CredentialForm from './credentials.form';
-
-export default
- angular.module('credentials', [])
- .directive('ownerList', ownerList)
- .factory('BecomeMethodChange', BecomeMethodChange)
- .factory('CredentialFormSave', CredentialFormSave)
- .factory('KindChange', KindChange)
- .factory('OwnerChange', OwnerChange)
- .controller('CredentialsList', CredentialsList)
- .factory('CredentialList', CredentialList)
- .factory('CredentialForm', CredentialForm);
diff --git a/awx/ui/client/src/credentials/ownerList.block.less b/awx/ui/client/src/credentials/ownerList.block.less
deleted file mode 100644
index 47ce63124e..0000000000
--- a/awx/ui/client/src/credentials/ownerList.block.less
+++ /dev/null
@@ -1,33 +0,0 @@
-.OwnerList {
- display: flex;
- flex-wrap: wrap;
- align-items: flex-start;
-}
-
-.OwnerList-seeBase {
- display: flex;
- max-width: 100%;
-
- color: @default-link;
- text-transform: uppercase;
- padding: 2px 15px;
- cursor: pointer;
- border-radius: 5px;
- font-size: 11px;
-}
-
-.OwnerList-seeBase:hover {
- color: @default-link-hov;
-}
-
-.OwnerList-seeLess {
- .OwnerList-seeBase;
-}
-
-.OwnerList-seeMore {
- .OwnerList-seeBase;
-}
-
-.OwnerList-Container {
- margin-right: 5px;
-}
diff --git a/awx/ui/client/src/credentials/ownerList.directive.js b/awx/ui/client/src/credentials/ownerList.directive.js
deleted file mode 100644
index a5178bc69b..0000000000
--- a/awx/ui/client/src/credentials/ownerList.directive.js
+++ /dev/null
@@ -1,13 +0,0 @@
-export default
- [ 'templateUrl',
- function(templateUrl) {
- return {
- restrict: 'E',
- scope: false,
- templateUrl: templateUrl('credentials/ownerList'),
- link: function(scope) {
- scope.owners_list = scope.credential.summary_fields.owners && scope.credential.summary_fields.owners.length > 0 ? scope.credential.summary_fields.owners : [];
- }
- };
- }
- ];
diff --git a/awx/ui/client/src/credentials/ownerList.partial.html b/awx/ui/client/src/credentials/ownerList.partial.html
deleted file mode 100644
index a0faea839b..0000000000
--- a/awx/ui/client/src/credentials/ownerList.partial.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- View More
-
-
-
- View Less
-
-
diff --git a/awx/ui/client/src/debug.js b/awx/ui/client/src/debug.js
deleted file mode 100644
index 4842112f71..0000000000
--- a/awx/ui/client/src/debug.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/*********************************************
- * @ngdoc function
- * @name __deferLoadIfEnabled
- * @description
- *
- * This function only included in debug releases.
- *
- * This function exists to make it easier to debug when using sourcemaps.
- * There is currently an issue in Chrome (and possibly other browsers) where
- * breakpoints that hit before sourcemaps are downloaded do not work.
- *
- * Calling this function uses a feature in Angular that looks for a prefix on
- * the `window.name` property to tell it to disable automatic loading of the app.
- *
- * If you need to debug code that runs at load time, first add:
- *
- * ?aw.suspend=true
- *
- * to the end of the URL. When you see the main logo loaded on an otherwise blank page,
- * open the Dev Tools console and execute the code:
- *
- * angular.resumeBootstrap()
- *
- * This should continue loading the app and hit your breakpoint.
- *
- * For more information on how this works see https://docs.angularjs.org/guide/bootstrap
-*/
-export function __deferLoadIfEnabled() {
-
- var deferPattern = /aw\.suspend=true/;
-
- if (deferPattern.test(window.location.search) || deferPattern.test(window.location.hash)) {
- /* jshint ignore:start */
- console.info('Deferred load due to "aw.suspend=true" in URL. Please execute `angular.resumeBootstrap()` to continue.');
- /* jshint ignore:end */
- window.name = 'NG_DEFER_BOOTSTRAP!' + (window.name || '');
- }
-
-}
-
-
-/* jshint ignore:start */
-export function time(fn, label) {
- return function() {
- console.timeline(label);
- return _.tap(fn.apply(this, arguments), function() {
- console.timelineEnd(label);
- });
- };
-}
-/* jshint ignore:end */
diff --git a/awx/ui/client/src/docs.js b/awx/ui/client/src/docs.js
deleted file mode 100644
index c66f9376a6..0000000000
--- a/awx/ui/client/src/docs.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import './shared/multi-select-list/main.js';
-import './shared/route-extensions/main.js';
diff --git a/awx/ui/client/src/home/dashboard/counts/dashboard-counts.block.less b/awx/ui/client/src/home/dashboard/counts/dashboard-counts.block.less
deleted file mode 100644
index 5aed519f10..0000000000
--- a/awx/ui/client/src/home/dashboard/counts/dashboard-counts.block.less
+++ /dev/null
@@ -1,88 +0,0 @@
-/** @define DashboardCounts */
-
-.DashboardCounts {
- display: flex;
- flex-direction: row;
- align-items: stretch;
- flex-wrap: wrap;
- justify-content: space-between;
- width: 100%;
- padding-top: 0;
- margin-top: 0;
-}
-
-.DashboardCounts-buttonStyle {
- text-align: center;
- padding: 8px;
- padding-bottom: 11px;
- padding-left: 15px;
- padding-right: 15px;
- border-radius: 5px;
- background-color: @db-panel-bg;
- border: 1px solid @b7grey;
- flex: 1 0 auto;
- max-width: ~"calc(16.6% - 15px)";
- flex-basis: ~"calc(16.6% - 15px)";
- transition: background-color 0.2s, border-color 0.2s;
-}
-
-.DashboardCounts-buttonStyle:hover {
- background-color: @db-count-succ;
- border-color: @db-count-succ;
-
- .DashboardCounts-number,
- .DashboardCounts-label {
- color: @db-count-label-hov;
- }
-}
-
-.DashboardCounts-buttonStyle.is-failure:hover {
- background-color: @db-count-fail;
- border-color: @db-count-fail;
-
- .DashboardCounts-number,
- .DashboardCounts-label {
- color: @db-count-label-hov;
- }
-}
-
-.DashboardCounts-number {
- font-size: 30px;
- line-height: 26px;
- flex: 1;
- transition: color 0.2s;
-}
-
-.DashboardCounts-number.is-failure {
- color: @db-count-fail;
-}
-
-.DashboardCounts-label {
- flex: 1;
- margin-bottom: 0px;
- margin-top: 0.625rem;
- color: @db-count-label;
- text-transform: uppercase;
- transition: color 0.2s;
- font-size: 0.75rem;
-}
-
-@media only screen and (max-width: 710px) {
- .DashboardCounts {
- margin-bottom: -15px;
- }
-
- .DashboardCounts-buttonStyle {
- margin-bottom: 15px;
- width: 33%;
- flex-basis: ~"calc(33% - 7px)";
- max-width: ~"calc(33% - 7px)";
- height: 96px;
- }
-}
-
-@media only screen and (max-width: 360px) {
- .DashboardCounts-label {
- font-size: 10px;
- }
-}
diff --git a/awx/ui/client/src/home/dashboard/counts/dashboard-counts.directive.js b/awx/ui/client/src/home/dashboard/counts/dashboard-counts.directive.js
deleted file mode 100644
index 4b4e8c1690..0000000000
--- a/awx/ui/client/src/home/dashboard/counts/dashboard-counts.directive.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* jshint unused: vars */
-export default
- [ 'templateUrl',
- 'i18n',
- function(templateUrl, i18n) {
- return {
- restrict: 'E',
- scope: {
- data: '='
- },
- replace: false,
- templateUrl: templateUrl('home/dashboard/counts/dashboard-counts'),
- link: function(scope, element, attrs) {
- scope.$watch("data", function(data) {
- if (data && data.hosts) {
- createCounts(data);
- }
- });
-
- function addFailureToCount(val) {
- if (val.isFailureCount) {
- // delete isFailureCount
- if (val.number > 0) {
- val.isFailure = true;
- } else {
- val.isFailure = false;
- }
- } else {
- val.isFailure = false;
- }
- return val;
- }
-
- function createCounts(data) {
- scope.counts = _.map([
- {
- url: "/#/hosts",
- number: scope.data.hosts.total,
- label: i18n._("Hosts")
- },
- {
- url: "/#/hosts?host_search=last_job_host_summary__failed:true",
- number: scope.data.hosts.failed,
- label: i18n._("Failed Hosts"),
- isFailureCount: true
- },
- {
- url: "/#/inventories",
- number: scope.data.inventories.total,
- label: i18n._("Inventories"),
- },
- {
- url: "/#/inventories?inventory_search=inventory_sources_with_failures__gt:0",
- number: scope.data.inventories.inventory_failed,
- label: i18n._("Inventory Sync Failures"),
- isFailureCount: true
- },
- {
- url: "/#/projects",
- number: scope.data.projects.total,
- label: i18n._("Projects")
- },
- {
- url: "/#/projects?project_search=status__in:failed,canceled",
- number: scope.data.projects.failed,
- label: i18n._("Project Sync Failures"),
- isFailureCount: true
- }
- ], function(val) { return addFailureToCount(val); });
- }
- }
- };
- }
- ];
diff --git a/awx/ui/client/src/home/dashboard/counts/dashboard-counts.partial.html b/awx/ui/client/src/home/dashboard/counts/dashboard-counts.partial.html
deleted file mode 100644
index 522b4fff4d..0000000000
--- a/awx/ui/client/src/home/dashboard/counts/dashboard-counts.partial.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/awx/ui/client/src/home/dashboard/counts/main.js b/awx/ui/client/src/home/dashboard/counts/main.js
deleted file mode 100644
index ae56888e3b..0000000000
--- a/awx/ui/client/src/home/dashboard/counts/main.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import dashboardCountsDirective from './dashboard-counts.directive';
-
-export default
- angular.module('DashboardCountModules', [])
- .directive('dashboardCounts', dashboardCountsDirective);
diff --git a/awx/ui/client/src/home/dashboard/dashboard.block.less b/awx/ui/client/src/home/dashboard/dashboard.block.less
deleted file mode 100644
index ec509d1833..0000000000
--- a/awx/ui/client/src/home/dashboard/dashboard.block.less
+++ /dev/null
@@ -1,42 +0,0 @@
-/** @define Dashboard */
-
-.Dashboard {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- width: 100%;
- margin-top: 20px;
-}
-
-.Dashboard-counts {
- flex: initial;
- width: 100%;
-}
-
-.Dashboard-graphs {
- flex: initial;
- width: 100%;
-}
-
-.Dashboard-list {
- border: 1px solid @b7grey;
- border-radius: 5px;
- margin-top: 20px;
- width: 50%;
- background-color: @default-bg;
- max-width: ~"calc(50% - 10px)";
- position: relative;
-}
-
-@media only screen and (max-width: 865px) {
- .Dashboard-counts {
- border: 0;
- padding: 0;
- }
-
- .Dashboard-list {
- flex: initial;
- width: 100%;
- max-width: 100%;
- }
-}
diff --git a/awx/ui/client/src/home/dashboard/dashboard.directive.js b/awx/ui/client/src/home/dashboard/dashboard.directive.js
deleted file mode 100644
index b7bf23d019..0000000000
--- a/awx/ui/client/src/home/dashboard/dashboard.directive.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/* jshint unused: vars */
-export default
- [ 'templateUrl',
- function(templateUrl) {
- return {
- restrict: 'E',
- scope: true,
- templateUrl: templateUrl('home/dashboard/dashboard'),
- link: function(scope, element, attrs) {
- }
- };
- }
- ];
diff --git a/awx/ui/client/src/home/dashboard/dashboard.partial.html b/awx/ui/client/src/home/dashboard/dashboard.partial.html
deleted file mode 100644
index dc2aa78245..0000000000
--- a/awx/ui/client/src/home/dashboard/dashboard.partial.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.block.less b/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.block.less
deleted file mode 100644
index e4acd76995..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.block.less
+++ /dev/null
@@ -1,233 +0,0 @@
-/** @define DashboardGraphs */
-
-.DashboardGraphs {
- margin-top: 20px;
- border: solid 1px @b7grey;
- border-radius: 5px;
- background-color: @db-panel-bg;
- padding-top:20px;
- padding-left: 20px;
- padding-right: 20px;
-}
-
-.DashboardGraphs-headerSection{
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- align-items: flex-start;
- justify-content: flex-start;
-}
-
-.DashboardGraphs-headerText {
- flex: 1;
- margin: 0px;
- font-size: 14px;
- font-weight: bold;
- color: @default-interface-txt;
- white-space: nowrap;
- margin-right: auto;
-}
-
-.DashboardGraphs-graphSection {
- display: block;
- flex: 1;
-}
-
-.DashboardGraphs-graphContainer {
- width: 0%;
- display: none;
-}
-
-.DashboardGraphs-graphContainer.is-selected {
- width: 100%;
- display: block;
-}
-
-.DashboardGraphs-filterLabelIcon{
- color: @db-graph-per-dd-icon;
- font-size: 14px;
- padding-top: 5px;
-}
-
-.DashboardGraphs-filterLabel{
- color: @db-graph-per-dd-txt;
- font-size: 10px;
- padding-right: 10px;
- padding-left: 10px;
- text-transform: uppercase;
- display: inline-block;
- vertical-align: middle;
- height: 20px;
-
- & > span {
- display: inline-block;
- vertical-align: middle;
- line-height: 20px;
- }
-}
-
-.DashboardGraphs-graph {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
-}
-
-.DashboardGraphs-graphToolbar {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
-}
-
-.DashboardGraphs-filterDropdownText,
-.DashboardGraphs-filterDropdownText:hover,
-.DashboardGraphs-filterDropdownText:focus,
-.DashboardGraphs-filterDropdownText:active {
- color: @default-data-txt;
-}
-
-.DashboardGraphs-filterDropdownText {
- align-items: center;
- background-color: @db-graph-per-dd-bg;
- border-radius: 5px;
- border: 1px solid @b7grey;
- display: inline-flex;
- font-size: 10px;
- height: 20px;
- justify-content: space-between;
- padding: 0 10px;
- text-transform: uppercase;
- transition: background-color 0.2s;
- width: 100%;
-
- > span {
- width: 100%;
- }
-}
-
-.DashboardGraphs-filterDropdownText:hover {
- background-color: @db-graph-per-dd-bg-hov;
-}
-
-.DashboardGraphs-filterIcon {
- color: @db-graph-per-dd-icon;
- font-size: 12px;
- width: 20px;
- padding: 0 10px;
- float: right;
- margin-top: 1px;
-}
-
-.DashboardGraphs-filterDropdownItems {
- position: absolute;
- left: auto;
- top: auto;
- box-shadow: none;
- text-transform: uppercase;
- cursor: pointer;
- border-color: @d7grey;
- min-width: 115px;
-
- a:not([href]):not([tabindex]) {
- color: @default-interface-txt;
- }
-
- a > span {
- float: none;
- }
-}
-
-.DashboardGraphs-filterDropdownItems {
- & > li {
- font-size: 10px;
- }
-}
-
-.DashboardGraphs-periodDropdown,
-.DashboardGraphs-jobTypeDropdown,
-.DashboardGraphs-statusDropdown {
- font-size: 10px;
- display: inline-block;
- padding-top: 0px;
- min-width: 115px;
- width: inherit;
-}
-
-.DashboardGraphs-statusFilters{
- padding-top: 5px;
-}
-
-.DashboardGraphs-statusFilter{
- color: @btn-txt;
- background-color: @btn-bg;
- font-size: 12px;
- text-transform: uppercase;
- padding-right: 10px;
- padding-left: 10px;
- height: 20px;
- border: 1px solid @btn-bord;
- border-radius: 5px;
- transition: background-color 0.2s;
- margin-left: 10px;
- line-height:1;
-}
-
-.DashboardGraphs-statusFilter:hover{
- cursor: pointer;
- background-color: @btn-bg-hov;
-}
-
-.DashboardGraphs-statusFilter.is-selected {
- color: @btn-txt-sel;
- background-color: @btn-bg-sel;
- border-color: @btn-bord-sel;
-}
-
-.DashboardGraphs-statusFilterIcon{
- padding-right: 5px;
-}
-
-.DashboardGraphs-filteringDropdowns {
- display: inherit;
- margin-left: 10px;
-}
-
-.DashboardGraphs-filterDropdownItems {
- li > a {
- text-align: left;
- color: @default-interface-txt;
- }
-}
-
-@media only screen and (max-width: 800px) {
- .DashboardGraphs-graphToolbar {
- width: 100%;
- margin-right: 0px;
- }
-
- .DashboardGraphs-filterDropdownItems {
- left: 50%;
- right: 35px;
- }
-
- .DashboardGraphs-filteringDropdowns {
- float: left;
- width: 100%;
- margin-left: 0;
- }
-
- .DashboardGraphs-filterLabel {
- margin-top: 10px;
- width: 50%;
- float: left;
- padding-left: 0;
- }
-
- .DashboardGraphs-periodDropdown,
- .DashboardGraphs-jobTypeDropdown,
- .DashboardGraphs-statusDropdown {
- margin-top: 10px;
- width: 50%;
- float: left;
- }
-}
diff --git a/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.directive.js b/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.directive.js
deleted file mode 100644
index 80a0d4e181..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.directive.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* jshint unused: vars */
-export default ['templateUrl',
- function(templateUrl) {
- return {
- restrict: 'E',
- scope: true,
- templateUrl: templateUrl('home/dashboard/graphs/dashboard-graphs'),
- link: function(scope, element, attrs) {
-
- function clearStatus() {
- scope.isSuccessful = true;
- scope.isFailed = true;
- }
-
- clearStatus();
- scope.jobStatusSelected = true;
- scope.$broadcast("resizeGraphs");
-
- }
- };
- }
-];
diff --git a/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.partial.html b/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.partial.html
deleted file mode 100644
index 4d1d547a86..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/dashboard-graphs.partial.html
+++ /dev/null
@@ -1,106 +0,0 @@
-
diff --git a/awx/ui/client/src/home/dashboard/graphs/graph-helpers/adjust-graph-size.service.js b/awx/ui/client/src/home/dashboard/graphs/graph-helpers/adjust-graph-size.service.js
deleted file mode 100644
index 4eb3f916dd..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/graph-helpers/adjust-graph-size.service.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
-export default function() {
-
-
- // Adjusts the size of graphs based on the current height
- // of the outer parent (see auto-size-module directive).
- //
- // Since the graph's svg element is set to width & height of 100%,
- // it will automatically size itself when the size of its container
- // changes. Since boxes in HTML automatically fill the width of their
- // parent, we don't have to change the container's width. However,
- // since the makers HTML never heard of vertical rhythm,
- // we have to manually set a new height on the container.
- //
- // ## Calculating the container's new height
- //
- // newHeight is the height we assign to the graph's immediate parent.
- // This is calculated as the height of the graph-container (the
- // outer parent), offset by the height of the toolbar row
- // (the contains the title and/or any filters) and the
- // bottom margin.
- //
- // ## Responsive Graph Stuff
- //
- // Letting the svg element automatically scale only solves part of
- // the responsive graph problem. d3 draws graphs as paths, with static
- // positioning of all elements. Therefore, we need to tell the graph how
- // to adjust itself so that it can resize properly.
- //
- // ### Resizing the axes
- //
- // First we get the width & height of the chart after it has been modified
- // by setting the height on its parent (see Calculating the New Container's
- // Height above). Note that we need to offset the width/height by the margins
- // to make sure we keep all the spacing intact.
- //
- // Next, we update the range for x & y to take the new width & height into
- // account. d3 uses this range to map domain values (the actual data) onto
- // pixels.
- //
- // After that we adjust the number of ticks on the axes. This makes sure we
- // will never have overlapping ticks. If that does become a problem, try
- // changing the divisor in the calculations to a different number until you
- // find something that helps. For example, (width / 75) should make the x
- // axis only ever display 1 tick per every 75 pixels.
- //
- // ### Redrawing the line
- //
- // Since this is a line graph, now that we've changed the range & ticks,
- // we need to instruct d3 to repaint (redraw) the actual lines representing
- // the data. We do this by setting the "d" attribute of the path element
- // that represents the line to the line function on the chart model. This
- // function triggers the mapping of domain to range, and plots the chart.
- // Calling chartModel.update() at the end instructs nv to process our changes.
- //
- return function adjustGraphSize(chartModel, element) {
- if (chartModel) {
- var margins = chartModel.margin();
- var graph = d3.select(element.find('svg')[0]);
- var width = parseInt(graph.style('width')) - margins.left - margins.right;
- // var height = parseInt(graph.style('height')) - margins.top - margins.bottom;
- // console.log(height);
- var height = 200;
-
- chartModel.xRange([0, width]);
- chartModel.yRange([height, 0]);
-
- chartModel.xAxis.ticks(Math.max(width / 75, 2));
- chartModel.yAxis.ticks(Math.max(height / 50, 2));
-
- if (height < 160) {
- graph.select('.y.nv-axis').select('.domain').style('display', 'none');
- graph.select('.y.nv-axis').select('.domain').style('display', 'initial');
- }
-
- graph.select('.x.nv-axis')
- .attr('transform', 'translate(0, ' + height + ')')
- .call(chartModel.xAxis);
-
- graph.selectAll('.line')
- .attr('d', chartModel.lines);
-
- if (chartModel.update) {
- chartModel.update();
- }
- }
- };
-}
diff --git a/awx/ui/client/src/home/dashboard/graphs/graph-helpers/auto-size.directive.js b/awx/ui/client/src/home/dashboard/graphs/graph-helpers/auto-size.directive.js
deleted file mode 100644
index 1604d58ba5..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/graph-helpers/auto-size.directive.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default
- [ '$window',
- AutoSizeModule
- ];
-
-function AutoSizeModule($window) {
-
- // Adjusts the size of the module so that all modules
- // fit into a single a page; assumes there are 2 rows
- // of modules, with the available height being offset
- // by the navbar & the count summaries module
- return function(scope, element, attrs) {
-
- function adjustSize() {
- if (attrs.graphType === "hostStatus") {
- if (element.parent().width() > 596) {
- element.height(285);//596);
- } else {
- element.height(element.parent().width());
- }
- } else {
- element.height(285);
- }
- }
-
- $($window).resize(adjustSize);
-
- element.on('$destroy', function() {
- $($window).off('resize', adjustSize);
- });
-
- // This makes sure count-container div is loaded
- // by controllers/Home.js before we use it
- // to determine the available window height
- scope.$on('resizeGraphs', function() {
- adjustSize();
- });
-
- };
-
-}
diff --git a/awx/ui/client/src/home/dashboard/graphs/graph-helpers/main.js b/awx/ui/client/src/home/dashboard/graphs/graph-helpers/main.js
deleted file mode 100644
index 9c2740fd58..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/graph-helpers/main.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import AutoSize from './auto-size.directive';
-import AdjustGraphSize from './adjust-graph-size.service';
-
-export default angular.module('DashboardGraphHelpers', [])
- .directive('autoSizeModule', AutoSize)
- .service('adjustGraphSize', AdjustGraphSize);
diff --git a/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.directive.js b/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.directive.js
deleted file mode 100644
index 51b56ec3bd..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.directive.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default
- [ '$window',
- 'adjustGraphSize',
- 'templateUrl',
- 'i18n',
- 'moment',
- 'jobStatusGraphData',
- JobStatusGraph
- ];
-
-function JobStatusGraph($window, adjustGraphSize, templateUrl, i18n, moment, graphDataService) {
- return {
- restrict: 'E',
- scope: {
- data: '=',
- period: '=',
- jobType: '=',
- status: '='
- },
- templateUrl: templateUrl('home/dashboard/graphs/job-status/job_status_graph'),
- link: link
- };
-
- function link(scope, element) {
- var job_status_chart = nv.models.lineChart();
-
- scope.$watchCollection('data', function(value) {
- if (value) {
- createGraph(scope.period, scope.jobType, value, scope.status);
- }
- });
-
- function recreateGraph(period, jobType, status) {
- graphDataService.get(period, jobType, status)
- .then(function(data) {
- scope.data = data;
- scope.period = period;
- scope.jobType = jobType;
- scope.status = Object.is(status, undefined) ? scope.status : status;
- });
- }
-
- function createGraph(period, jobtype, data, status){
- scope.period = period;
- scope.jobType = jobtype;
- scope.status = status;
-
- var timeFormat, graphData = [
- { "color": "#5CB85C",
- "key": i18n._("SUCCESSFUL"),
- "values": data.jobs.successful
- },
- { "key" : i18n._("FAILED") ,
- "color" : "#D9534F",
- "values": data.jobs.failed
- }
- ];
-
- graphData = _.reject(graphData, function(num){
- if(status!== undefined && status === num.key.toLowerCase()){
- return num;
- }
- });
-
- if(period === "day") {
- timeFormat="H:mm";
- }
- else {
- timeFormat = "MMM D";
- }
- graphData.map(function(series) {
- series.values = series.values.map(function(d) {
- return {
- x: d[0],
- y: d[1]
- };
- });
- return series;
- });
-
- job_status_chart
- .useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
- .showLegend(false) //Show the legend, allowing users to turn on/off line series.
- .showYAxis(true) //Show the y-axis
- .showXAxis(true) //Show the x-axis
- .margin({ right: 32 });
-
- job_status_chart.interactiveLayer.tooltip.fixedTop(-10); //distance from the top of the chart to tooltip
- job_status_chart.interactiveLayer.tooltip.distance(-1); //distance from interactive line to tooltip
-
- scope.$on('$destroy', function() {
- job_status_chart.tooltip.hidden(true);
- job_status_chart.interactiveLayer.tooltip.hidden(true);
- });
-
- job_status_chart.xAxis
- .axisLabel(i18n._("TIME"))//.showMaxMin(true)
- .tickFormat(function(d) {
- if (d) {
- const tickDate = new Date(Number(d + '000'));
- return moment(tickDate).format(timeFormat);
- }
- else {
- return '';
- }
- });
-
- job_status_chart.yAxis //Chart y-axis settings
- .axisLabel(i18n._('JOBS'))
- .tickFormat(d3.format('.f'));
-
- d3.select(element.find('svg')[0])
- .datum(graphData)
- .call(job_status_chart)
- .style({
- "font-family": 'Open Sans',
- "font-style": "normal",
- "font-weight":400,
- "src": "url(/static/assets/OpenSans-Regular.ttf)"
- });
-
- // when the Period drop down filter is used, create a new graph based on the
- $('.n').off('click').on("click", function(){
- $('#period-dropdown-display')
- .html(`
-
${this.text}
-
- `);
-
- scope.$parent.isFailed = true;
- scope.$parent.isSuccessful = true;
- recreateGraph(this.getAttribute("id"), scope.jobType, scope.status);
- });
-
- //On click, update with new data
- $('.m').off('click').on("click", function(){
- $('#type-dropdown-display')
- .html(`
-
${this.text}
-
- `);
-
- scope.$parent.isFailed = true;
- scope.$parent.isSuccessful = true;
- recreateGraph(scope.period, this.getAttribute("id"), scope.status);
- });
-
- $('.o').off('click').on('click', function() {
- $('#status-dropdown-display')
- .html(`
-
${this.text}
-
- `);
-
- recreateGraph(scope.period, scope.jobType, this.getAttribute("id"));
- });
-
- adjustGraphSize(job_status_chart, element);
- }
-
- function onResize() {
- adjustGraphSize(job_status_chart, element);
-
- }
-
- angular.element($window).on('resize', onResize);
- $(".DashboardGraphs-graph--jobStatusGraph").resize(onResize);
-
- element.on('$destroy', function() {
- angular.element($window).off('resize', onResize);
- $(".DashboardGraphs-graph--jobStatusGraph").removeResize(onResize);
- });
-
- if (scope.removeGraphDataReady) {
- scope.removeGraphDataReady();
- }
-
- }
- }
diff --git a/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js b/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js
deleted file mode 100644
index 8d7f5fb690..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ["Rest", "GetBasePath", "ProcessErrors", "$q", JobStatusGraphData];
-
-function JobStatusGraphData(Rest, getBasePath, processErrors, $q) {
- return {
- get: function(period, jobType, status) {
- var url, dash_path = getBasePath('dashboard');
- if(dash_path === '' ){
- processErrors(null,
- null,
- null,
- null, {
- hdr: 'Error!',
- msg: "There was an error. Please try again."
- });
- return;
- }
- url = dash_path + 'graphs/jobs/?period='+period+'&job_type='+jobType;
- Rest.setHeader({'X-WS-Session-Quiet': true});
- Rest.setUrl(url);
- return Rest.get()
- .then(function(value) {
- if(status === "successful" || status === "failed"){
- delete value.data.jobs[status];
- }
- return value.data;
- })
- .catch(function(response) {
- var errorMessage = 'Failed to get: ' + response.url + ' GET returned: ' + response.status;
-
- processErrors(null,
- response.data,
- response.status,
- null, {
- hdr: 'Error!',
- msg: errorMessage
- });
- return $q.reject(response);
- });
-
- }
- };
-}
diff --git a/awx/ui/client/src/home/dashboard/graphs/job-status/job_status_graph.partial.html b/awx/ui/client/src/home/dashboard/graphs/job-status/job_status_graph.partial.html
deleted file mode 100644
index adfd5df6dd..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/job-status/job_status_graph.partial.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/awx/ui/client/src/home/dashboard/graphs/job-status/main.js b/awx/ui/client/src/home/dashboard/graphs/job-status/main.js
deleted file mode 100644
index 927bc475df..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/job-status/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import JobStatusGraphDirective from './job-status-graph.directive';
-import JobStatusGraphService from './job-status-graph.service';
-import DashboardGraphHelpers from '../graph-helpers/main';
-import templateUrl from '../../../../shared/template-url/main';
-
-export default angular.module('JobStatusGraph', [DashboardGraphHelpers.name, templateUrl.name])
- .directive('jobStatusGraph', JobStatusGraphDirective)
- .service('jobStatusGraphData', JobStatusGraphService);
diff --git a/awx/ui/client/src/home/dashboard/graphs/main.js b/awx/ui/client/src/home/dashboard/graphs/main.js
deleted file mode 100644
index 705f2986b8..0000000000
--- a/awx/ui/client/src/home/dashboard/graphs/main.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import jobStatus from './job-status/main';
-import dashboardGraphsDirective from './dashboard-graphs.directive';
-
-export default
- angular.module('DashboardGraphModules', [jobStatus.name])
- .directive('dashboardGraphs', dashboardGraphsDirective);
diff --git a/awx/ui/client/src/home/dashboard/lists/dashboard-list.block.less b/awx/ui/client/src/home/dashboard/lists/dashboard-list.block.less
deleted file mode 100644
index 861da5a1ac..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/dashboard-list.block.less
+++ /dev/null
@@ -1,124 +0,0 @@
-/** @define DashboardList */
-
-.DashboardList {
- flex: 1;
-}
-.DashboardList--noJobTemplates {
- color: @list-empty-txt;
-}
-
-.DashboardList-header {
- display: flex;
- border-bottom: 1px solid @list-header-bord;
- margin-top: 20px;
-}
-
-.DashboardList-headerText {
- flex: 1;
- margin: 0px;
- font-size: 14px;
- font-weight: bold;
- color: @list-header-txt;
- white-space: nowrap;
- padding-left: 20px;
-}
-
-.DashboardList-tableHeaderIcon {
- color: @list-header-icon;
-}
-
-.DashboardList-viewAll {
- font-size: 11px;
- margin-right: 15px;
- padding-left: 10px;
- padding-right: 10px;
-}
-
-.DashboardList-container {
- flex: 1;
- width: 100%;
- padding: 20px;
- padding-top: 0;
-}
-
-.DashboardList-tableHeader--name {
- border-top-left-radius: 5px;
- padding-left: 15px;
-}
-
-.DashboardList-tableHeader--activity {
- width: 205px;
- padding-left:20px
-}
-
-.DashboardList-tableHeader--time {
- justify-content: flex-end;
-}
-
-.DashboardList-tableHeader--actions {
- border-top-right-radius: 5px;
- width: 110px;
- padding-right: 15px;
- text-align: right;
-}
-
-.DashboardList-status{
- padding-right: 9px;
-}
-
-.DashboardList-status--success{
- color: @default-succ;
-}
-
-.DashboardList-status--failed{
- color: @default-err;
-}
-
-.DashboardList-status--failed{
- color: @default-err;
- margin-top: 10px;
- margin-bottom: 10px;
- padding: 0px;
- margin-right: 5px;
-}
-
-.DashboardList-status--failed:before {
- content: "\f06a";
-}
-
-.DashboardList-timeCell {
- white-space: nowrap;
- display: flex;
- justify-content: flex-end;
-}
-
-.DashboardList-nameContainer:hover {
- color: @default-link-hov;
- cursor: pointer;
-}
-
-.DashboardList-noJobs {
- color: @list-empty-txt;
- margin-top: 20px;
-}
-
-@media only screen and (max-width: 360px) {
- .DashboardList-headerText {
- white-space: normal;
- line-height: 22px;
- padding-top: 10px;
- }
-
- .DashboardList-timeCell {
- white-space: normal;
- }
-}
-
-@media only screen and (max-width: 540px) {
- .DashboardList-container {
- th {
- width: 25%;
- white-space: nowrap;
- }
- }
-}
diff --git a/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js b/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js
deleted file mode 100644
index b1ba95a73d..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* jshint unused: vars */
-export default
- ['templateUrl', '$state', 'Rest', 'GetBasePath',
- function JobTemplatesList(templateUrl, $state, Rest, GetBasePath) {
- return {
- restrict: 'E',
- link: link,
- scope: {
- data: '='
- },
- templateUrl: templateUrl('home/dashboard/lists/job-templates/job-templates-list')
- };
-
- function link(scope) {
-
- scope.$watch("data", function(data) {
- if (data) {
- if (data.length > 0) {
- createList(data);
- scope.noJobTemplates = false;
- } else {
- scope.noJobTemplates = true;
- }
- }
- }, true);
-
- scope.canAddJobTemplate = false;
- let url = GetBasePath('job_templates');
- Rest.setUrl(url);
- Rest.options()
- .then(({ data }) => {
- if (!data.actions.POST) {
- scope.canAddJobTemplate = false;
- } else {
- scope.canAddJobTemplate = true;
- }
- });
-
- function createList(list) {
- // smartStatus?, launchUrl, editUrl, name
- scope.templates = _.map(list, function(template){ return {
- recent_jobs: template.summary_fields.recent_jobs,
- can_start: template.summary_fields.user_capabilities.start,
- name: template.name,
- id: template.id,
- type: template.type,
- can_edit: template.summary_fields.user_capabilities.edit
- }; });
- }
-
- scope.isSuccessful = function (status) {
- return (status === "successful");
- };
-
- scope.editTemplate = function (template) {
- if(template) {
- if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) {
- $state.go('templates.editJobTemplate', {job_template_id: template.id});
- }
- else if(template.type && (template.type === 'Workflow Job Template' || template.type === 'workflow_job_template')) {
- $state.go('templates.editWorkflowJobTemplate', {workflow_job_template_id: template.id});
- }
- }
- };
- }
-}];
diff --git a/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.partial.html b/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.partial.html
deleted file mode 100644
index 8bff9f7bb4..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.partial.html
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
No job templates were recently used.
-
-
-
You can create a job template here .
-
-
-
diff --git a/awx/ui/client/src/home/dashboard/lists/job-templates/main.js b/awx/ui/client/src/home/dashboard/lists/job-templates/main.js
deleted file mode 100644
index 9825630182..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/job-templates/main.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import JobTemplatesListDirective from './job-templates-list.directive';
-import systemStatus from '../../../../smart-status/main';
-
-export default angular.module('JobTemplatesList', [systemStatus.name])
- .directive('jobTemplatesList', JobTemplatesListDirective);
diff --git a/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js b/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js
deleted file mode 100644
index cd7ad27842..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/* jshint unused: vars */
-export default
- [ '$filter',
- 'templateUrl',
- '$location',
- 'i18n',
- 'JobsStrings',
- function JobsList($filter, templateUrl, $location, i18n, strings) {
- return {
- restrict: 'E',
- link: link,
- scope: {
- data: '='
- },
- templateUrl: templateUrl('home/dashboard/lists/jobs/jobs-list')
- };
-
- function link(scope, element, attr) {
- scope.strings = strings;
- scope.$watch("data", function(data) {
- if (data) {
- if (data.length > 0) {
- createList(data);
- scope.noJobs = false;
- } else {
- scope.noJobs = true;
- }
- }
- });
-
- function createList(list) {
- // detailsUrl, status, name, time
- scope.jobs = _.map(list, function(job){
-
- let detailsUrl, tooltip;
-
- if (job.type === 'workflow_job') {
- detailsUrl = `/#/workflows/${job.id}`;
- } else {
- detailsUrl = `/#/jobs/playbook/${job.id}`;
- }
-
- return {
- detailsUrl,
- status: job.status,
- name: job.name,
- id: job.id,
- time: $filter('longDate')(job.finished),
- tooltip: tooltip
- }; });
- }
-
- scope.isSuccessful = function (status) {
- return (status === "successful");
- };
- }
-}];
diff --git a/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.partial.html b/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.partial.html
deleted file mode 100644
index e5fbc87e04..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.partial.html
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
No jobs were recently run.
-
-
diff --git a/awx/ui/client/src/home/dashboard/lists/jobs/main.js b/awx/ui/client/src/home/dashboard/lists/jobs/main.js
deleted file mode 100644
index ed520cb435..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/jobs/main.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import JobsListDirective from './jobs-list.directive';
-
-export default angular.module('JobsList', [])
- .directive('jobsList', JobsListDirective);
diff --git a/awx/ui/client/src/home/dashboard/lists/main.js b/awx/ui/client/src/home/dashboard/lists/main.js
deleted file mode 100644
index 5800cca51e..0000000000
--- a/awx/ui/client/src/home/dashboard/lists/main.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import jobTemplates from './job-templates/main';
-import jobs from './jobs/main';
-
-export default
- angular.module('DashboardListsModules', [jobTemplates.name, jobs.name]);
diff --git a/awx/ui/client/src/home/dashboard/main.js b/awx/ui/client/src/home/dashboard/main.js
deleted file mode 100644
index 80f27a1ff1..0000000000
--- a/awx/ui/client/src/home/dashboard/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import dashboardCounts from './counts/main';
-import dashboardGraphs from './graphs/main';
-import dashboardLists from './lists/main';
-import dashboardDirective from './dashboard.directive';
-
-export default
- angular.module('dashboard', [dashboardCounts.name, dashboardGraphs.name, dashboardLists.name])
- .directive('dashboard', dashboardDirective);
diff --git a/awx/ui/client/src/home/home.controller.js b/awx/ui/client/src/home/home.controller.js
deleted file mode 100644
index cef2324fd0..0000000000
--- a/awx/ui/client/src/home/home.controller.js
+++ /dev/null
@@ -1,246 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['$scope','Wait', '$timeout', 'i18n',
- 'Rest', 'GetBasePath', 'ProcessErrors', 'graphData',
- function($scope, Wait, $timeout, i18n,
- Rest, GetBasePath, ProcessErrors, graphData) {
-
- var dataCount = 0;
- let launchModalOpen = false;
- let refreshAfterLaunchClose = false;
- let pendingDashboardRefresh = false;
- let dashboardTimerRunning = false;
- let newJobsTimerRunning = false;
- let newTemplatesTimerRunning = false;
- let newJobs = [];
- let newTemplates =[];
-
- const fetchDashboardData = () => {
- Rest.setUrl(GetBasePath('dashboard'));
- Rest.get()
- .then(({data}) => {
- $scope.dashboardData = data;
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, { hdr: i18n._('Error!'), msg: i18n._(`Failed to get dashboard host graph data: ${status}`) });
- });
-
- if ($scope.graphData) {
- Rest.setUrl(`${GetBasePath('dashboard')}graphs/jobs/?period=${$scope.graphData.period}&job_type=${$scope.graphData.jobType}`);
- Rest.setHeader({'X-WS-Session-Quiet': true});
- Rest.get()
- .then(function(value) {
- if($scope.graphData.status === "successful" || $scope.graphData.status === "failed"){
- delete value.data.jobs[$scope.graphData.status];
- }
- $scope.graphData.jobStatus = value.data;
- })
- .catch(function({data, status}) {
- ProcessErrors(null, data, status, null, { hdr: i18n._('Error!'), msg: i18n._(`Failed to get dashboard graph data: ${status}`)});
- });
- }
-
- pendingDashboardRefresh = false;
- dashboardTimerRunning = true;
- $timeout(() => {
- if (pendingDashboardRefresh) {
- fetchDashboardData();
- } else {
- dashboardTimerRunning = false;
- }
- }, 5000);
- };
-
- const fetchNewJobs = () => {
- newJobsTimerRunning = true;
- const newJobIdsFilter = newJobs.join(',');
- newJobs = [];
- Rest.setUrl(`${GetBasePath("unified_jobs")}?id__in=${newJobIdsFilter}&order_by=-finished&finished__isnull=false&type=workflow_job,job&count_disabled=1`);
- Rest.get()
- .then(({ data }) => {
- const joinedJobs = data.results.concat($scope.dashboardJobsListData);
- $scope.dashboardJobsListData =
- joinedJobs.length > 5 ? joinedJobs.slice(0, 5) : joinedJobs;
- $timeout(() => {
- if (newJobs.length > 0) {
- fetchNewJobs();
- } else {
- newJobsTimerRunning = false;
- }
- }, 5000);
- })
- .catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: i18n._('Error!'),
- msg: i18n._(`Failed to get new jobs for dashboard: ${status}`)
- });
- });
- };
-
- const fetchNewTemplates = () => {
- newTemplatesTimerRunning = true;
- const newTemplateIdsFilter = newTemplates.join(',');
- newTemplates = [];
- Rest.setUrl(`${GetBasePath("unified_job_templates")}?id__in=${newTemplateIdsFilter}&order_by=-last_job_run&last_job_run__isnull=false&type=workflow_job_template,job_template&count_disabled=1"`);
- Rest.get()
- .then(({ data }) => {
- const joinedTemplates = data.results.concat($scope.dashboardJobTemplatesListData).sort((a, b) => new Date(b.last_job_run) - new Date(a.last_job_run));
- $scope.dashboardJobTemplatesListData =
- joinedTemplates.length > 5 ? joinedTemplates.slice(0, 5) : joinedTemplates;
- $timeout(() => {
- if (newTemplates.length > 0 && !launchModalOpen) {
- fetchNewTemplates();
- } else {
- newTemplatesTimerRunning = false;
- }
- }, 5000);
- })
- .catch(({ data, status }) => {
- ProcessErrors($scope, data, status, null, {
- hdr: i18n._('Error!'),
- msg: i18n._(`Failed to get new templates for dashboard: ${status}`)
- });
- });
- };
-
- $scope.$on('ws-jobs', function (e, msg) {
- if (msg.status === 'successful' || msg.status === 'failed' || msg.status === 'canceled' || msg.status === 'error') {
- newJobs.push(msg.unified_job_id);
- if (!newJobsTimerRunning) {
- fetchNewJobs();
- }
- if (!launchModalOpen) {
- if (!dashboardTimerRunning) {
- fetchDashboardData();
- } else {
- pendingDashboardRefresh = true;
- }
- } else {
- refreshAfterLaunchClose = true;
- }
- }
-
- const template = $scope.dashboardJobTemplatesListData.find((t) => t.id === msg.unified_job_template_id);
- if (template) {
- if (msg.status === 'pending') {
- if (template.summary_fields.recent_jobs.length === 10) {
- template.summary_fields.recent_jobs.pop();
- }
-
- template.summary_fields.recent_jobs.unshift({
- id: msg.unified_job_id,
- status: msg.status,
- type: msg.type
- });
- } else {
- for (let i=0; i
new Date(b.last_job_run) - new Date(a.last_job_run));
- }
- }
- } else {
- newTemplates.push(msg.unified_job_template_id);
- if (!launchModalOpen && !newTemplatesTimerRunning) {
- fetchNewTemplates();
- }
- }
- });
-
- $scope.$on('launchModalOpen', (evt, isOpen) => {
- evt.stopPropagation();
- if (!isOpen && refreshAfterLaunchClose) {
- refreshAfterLaunchClose = false;
- fetchDashboardData();
- if (newTemplates.length > 0) {
- fetchNewTemplates();
- }
- }
- launchModalOpen = isOpen;
- });
-
- if ($scope.removeDashboardDataLoadComplete) {
- $scope.removeDashboardDataLoadComplete();
- }
- $scope.removeDashboardDataLoadComplete = $scope.$on('dashboardDataLoadComplete', function () {
- dataCount++;
- if (dataCount === 3) {
- Wait("stop");
- dataCount = 0;
- }
- });
-
- if ($scope.removeDashboardReady) {
- $scope.removeDashboardReady();
- }
- $scope.removeDashboardReady = $scope.$on('dashboardReady', function (e, data) {
- $scope.dashboardCountsData = data;
- $scope.graphData = graphData;
- $scope.graphData.period = "month";
- $scope.graphData.jobType = "all";
- $scope.graphData.status = "both";
- $scope.$emit('dashboardDataLoadComplete');
- });
-
- if ($scope.removeDashboardJobsListReady) {
- $scope.removeDashboardJobsListReady();
- }
- $scope.removeDashboardJobsListReady = $scope.$on('dashboardJobsListReady', function (e, data) {
- $scope.dashboardJobsListData = data;
- $scope.$emit('dashboardDataLoadComplete');
- });
-
- if ($scope.removeDashboardJobTemplatesListReady) {
- $scope.removeDashboardJobTemplatesListReady();
- }
- $scope.removeDashboardJobTemplatesListReady = $scope.$on('dashboardJobTemplatesListReady', function (e, data) {
- $scope.dashboardJobTemplatesListData = data;
- $scope.$emit('dashboardDataLoadComplete');
- });
-
- Wait('start');
- Rest.setUrl(GetBasePath('dashboard'));
- Rest.get()
- .then(({data}) => {
- $scope.dashboardData = data;
- $scope.$emit('dashboardReady', data);
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, { hdr: i18n._('Error!'), msg: i18n._(`Failed to get dashboard: ${status}`) });
- });
- Rest.setUrl(GetBasePath("unified_jobs") + "?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job&count_disabled=1");
- Rest.setHeader({'X-WS-Session-Quiet': true});
- Rest.get()
- .then(({data}) => {
- data = data.results;
- $scope.$emit('dashboardJobsListReady', data);
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, { hdr: i18n._('Error!'), msg: i18n._(`Failed to get dashboard jobs list: ${status}`) });
- });
- Rest.setUrl(GetBasePath("unified_job_templates") + "?order_by=-last_job_run&page_size=5&last_job_run__isnull=false&type=workflow_job_template,job_template");
- Rest.get()
- .then(({data}) => {
- data = data.results;
- $scope.$emit('dashboardJobTemplatesListReady', data);
- })
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, { hdr: i18n._('Error!'), msg: i18n._(`Failed to get dashboard job templates list: ${status}`) });
- });
-
- }
-];
diff --git a/awx/ui/client/src/home/home.partial.html b/awx/ui/client/src/home/home.partial.html
deleted file mode 100644
index 6a45b63334..0000000000
--- a/awx/ui/client/src/home/home.partial.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/awx/ui/client/src/home/home.route.js b/awx/ui/client/src/home/home.route.js
deleted file mode 100644
index 3f6c657dd0..0000000000
--- a/awx/ui/client/src/home/home.route.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import {templateUrl} from '../shared/template-url/template-url.factory';
-import controller from './home.controller';
-import { N_ } from '../i18n';
-
-export default {
- name: 'dashboard',
- url: '/home',
- templateUrl: templateUrl('home/home'),
- controller: controller,
- params: { licenseMissing: null },
- data: {
- activityStream: true,
- refreshButton: true
- },
- ncyBreadcrumb: {
- label: N_("DASHBOARD")
- },
- resolve: {
- graphData: ['$q', 'jobStatusGraphData', '$rootScope',
- function($q, jobStatusGraphData, $rootScope) {
- return $rootScope.basePathsLoaded.promise.then(function() {
- return $q.all({
- jobStatus: jobStatusGraphData.get("month", "all"),
- });
- });
- }
- ]
- }
- // name: 'setup.about',
- // route: '/about',
- // controller: controller,
- // ncyBreadcrumb: {
- // label: N_("ABOUT")
- // },
- // onExit: function(){
- // // hacky way to handle user browsing away via URL bar
- // $('.modal-backdrop').remove();
- // $('body').removeClass('modal-open');
- // },
- // templateUrl: templateUrl('about/about')
-};
diff --git a/awx/ui/client/src/home/main.js b/awx/ui/client/src/home/main.js
deleted file mode 100644
index cc4c6ebb19..0000000000
--- a/awx/ui/client/src/home/main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import dashboard from './dashboard/main';
-import HomeController from './home.controller';
-import route from './home.route';
-
-export default
- angular.module('home', [
- dashboard.name
- ])
- .controller('HomeController', HomeController)
- .run(['$stateExtender', function($stateExtender){
- $stateExtender.addState(route);
- }]);
diff --git a/awx/ui/client/src/i18n.js b/awx/ui/client/src/i18n.js
deleted file mode 100644
index 04ee4ebcf7..0000000000
--- a/awx/ui/client/src/i18n.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { sprintf } from 'sprintf-js';
-
-function I18n (gettextCatalog) {
- return {
- N_,
- sprintf,
- _: s => gettextCatalog.getString(s),
- translate: (singular, context) => gettextCatalog.getString(singular, context),
- translatePlural: (count, singular, plural, context) => {
- return gettextCatalog.getPlural(count, singular, plural, context);
- },
- hasTranslation: () => gettextCatalog.strings[gettextCatalog.currentLanguage] !== undefined
- };
-}
-
-I18n.$inject = ['gettextCatalog'];
-
-function run (LOCALE, gettextCatalog) {
- if (LOCALE.code && LOCALE.strings) {
- gettextCatalog.setCurrentLanguage(LOCALE.code);
- gettextCatalog.setStrings(LOCALE.code, LOCALE.strings);
- }
-}
-
-run.$inject = ['LOCALE', 'gettextCatalog'];
-
-export function N_(s) {
- return s;
-}
-
-export default angular
- .module('I18N', [
- 'gettext'
- ])
- .factory('i18n', I18n)
- .run(run);
diff --git a/awx/ui/client/src/instance-groups/add-edit/add-edit-instance-groups.view.html b/awx/ui/client/src/instance-groups/add-edit/add-edit-instance-groups.view.html
deleted file mode 100644
index 73ca5b868f..0000000000
--- a/awx/ui/client/src/instance-groups/add-edit/add-edit-instance-groups.view.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.INSTANCES') }}
- {{:: vm.strings.get('tab.JOBS') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/awx/ui/client/src/instance-groups/add-edit/add-instance-group.controller.js b/awx/ui/client/src/instance-groups/add-edit/add-instance-group.controller.js
deleted file mode 100644
index d556c6dbbe..0000000000
--- a/awx/ui/client/src/instance-groups/add-edit/add-instance-group.controller.js
+++ /dev/null
@@ -1,40 +0,0 @@
-function AddController ($state, models, strings) {
- const vm = this || {};
- const { instanceGroup } = models;
-
- vm.mode = 'add';
- vm.strings = strings;
- vm.panelTitle = strings.get('state.ADD_BREADCRUMB_LABEL');
-
- vm.docs = {
- url: 'https://docs.ansible.com/ansible-tower/latest/html/userguide/instance_groups.html',
- help_text: vm.strings.get('tooltips.IG_DOCS_HELP_TEXT')
- };
-
- vm.tab = {
- details: { _active: true },
- instances: {_disabled: true },
- jobs: {_disabled: true }
- };
-
- vm.form = instanceGroup.createFormSchema('post');
-
- // Default policy instance percentage value is 0
- vm.form.policy_instance_percentage._value = 0;
-
- vm.form.save = data => {
- return instanceGroup.request('post', { data });
- };
-
- vm.form.onSaveSuccess = res => {
- $state.go('instanceGroups.edit', { instance_group_id: res.data.id }, { reload: true });
- };
-}
-
-AddController.$inject = [
- '$state',
- 'resolvedModels',
- 'InstanceGroupsStrings'
-];
-
-export default AddController;
\ No newline at end of file
diff --git a/awx/ui/client/src/instance-groups/add-edit/edit-instance-group.controller.js b/awx/ui/client/src/instance-groups/add-edit/edit-instance-group.controller.js
deleted file mode 100644
index 55972e36fe..0000000000
--- a/awx/ui/client/src/instance-groups/add-edit/edit-instance-group.controller.js
+++ /dev/null
@@ -1,62 +0,0 @@
-function EditController ($rootScope, $state, models, strings) {
- const vm = this || {};
- const { instanceGroup } = models;
-
- if (instanceGroup.get('is_containerized')) {
- return $state.go(
- 'instanceGroups.editContainerGroup',
- { instance_group_id: instanceGroup.get('id') },
- { reload: true }
- );
- }
-
- $rootScope.breadcrumb.instance_group_name = instanceGroup.get('name');
-
- vm.mode = 'edit';
- vm.strings = strings;
- vm.panelTitle = instanceGroup.get('name');
-
- vm.docs = {
- url: 'https://docs.ansible.com/ansible-tower/latest/html/userguide/instance_groups.html',
- help_text: vm.strings.get('tooltips.IG_DOCS_HELP_TEXT')
- };
-
- vm.tab = {
- details: {
- _active: true,
- _go: 'instanceGroups.edit',
- _params: { instance_group_id: instanceGroup.get('id') }
- },
- instances: {
- _go: 'instanceGroups.instances',
- _params: { instance_group_id: instanceGroup.get('id') }
- },
- jobs: {
- _go: 'instanceGroups.jobs',
- _params: { instance_group_id: instanceGroup.get('id') }
- }
- };
-
- vm.form = instanceGroup.createFormSchema('put');
-
- vm.form.disabled = !instanceGroup.has('options', 'actions.PUT');
-
- vm.form.name._disabled = instanceGroup.get('name') === 'tower';
-
- vm.form.save = data => {
- return instanceGroup.request('put', { data });
- };
-
- vm.form.onSaveSuccess = res => {
- $state.go('instanceGroups.edit', { instance_group_id: res.data.id }, { reload: true });
- };
-}
-
-EditController.$inject = [
- '$rootScope',
- '$state',
- 'resolvedModels',
- 'InstanceGroupsStrings'
-];
-
-export default EditController;
diff --git a/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.block.less b/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.block.less
deleted file mode 100644
index 0417101a73..0000000000
--- a/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.block.less
+++ /dev/null
@@ -1,24 +0,0 @@
-.CapacityAdjuster {
- margin-right: @at-space-4x;
- margin-top: 15px;
- margin-left: -10px;
- position: relative;
-
- &-valueLabel {
- top: -10px;
- color: @at-color-body-text;
- font-size: @at-font-size;
- position: absolute;
- text-align: center;
- width: 100%;
- }
-
- .at-InputSlider {
- align-items: center;
- }
-
- .at-InputSlider p {
- white-space: nowrap;
- margin: 0 10px;
- }
-}
\ No newline at end of file
diff --git a/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.directive.js b/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.directive.js
deleted file mode 100644
index d7a1c9d398..0000000000
--- a/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.directive.js
+++ /dev/null
@@ -1,75 +0,0 @@
-function CapacityAdjuster (templateUrl, ProcessErrors, Wait, strings) {
- return {
- scope: {
- state: '=',
- disabled: '@'
- },
- templateUrl: templateUrl('instance-groups/capacity-adjuster/capacity-adjuster'),
- restrict: 'E',
- replace: true,
- link: function(scope, el, attrs, controller) {
- const capacityAdjusterController = controller;
- const adjustment_values = [{
- label: strings.get('capacityAdjuster.CPU'),
- value: scope.state.cpu_capacity,
- },{
- label: strings.get('capacityAdjuster.RAM'),
- value: scope.state.mem_capacity
- }];
-
- scope.min_capacity = _.minBy(adjustment_values, 'value');
- scope.max_capacity = _.maxBy(adjustment_values, 'value');
-
- capacityAdjusterController.init();
- },
- controller: ['$scope', '$http', 'InstanceGroupsStrings',
- function($scope, $http, strings) {
- const vm = this || {};
- vm.strings = strings;
-
- function computeForks () {
- $scope.forks = Math.floor($scope.min_capacity.value + ($scope.max_capacity.value - $scope.min_capacity.value) * $scope.state.capacity_adjustment);
- }
-
- vm.init = () => {
- computeForks();
- };
-
- vm.slide = (state) => {
- Wait('start');
-
- computeForks();
-
- const data = {
- "capacity_adjustment": `${state.capacity_adjustment}`
- };
- const req = {
- method: 'PUT',
- url: state.url,
- data
- };
- $http(req)
- .catch(({data, status}) => {
- ProcessErrors(data, status, null, {
- hdr: 'Error!',
- msg: 'Call failed. Return status: ' + status
- });
- })
- .finally(() => {
- Wait('stop');
- });
- };
- }
- ],
- controllerAs: 'vm'
- };
-}
-
-CapacityAdjuster.$inject = [
- 'templateUrl',
- 'ProcessErrors',
- 'Wait',
- 'InstanceGroupsStrings'
-];
-
-export default CapacityAdjuster;
diff --git a/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.partial.html b/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.partial.html
deleted file mode 100644
index 66401d62d1..0000000000
--- a/awx/ui/client/src/instance-groups/capacity-adjuster/capacity-adjuster.partial.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- {{ forks }} {{:: vm.strings.get('capacityAdjuster.FORKS')}}
-
-
-
diff --git a/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.block.less b/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.block.less
deleted file mode 100644
index 03b5464195..0000000000
--- a/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.block.less
+++ /dev/null
@@ -1,47 +0,0 @@
-capacity-bar {
- align-items: center;
- color: @at-color-body-background-dark;
- display: flex;
- font-size: @at-font-size;
- min-width: 100px;
- white-space: nowrap;
- margin-top: 5px;
- margin-bottom: 5px;
-
- .CapacityBar {
- background-color: @default-bg;
- border-radius: 100vw;
- border: 1px solid @default-link;
- display: flex;
- flex: 1;
- height: 10px;
- margin-right: @at-space-2x;
- min-width: 100px;
- overflow: hidden;
- width: 100%;
- }
-
- .CapacityBar-remaining {
- background-color: @default-link;
- flex: 0 0 auto;
- }
-
- .CapacityBar-consumed {
- flex: 0 0 auto;
- }
-
- .CapacityBar--offline {
- color: @at-red;
- border-color: @at-gray-a9;
-
- .CapacityBar-remaining {
- background-color: @at-gray-b7;
- }
- }
-
- .Capacity-details--label {
- margin-right: @at-space-2x;
- text-align: right;
- text-transform: uppercase;
- }
-}
\ No newline at end of file
diff --git a/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.directive.js b/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.directive.js
deleted file mode 100644
index e1aea6a50f..0000000000
--- a/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.directive.js
+++ /dev/null
@@ -1,52 +0,0 @@
-function CapacityBar (templateUrl, strings) {
- return {
- scope: {
- capacity: '=',
- totalCapacity: '=',
- labelValue: '@',
- badge: '='
- },
- templateUrl: templateUrl('instance-groups/capacity-bar/capacity-bar'),
- restrict: 'E',
- link: function(scope) {
- scope.isOffline = false;
-
- scope.$watch('totalCapacity', function(val) {
- if (val === 0) {
- scope.isOffline = true;
- scope.labelValue = strings.get(`capacityBar.IS_OFFLINE_LABEL`);
- scope.offlineTip = strings.get(`capacityBar.IS_OFFLINE`);
- } else {
- scope.isOffline = false;
- scope.offlineTip = null;
- }
- }, true);
-
- scope.$watch('capacity', function() {
- if (scope.totalCapacity !== 0) {
- var percentageCapacity = Math
- .round(scope.capacity / scope.totalCapacity * 1000) / 10;
-
- scope.CapacityStyle = {
- 'flex-grow': percentageCapacity * 0.01
- };
-
- scope.consumedCapacity = `${percentageCapacity}%`;
- } else {
- scope.CapacityStyle = {
- 'flex-grow': 1
- };
-
- scope.consumedCapacity = null;
- }
- }, true);
- }
- };
-}
-
-CapacityBar.$inject = [
- 'templateUrl',
- 'InstanceGroupsStrings'
-];
-
-export default CapacityBar;
\ No newline at end of file
diff --git a/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.partial.html b/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.partial.html
deleted file mode 100644
index a708bb87d0..0000000000
--- a/awx/ui/client/src/instance-groups/capacity-bar/capacity-bar.partial.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
- {{ labelValue }}
-
-
-
-
-
- {{ consumedCapacity }}
-
\ No newline at end of file
diff --git a/awx/ui/client/src/instance-groups/container-groups/add-container-group.controller.js b/awx/ui/client/src/instance-groups/container-groups/add-container-group.controller.js
deleted file mode 100644
index cdab0e89fc..0000000000
--- a/awx/ui/client/src/instance-groups/container-groups/add-container-group.controller.js
+++ /dev/null
@@ -1,89 +0,0 @@
-function AddContainerGroupController(ToJSON, $scope, $state, models, strings, i18n, DataSet) {
- const vm = this || {};
- const {
- instanceGroup,
- credential
- } = models;
-
- vm.mode = 'add';
- vm.strings = strings;
- vm.panelTitle = strings.get('state.ADD_CONTAINER_GROUP_BREADCRUMB_LABEL');
- vm.lookUpTitle = strings.get('container.LOOK_UP_TITLE');
-
- vm.docs = {
- url: 'https://docs.ansible.com/ansible-tower/latest/html/administration/external_execution_envs.html#ag-container-groups',
- help_text: vm.strings.get('tooltips.CG_DOCS_HELP_TEXT')
- };
-
- vm.form = instanceGroup.createFormSchema('post');
- vm.form.name.required = true;
- delete vm.form.name.help_text;
-
- vm.form.credential = {
- type: 'field',
- label: i18n._('Credential'),
- id: 'credential'
- };
- vm.form.credential._resource = 'credential';
- vm.form.credential._route = "instanceGroups.addContainerGroup.credentials";
- vm.form.credential._model = credential;
- vm.form.credential._placeholder = strings.get('container.CREDENTIAL_PLACEHOLDER');
- vm.form.credential.help_text = strings.get('container.CREDENTIAL_HELP_TEXT');
- vm.form.credential.required = true;
-
- vm.form.extraVars = {
- label: strings.get('container.POD_SPEC_LABEL'),
- value: DataSet.data.actions.POST.pod_spec_override.default,
- name: 'extraVars',
- toggleLabel: strings.get('container.POD_SPEC_TOGGLE'),
- tooltip: strings.get('container.EXTRA_VARS_HELP_TEXT')
- };
-
- vm.tab = {
- details: { _active: true },
- instances: {_disabled: true },
- jobs: {_disabled: true }
-};
-
- $scope.variables = vm.form.extraVars.value;
- $scope.name = vm.form.extraVars.name;
- vm.panelTitle = strings.get('container.PANEL_TITLE');
-
-
- $scope.$watch('credential', () => {
- if ($scope.credential) {
- vm.form.credential._idFromModal= $scope.credential;
- }
- });
- vm.form.save = (data) => {
- data.pod_spec_override = null;
- if (vm.form.extraVars.isOpen) {
- data.pod_spec_override = vm.form.extraVars.value;
- }
- return instanceGroup.request('post', { data: data }).then((res) => {
- $state.go('instanceGroups.editContainerGroup', { instance_group_id: res.data.id }, { reload: true });
- });
- };
- vm.form.extraVars.isOpen = false;
- vm.toggle = () => {
- if (vm.form.extraVars.isOpen === true) {
- vm.form.extraVars.isOpen = false;
- } else {
- vm.form.extraVars.isOpen = true;
- }
- return vm.form.extraVars.isOpen;
- };
-}
-
-
-AddContainerGroupController.$inject = [
- 'ToJSON',
- '$scope',
- '$state',
- 'resolvedModels',
- 'InstanceGroupsStrings',
- 'i18n',
- 'DataSet'
-];
-
-export default AddContainerGroupController;
diff --git a/awx/ui/client/src/instance-groups/container-groups/add-container-group.view.html b/awx/ui/client/src/instance-groups/container-groups/add-container-group.view.html
deleted file mode 100644
index 238aa1b21e..0000000000
--- a/awx/ui/client/src/instance-groups/container-groups/add-container-group.view.html
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
- {{:: vm.strings.get('state.TECH_PREVIEW_MESSAGE_BAR') }}
-
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.JOBS') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/instance-groups/container-groups/edit-container-group.controller.js b/awx/ui/client/src/instance-groups/container-groups/edit-container-group.controller.js
deleted file mode 100644
index 45b6f9a3b1..0000000000
--- a/awx/ui/client/src/instance-groups/container-groups/edit-container-group.controller.js
+++ /dev/null
@@ -1,160 +0,0 @@
-function EditContainerGroupController($rootScope, $scope, $state, models, strings, i18n, EditContainerGroupDataset) {
- const vm = this || {};
- const {
- instanceGroup,
- credential
- } = models;
- let canEdit = false;
- if (instanceGroup.has('options', 'actions.PUT')) {
- canEdit = instanceGroup.model.OPTIONS.actions.PUT;
-}
- if (!instanceGroup.get('is_containerized')) {
- return $state.go(
- 'instanceGroups.edit',
- { instance_group_id: instanceGroup.get('id') },
- { reload: true }
- );
- }
-
- $rootScope.breadcrumb.instance_group_name = instanceGroup.get('name');
-
- vm.mode = 'edit';
- vm.strings = strings;
- vm.panelTitle = EditContainerGroupDataset.data.name;
- vm.lookUpTitle = strings.get('container.LOOK_UP_TITLE');
-
- vm.docs = {
- url: 'https://docs.ansible.com/ansible-tower/latest/html/administration/external_execution_envs.html#ag-container-groups',
- help_text: vm.strings.get('tooltips.CG_DOCS_HELP_TEXT')
- };
-
- vm.form = instanceGroup.createFormSchema('post');
- vm.switchDisabled = false;
- vm.form.disabled = !instanceGroup.has('options', 'actions.PUT');
- vm.form.name.required = true;
- delete vm.form.name.help_text;
- vm.form.credential = {
- type: 'field',
- label: i18n._('Credential'),
- id: 'credential'
- };
- vm.form.credential._resource = 'credential';
- vm.form.credential._route = "instanceGroups.editContainerGroup.credentials";
- vm.form.credential._model = credential;
- vm.form.credential._displayValue = EditContainerGroupDataset.data.summary_fields.credential.name;
- vm.form.credential.required = true;
- vm.form.credential._value = EditContainerGroupDataset.data.summary_fields.credential.id;
- vm.form.credential.help_text = strings.get('container.CREDENTIAL_HELP_TEXT');
-
- vm.tab = {
- details: {
- _active: true,
- _go: 'instanceGroups.editContainerGroup',
- _params: { instance_group_id: instanceGroup.get('id') }
- },
- instances: {
- _go: 'instanceGroups.containerGroupInstances',
- _params: { instance_group_id: instanceGroup.get('id') }
- },
- jobs: {
- _go: 'instanceGroups.containerGroupJobs',
- _params: { instance_group_id: instanceGroup.get('id') }
- }
- };
- if (!canEdit) {
- vm.form.extraVars = {
- label: strings.get('container.POD_SPEC_LABEL'),
- value: EditContainerGroupDataset.data.pod_spec_override || "---",
- name: 'extraVars',
- disabled: true,
- tooltip: strings.get('container.EXTRA_VARS_HELP_TEXT')
- };
- vm.switchDisabled = true;
- } else {
- vm.form.extraVars = {
- label: strings.get('container.POD_SPEC_LABEL'),
- value: EditContainerGroupDataset.data.pod_spec_override || instanceGroup.model.OPTIONS.actions.PUT.pod_spec_override.default,
- name: 'extraVars',
- toggleLabel: strings.get('container.POD_SPEC_TOGGLE'),
- tooltip: strings.get('container.EXTRA_VARS_HELP_TEXT')
- };
- }
-
- function sanitizeVars (str) {
- // Quick function to test if the host vars are a json-object-string,
- // by testing if they can be converted to a JSON object w/o error.
- function IsJsonString (varStr) {
- try {
- JSON.parse(varStr);
- } catch (e) {
- return false;
- }
- return true;
- }
-
- if (typeof str === 'undefined') {
- return '---';
- }
- if (typeof str !== 'string') {
- const yamlStr = jsyaml.safeDump(str);
- // jsyaml.safeDump doesn't process an empty object correctly
- if (yamlStr === '{}\n') {
- return '---';
- }
- return yamlStr;
- }
- if (str === '' || str === '{}') {
- return '---';
- } else if (IsJsonString(str)) {
- str = JSON.parse(str);
- return jsyaml.safeDump(str);
- }
- return str;
- }
-
- const podSpecValue = sanitizeVars(EditContainerGroupDataset.data.pod_spec_override);
- const defaultPodSpecValue = canEdit ? sanitizeVars(instanceGroup.model.OPTIONS.actions.PUT.pod_spec_override.default) : '---';
-
- if ((podSpecValue !== '---') && podSpecValue && podSpecValue.trim() !== defaultPodSpecValue.trim()) {
- vm.form.extraVars.isOpen = true;
- } else {
- vm.form.extraVars.isOpen = false;
- }
-
- $scope.$watch('credential', () => {
- if ($scope.credential) {
- vm.form.credential._idFromModal= $scope.credential;
- }
- });
- vm.form.save = (data) => {
- if (!vm.form.extraVars.isOpen) {
- data.pod_spec_override = null;
- } else {
- data.pod_spec_override = vm.form.extraVars.value;
- }
- return instanceGroup.request('put', { data: data }).then((res) => {
- $state.go('instanceGroups.editContainerGroup', { instance_group_id: res.data.id }, { reload: true });
- } );
- };
-
- vm.toggle = () => {
- if (vm.form.extraVars.isOpen === true) {
- vm.form.extraVars.isOpen = false;
- } else {
- vm.form.extraVars.isOpen = true;
- }
- return vm.form.extraVars.isOpen;
- };
-}
-
-EditContainerGroupController.$inject = [
- '$rootScope',
- '$scope',
- '$state',
- 'resolvedModels',
- 'InstanceGroupsStrings',
- 'i18n',
- 'EditContainerGroupDataset'
-];
-
-export default EditContainerGroupController;
diff --git a/awx/ui/client/src/instance-groups/instance-group.block.less b/awx/ui/client/src/instance-groups/instance-group.block.less
deleted file mode 100644
index 9634b97b69..0000000000
--- a/awx/ui/client/src/instance-groups/instance-group.block.less
+++ /dev/null
@@ -1,100 +0,0 @@
-.at-Row--instances {
- .at-Row-content {
- flex-wrap: nowrap;
- }
-
- .at-Row-toggle {
- align-self: auto;
- flex: initial;
- }
-
- .at-Row-itemGroup {
- display: flex;
- flex: 1;
- flex-wrap: wrap;
- }
-
- .at-Row-items--instances {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- align-content: center;
- flex: 1;
- }
-
- .at-RowItem--isHeader {
- min-width: 250px;
- }
-
- .at-Row-items--capacity {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- }
-
- .CapacityAdjuster {
- padding-bottom: 15px;
- }
-}
-
-.at-Row--instanceGroups {
- .at-Row-content {
- flex-wrap: nowrap;
- }
-
- .at-Row-itemGroup {
- display: flex;
- flex: 1;
- flex-wrap: wrap;
- }
-
- .at-Row-items--instanceGroups {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- flex: 1;
- max-width: 100%;
- }
-
- .at-Row-itemHeaderGroup {
- min-width: 320px;
- display: flex;
- }
-
- .at-Row-items--capacity {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- margin-right: 5px;
- min-width: 215px;
- }
-
- .at-Row--instanceSpacer {
- width: 140px;
- }
-
- .at-Row--capacitySpacer {
- flex: .6;
- }
-
- .at-Row-actions {
- min-width: 50px;
- }
-}
-
-@media screen and (max-width: 1260px) {
- .at-Row--instances .at-Row-items--capacity {
- flex: 1
- }
-
- .at-Row--instances .CapacityAdjuster {
- padding-bottom: 5px;
- }
-}
-
-@media screen and (max-width: 600px) {
- .at-Row--instanceGroups .at-Row-itemHeaderGroup,
- .at-Row--instanceGroups .at-Row-itemGroup {
- max-width: 270px;
- }
-}
diff --git a/awx/ui/client/src/instance-groups/instance-groups.list.js b/awx/ui/client/src/instance-groups/instance-groups.list.js
deleted file mode 100644
index 6d22e6cd39..0000000000
--- a/awx/ui/client/src/instance-groups/instance-groups.list.js
+++ /dev/null
@@ -1,31 +0,0 @@
-export default ['i18n', function(i18n) {
- return {
- name: 'instance_groups' ,
- basePath: 'instance_groups',
- iterator: 'instance_group',
- editTitle: i18n._('INSTANCE GROUPS'),
- listTitle: i18n._('INSTANCE GROUPS'),
- emptyListText: i18n._('THERE ARE CURRENTLY NO INSTANCE GROUPS DEFINED'),
- index: false,
- hover: false,
-
- fields: {
- name: {
- key: true,
- label: i18n._('Name'),
- columnClass: 'col-md-3 col-sm-9 col-xs-9',
- modalColumnClass: 'col-md-8',
- uiSref: 'instanceGroups.instances.list({instance_group_id: instance_group.id})',
- ngClass: "{'isActive' : isActive()}"
- },
- consumed_capacity: {
- label: i18n._('Capacity'),
- nosort: true,
- },
- jobs_running: {
- label: i18n._('Running Jobs'),
- nosort: true,
- },
- }
- };
-}];
diff --git a/awx/ui/client/src/instance-groups/instance-groups.partial.html b/awx/ui/client/src/instance-groups/instance-groups.partial.html
deleted file mode 100644
index c9b49020b9..0000000000
--- a/awx/ui/client/src/instance-groups/instance-groups.partial.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/instance-groups/instance-groups.service.js b/awx/ui/client/src/instance-groups/instance-groups.service.js
deleted file mode 100644
index f8657fd36b..0000000000
--- a/awx/ui/client/src/instance-groups/instance-groups.service.js
+++ /dev/null
@@ -1,96 +0,0 @@
-export default
- ['Rest', function(Rest) {
- return {
- addInstanceGroups: function(url, instance_groups) {
- let groups = (instance_groups || []);
- Rest.setUrl(url);
- let defers = groups.map((group) => Rest.post(group));
- return Promise.all(defers);
- },
- /**
- * This function compares the currently saved ids and the selected ids - as soon as
- * we encounter a difference between the two arrays, we mark all remaining currently
- * saved ids in the array for disassociation.
- *
- * Example Scenario
- * -----------------
- * page is loaded with [1,2,3,4,5,6] as the currently selected tags
- * user removes tag 3 from the middle
- * user adds a new tag 7 to the end
- * user appends tag 3 to the end
- *
- * _______ all ids here and to the right are disassociated
- * |
- * current: [1,2,3,4,5,6]
- * selected: [1,2,4,5,6,7,3]
- * |_______ all ids here and to the right are (re)associated
- */
- editInstanceGroups: function(url, instance_groups) {
- Rest.setUrl(url);
- return Rest.get()
- .then(res => {
- const { data: { results = [] } } = res;
- const updatedGroupIds = (instance_groups || []).map(({ id }) => id);
- const currentGroupIds = results.map(({ id }) => id);
-
- const groupIdsToAssociate = [];
- const groupIdsToDisassociate = [];
- // loop over the array of currently saved instance group ids - if we encounter
- // a difference between the current array and the updated array at a particular
- // position, mark it and all remaining currentIds in the array for disassociation.
- let disassociateRemainingIds = false;
- currentGroupIds.forEach((currentId, position) => {
- if (!disassociateRemainingIds && updatedGroupIds[position] !== currentId) {
- disassociateRemainingIds = true;
- }
-
- if (disassociateRemainingIds) {
- groupIdsToDisassociate.push(currentId);
- }
- });
-
- updatedGroupIds.forEach(updatedId => {
- if (groupIdsToDisassociate.includes(updatedId)) {
- // we get here if the id was marked for disassociation due to being
- // out of order - we'll need to re-associate it.
- groupIdsToAssociate.push(updatedId);
- } else if (!currentGroupIds.includes(updatedId)) {
- // we get here if the id is a new association
- groupIdsToAssociate.push(updatedId);
- }
- });
-
- // convert the id arrays into request data
- const groupsToAssociate = groupIdsToAssociate.map(id => ({ id, associate: true}));
- const groupsToDisassociate = groupIdsToDisassociate.map(id => ({ id, disassociate: true }));
-
- // make the disassociate request sequence - we need to do these requests
- // sequentially to make sure they get processed in the right order so we
- // build a promise chain here instead of using .all()
- let disassociationPromise = Promise.resolve();
- groupsToDisassociate.forEach(data => {
- disassociationPromise = disassociationPromise.then(() => {
- Rest.setUrl(url);
- return Rest.post(data);
- });
- });
-
- // make the disassociate-then-associate request sequence
- return disassociationPromise
- .then(() => {
- // we need to do these requests sequentially to make sure they get
- // processed in the right order so we build a promise chain here
- // instead of using .all()
- let associationPromise = Promise.resolve();
- groupsToAssociate.forEach(data => {
- associationPromise = associationPromise.then(() => {
- Rest.setUrl(url);
- return Rest.post(data);
- });
- });
- return associationPromise;
- });
- });
- }
- };
-}];
diff --git a/awx/ui/client/src/instance-groups/instance-groups.strings.js b/awx/ui/client/src/instance-groups/instance-groups.strings.js
deleted file mode 100644
index 26b4b4c1f2..0000000000
--- a/awx/ui/client/src/instance-groups/instance-groups.strings.js
+++ /dev/null
@@ -1,87 +0,0 @@
-function InstanceGroupsStrings(BaseString) {
- BaseString.call(this, 'instanceGroups');
-
- const {
- t
- } = this;
- const ns = this.instanceGroups;
-
- ns.state = {
- INSTANCE_GROUPS_BREADCRUMB_LABEL: t.s('INSTANCE GROUPS'),
- INSTANCES_BREADCRUMB_LABEL: t.s('INSTANCES'),
- ADD_BREADCRUMB_LABEL: t.s('CREATE INSTANCE GROUP'),
- ADD_CONTAINER_GROUP_BREADCRUMB_LABEL: t.s('CREATE CONTAINER GROUP'),
- TECH_PREVIEW_MESSAGE_BAR: t.s('This feature is currently in tech preview and is subject to change in a future release. Click here for documentation.'),
- };
-
- ns.list = {
- MANUAL: t.s('MANUAL'),
- PANEL_TITLE: t.s('INSTANCE GROUPS'),
- ROW_ITEM_LABEL_INSTANCES: t.s('Instances'),
- ROW_ITEM_LABEL_ISOLATED: t.s('ISOLATED'),
- ROW_ITEM_LABEL_RUNNING_JOBS: t.s('Running Jobs'),
- ROW_ITEM_LABEL_TOTAL_JOBS: t.s('Total Jobs'),
- ROW_ITEM_LABEL_USED_CAPACITY: t.s('Used Capacity'),
- ADD: t.s('Add a new instance group')
- };
-
- ns.tab = {
- DETAILS: t.s('DETAILS'),
- INSTANCES: t.s('INSTANCES'),
- JOBS: t.s('JOBS')
- };
-
- ns.tooltips = {
- ADD_INSTANCE_GROUP: t.s('Create a new Instance Group'),
- ASSOCIATE_INSTANCES: t.s('Associate an existing Instance'),
- IG_DOCS_HELP_TEXT: t.s('Instance Groups Help'),
- CG_DOCS_HELP_TEXT: t.s('Container Groups Help')
- };
-
- ns.instance = {
- PANEL_TITLE: t.s('SELECT INSTANCE'),
- BADGE_TEXT: t.s('Instance Group'),
- ADD: t.s('Add a new instance')
- };
-
- ns.capacityBar = {
- IS_OFFLINE: t.s('Unavailable to run jobs.'),
- IS_OFFLINE_LABEL: t.s('Unavailable'),
- USED_CAPACITY: t.s('Used Capacity')
- };
-
- ns.capacityAdjuster = {
- CPU: t.s('CPU'),
- RAM: t.s('RAM'),
- FORKS: t.s('Forks')
- };
-
- ns.jobs = {
- PANEL_TITLE: t.s('Jobs'),
- RUNNING_JOBS: t.s('Running Jobs')
- };
-
- ns.error = {
- HEADER: this.error.HEADER,
- CALL: this.error.CALL,
- DELETE: t.s('Unable to delete instance group.'),
- };
-
- ns.alert = {
- MISSING_PARAMETER: t.s('Instance Group parameter is missing.'),
- };
- ns.container = {
- PANEL_TITLE: t.s('Add Container Group'),
- LOOK_UP_TITLE: t.s('Add Credential'),
- CREDENTIAL_PLACEHOLDER: t.s('SELECT A CREDENTIAL'),
- POD_SPEC_LABEL: t.s('Pod Spec Override'),
- BADGE_TEXT: t.s('Container Group'),
- POD_SPEC_TOGGLE: t.s('Customize Pod Spec'),
- CREDENTIAL_HELP_TEXT: t.s('Credential to authenticate with Kubernetes or OpenShift. Must be of type \"Kubernetes/OpenShift API Bearer Token\”.'),
- EXTRA_VARS_HELP_TEXT: t.s('Field for passing a custom Kubernetes or OpenShift Pod specification.')
- };
-}
-
-InstanceGroupsStrings.$inject = ['BaseStringService'];
-
-export default InstanceGroupsStrings;
diff --git a/awx/ui/client/src/instance-groups/instances/instance-modal.block.less b/awx/ui/client/src/instance-groups/instances/instance-modal.block.less
deleted file mode 100644
index 59dfa8602a..0000000000
--- a/awx/ui/client/src/instance-groups/instances/instance-modal.block.less
+++ /dev/null
@@ -1,29 +0,0 @@
-#instance-modal .at-Panel-headingRow {
- margin-bottom: @at-space-4x;
-}
-
-.Modal-backdrop {
- background: #000;
- height:100%;
- left: 0px;
- opacity: 0.25;
- position: fixed;
- top: 0px;
- width:100%;
- z-index: 1050;
-}
-
-.Modal-holder {
- bottom: 0px;
- left: 0px;
- overflow-y: scroll;
- position: fixed;
- right: 0px;
- top: 0px;
- top: 1;
- z-index: 1100;
-
- .modal-dialog {
- padding-top: 100px;
- }
-}
diff --git a/awx/ui/client/src/instance-groups/instances/instance-modal.controller.js b/awx/ui/client/src/instance-groups/instances/instance-modal.controller.js
deleted file mode 100644
index ec92f51cac..0000000000
--- a/awx/ui/client/src/instance-groups/instances/instance-modal.controller.js
+++ /dev/null
@@ -1,170 +0,0 @@
-function InstanceModalController ($scope, $state, Dataset, models, strings, ProcessErrors, Wait, routeData) {
- const { instanceGroup } = models;
- const vm = this || {};
- let relatedInstanceIds = [];
- let paginateQuerySet = {};
-
- function setRelatedInstances () {
- vm.relatedInstances = instanceGroup.get('related.instances.results');
- vm.selectedRows = _.cloneDeep(vm.relatedInstances);
- relatedInstanceIds = vm.relatedInstances.map(instance => instance.id);
- vm.instances = vm.instances.map(instance => {
- instance.isSelected = relatedInstanceIds.includes(instance.id);
- return instance;
- });
- }
-
- init();
-
- function init() {
- vm.strings = strings;
- vm.panelTitle = strings.get('instance.PANEL_TITLE');
- vm.instanceGroupId = instanceGroup.get('id');
- vm.instanceGroupName = instanceGroup.get('name');
-
- vm.list = {
- name: 'instances',
- iterator: 'add_instance',
- basePath: `/api/v2/instances/`
- };
-
- vm.instances = Dataset.data.results;
- vm.instance_dataset = Dataset.data;
-
- setRelatedInstances();
- }
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'hostname'
- };
-
- vm.toolbarSortValue = toolbarSortDefault;
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-hostname' },
- { label: `${strings.get('sort.UUID_ASCENDING')}`, value: 'uuid' },
- { label: `${strings.get('sort.UUID_DESCENDING')}`, value: '-uuid' },
- { label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
- { label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
- { label: `${strings.get('sort.CAPACITY_ASCENDING')}`, value: 'capacity' },
- { label: `${strings.get('sort.CAPACITY_DESCENDING')}`, value: '-capacity' }
- ];
-
- const removeStateParamsListener = $scope.$watchCollection('$state.params', () => {
- setToolbarSort();
- });
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'add_instance_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.add_instance_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- $state.go('.', {
- add_instance_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- vm.submit = () => {
- Wait('start');
- const selectedRowIds = vm.selectedRows.map(instance => instance.id);
-
- const associate = selectedRowIds.filter(instanceId => {
- return !relatedInstanceIds.includes(instanceId);
- }).map(id => ({id}));
- const disassociate = relatedInstanceIds.filter(instanceId => {
- return !selectedRowIds.includes(instanceId);
- }).map(id => ({id, disassociate: true}));
-
- const all = associate.concat(disassociate);
- const defers = all.map((data) => {
- const config = {
- url: `${vm.instanceGroupId}/instances/`,
- data: data
- };
- return instanceGroup.http.post(config);
- });
-
- Promise.all(defers)
- .then(vm.onSaveSuccess)
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Call failed. Return status: ' + status
- });
- })
- .finally(() => {
- Wait('stop');
- });
- };
-
- vm.onSaveSuccess = () => {
- $state.go(`${routeData}`, {}, {reload: `${routeData}`});
- };
-
- vm.dismiss = () => {
- $state.go(`${routeData}`);
- };
-
- vm.toggleRow = (row) => {
- if (row.isSelected) {
- let matchingIndex;
- angular.forEach(vm.selectedRows, function(value, index) {
- if(row.id === vm.selectedRows[index].id) {
- matchingIndex = index;
- }
- });
-
- vm.selectedRows.splice(matchingIndex, 1);
- row.isSelected = false;
- } else {
- row.isSelected = true;
- vm.selectedRows.push(row);
- }
- };
-
- const removeUpdateDatasetListener = $scope.$on('updateDataset', (e, dataset, queryset) => {
- vm.instances = dataset.results;
- vm.instance_dataset = dataset;
- paginateQuerySet = queryset;
-
- angular.forEach(vm.instances, function(instance) {
- instance.isSelected = _.filter(vm.selectedRows, { 'id': instance.id }).length > 0;
- });
- });
-
- $scope.$on('$destroy', function() {
- removeUpdateDatasetListener();
- removeStateParamsListener();
- });
-}
-
-InstanceModalController.$inject = [
- '$scope',
- '$state',
- 'Dataset',
- 'resolvedModels',
- 'InstanceGroupsStrings',
- 'ProcessErrors',
- 'Wait',
- 'routeData'
-];
-
-export default InstanceModalController;
diff --git a/awx/ui/client/src/instance-groups/instances/instance-modal.partial.html b/awx/ui/client/src/instance-groups/instances/instance-modal.partial.html
deleted file mode 100644
index 1b3f2ac2a3..0000000000
--- a/awx/ui/client/src/instance-groups/instances/instance-modal.partial.html
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
{{ vm.panelTitle }} | {{ vm.instanceGroupName}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{:: vm.strings.get('CANCEL') }}
-
-
- {{:: vm.strings.get('SAVE') }}
-
-
-
-
-
-
diff --git a/awx/ui/client/src/instance-groups/instances/instances-list.partial.html b/awx/ui/client/src/instance-groups/instances/instances-list.partial.html
deleted file mode 100644
index 510f73e6d7..0000000000
--- a/awx/ui/client/src/instance-groups/instances/instances-list.partial.html
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.INSTANCES') }}
- {{:: vm.strings.get('tab.JOBS') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/instance-groups/instances/instances.controller.js b/awx/ui/client/src/instance-groups/instances/instances.controller.js
deleted file mode 100644
index 566161d850..0000000000
--- a/awx/ui/client/src/instance-groups/instances/instances.controller.js
+++ /dev/null
@@ -1,196 +0,0 @@
-function InstancesController ($scope, $state, $http, $transitions, models, strings, Dataset, ProcessErrors) {
- const { instanceGroup } = models;
- const vm = this || {};
- let paginateQuerySet = {};
- vm.strings = strings;
- vm.panelTitle = instanceGroup.get('name');
- vm.instance_group_id = instanceGroup.get('id');
- vm.policy_instance_list = instanceGroup.get('policy_instance_list');
- vm.isSuperuser = $scope.$root.user_is_superuser;
-
- let tabs = {};
- let addInstancesRoute ="";
- if ($state.is("instanceGroups.instances")) {
- tabs={ state: {
- details: {
- _go: 'instanceGroups.edit'
- },
- instances: {
- _active: true,
- _go: 'instanceGroups.instances'
- },
- jobs: {
- _go: 'instanceGroups.jobs'
- }
- }
- };
- addInstancesRoute = 'instanceGroups.instances.modal.add';
- } else if ($state.is("instanceGroups.containerGroupInstances")) {
- tabs={
- state: {
- details: {
- _go: 'instanceGroups.editContainerGroup'
- },
- instances: {
- _active: true,
- _go: 'instanceGroups.containerGroupInstances'
- },
- jobs: {
- _go: 'instanceGroups.containerGroupJobs'
- }
- }
- };
- addInstancesRoute = 'instanceGroups.containerGroupInstances.modal.add';
- }
-
- vm.list = {
- name: 'instances',
- iterator: 'instance',
- basePath: `/api/v2/instance_groups/${vm.instance_group_id}/instances/`
- };
- vm.instance_dataset = Dataset.data;
- vm.instances = Dataset.data.results;
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'hostname'
- };
-
- vm.addInstances = () => {
-
- return $state.go(`${addInstancesRoute}`);
- };
-
-
- vm.toolbarSortValue = toolbarSortDefault;
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-hostname' },
- { label: `${strings.get('sort.UUID_ASCENDING')}`, value: 'uuid' },
- { label: `${strings.get('sort.UUID_DESCENDING')}`, value: '-uuid' },
- { label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
- { label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
- { label: `${strings.get('sort.CAPACITY_ASCENDING')}`, value: 'capacity' },
- { label: `${strings.get('sort.CAPACITY_DESCENDING')}`, value: '-capacity' }
- ];
-
- const removeStateParamsListener = $scope.$watchCollection('$state.params', () => {
- setToolbarSort();
- });
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'instance_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.instance_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- $state.go('.', {
- instance_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- const tabObj = {};
- const params = { instance_group_id: instanceGroup.get('id') };
-
- tabObj.details = { _go: tabs.state.details._go, _params: params };
- tabObj.instances = { _go: tabs.state.instances._go, _params: params, _active: true };
- tabObj.jobs = { _go: tabs.state.jobs._go, _params: params };
- vm.tab = tabObj;
-
-
- vm.tooltips = {
- add: strings.get('tooltips.ASSOCIATE_INSTANCES')
- };
-
- vm.rowAction = {
- toggle: {
- _disabled: !vm.isSuperuser
- },
- capacity_adjustment: {
- _disabled: !vm.isSuperuser
- }
- };
-
- vm.toggle = (toggled) => {
- const instance = _.find(vm.instances, ['id', toggled.id]);
- instance.enabled = !instance.enabled;
-
- const data = {
- "capacity_adjustment": instance.capacity_adjustment,
- "enabled": instance.enabled
- };
-
- const req = {
- method: 'PUT',
- url: instance.url,
- data
- };
- $http(req).then(vm.onSaveSuccess)
- .catch(({data, status}) => {
- ProcessErrors($scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Call failed. Return status: ' + status
- });
- });
- };
-
- vm.onSaveSuccess = () => {
- $state.transitionTo($state.current, $state.params, {
- reload: true, location: true, inherit: false, notify: true
- });
- };
-
- $scope.isActive = function(id) {
- let selected = parseInt($state.params.instance_id);
- return id === selected;
- };
-
- const removeUpdateDatasetListener = $scope.$on('updateDataset', (e, dataset, queryset) => {
- vm.instances = dataset.results;
- vm.instance_dataset = dataset;
- paginateQuerySet = queryset;
- });
-
- const removeStateChangeListener = $transitions.onSuccess({}, function(trans) {
- if (trans.to().name === 'instanceGroups.instances.modal.add') {
- removeUpdateDatasetListener();
- removeStateChangeListener();
- removeStateParamsListener();
- }
- });
-
- $scope.$on('$destroy', function() {
- removeUpdateDatasetListener();
- removeStateChangeListener();
- removeStateParamsListener();
- });
-}
-
-InstancesController.$inject = [
- '$scope',
- '$state',
- '$http',
- '$transitions',
- 'resolvedModels',
- 'InstanceGroupsStrings',
- 'Dataset',
- 'ProcessErrors',
-];
-
-export default InstancesController;
diff --git a/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js
deleted file mode 100644
index bffe4d6064..0000000000
--- a/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js
+++ /dev/null
@@ -1,61 +0,0 @@
-
-function InstanceGroupJobsContainerController ($scope, strings, $state) {
- const vm = this || {};
- const instanceGroupId = $state.params.instance_group_id;
-
- let tabs = {};
- if ($state.is('instanceGroups.jobs')) {
- tabs = {
- state: {
- details: {
- _go: 'instanceGroups.edit'
- },
- instances: {
- _go: 'instanceGroups.instances'
- },
- jobs: {
- _active: true,
- _go: 'instanceGroups.jobs'
- }
- }
- };
- } else if ($state.is('instanceGroups.containerGroupJobs')) {
- tabs = {
- state: {
- details: {
- _go: 'instanceGroups.editContainerGroup'
- },
- instances: {
- _go: 'instanceGroups.containerGroupInstances'
- },
- jobs: {
- _active: true,
- _go: 'instanceGroups.containerGroupJobs'
- }
- }
- };
- }
-
- vm.panelTitle = strings.get('jobs.PANEL_TITLE');
- vm.strings = strings;
- const tabObj = {};
-
- tabObj.details = { _go: tabs.state.details._go, _params: { instance_group_id: parseInt(instanceGroupId) } };
- tabObj.instances = { _go: tabs.state.instances._go, _params: { instance_group_id: parseInt(instanceGroupId) } };
- tabObj.jobs = { _go: tabs.state.jobs._go, _params: { instance_group_id: parseInt(instanceGroupId) }, _active: true };
- vm.tab = tabObj;
-
- $scope.$on('updateCount', (e, count) => {
- if (typeof count === 'number') {
- vm.count = count;
- }
- });
-}
-
-InstanceGroupJobsContainerController.$inject = [
- '$scope',
- 'InstanceGroupsStrings',
- '$state'
-];
-
-export default InstanceGroupJobsContainerController;
diff --git a/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html
deleted file mode 100644
index de8808bda8..0000000000
--- a/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- {{:: vm.strings.get('tab.DETAILS') }}
- {{:: vm.strings.get('tab.INSTANCES') }}
- {{:: vm.strings.get('tab.JOBS') }}
-
-
-
diff --git a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js
deleted file mode 100644
index 7e661ab41d..0000000000
--- a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js
+++ /dev/null
@@ -1,23 +0,0 @@
-
-function InstanceGroupJobsContainerController ($scope, strings) {
- const vm = this || {};
-
- init();
- function init() {
- vm.panelTitle = strings.get('jobs.PANEL_TITLE');
- vm.strings = strings;
- }
-
- $scope.$on('updateCount', (e, count) => {
- if (typeof count === 'number') {
- vm.count = count;
- }
- });
-}
-
-InstanceGroupJobsContainerController.$inject = [
- '$scope',
- 'InstanceGroupsStrings'
-];
-
-export default InstanceGroupJobsContainerController;
diff --git a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html
deleted file mode 100644
index 744b4af256..0000000000
--- a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/awx/ui/client/src/instance-groups/list/instance-groups-list.controller.js b/awx/ui/client/src/instance-groups/list/instance-groups-list.controller.js
deleted file mode 100644
index 1433231dd9..0000000000
--- a/awx/ui/client/src/instance-groups/list/instance-groups-list.controller.js
+++ /dev/null
@@ -1,164 +0,0 @@
-export default [
- '$rootScope',
- '$scope',
- '$filter',
- '$state',
- 'Alert',
- 'resolvedModels',
- 'Dataset',
- 'InstanceGroupsStrings',
- 'ProcessErrors',
- 'Prompt',
- 'Wait',
- function(
- $rootScope,
- $scope,
- $filter,
- $state,
- Alert,
- resolvedModels,
- Dataset,
- strings,
- ProcessErrors,
- Prompt,
- Wait
- ) {
- const vm = this;
- const { instanceGroup } = resolvedModels;
- let paginateQuerySet = {};
-
- vm.strings = strings;
- vm.isSuperuser = $scope.$root.user_is_superuser;
-
- init();
-
- function init(){
- $rootScope.breadcrumb.instance_group_name = $filter('sanitize')(instanceGroup.get('name'));
- $scope.list = {
- iterator: 'instance_group',
- name: 'instance_groups'
- };
-
- $scope.collection = {
- basePath: 'instance_groups',
- iterator: 'instance_group'
- };
-
- $scope[`${$scope.list.iterator}_dataset`] = Dataset.data;
- $scope[$scope.list.name] = $scope[`${$scope.list.iterator}_dataset`].results;
- $scope.instanceGroupCount = Dataset.data.count;
-
- $scope.$on('updateDataset', function(e, dataset, queryset) {
- $scope[`${$scope.list.iterator}_dataset`] = dataset;
- $scope[$scope.list.name] = dataset.results;
- paginateQuerySet = queryset;
- });
- }
-
- $scope.$watchCollection('$state.params', () => {
- vm.activeId = parseInt($state.params.instance_group_id);
- setToolbarSort();
- });
-
- const toolbarSortDefault = {
- label: `${strings.get('sort.NAME_ASCENDING')}`,
- value: 'name'
- };
-
- vm.toolbarSortOptions = [
- toolbarSortDefault,
- { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
- { label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
- { label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
- { label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
- { label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' }
- ];
-
- vm.toolbarSortValue = toolbarSortDefault;
-
- function setToolbarSort () {
- const orderByValue = _.get($state.params, 'instance_group_search.order_by');
- const sortValue = _.find(vm.toolbarSortOptions, (option) => option.value === orderByValue);
- if (sortValue) {
- vm.toolbarSortValue = sortValue;
- } else {
- vm.toolbarSortValue = toolbarSortDefault;
- }
- }
-
- vm.onToolbarSort = (sort) => {
- vm.toolbarSortValue = sort;
-
- const queryParams = Object.assign(
- {},
- $state.params.instance_group_search,
- paginateQuerySet,
- { order_by: sort.value }
- );
-
- // Update URL with params
- $state.go('.', {
- instance_group_search: queryParams
- }, { notify: false, location: 'replace' });
- };
-
- vm.tooltips = {
- add: strings.get('tooltips.ADD_INSTANCE_GROUP')
- };
-
- vm.rowAction = {
- trash: instance_group => {
- return vm.isSuperuser && instance_group.name !== 'tower' && !instance_group.is_controller && !instance_group.is_isolated;
- }
- };
-
- vm.deleteInstanceGroup = instance_group => {
- if (!instance_group) {
- Alert(strings.get('error.DELETE'), strings.get('alert.MISSING_PARAMETER'));
- return;
- }
-
- Prompt({
- action() {
- $('#prompt-modal').modal('hide');
- Wait('start');
- instanceGroup
- .request('delete', instance_group.id)
- .then(() => handleSuccessfulDelete(instance_group))
- .catch(createErrorHandler('delete instance group', 'DELETE'))
- .finally(() => Wait('stop'));
- },
- hdr: strings.get('DELETE'),
- resourceName: $filter('sanitize')(instance_group.name),
- body: `${strings.get('deleteResource.CONFIRM', 'instance group')}`
- });
- };
-
- function handleSuccessfulDelete(instance_group) {
- let reloadListStateParams = null;
-
- if($scope.instance_groups.length === 1 && $state.params.instance_group_search && _.has($state, 'params.instance_group_search.page') && $state.params.instance_group_search.page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.instance_group_search.page = (parseInt(reloadListStateParams.instance_group_search.page)-1).toString();
- }
-
- if (parseInt($state.params.instance_group_id, 0) === instance_group.id) {
- $state.go('instanceGroups', reloadListStateParams, { reload: true });
- } else {
- $state.go('.', reloadListStateParams, { reload: true });
- }
- }
-
- function createErrorHandler(path, action) {
- return ({ data, status }) => {
- const hdr = strings.get('error.HEADER');
- const msg = strings.get('error.CALL', { path, action, status });
- ProcessErrors($scope, data, status, null, { hdr, msg });
- };
- }
-
- $scope.createInstanceGroup = () => {
- $state.go('instanceGroups.add');
- };
- }
-];
diff --git a/awx/ui/client/src/instance-groups/list/instance-groups-list.partial.html b/awx/ui/client/src/instance-groups/list/instance-groups-list.partial.html
deleted file mode 100644
index 4f5a45845d..0000000000
--- a/awx/ui/client/src/instance-groups/list/instance-groups-list.partial.html
+++ /dev/null
@@ -1,146 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/instance-groups/main.js b/awx/ui/client/src/instance-groups/main.js
deleted file mode 100644
index 1c0d80bbf7..0000000000
--- a/awx/ui/client/src/instance-groups/main.js
+++ /dev/null
@@ -1,470 +0,0 @@
-import {
- templateUrl
-} from '../shared/template-url/template-url.factory';
-import CapacityAdjuster from './capacity-adjuster/capacity-adjuster.directive';
-import AddContainerGroup from './container-groups/add-container-group.view.html';
-import EditContainerGroupController from './container-groups/edit-container-group.controller';
-import AddContainerGroupController from './container-groups/add-container-group.controller';
-import CapacityBar from './capacity-bar/capacity-bar.directive';
-import instanceGroupsMultiselect from '../shared/instance-groups-multiselect/instance-groups.directive';
-import instanceGroupsModal from '../shared/instance-groups-multiselect/instance-groups-modal/instance-groups-modal.directive';
-
-import AddEditTemplate from './add-edit/add-edit-instance-groups.view.html';
-import AddInstanceGroupController from './add-edit/add-instance-group.controller';
-import EditInstanceGroupController from './add-edit/edit-instance-group.controller';
-
-import InstanceGroupsTemplate from './list/instance-groups-list.partial.html';
-import InstanceGroupsListController from './list/instance-groups-list.controller';
-
-import InstancesTemplate from './instances/instances-list.partial.html';
-import InstanceListController from './instances/instances.controller';
-
-import InstanceModalTemplate from './instances/instance-modal.partial.html';
-import InstanceModalController from './instances/instance-modal.controller.js';
-
-import list from './instance-groups.list';
-import service from './instance-groups.service';
-
-import InstanceGroupsStrings from './instance-groups.strings';
-
-import {instanceGroupJobsRoute, containerGroupJobsRoute} from '~features/jobs/routes/instanceGroupJobs.route.js';
-import instanceJobsRoute from '~features/jobs/routes/instanceJobs.route.js';
-
-
-const MODULE_NAME = 'instanceGroups';
-
-function InstanceGroupsResolve($q, $stateParams, InstanceGroup, Credential, Instance, ProcessErrors, strings) {
- const instanceGroupId = $stateParams.instance_group_id;
- const instanceId = $stateParams.instance_id;
- let promises = {};
-
- if (!instanceGroupId && !instanceId) {
- promises.instanceGroup = new InstanceGroup(['get', 'options']);
- promises.credential = new Credential(['get', 'options']);
- return $q.all(promises);
- }
-
- if (instanceGroupId && instanceId) {
- promises.instance = new Instance(['get', 'options'], [instanceId, instanceId])
- .then((instance) => instance.extend('get', 'jobs', {
- params: {
- page_size: "10",
- order_by: "-finished"
- }
- }));
- return $q.all(promises);
- }
-
- promises.instanceGroup = new InstanceGroup(['get', 'options'], [instanceGroupId, instanceGroupId])
- .then((instanceGroup) => instanceGroup.extend('get', 'jobs', {
- params: {
- page_size: "10",
- order_by: "-finished"
- }
- }))
- .then((instanceGroup) => instanceGroup.extend('get', 'instances'));
-
- promises.credential = new Credential();
-
- return $q.all(promises)
- .then(models => models)
- .catch(({
- data,
- status,
- config
- }) => {
- ProcessErrors(null, data, status, null, {
- hdr: strings.get('error.HEADER'),
- msg: strings.get('error.CALL', {
- path: `${config.url}`,
- status
- })
- });
- return $q.reject();
- });
-}
-
-InstanceGroupsResolve.$inject = [
- '$q',
- '$stateParams',
- 'InstanceGroupModel',
- 'CredentialModel',
- 'InstanceModel',
- 'ProcessErrors',
- 'InstanceGroupsStrings'
-];
-
-function InstanceGroupsRun($stateExtender, strings) {
- $stateExtender.addState({
- name: 'instanceGroups',
- url: '/instance_groups',
- searchPrefix: 'instance_group',
- ncyBreadcrumb: {
- label: strings.get('state.INSTANCE_GROUPS_BREADCRUMB_LABEL')
- },
- params: {
- instance_group_search: {
- value: {
- page_size: '10',
- order_by: 'name'
- },
- dynamic: true
- }
- },
- data: {
- alwaysShowRefreshButton: true,
- },
- views: {
- '@': {
- templateUrl: templateUrl('./instance-groups/instance-groups'),
- },
- 'list@instanceGroups': {
- templateUrl: InstanceGroupsTemplate,
- controller: 'InstanceGroupsListController',
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- Dataset: ['InstanceGroupList', 'QuerySet', '$stateParams', 'GetBasePath',
- function (list, qs, $stateParams, GetBasePath) {
- let path = GetBasePath(list.basePath) || GetBasePath(list.name);
- return qs.search(path, $stateParams[`${list.iterator}_search`]);
- }
- ]
- }
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.add',
- url: '/add',
- ncyBreadcrumb: {
- label: strings.get('state.ADD_BREADCRUMB_LABEL')
- },
- params: {
- instance_search: {
- value: {
- order_by: 'hostname',
- page_size: '10'
- }
- }
- },
- views: {
- 'add@instanceGroups': {
- templateUrl: AddEditTemplate,
- controller: AddInstanceGroupController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- Dataset: [
- '$stateParams',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, GetBasePath, qs) => {
- const searchParams = $stateParams.instance_search;
- const searchPath = GetBasePath('instances');
- return qs.search(searchPath, searchParams);
- }
- ]
- }
- });
- $stateExtender.addState({
- name: 'instanceGroups.addContainerGroup',
- url: '/container_group',
- views: {
- 'addContainerGroup@instanceGroups': {
- templateUrl: AddContainerGroup,
- controller: AddContainerGroupController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- DataSet: ['Rest', 'GetBasePath', (Rest, GetBasePath) => {
- Rest.setUrl(`${GetBasePath('instance_groups')}`);
- return Rest.options();
- }]
- },
- ncyBreadcrumb: {
- label: strings.get('state.ADD_CONTAINER_GROUP_BREADCRUMB_LABEL')
- },
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.addContainerGroup.credentials',
- url: '/credential?selected',
- searchPrefix: 'credential',
- params: {
- credential_search: {
- value: {
- credential_type__kind: 'kubernetes',
- order_by: 'name',
- page_size: 5,
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'credentials',
- formChildState: true
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'credentials@instanceGroups.addContainerGroup': {
- templateProvider: (ListDefinition, generateList) => {
- const html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
- return `
${html} `;
- }
- }
- },
- resolve: {
- ListDefinition: ['CredentialList', list => list],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
-
-
- const searchPath = GetBasePath('credentials');
- return qs.search(
- searchPath,
- $stateParams[`${list.iterator}_search`]
- );
- }]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.editContainerGroup',
- url: '/container_group/:instance_group_id',
- views: {
- 'editContainerGroup@instanceGroups': {
- templateUrl: AddContainerGroup,
- controller: EditContainerGroupController,
- controllerAs: 'vm'
- }
- },
-
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- EditContainerGroupDataset: ['GetBasePath', 'QuerySet', '$stateParams',
- function (GetBasePath, qs, $stateParams) {
- let path = `${GetBasePath('instance_groups')}${$stateParams.instance_group_id}`;
- return qs.search(path, $stateParams);
- }
- ],
- },
- ncyBreadcrumb: {
- label: '{{breadcrumb.instance_group_name}}'
- },
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.editContainerGroup.credentials',
- url: '/credential?selected',
- searchPrefix: 'credential',
- params: {
- credential_search: {
- value: {
- credential_type__kind: 'kubernetes',
- order_by: 'name',
- page_size: 5,
- },
- dynamic: true,
- squash: ''
- }
- },
- data: {
- basePath: 'credentials',
- formChildState: true
- },
- views: {
- 'credentials@instanceGroups.editContainerGroup': {
- templateProvider: (ListDefinition, generateList) => {
- const html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
- return `
${html} `;
- }
- }
- },
- resolve: {
- ListDefinition: ['CredentialList', list => list],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
- const searchPath = GetBasePath('credentials');
- return qs.search(
- searchPath,
- $stateParams[`${list.iterator}_search`]
- );
- }]
- },
- onExit ($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.edit',
- route: '/:instance_group_id',
- ncyBreadcrumb: {
- label: '{{breadcrumb.instance_group_name}}'
- },
- params: {
- instance_search: {
- value: {
- order_by: 'hostname',
- page_size: '10'
- }
- }
- },
- views: {
- 'edit@instanceGroups': {
- templateUrl: AddEditTemplate,
- controller: EditInstanceGroupController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- Dataset: [
- '$stateParams',
- 'GetBasePath',
- 'QuerySet',
- ($stateParams, GetBasePath, qs) => {
- const searchParams = $stateParams.instance_search;
- const searchPath = GetBasePath('instances');
- return qs.search(searchPath, searchParams);
- }
- ]
- }
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.instances',
- url: '/:instance_group_id/instances',
- searchPrefix: 'instance',
- ncyBreadcrumb: {
- parent: 'instanceGroups.edit',
- label: strings.get('state.INSTANCES_BREADCRUMB_LABEL')
- },
- params: {
- instance_search: {
- value: {
- order_by: 'hostname',
- page_size: '10'
- },
- dynamic: true
- }
- },
- views: {
- 'instances@instanceGroups': {
- templateUrl: InstancesTemplate,
- controller: 'InstanceListController',
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- Dataset: ['GetBasePath', 'QuerySet', '$stateParams',
- function (GetBasePath, qs, $stateParams) {
- let path = `${GetBasePath('instance_groups')}${$stateParams.instance_group_id}/instances`;
- return qs.search(path, $stateParams[`instance_search`]);
- }
- ],
- }
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.instances.modal',
- abstract: true,
- ncyBreadcrumb: {
- skip: true,
- },
- views: {
- "modal": {
- template: `
-
`,
- }
- }
- });
-
- $stateExtender.addState({
- name: 'instanceGroups.instances.modal.add',
- url: '/add',
- ncyBreadcrumb: {
- skip: true,
- },
- searchPrefix: 'add_instance',
- params: {
- add_instance_search: {
- value: {
- page_size: '10',
- order_by: 'hostname'
- },
- dynamic: true
- }
- },
- views: {
- "modal": {
- templateUrl: InstanceModalTemplate,
- controller: InstanceModalController,
- controllerAs: 'vm'
- }
- },
- resolve: {
- resolvedModels: InstanceGroupsResolve,
- Dataset: ['GetBasePath', 'QuerySet', '$stateParams',
- function (GetBasePath, qs, $stateParams) {
- let path = `${GetBasePath('instances')}`;
- return qs.search(path, $stateParams[`add_instance_search`]);
- }
- ],
- routeData: [function () {
- return "instanceGroups.instances";
- }]
- }
- });
-
- $stateExtender.addState(instanceJobsRoute);
- $stateExtender.addState(instanceGroupJobsRoute);
- $stateExtender.addState(containerGroupJobsRoute);
-}
-
-InstanceGroupsRun.$inject = [
- '$stateExtender',
- 'InstanceGroupsStrings',
- 'Rest'
-];
-
-angular.module(MODULE_NAME, [])
- .service('InstanceGroupsService', service)
- .factory('InstanceGroupList', list)
- .controller('InstanceGroupsListController', InstanceGroupsListController)
- .controller('InstanceListController', InstanceListController)
- .directive('instanceGroupsMultiselect', instanceGroupsMultiselect)
- .directive('instanceGroupsModal', instanceGroupsModal)
- .directive('capacityAdjuster', CapacityAdjuster)
- .directive('capacityBar', CapacityBar)
- .service('InstanceGroupsStrings', InstanceGroupsStrings)
- .run(InstanceGroupsRun);
-
-export default MODULE_NAME;
diff --git a/awx/ui/client/src/inventories-hosts/hosts/edit/host-edit.controller.js b/awx/ui/client/src/inventories-hosts/hosts/edit/host-edit.controller.js
deleted file mode 100644
index ab304cb37c..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/edit/host-edit.controller.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default
- ['$scope', '$state', 'HostsService', 'host', '$rootScope',
- function($scope, $state, HostsService, host, $rootScope){
- $scope.parseType = 'yaml';
- $scope.formCancel = function(){
- $state.go('^', null, {reload: true});
- };
- $scope.toggleHostEnabled = function(){
- $scope.host.enabled = !$scope.host.enabled;
- };
- $scope.toggleEnabled = function(){
- $scope.host.enabled = !$scope.host.enabled;
- };
- $scope.groupsTab = function(){
- let id = $scope.host.summary_fields.inventory.id;
- $state.go('hosts.edit.nested_groups', {inventory_id: id});
- };
- $scope.formSave = function(){
- var host = {
- id: $scope.host.id,
- variables: $scope.variables === '---' || $scope.variables === '{}' ? null : $scope.variables,
- name: $scope.name,
- description: $scope.description,
- enabled: $scope.host.enabled
- };
- HostsService.put(host).then(function(){
- $state.go('.', null, {reload: true});
- });
-
- };
- var init = function(){
- $scope.host = host.data;
- $rootScope.breadcrumb.host_name = host.data.name;
- $scope.name = host.data.name;
- $scope.description = host.data.description;
- $scope.variables = host.data.variables;
- };
-
- init();
- }];
diff --git a/awx/ui/client/src/inventories-hosts/hosts/edit/main.js b/awx/ui/client/src/inventories-hosts/hosts/edit/main.js
deleted file mode 100644
index 2f0c5aee39..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/edit/main.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import controller from './host-edit.controller';
-
-export default
-angular.module('hostsEdit', [])
- .controller('HostEditController', controller);
diff --git a/awx/ui/client/src/inventories-hosts/hosts/host.form.js b/awx/ui/client/src/inventories-hosts/hosts/host.form.js
deleted file mode 100644
index e8d42123a3..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/host.form.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc function
- * @name forms.function:Hosts
- * @description This form is for adding/editing a host on the inventory page
-*/
-
-export default ['i18n',
-function(i18n) {
- return {
-
- addTitle: i18n._('CREATE HOST'),
- editTitle: '{{ host.name }}',
- name: 'host',
- basePath: 'hosts',
- well: false,
- formLabelSize: 'col-lg-3',
- formFieldSize: 'col-lg-9',
- iterator: 'host',
- detailsClick: "$state.go('hosts.edit', null, {reload:true})",
- activeEditState: 'hosts.edit',
- stateTree: 'hosts',
- headerFields:{
- enabled: {
- class: 'Form-header-field',
- ngClick: 'toggleHostEnabled(host)',
- type: 'toggle',
- awToolTip: "
" +
- i18n._("Indicates if a host is available and should be included in running jobs.") +
- "
" +
- i18n._("For hosts that are part of an external" +
- " inventory, this may be" +
- " reset by the inventory sync process.") +
- "
",
- dataTitle: i18n._('Host Enabled'),
- }
- },
- fields: {
- name: {
- label: i18n._('Host Name'),
- type: 'text',
- required: true,
- awPopOver: "
" +
- i18n._("Provide a host name, ip address, or ip address:port. Examples include:") +
- "
" +
- "
myserver.domain.com " +
- "127.0.0.1 " +
- "10.1.0.140:25 " +
- "server.example.com:25" +
- " ",
- dataTitle: i18n._('Host Name'),
- dataPlacement: 'right',
- dataContainer: 'body',
- ngDisabled: '!(host.summary_fields.user_capabilities.edit || canAdd)'
- },
- description: {
- label: i18n._('Description'),
- ngDisabled: '!(host.summary_fields.user_capabilities.edit || canAdd)',
- type: 'text'
- },
- variables: {
- label: i18n._('Variables'),
- type: 'code_mirror',
- variables: 'variables',
- class: 'Form-formGroup--fullWidth',
- "default": "---",
- awPopOver: "
" + i18n._("Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two.") + "
" +
- "JSON:
\n" +
- "
{ "somevar": "somevalue", "password": "magic" } \n" +
- "YAML:
\n" +
- "
--- somevar: somevalue password: magic \n" +
- '
' + i18n.sprintf(i18n._('View JSON examples at %s'), 'www.json.org ') + '
' +
- '
' + i18n.sprintf(i18n._('View YAML examples at %s'), 'docs.ansible.com ') + '
',
- }
- },
-
- buttons: {
- cancel: {
- ngClick: 'formCancel()',
- ngShow: '(host.summary_fields.user_capabilities.edit || canAdd)'
- },
- close: {
- ngClick: 'formCancel()',
- ngShow: '!(host.summary_fields.user_capabilities.edit || canAdd)'
- },
- save: {
- ngClick: 'formSave()',
- ngDisabled: true,
- ngShow: '(host.summary_fields.user_capabilities.edit || canAdd)'
- }
- },
-
- related: {
- ansible_facts: {
- name: 'ansible_facts',
- awToolTip: i18n._('Please save before viewing facts.'),
- dataPlacement: 'top',
- title: i18n._('Facts'),
- skipGenerator: true
- },
- groups: {
- name: 'groups',
- awToolTip: i18n._('Please save before defining groups.'),
- dataPlacement: 'top',
- ngClick: "$state.go('hosts.edit.groups')",
- title: i18n._('Groups'),
- iterator: 'group',
- skipGenerator: true
- },
- insights: {
- name: 'insights',
- awToolTip: i18n._('Please save before viewing Insights.'),
- dataPlacement: 'top',
- title: i18n._('Insights'),
- skipGenerator: true,
- ngIf: "host.insights_system_id!==null && host.summary_fields.inventory.hasOwnProperty('insights_credential_id')"
- },
- completed_jobs: {
- name: 'completed_jobs',
- title: i18n._('Completed Jobs'),
- skipGenerator: true
- }
- }
- };
- }];
diff --git a/awx/ui/client/src/inventories-hosts/hosts/host.list.js b/awx/ui/client/src/inventories-hosts/hosts/host.list.js
deleted file mode 100644
index 9cf8f98274..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/host.list.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'hosts',
- iterator: 'host',
- editTitle: '{{ selected_group }}',
- singleSearchParam: {
- param: 'host_filter'
- },
- showTitle: false,
- well: true,
- index: false,
- hover: true,
- hasChildren: true,
- 'class': 'table-no-border',
- trackBy: 'host.id',
- basePath: 'hosts',
- title: false,
- actionHolderClass: 'List-actionHolder',
- layoutClass: 'List-staticColumnLayout--hostsWithCheckbox',
- staticColumns: [
- {
- field: 'toggleHost',
- content: {
- label: '',
- columnClass: 'List-staticColumn--toggle',
- type: "toggle",
- ngClick: "toggleHost($event, host)",
- awToolTip: "
" +
- i18n._("Indicates if a host is available and should be included in running jobs.") +
- "
" +
- i18n._("For hosts that are part of an external" +
- " inventory, this flag may be" +
- " reset by the inventory sync process.") +
- "
",
- dataPlacement: "right",
- nosort: true,
- }
- }, {
- field: 'active_failures',
- content: {
- label: '',
- iconOnly: true,
- nosort: true,
- // do not remove this ng-click directive
- // the list generator case to handle fields without ng-click
- // cannot handle the aw-* directives
- ngClick: 'noop()',
- awPopOver: "{{ host.job_status_html }}",
- dataTitle: "{{ host.job_status_title }}",
- awToolTip: "{{ host.badgeToolTip }}",
- dataPlacement: 'top',
- icon: "{{ 'fa icon-job-' + host.active_failures }}",
- id: 'active-failures-action',
- columnClass: 'status-column List-staticColumn--smallStatus'
- }
- }
- ],
-
- fields: {
- name: {
- key: true,
- label: i18n._('Name'),
- ngClick: "editHost(host.id)",
- columnClass: 'col-sm-4',
- dataHostId: "{{ host.id }}",
- dataType: "host",
- },
- inventory: {
- label: i18n._('Inventory'),
- sourceModel: 'inventory',
- sourceField: 'name',
- columnClass: 'd-none d-sm-flex col-sm-4 elllipsis',
- ngClick: "editInventory(host)"
- }
- },
-
- fieldActions: {
-
- columnClass: 'col-sm-4 col-xs-5 text-right',
- edit: {
- ngClick: "editHost(host.id)",
- icon: 'icon-edit',
- awToolTip: i18n._('Edit host'),
- dataPlacement: 'top',
- ngShow: 'host.summary_fields.user_capabilities.edit'
- },
- view: {
- ngClick: "editHost(host.id)",
- awToolTip: i18n._('View host'),
- dataPlacement: 'top',
- ngShow: '!host.summary_fields.user_capabilities.edit'
- }
- },
-
- actions: {
- refresh: {
- mode: 'all',
- awToolTip: i18n._("Refresh the page"),
- ngClick: "refreshGroups()",
- ngShow: "socketStatus == 'error'",
- actionClass: 'btn List-buttonDefault',
- buttonContent: i18n._('REFRESH')
- },
- smart_inventory: {
- mode: 'all',
- ngClick: "smartInventory()",
- awToolTip: "{{ smartInventoryButtonTooltip }}",
- dataTipWatch: 'smartInventoryButtonTooltip',
- actionClass: 'btn List-buttonDefault',
- buttonContent: i18n._('SMART INVENTORY'),
- ngShow: 'canAdd && (hosts.length > 0 || !(searchTags | isEmpty))',
- dataPlacement: "top",
- ngDisabled: '!enableSmartInventoryButton',
- showTipWhenDisabled: true
- }
- }
- };
-}];
diff --git a/awx/ui/client/src/inventories-hosts/hosts/hosts.partial.html b/awx/ui/client/src/inventories-hosts/hosts/hosts.partial.html
deleted file mode 100644
index 7f594d599d..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/hosts.partial.html
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
No records matched your search.
-
-
NO HOSTS HAVE BEEN CREATED
-
-
-
-
-
-
-
-
-
-
-
- {{ host.description }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/inventories-hosts/hosts/list/host-list.controller.js b/awx/ui/client/src/inventories-hosts/hosts/list/host-list.controller.js
deleted file mode 100644
index 52d82796b9..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/list/host-list.controller.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
-function HostsList($scope, HostsList, $rootScope, GetBasePath,
- rbacUiControlService, Dataset, $state, $filter, Prompt, Wait,
- HostsService, SetStatus, canAdd, $transitions, InventoryHostsStrings) {
-
- let list = HostsList;
-
- init();
-
- function init(){
- $scope.canAdd = canAdd;
- $scope.enableSmartInventoryButton = false;
- $scope.smartInventoryButtonTooltip = InventoryHostsStrings.get('smartinventorybutton.DISABLED_INSTRUCTIONS');
- $scope.strings = InventoryHostsStrings;
-
- // Search init
- $scope.list = list;
- $scope[`${list.iterator}_dataset`] = Dataset.data;
- $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
-
- $rootScope.flashMessage = null;
-
- $scope.$watchCollection(list.name, function() {
- $scope[list.name] = _.map($scope.hosts, function(value) {
- value.inventory_name = value.summary_fields.inventory.name;
- value.inventory_id = value.summary_fields.inventory.id;
- return value;
- });
- setJobStatus();
- });
-
- $transitions.onSuccess({}, function(trans) {
- if(trans.params('to') && trans.params('to').host_search) {
- let hasMoreThanDefaultKeys = false;
- angular.forEach(trans.params('to').host_search, function(value, key) {
- if(key !== 'order_by' && key !== 'page_size' && key !== 'page') {
- hasMoreThanDefaultKeys = true;
- }
- });
- $scope.enableSmartInventoryButton = hasMoreThanDefaultKeys ? true : false;
- $scope.smartInventoryButtonTooltip = hasMoreThanDefaultKeys ? InventoryHostsStrings.get('smartinventorybutton.ENABLED_INSTRUCTIONS') : InventoryHostsStrings.get('smartinventorybutton.DISABLED_INSTRUCTIONS');
- }
- else {
- $scope.enableSmartInventoryButton = false;
- $scope.smartInventoryButtonTooltip = InventoryHostsStrings.get('smartinventorybutton.DISABLED_INSTRUCTIONS');
- }
- });
-
- }
-
- function setJobStatus(){
- _.forEach($scope.hosts, function(value) {
- SetStatus({
- scope: $scope,
- host: value
- });
- });
- }
-
- $scope.createHost = function(){
- $state.go('hosts.add');
- };
- $scope.editHost = function(id){
- $state.go('hosts.edit', {host_id: id});
- };
- $scope.goToInsights = function(id){
- $state.go('hosts.edit.insights', {host_id:id});
- };
- $scope.toggleHost = function(event, host) {
- try {
- $(event.target).tooltip('hide');
- } catch (e) {
- // ignore
- }
-
- host.enabled = !host.enabled;
- HostsService.patch(host.id, {
- enabled: host.enabled
- });
- };
-
- $scope.smartInventory = function() {
- $state.go('inventories.addSmartInventory', {hostfilter: JSON.stringify({"host_filter":`${$state.params.host_search.host_filter}`})});
- };
-
- $scope.editInventory = function(host) {
- if(host.summary_fields && host.summary_fields.inventory) {
- if(host.summary_fields.inventory.kind && host.summary_fields.inventory.kind === 'smart') {
- $state.go('inventories.editSmartInventory', {smartinventory_id: host.inventory});
- }
- else {
- $state.go('inventories.edit', {inventory_id: host.inventory});
- }
- }
- };
-
-}
-
-export default ['$scope', 'HostsList', '$rootScope', 'GetBasePath',
- 'rbacUiControlService', 'Dataset', '$state', '$filter', 'Prompt', 'Wait',
- 'HostsService', 'SetStatus', 'canAdd', '$transitions', 'InventoryHostsStrings', HostsList
-];
diff --git a/awx/ui/client/src/inventories-hosts/hosts/list/main.js b/awx/ui/client/src/inventories-hosts/hosts/list/main.js
deleted file mode 100644
index 0682898494..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/list/main.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import controller from './host-list.controller';
-
-export default
-angular.module('hostsList', [])
- .controller('HostListController', controller);
diff --git a/awx/ui/client/src/inventories-hosts/hosts/main.js b/awx/ui/client/src/inventories-hosts/hosts/main.js
deleted file mode 100644
index 575a2a8e49..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/main.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- import hostEdit from './edit/main';
- import hostList from './list/main';
- import HostsList from './host.list';
- import HostsForm from './host.form';
- import { templateUrl } from '../../shared/template-url/template-url.factory';
- import { N_ } from '../../i18n';
- import ansibleFactsRoute from '../shared/ansible-facts/ansible-facts.route';
- import insightsRoute from '../inventories/insights/insights.route';
- import hostGroupsRoute from './related/groups/hosts-related-groups.route';
- import hostGroupsAssociateRoute from './related/groups/hosts-related-groups-associate.route';
- import hostCompletedJobsRoute from '~features/jobs/routes/hostCompletedJobs.route.js';
- import hostGroups from './related/groups/main';
-
-export default
-angular.module('host', [
- hostEdit.name,
- hostList.name,
- hostGroups.name
- ])
- .factory('HostsForm', HostsForm)
- .factory('HostsList', HostsList)
- .config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
- function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
- let stateDefinitions = stateDefinitionsProvider.$get(),
- stateExtender = $stateExtenderProvider.$get();
-
- let generateHostStates = function(){
- let hostTree = stateDefinitions.generateTree({
- parent: 'hosts', // top-most node in the generated tree (will replace this state definition)
- modes: ['edit'],
- list: 'HostsList',
- form: 'HostsForm',
- controllers: {
- edit: 'HostEditController'
- },
- breadcrumbs: {
- edit: '{{breadcrumb.host_name}}'
- },
- urls: {
- list: '/hosts'
- },
- data: {
- activityStream: true,
- activityStreamTarget: 'host'
- },
- resolve: {
- edit: {
- host: ['Rest', '$stateParams', 'GetBasePath',
- function(Rest, $stateParams, GetBasePath) {
- let path = GetBasePath('hosts') + $stateParams.host_id;
- Rest.setUrl(path);
- return Rest.get();
- }
- ]
- },
- list: {
- canAdd: ['rbacUiControlService', function(rbacUiControlService) {
- return rbacUiControlService.canAdd('hosts')
- .then(function(res) {
- return res.canAdd;
- })
- .catch(function() {
- return false;
- });
- }]
- }
- },
- views: {
- '@': {
- templateUrl: templateUrl('inventories-hosts/hosts/hosts'),
- controller: 'HostListController'
- }
- },
- ncyBreadcrumb: {
- label: N_('HOSTS')
- }
- });
-
- let hostAnsibleFacts = _.cloneDeep(ansibleFactsRoute);
- hostAnsibleFacts.name = 'hosts.edit.ansible_facts';
-
- let hostInsights = _.cloneDeep(insightsRoute);
- hostInsights.name = 'hosts.edit.insights';
-
- let hostCompletedJobs = _.cloneDeep(hostCompletedJobsRoute);
- hostCompletedJobs.name = 'hosts.edit.completed_jobs';
-
- return Promise.all([
- hostTree
- ]).then((generated) => {
- return {
- states: _.reduce(generated, (result, definition) => {
- return result.concat(definition.states);
- }, [
- stateExtender.buildDefinition(hostAnsibleFacts),
- stateExtender.buildDefinition(hostInsights),
- stateExtender.buildDefinition(hostGroupsRoute),
- stateExtender.buildDefinition(hostGroupsAssociateRoute),
- stateExtender.buildDefinition(hostCompletedJobs)
- ])
- };
- });
- };
-
- $stateProvider.state({
- name: 'hosts.**',
- url: '/hosts',
- lazyLoad: () => generateHostStates()
- });
- }
- ]);
diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups-associate.route.js b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups-associate.route.js
deleted file mode 100644
index 9ed6dbfa0b..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups-associate.route.js
+++ /dev/null
@@ -1,32 +0,0 @@
-export default {
- name: 'hosts.edit.groups.associate',
- squashSearchUrl: true,
- url: '/associate?inventory_id',
- ncyBreadcrumb:{
- skip:true
- },
- views: {
- 'modal@hosts.edit': {
- templateProvider: function() {
- return ` `;
- },
- controller: function($scope, $q, GroupsService, $state){
- $scope.associateGroups = function(selectedItems){
- var deferred = $q.defer();
- return $q.all( _.map(selectedItems, (selectedItem) => GroupsService.associateHost({id: parseInt($state.params.host_id)}, selectedItem.id)) )
- .then( () =>{
- deferred.resolve();
- }, (error) => {
- deferred.reject(error);
- });
- };
- }
- }
- },
- onExit: function($state) {
- if ($state.transition) {
- $('#associate-groups-modal').modal('hide');
- $('body').removeClass('modal-open');
- }
- },
-};
diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.controller.js b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.controller.js
deleted file mode 100644
index 72b1ad7bc9..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.controller.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
- export default
- ['$scope', '$rootScope', '$state', '$stateParams', 'HostsRelatedGroupsList', 'InventoryHostsStrings',
- 'CancelSourceUpdate', 'rbacUiControlService', 'GetBasePath', 'Dataset', 'Find', 'QuerySet', 'inventoryData', 'host', 'GroupsService',
- function($scope, $rootScope, $state, $stateParams, HostsRelatedGroupsList, InventoryHostsStrings,
- CancelSourceUpdate, rbacUiControlService, GetBasePath, Dataset, Find, qs, inventoryData, host, GroupsService){
-
- let list = HostsRelatedGroupsList;
-
- init();
-
- function init(){
- $scope.inventory_id = inventoryData.id;
- $scope.canAdd = false;
- $scope.strings = InventoryHostsStrings;
-
- rbacUiControlService.canAdd(GetBasePath('inventory') + $scope.inventory_id + "/groups")
- .then(function(canAdd) {
- $scope.canAdd = canAdd;
- });
-
- // Search init
- $scope.list = list;
- $scope[`${list.iterator}_dataset`] = Dataset.data;
- $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
-
- }
-
- $scope.editGroup = function(id){
- $state.go('inventories.edit.groups.edit', {inventory_id: $scope.inventory_id, group_id: id});
- };
-
- $scope.goToGroupGroups = function(id){
- $state.go('inventories.edit.groups.edit.nested_groups', {inventory_id: $scope.inventory_id, group_id: id});
- };
-
- $scope.associateGroup = function() {
- $state.go('.associate', {inventory_id: $scope.inventory_id});
- };
-
- $scope.disassociateHost = function(group){
- $scope.disassociateGroup = {};
- angular.extend($scope.disassociateGroup, group);
- $('#host-disassociate-modal').modal('show');
- };
-
- $scope.confirmDisassociate = function(){
-
- $('#host-disassociate-modal').off('hidden.bs.modal').on('hidden.bs.modal', function () {
- $('#host-disassociate-modal').off('hidden.bs.modal');
-
- let reloadListStateParams = null;
-
- if($scope.groups.length === 1 && $state.params.group_search && !_.isEmpty($state.params.group_search.page) && $state.params.group_search.page !== '1') {
- reloadListStateParams = _.cloneDeep($state.params);
- reloadListStateParams.group_search.page = (parseInt(reloadListStateParams.group_search.page)-1).toString();
- }
-
- $state.go('.', reloadListStateParams, {reload: true});
- });
-
- GroupsService.disassociateHost(host.id, $scope.disassociateGroup.id).then(() => {
- $state.go($state.current, null, {reload: true});
- $('#host-disassociate-modal').modal('hide');
- $('body').removeClass('modal-open');
- $('.modal-backdrop').remove();
- });
-
- };
- }];
diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js
deleted file mode 100644
index ee7b5cb560..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-export default ['i18n', function(i18n) {
- return {
- name: 'groups',
- iterator: 'group',
- editTitle: '{{ host.name }}',
- well: true,
- wellOverride: true,
- index: false,
- hover: true,
- trackBy: 'group.id',
- basePath: 'api/v2/hosts/{{$stateParams.host_id}}/groups/',
- layoutClass: 'List-staticColumnLayout--statusOrCheckbox',
- staticColumns: [
- {
- field: 'failed_hosts',
- content: {
- label: '',
- nosort: true,
- mode: 'all',
- iconOnly: true,
- awToolTip: "{{ group.hosts_status_tip }}",
- dataPlacement: "top",
- icon: "{{ 'fa icon-job-' + group.hosts_status_class }}",
- columnClass: 'status-column'
- }
- }
- ],
-
- fields: {
- name: {
- label: i18n._('Groups'),
- key: true,
- ngClick: "goToGroupGroups(group.id)",
- columnClass: 'col-lg-6 col-md-6 col-sm-6 col-xs-6',
- }
- },
-
- actions: {
- refresh: {
- mode: 'all',
- awToolTip: i18n._("Refresh the page"),
- ngClick: "refreshGroups()",
- ngShow: "socketStatus == 'error'",
- actionClass: 'btn List-buttonDefault',
- buttonContent: i18n._('REFRESH')
- },
- associate: {
- mode: 'all',
- ngClick: "associateGroup()",
- awToolTip: i18n._("Associate this host with a new group"),
- actionClass: 'at-Button--add',
- actionId: 'button-add',
- ngShow: 'canAdd',
- dataPlacement: "top",
- }
- },
-
- fieldActions: {
- columnClass: 'col-lg-6 col-md-6 col-sm-6 col-xs-6 text-right',
- "delete": {
- //label: 'Delete',
- mode: 'all',
- ngClick: "disassociateHost(group)",
- awToolTip: i18n._('Disassociate group'),
- iconClass: 'fa fa-times',
- dataPlacement: "top",
- ngShow: "group.summary_fields.user_capabilities.delete"
- }
- }
- };
-}];
diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.partial.html b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.partial.html
deleted file mode 100644
index 93aeab36bf..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.partial.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
- Are you sure you want to disassociate the host below from {{disassociateGroup.name}}?
-
-
{{ host.name }}
-
-
-
-
-
-
diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.route.js b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.route.js
deleted file mode 100644
index fd21ff7b1d..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.route.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import { N_ } from '../../../../i18n';
-import {templateUrl} from '../../../../shared/template-url/template-url.factory';
-
-export default {
- name: "hosts.edit.groups",
- url: "/groups?{group_search:queryset}",
- resolve: {
- Dataset: ['HostsRelatedGroupsList', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
- (list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
- // allow related list definitions to use interpolated $rootScope / $stateParams in basePath field
- let path, interpolator;
- if (GetBasePath(list.basePath)) {
- path = GetBasePath(list.basePath);
- } else {
- interpolator = $interpolate(list.basePath);
- path = interpolator({ $rootScope: $rootScope, $stateParams: $stateParams });
- }
- return qs.search(path, $stateParams[`${list.iterator}_search`]);
- }
- ],
- host: ['$stateParams', 'HostsService', function($stateParams, HostsService) {
- if($stateParams.host_id){
- return HostsService.get({ id: $stateParams.host_id }).then(function(res) {
- return res.data.results[0];
- });
- }
- }],
- inventoryData: ['InventoriesService', '$stateParams', 'host', function(InventoriesService, $stateParams, host) {
- var id = ($stateParams.inventory_id) ? $stateParams.inventory_id : host.summary_fields.inventory.id;
- return InventoriesService.getInventory(id).then(res => res.data);
- }]
- },
- params: {
- group_search: {
- value: {
- page_size: "20",
- order_by: "name"
- },
- dynamic: true,
- squash: ""
- }
- },
- ncyBreadcrumb: {
- parent: "hosts.edit",
- label: N_("GROUPS")
- },
- views: {
- 'related': {
- templateProvider: function(HostsRelatedGroupsList, generateList, $templateRequest) {
- let html = generateList.build({
- list: HostsRelatedGroupsList,
- mode: 'edit'
- });
-
- return $templateRequest(templateUrl('inventories-hosts/hosts/related/groups/hosts-related-groups')).then((template) => {
- return html.concat(template);
- });
- },
- controller: 'HostsRelatedGroupsController'
- }
- }
-};
diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/main.js b/awx/ui/client/src/inventories-hosts/hosts/related/groups/main.js
deleted file mode 100644
index 7caaa49f41..0000000000
--- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/main.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*************************************************
- * Copyright (c) 2017 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import controller from './hosts-related-groups.controller';
-import hostGroupsDefinition from './hosts-related-groups.list';
-
-
-export default
- angular.module('hostGroups', [])
- .factory('HostsRelatedGroupsList', hostGroupsDefinition)
- .controller('HostsRelatedGroupsController', controller);
diff --git a/awx/ui/client/src/inventories-hosts/inventories/adhoc/adhoc-credential.route.js b/awx/ui/client/src/inventories-hosts/inventories/adhoc/adhoc-credential.route.js
deleted file mode 100644
index c62ba4d547..0000000000
--- a/awx/ui/client/src/inventories-hosts/inventories/adhoc/adhoc-credential.route.js
+++ /dev/null
@@ -1,52 +0,0 @@
-export default {
- searchPrefix: 'credential',
- url: '/credential',
- data: {
- formChildState: true
- },
- params: {
- credential_search: {
- value: {
- page_size: '5',
- credential_type: null
- },
- squash: true,
- dynamic: true
- }
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'related': {
- templateProvider: function(ListDefinition, generateList) {
- let list_html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
- return `${list_html} `;
-
- }
- }
- },
- resolve: {
- ListDefinition: ['CredentialList', function(CredentialList) {
- let list = _.cloneDeep(CredentialList);
- return list;
- }],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => {
- let path = GetBasePath(list.name) || GetBasePath(list.basePath);
- return qs.search(path, $stateParams[`${list.iterator}_search`]);
- }
- ]
- },
- onExit: function($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- }
-};
diff --git a/awx/ui/client/src/inventories-hosts/inventories/adhoc/adhoc.controller.js b/awx/ui/client/src/inventories-hosts/inventories/adhoc/adhoc.controller.js
deleted file mode 100644
index f4cc2b447f..0000000000
--- a/awx/ui/client/src/inventories-hosts/inventories/adhoc/adhoc.controller.js
+++ /dev/null
@@ -1,320 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/**
- * @ngdoc function
- * @name controllers.function:Adhoc
- * @description This controller controls the adhoc form creation, command launching and navigating to standard out after command has been succesfully ran.
-*/
-function adhocController($q, $scope, $stateParams,
- $state, CheckPasswords, PromptForPasswords, CreateLaunchDialog, CreateSelect2, adhocForm,
- GenerateForm, Rest, ProcessErrors, GetBasePath, GetChoices,
- KindChange, Wait, ParseTypeChange, machineCredentialType) {
-
- // this is done so that we can access private functions for testing, but
- // we don't want to populate the "public" scope with these internal
- // functions
- var privateFn = {};
- this.privateFn = privateFn;
-
- var id = $stateParams.inventory_id ? $stateParams.inventory_id : $stateParams.smartinventory_id,
- hostPattern = $stateParams.pattern;
-
- // note: put any urls that the controller will use in here!!!!
- privateFn.setAvailableUrls = function() {
- return {
- adhocUrl: GetBasePath('inventory') + id + '/ad_hoc_commands/',
- inventoryUrl: GetBasePath('inventory') + id + '/',
- machineCredentialUrl: GetBasePath('credentials') + '?credential_type__namespace=ssh'
- };
- };
-
- var urls = privateFn.setAvailableUrls();
-
- // set the default options for the selects of the adhoc form
- privateFn.setFieldDefaults = function(verbosity_options, forks_default) {
- var verbosity;
- for (verbosity in verbosity_options) {
- if (verbosity_options[verbosity].isDefault) {
- $scope.verbosity = verbosity_options[verbosity];
- }
- }
- if (forks_default !== 0) {
- $("#forks-number").spinner("value", forks_default);
- $scope.forks = forks_default;
- }
- };
-
- // set when "working" starts and stops
- privateFn.setLoadingStartStop = function() {
- var asyncHelper = {},
- formReadyPromise = 0;
-
- Wait('start');
-
- if (asyncHelper.removeChoicesReady) {
- asyncHelper.removeChoicesReady();
- }
- asyncHelper.removeChoicesReady = $scope.$on('adhocFormReady',
- isFormDone);
-
- // check to see if all requests have completed
- function isFormDone() {
- formReadyPromise++;
-
- if (formReadyPromise === 2) {
- privateFn.setFieldDefaults($scope.adhoc_verbosity_options,
- $scope.forks_field.default);
-
- CreateSelect2({
- element: '#adhoc_module_name',
- multiple: false
- });
-
- CreateSelect2({
- element: '#adhoc_verbosity',
- multiple: false
- });
-
- Wait('stop');
- }
- }
- };
-
- // set the arguments help to watch on change of the module
- privateFn.instantiateArgumentHelp = function() {
- $scope.$watch('module_name', function(val) {
- if (val) {
- // give the docs for the selected module in the popover
- $scope.argsPopOver = 'These arguments are used with the ' +
- 'specified module. You can find information about the ' +
- val.value + ' module here .
';
- } else {
- // no module selected
- $scope.argsPopOver = "These arguments are used with the" +
- " specified module.
";
- }
- }, true);
-
- // initially set to the same as no module selected
- $scope.argsPopOver = "These arguments are used with the " +
- "specified module.
";
- };
-
- // pre-populate host patterns from the inventory page and
- // delete the value off of rootScope
- privateFn.instantiateHostPatterns = function(hostPattern) {
- $scope.limit = hostPattern;
- $scope.providedHostPatterns = $scope.limit;
- };
-
- // call helpers to initialize lookup and select fields through get
- // requests
- privateFn.initializeFields = function(machineCredentialUrl, adhocUrl) {
-
- // setup module name select
- GetChoices({
- scope: $scope,
- url: adhocUrl,
- field: 'module_name',
- variable: 'adhoc_module_options',
- callback: 'adhocFormReady'
- });
-
- // setup verbosity options select
- GetChoices({
- scope: $scope,
- url: adhocUrl,
- field: 'verbosity',
- variable: 'adhoc_verbosity_options',
- callback: 'adhocFormReady'
- });
- };
-
- // instantiate all variables on scope for display in the partial
- privateFn.initializeForm = function(id, urls, hostPattern) {
- // inject the adhoc command form
- GenerateForm.inject(adhocForm,
- { mode: 'add', related: true, scope: $scope });
-
- // set when "working" starts and stops
- privateFn.setLoadingStartStop();
-
- // put the inventory id on scope for the partial to use
- $scope.inv_id = id;
-
- // set the arguments help to watch on change of the module
- privateFn.instantiateArgumentHelp();
-
- // pre-populate host patterns from the inventory page and
- // delete the value off of rootScope
- privateFn.instantiateHostPatterns(hostPattern);
-
- privateFn.initializeFields(urls.machineCredentialUrl, urls.adhocUrl);
- };
-
- privateFn.initializeForm(id, urls, hostPattern);
-
- // init codemirror
- $scope.extra_vars = '---';
- $scope.parseType = 'yaml';
- $scope.envParseType = 'yaml';
- ParseTypeChange({ scope: $scope, field_id: 'adhoc_extra_vars' , variable: "extra_vars"});
-
- $scope.toggleForm = function(key) {
- $scope[key] = !$scope[key];
- };
-
- $scope.formCancel = function(){
- $state.go('^');
- };
-
- // remove all data input into the form and reset the form back to defaults
- $scope.formReset = function () {
- GenerateForm.reset();
-
- // pre-populate host patterns from the inventory page and
- // delete the value off of rootScope
- privateFn.instantiateHostPatterns($scope.providedHostPatterns);
-
- KindChange({ scope: $scope, form: adhocForm, reset: false });
-
- // set the default options for the selects of the adhoc form
- privateFn.setFieldDefaults($scope.adhoc_verbosity_options,
- $scope.forks_default);
- };
-
- // launch the job with the provided form data
- $scope.launchJob = function () {
- var adhocUrl = GetBasePath('inventory') + id +
- '/ad_hoc_commands/', fld, data={}, html;
-
- html = '