From 7cdd4e5bb81892e6cf7f07c4b29ccc9c7781267c Mon Sep 17 00:00:00 2001 From: PengfeiLi0218 Date: Wed, 3 Jul 2019 21:04:52 +0800 Subject: [PATCH] add Webui function --- apimanager/apimanager/settings.py | 34 ++++----- apimanager/apimanager/urls.py | 1 + apimanager/base/templates/base.html | 2 + .../metrics/templates/metrics/summary.html | 5 ++ apimanager/metrics/views.py | 18 +++++ apimanager/webui/__init__.py | 0 apimanager/webui/apps.py | 11 +++ apimanager/webui/forms.py | 14 ++++ apimanager/webui/static/webui/css/webui.css | 10 +++ apimanager/webui/static/webui/js/webui.js | 25 ++++++ apimanager/webui/templates/webui/index.html | 49 ++++++++++++ apimanager/webui/urls.py | 14 ++++ apimanager/webui/views.py | 76 +++++++++++++++++++ requirements.txt | 3 +- 14 files changed, 244 insertions(+), 18 deletions(-) create mode 100644 apimanager/webui/__init__.py create mode 100644 apimanager/webui/apps.py create mode 100644 apimanager/webui/forms.py create mode 100644 apimanager/webui/static/webui/css/webui.css create mode 100644 apimanager/webui/static/webui/js/webui.js create mode 100644 apimanager/webui/templates/webui/index.html create mode 100644 apimanager/webui/urls.py create mode 100644 apimanager/webui/views.py diff --git a/apimanager/apimanager/settings.py b/apimanager/apimanager/settings.py index d21d1d6..b22314b 100644 --- a/apimanager/apimanager/settings.py +++ b/apimanager/apimanager/settings.py @@ -56,6 +56,7 @@ INSTALLED_APPS = [ 'customers', 'metrics', 'config', + 'webui', ] MIDDLEWARE = [ @@ -224,21 +225,7 @@ DIRECTLOGIN_PATH = '/my/logins/direct' # Set to true if the API is connected to a core banking system GATEWAYLOGIN_HAS_CBS = False -# Local settings can override anything in here -try: - from apimanager.local_settings import * # noqa -except ImportError: - pass -if not OAUTH_CONSUMER_KEY: - raise ImproperlyConfigured('Missing settings for OAUTH_CONSUMER_KEY') -if not OAUTH_CONSUMER_SECRET: - raise ImproperlyConfigured('Missing settings for OAUTH_CONSUMER_SECRET') - -# Settings here might use parts overwritten in local settings -API_ROOT = API_HOST + API_BASE_PATH + API_VERSION -# For some reason, swagger is not available at the latest API version -API_URL_SWAGGER = API_HOST + '/obp/v1.4.0/resource-docs/v' + API_VERSION + '/swagger' # noqa CACHES = { 'default': { @@ -261,8 +248,21 @@ EXCLUDE_URL_PATTERN = [] # App Name to aggregate metrics API_EXPLORER_APP_NAME = 'xxx' + +# Local settings can override anything in here +try: + from apimanager.local_settings import * # noqa +except ImportError: + pass + +# Settings here might use parts overwritten in local settings +API_ROOT = API_HOST + API_BASE_PATH + API_VERSION +# For some reason, swagger is not available at the latest API version +API_URL_SWAGGER = API_HOST + '/obp/v1.4.0/resource-docs/v' + API_VERSION + '/swagger' # noqa + VERIFY = True if API_HOST.startswith("https") else False - - - +if not OAUTH_CONSUMER_KEY: + raise ImproperlyConfigured('Missing settings for OAUTH_CONSUMER_KEY') +if not OAUTH_CONSUMER_SECRET: + raise ImproperlyConfigured('Missing settings for OAUTH_CONSUMER_SECRET') diff --git a/apimanager/apimanager/urls.py b/apimanager/apimanager/urls.py index 1d0da46..86ca726 100644 --- a/apimanager/apimanager/urls.py +++ b/apimanager/apimanager/urls.py @@ -35,4 +35,5 @@ urlpatterns = [ url(r'^customers/', include('customers.urls')), url(r'^metrics/', include('metrics.urls')), url(r'^config/', include('config.urls')), + url(r'^webui/', include('webui.urls')), ] diff --git a/apimanager/base/templates/base.html b/apimanager/base/templates/base.html index aa46c6e..7389ea6 100644 --- a/apimanager/base/templates/base.html +++ b/apimanager/base/templates/base.html @@ -62,6 +62,8 @@ {% url "config-index" as config_index_url %} Config + {% url "webui-index" as webui_props_index_url %} + Webui Props {% if API_TESTER_URL %}
  • diff --git a/apimanager/metrics/templates/metrics/summary.html b/apimanager/metrics/templates/metrics/summary.html index eb938a9..01d8378 100644 --- a/apimanager/metrics/templates/metrics/summary.html +++ b/apimanager/metrics/templates/metrics/summary.html @@ -55,7 +55,12 @@
    {{ form.include_obp_apps }} Include System Calls + {{ excluded_functions }} + {{ excluded_url_pattern }}
    + {% if excluded_apps %} + {{ excluded_apps }} + {% endif %}
    diff --git a/apimanager/metrics/views.py b/apimanager/metrics/views.py index a4e85f3..0dc8225 100644 --- a/apimanager/metrics/views.py +++ b/apimanager/metrics/views.py @@ -818,6 +818,9 @@ class MetricsSummaryView(LoginRequiredMixin, TemplateView): 'top_apis_bar_chart': top_apis_bar_chart, 'median_time_to_first_api_call': median_time_to_first_api_call, 'form': form, + 'excluded_apps':EXCLUDE_APPS, + 'excluded_functions':EXCLUDE_FUNCTIONS, + 'excluded_url_pattern':EXCLUDE_URL_PATTERN, }) return context @@ -868,6 +871,9 @@ class YearlySummaryView(MetricsSummaryView): 'top_apis_bar_chart': top_apis_bar_chart, 'median_time_to_first_api_call': median_time_to_first_api_call, 'form': form, + 'excluded_apps':EXCLUDE_APPS, + 'excluded_functions':EXCLUDE_FUNCTIONS, + 'excluded_url_pattern':EXCLUDE_URL_PATTERN, }) return context @@ -922,6 +928,9 @@ class QuarterlySummaryView(MetricsSummaryView): 'top_apis_bar_chart': top_apis_bar_chart, 'median_time_to_first_api_call': median_time_to_first_api_call, 'form': form, + 'excluded_apps':EXCLUDE_APPS, + 'excluded_functions':EXCLUDE_FUNCTIONS, + 'excluded_url_pattern':EXCLUDE_URL_PATTERN, }) return context @@ -973,6 +982,9 @@ class WeeklySummaryView(MetricsSummaryView): # ##'calls_per_half_day': calls_per_half_day, 'median_time_to_first_api_call': median_time_to_first_api_call, 'form': form, + 'excluded_apps':EXCLUDE_APPS, + 'excluded_functions':EXCLUDE_FUNCTIONS, + 'excluded_url_pattern':EXCLUDE_URL_PATTERN, }) return context @@ -1026,6 +1038,9 @@ class DailySummaryView(MetricsSummaryView): 'top_apis_bar_chart': top_apis_bar_chart, 'median_time_to_first_api_call': median_time_to_first_api_call, 'form': form, + 'excluded_apps':EXCLUDE_APPS, + 'excluded_functions':EXCLUDE_FUNCTIONS, + 'excluded_url_pattern':EXCLUDE_URL_PATTERN, }) return context @@ -1085,5 +1100,8 @@ class CustomSummaryView(MetricsSummaryView): # ##'calls_per_day': calls_per_day, # ##'calls_per_half_day': calls_per_half_day, 'form': form, + 'excluded_apps':EXCLUDE_APPS, + 'excluded_functions':EXCLUDE_FUNCTIONS, + 'excluded_url_pattern':EXCLUDE_URL_PATTERN, }) return context \ No newline at end of file diff --git a/apimanager/webui/__init__.py b/apimanager/webui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/webui/apps.py b/apimanager/webui/apps.py new file mode 100644 index 0000000..5196c49 --- /dev/null +++ b/apimanager/webui/apps.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +""" +App config for config app +""" + +from django.apps import AppConfig + + +class ConfigConfig(AppConfig): + """Config for config""" + name = 'config' diff --git a/apimanager/webui/forms.py b/apimanager/webui/forms.py new file mode 100644 index 0000000..916066c --- /dev/null +++ b/apimanager/webui/forms.py @@ -0,0 +1,14 @@ +from django import forms + + +class WebuiForm(forms.Form): + + webui_props = forms.CharField( + label='WEBUI Props', + widget=forms.Textarea( + attrs={ + 'class': 'form-control', + } + ), + required=False + ) \ No newline at end of file diff --git a/apimanager/webui/static/webui/css/webui.css b/apimanager/webui/static/webui/css/webui.css new file mode 100644 index 0000000..c2c54e3 --- /dev/null +++ b/apimanager/webui/static/webui/css/webui.css @@ -0,0 +1,10 @@ +#config pre { + overflow: auto; + word-wrap: normal; + white-space: pre; +} +#config .string { color: green; } +#config .number { color: darkorange; } +#config .boolean { color: blue; } +#config .null { color: magenta; } +#config .key { color: red; } diff --git a/apimanager/webui/static/webui/js/webui.js b/apimanager/webui/static/webui/js/webui.js new file mode 100644 index 0000000..fb0ea03 --- /dev/null +++ b/apimanager/webui/static/webui/js/webui.js @@ -0,0 +1,25 @@ +$(document).ready(function($) { + function syntaxHighlight(json) { + if (typeof json != 'string') { + json = JSON.stringify(json, undefined, 2); + } + json = json.replace(/&/g, '&').replace(//g, '>'); + return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { + var cls = 'number'; + if (/^"/.test(match)) { + if (/:$/.test(match)) { + cls = 'key'; + } else { + cls = 'string'; + } + } else if (/true|false/.test(match)) { + cls = 'boolean'; + } else if (/null/.test(match)) { + cls = 'null'; + } + return '' + match + ''; + }); + } + + $('#config-json').html((syntaxHighlight(ConfigJson))); +}); diff --git a/apimanager/webui/templates/webui/index.html b/apimanager/webui/templates/webui/index.html new file mode 100644 index 0000000..ac9fbe8 --- /dev/null +++ b/apimanager/webui/templates/webui/index.html @@ -0,0 +1,49 @@ +{% extends 'base.html' %} +{% load static %} + +{% block page_title %}{{ block.super }} / Users{% endblock page_title %} + +{% block content %} +
    +
    +

    WEBUI

    + +
    + {% csrf_token %} + {% if form.non_field_errors %} +
    + {{ form.non_field_errors }} +
    + {% endif %} + +
    +
    + {% if form.webui_props.errors %}
    {{ form.webui_props.errors }}
    {% endif %} +
    + {{ form.webui_props.label_tag }} + {{ form.webui_props }} +
    +
    +
    + +
    + +
    +
    +
    +
    +{% endblock %} + +{% block extrajs %} + + +{% endblock extrajs %} + + +{% block extracss %} + +{% endblock extracss %} diff --git a/apimanager/webui/urls.py b/apimanager/webui/urls.py new file mode 100644 index 0000000..bb9b59e --- /dev/null +++ b/apimanager/webui/urls.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +""" +URLs for config app +""" + +from django.conf.urls import url + +from .views import IndexView + +urlpatterns = [ + url(r'^$', + IndexView.as_view(), + name='webui-index'), +] diff --git a/apimanager/webui/views.py b/apimanager/webui/views.py new file mode 100644 index 0000000..279289a --- /dev/null +++ b/apimanager/webui/views.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +""" +Views of config app +""" + +import json + +from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin +from django.views.generic import FormView +from obp.api import API, APIError +from .forms import WebuiForm +from django.urls import reverse_lazy + +def error_once_only(request, err): + """ + Just add the error once + :param request: + :param err: + :return: + """ + storage = messages.get_messages(request) + if str(err) not in [str(m.message) for m in storage]: + messages.error(request, err) + +class IndexView(LoginRequiredMixin, FormView): + """Index view for config""" + template_name = "webui/index.html" + form_class = WebuiForm + success_url = reverse_lazy('webui_list') + + def dispatch(self, request, *args, **kwargs): + self.api = API(request.session.get('obp')) + return super(IndexView, self).dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super(IndexView, self).get_context_data(**kwargs) + + return context + + def get_form(self, *args, **kwargs): + form = super(IndexView, self).get_form(*args, **kwargs) + # Cannot add api in constructor: super complains about unknown kwarg + fields = form.fields + form.api = self.api + try: + fields['webui_props'].initial = "" + + except APIError as err: + messages.error(self.request, err) + except: + messages.error(self.request, "Unknown Error") + + return form + + def form_valid(self, form): + try: + data = form.cleaned_data + urlpath = '/management/webui_props' + payload = { + "name":"webui_api_explorer_url", + "value" : str(data["webui_props"]).replace("\n", "\\n").replace("\"", '\\"') + } + result = self.api.post(urlpath, payload=payload) + except APIError as err: + error_once_only(self.request, err) + return super(IndexView, self).form_invalid(form) + except Exception as err: + error_once_only(self.request, "Unknown Error") + return super(IndexView, self).form_invalid(form) + if 'code' in result and result['code']>=400: + error_once_only(self.request, result['message']) + return super(IndexView, self).form_valid(form) + msg = 'Submission successfully!' + messages.success(self.request, msg) + return super(IndexView, self).form_valid(form) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 9123025..675ad08 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ gunicorn==19.6.0 matplotlib django-bootstrap-datepicker-plus django-mathfilters -django-bootstrap3 \ No newline at end of file +django-bootstrap3 +psycopg2 \ No newline at end of file