summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in2
-rw-r--r--awx/main/tests/functional/test_licenses.py26
-rw-r--r--awx/settings/defaults.py3
-rw-r--r--awx/ui/__init__.py5
-rw-r--r--awx/ui/apps.py10
-rw-r--r--awx/ui/conf.py74
-rw-r--r--awx/ui/fields.py45
-rw-r--r--awx/ui_next/src/App.jsx6
-rw-r--r--awx/ui_next/src/components/AppContainer/PageHeaderToolbar.jsx4
-rw-r--r--awx/ui_next/urls.py3
-rw-r--r--awx/urls.py1
11 files changed, 141 insertions, 38 deletions
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/awx/main/tests/functional/test_licenses.py b/awx/main/tests/functional/test_licenses.py
index f3e623d281..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
@@ -65,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())
@@ -113,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/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/ui/__init__.py b/awx/ui/__init__.py
new file mode 100644
index 0000000000..bfb3e776cd
--- /dev/null
+++ b/awx/ui/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (c) 2015 Ansible, Inc.
+# All Rights Reserved.
+
+default_app_config = 'awx.ui.apps.UIConfig'
+
diff --git a/awx/ui/apps.py b/awx/ui/apps.py
new file mode 100644
index 0000000000..5b8e5083c1
--- /dev/null
+++ b/awx/ui/apps.py
@@ -0,0 +1,10 @@
+# Django
+from django.apps import AppConfig
+from django.utils.translation import ugettext_lazy as _
+
+
+class UIConfig(AppConfig):
+
+ name = 'awx.ui'
+ verbose_name = _('UI')
+
diff --git a/awx/ui/conf.py b/awx/ui/conf.py
new file mode 100644
index 0000000000..3148aec6ee
--- /dev/null
+++ b/awx/ui/conf.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2016 Ansible, Inc.
+# All Rights Reserved.
+
+# Django
+from django.utils.translation import ugettext_lazy as _
+
+# Tower
+from awx.conf import register, fields
+from awx.ui.fields import PendoTrackingStateField, CustomLogoField # noqa
+
+
+register(
+ 'PENDO_TRACKING_STATE',
+ field_class=PendoTrackingStateField,
+ choices=[
+ ('off', _('Off')),
+ ('anonymous', _('Anonymous')),
+ ('detailed', _('Detailed')),
+ ],
+ label=_('User Analytics Tracking State'),
+ help_text=_('Enable or Disable User Analytics Tracking.'),
+ category=_('UI'),
+ category_slug='ui',
+)
+
+register(
+ 'CUSTOM_LOGIN_INFO',
+ field_class=fields.CharField,
+ allow_blank=True,
+ default='',
+ label=_('Custom Login Info'),
+ help_text=_('If needed, you can add specific information (such as a legal '
+ 'notice or a disclaimer) to a text box in the login modal using '
+ 'this setting. Any content added must be in plain text or an '
+ 'HTML fragment, as other markup languages are not supported.'),
+ category=_('UI'),
+ category_slug='ui',
+)
+
+register(
+ 'CUSTOM_LOGO',
+ field_class=CustomLogoField,
+ allow_blank=True,
+ default='',
+ label=_('Custom Logo'),
+ help_text=_('To set up a custom logo, provide a file that you create. For '
+ 'the custom logo to look its best, use a .png file with a '
+ 'transparent background. GIF, PNG and JPEG formats are supported.'),
+ placeholder='data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=',
+ category=_('UI'),
+ category_slug='ui',
+)
+
+register(
+ 'MAX_UI_JOB_EVENTS',
+ field_class=fields.IntegerField,
+ min_value=100,
+ label=_('Max Job Events Retrieved by UI'),
+ help_text=_('Maximum number of job events for the UI to retrieve within a '
+ 'single request.'),
+ category=_('UI'),
+ category_slug='ui',
+)
+
+register(
+ 'UI_LIVE_UPDATES_ENABLED',
+ field_class=fields.BooleanField,
+ label=_('Enable Live Updates in the UI'),
+ help_text=_('If disabled, the page will not refresh when events are received. '
+ 'Reloading the page will be required to get the latest details.'),
+ category=_('UI'),
+ category_slug='ui',
+)
+
diff --git a/awx/ui/fields.py b/awx/ui/fields.py
new file mode 100644
index 0000000000..4d96165d4d
--- /dev/null
+++ b/awx/ui/fields.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2016 Ansible, Inc.
+# All Rights Reserved.
+
+# Python
+import base64
+import binascii
+import re
+
+# Django
+from django.utils.translation import ugettext_lazy as _
+
+# Tower
+from awx.conf import fields, register
+
+
+class PendoTrackingStateField(fields.ChoiceField):
+
+ def to_internal_value(self, data):
+ # Any false/null values get converted to 'off'.
+ if data in fields.NullBooleanField.FALSE_VALUES or data in fields.NullBooleanField.NULL_VALUES:
+ return 'off'
+ return super(PendoTrackingStateField, self).to_internal_value(data)
+
+
+class CustomLogoField(fields.CharField):
+
+ CUSTOM_LOGO_RE = re.compile(r'^data:image/(?:png|jpeg|gif);base64,([A-Za-z0-9+/=]+?)$')
+
+ default_error_messages = {
+ 'invalid_format': _('Invalid format for custom logo. Must be a data URL with a base64-encoded GIF, PNG or JPEG image.'),
+ 'invalid_data': _('Invalid base64-encoded data in data URL.'),
+ }
+
+ def to_internal_value(self, data):
+ data = super(CustomLogoField, self).to_internal_value(data)
+ match = self.CUSTOM_LOGO_RE.match(data)
+ if not match:
+ self.fail('invalid_format')
+ b64data = match.group(1)
+ try:
+ base64.b64decode(b64data)
+ except (TypeError, binascii.Error):
+ self.fail('invalid_data')
+ return data
+
diff --git a/awx/ui_next/src/App.jsx b/awx/ui_next/src/App.jsx
index 9b230ac553..ffafd07dba 100644
--- a/awx/ui_next/src/App.jsx
+++ b/awx/ui_next/src/App.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import {
useRouteMatch,
useLocation,
- BrowserRouter,
+ HashRouter,
Route,
Switch,
Redirect,
@@ -76,7 +76,7 @@ function App() {
}
export default () => (
- <BrowserRouter basename="/next">
+ <HashRouter>
<App />
- </BrowserRouter>
+ </HashRouter>
);
diff --git a/awx/ui_next/src/components/AppContainer/PageHeaderToolbar.jsx b/awx/ui_next/src/components/AppContainer/PageHeaderToolbar.jsx
index 970e5651d6..f09bdbdf3f 100644
--- a/awx/ui_next/src/components/AppContainer/PageHeaderToolbar.jsx
+++ b/awx/ui_next/src/components/AppContainer/PageHeaderToolbar.jsx
@@ -118,8 +118,8 @@ class PageHeaderToolbar extends Component {
key="user"
href={
loggedInUser
- ? `/next/users/${loggedInUser.id}/details`
- : '/next/home'
+ ? `/users/${loggedInUser.id}/details`
+ : '/home'
}
>
{i18n._(t`User Details`)}
diff --git a/awx/ui_next/urls.py b/awx/ui_next/urls.py
index bb288cf625..03c3bbd3d2 100644
--- a/awx/ui_next/urls.py
+++ b/awx/ui_next/urls.py
@@ -10,5 +10,6 @@ class IndexView(TemplateView):
app_name = 'ui_next'
urlpatterns = [
- url(r'^next/*', IndexView.as_view(), name='ui_next')
+ url(r'^$', IndexView.as_view(), name='index'),
+ #url(r'^migrations_notran/$', migrations_notran, name='migrations_notran'),
]
diff --git a/awx/urls.py b/awx/urls.py
index bdcae84bcb..d26ea0d6f5 100644
--- a/awx/urls.py
+++ b/awx/urls.py
@@ -15,7 +15,6 @@ from awx.main.views import (
urlpatterns = [
url(r'', include('awx.ui_next.urls', namespace='ui_next')),
- url(r'', include('awx.ui.urls', namespace='ui')),
url(r'^api/', include('awx.api.urls', namespace='api')),
url(r'^sso/', include('awx.sso.urls', namespace='sso')),
url(r'^sso/', include('social_django.urls', namespace='social')),