/feature add Export_CSV in ATM_Detail

This commit is contained in:
Reena-cell 2022-08-03 13:38:46 +02:00
parent 7fa33153fd
commit d1522d60f5
19 changed files with 4800 additions and 11 deletions

View File

@ -60,6 +60,7 @@ INSTALLED_APPS = [
'config',
'webui',
'methodrouting',
'connectormethod',
'dynamicendpoints',
'apicollections'
]

View File

@ -45,6 +45,7 @@ urlpatterns += i18n_patterns(
url(r'^config/', include('config.urls')),
url(r'^webui/', include('webui.urls')),
url(r'^methodrouting/', include('methodrouting.urls')),
url(r'^connectormethod/', include('connectormethod.urls')),
url(r'^dynamicendpoints/', include('dynamicendpoints.urls')),
url(r'^apicollections/', include('apicollections.urls')),
)

View File

@ -2,6 +2,9 @@
{% block page_title %} {% trans "API Manager" %}/{% trans "ATMs Detail" %}{% endblock page_title %} {% block content %}
<div id="atms">
<h1>{% trans "ATMs List" %}</h1>
<form class="form-inline" method="get">
<input type="submit" class="btn btn-default" value ="Export CSV" onclick="javascript: form.action='{% url 'export-csv' %}';">
</form>
<div class="table-responsive">
<table class="table table-hover tablesorter" id="atms-list" aria-describedby="atms list">
<thead>

View File

@ -4,10 +4,13 @@ URLs for metrics app
"""
from django.conf.urls import url
from .views import AtmListView
from .views import AtmListView, ExportCsvView
urlpatterns = [
url(r'^$',
AtmListView.as_view(),
name='atm-detail')
name='atm-detail'),
url(r'^export_csv$',
ExportCsvView.as_view(),
name='export-csv')
]

View File

@ -5,13 +5,16 @@ from django.shortcuts import render
"""
Views of atms app
"""
import datetime
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
import json
from django.urls import reverse_lazy
from django.views.generic import FormView
from django.http import HttpResponse
from django.views.generic import FormView,TemplateView, View
from atms.views import IndexAtmsView
from obp.api import API, APIError
import csv
@ -58,3 +61,45 @@ class AtmListView(IndexAtmsView, LoginRequiredMixin, FormView ):
'bankids': self.bankids
})
return context
class ExportCsvView(LoginRequiredMixin, View):
"""View to export the user to csv"""
def get_banks(self):
api = API(self.request.session.get('obp'))
try:
urlpath = '/banks'
result = api.get(urlpath)
if 'banks' in result:
return [bank['id'] for bank in sorted(result['banks'], key=lambda d: d['id'])]
else:
return []
except APIError as err:
messages.error(self.request, err)
return []
def get(self, request, *args, **kwargs):
api = API(self.request.session.get('obp'))
try:
print("Helooooooo")
self.bankids = self.get_banks()
print("Worlddddddd", )
atms_list = []
for bank_id in self.bankids:
urlpath = '/banks/{}/atms'.format(bank_id)
result = api.get(urlpath)
#print(result)
if 'atms' in result:
atms_list.extend(result['atms'])
except APIError as err:
messages.error(self.request, err)
except Exception as inst:
messages.error(self.request, "Unknown Error {}".format(type(inst).__name__))
response = HttpResponse(content_type = 'text/csv')
response['Content-Disposition'] = 'attachment;filename= Atms'+ str(datetime.datetime.now())+'.csv'
writer = csv.writer(response)
writer.writerow(["id","name","notes","line_1","line_2","line_3","city", "county", "state", "postcode","country_code", "longitude","latitude","more_info"])
for user in atms_list:
writer.writerow([user['id'],user['name'], user['notes'], user["address"]['line_1'], user["address"]['line_2'],
user["address"]['line_3'], user["address"]['city'], user["address"]['county'], user["address"]['state'], user["address"]['postcode'], user["address"]['country_code'], user["location"]['longitude'], user["location"]['latitude'], user['more_info']])
return response
#print(atms_list)

View File

@ -88,6 +88,7 @@
{% url "config-index" as config_index_url %}
{% url "webui-index" as webui_props_index_url %}
{% url "methodrouting-index" as methodrouting_index_url %}
{% url "connectormethod" as connectormethod_url %}
{% url "dynamicendpoints-index" as dynamic_endpoints_index_url %}
{% url "apicollections-index" as api_collections_index_url %}
<li class="dropdown{% if config_index_url in request.path %} active{% endif %}">
@ -96,6 +97,7 @@
<li{% if config_index_url in request.path %} class="active"{% endif %}><a href="{{ config_index_url }}">{% trans "Config" %}</a></li><hr class="dropdown-hr">
<li{% if webui_props_index_url in request.path %} class="active"{% endif %}><a href="{{ webui_props_index_url }}">{% trans "Webui Props" %}</a></li><hr class="dropdown-hr">
<li{% if methodrouting_index_url in request.path %} class="active"{% endif %}><a href="{{ methodrouting_index_url }}">{% trans "Method Routings" %}</a></li><hr class="dropdown-hr">
<li{% if connectormethod_url in request.path %} class="active"{% endif %}><a href="{{ connectormethod_url }}">{% trans "Connector Method" %}</a></li><hr class="dropdown-hr">
<li{% if dynamic_endpoints_index_url in request.path %} class="active"{% endif %}><a href="{{ dynamic_endpoints_index_url }}">{% trans "Dynamic Endpoints" %}</a></li><hr class="dropdown-hr">
<li{% if api_collections_index_url in request.path %} class="active"{% endif %}><a href="{{ api_collections_index_url }}">{% trans "My API Collections" %}</a></li>
</ul>

View File

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
"""
App config for config app
"""
from django.apps import AppConfig
class ApiCollectionsConfig(AppConfig):
"""Config for connectormethod"""
name = 'connectormethod'

View File

@ -0,0 +1,24 @@
from django import forms
class ConnectorMethodForm(forms.Form):
api_collections_body = forms.CharField(
label='API Collections Body',
widget=forms.Textarea(
attrs={
'class': 'form-control',
}
),
required=False
)
class ConnectorMethodEndpointForm(forms.Form):
operation_id = forms.CharField(
label='Operation Id',
widget=forms.TextInput(
attrs={
'class': 'form-control',
}
),
required=True
)

View File

@ -0,0 +1,34 @@
$(document).ready(function($) {
$('.runner button.forSave').click(function(e) {
e.preventDefault();
var t = $(this);
var runner = t.parent().parent().parent();
var api_collection_name = $(runner).find('.api_collection_name').val();
var api_collection_is_sharable = $(runner).find('.api_collection_is_sharable').val();
var api_collection_description = $(runner).find('.api_collection_description').val();
$('.runner button.forSave').attr("disabled","disabled");
$('.runner button.forDelete').attr("disabled","disabled");
$.post('save/apicollection', {
'api_collection_name': api_collection_name,
'api_collection_is_sharable': api_collection_is_sharable,
'api_collection_description': api_collection_description,
}, function (response) {
location.reload();
});
});
$('.runner button.forDelete').click(function(e) {
e.preventDefault();
var t = $(this);
var runner = t.parent().parent().parent();
var api_collection_id = $(runner).find('.api_collection_id').html();
$('.runner button.forSave').attr("disabled","disabled");
$('.runner button.forDelete').attr("disabled","disabled");
$.post('delete/apicollection', {
'api_collection_id': api_collection_id
}, function (response) {
location.reload();
});
});
});

View File

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div id="api-collection-detail">
<h2>Add Endpoint to API Collection</h2>
<form class="form" action="" method="post">
{% csrf_token %}
<div class="row">
<div class="col-xs-12 col-md-4">
<div class="form-group">
{{ form.operation_id.label_tag}}
{{ form.operation_id }}
</div>
<input type="text" class="hidden" name="api-collection-id" value={{ connector_method_id }} >
<button type="submit" class="btn btn-primary btn-green">Add</button>
</div>
</div>
</form>
<h2>Endpoints</h2>
<div class="table-responsive">
<table class="table table-striped" aria-describedby="api collection">
<thead>
<th scope="col">Operation Ids</th>
</thead>
<tbody>
{% for connector_method in connector_method_endpoint %}
<tr>
<td>{{ connector_method.operation_id }}</td>
<td>
<form action="{% url 'delete-api-collection-endpoint' api_collection_endpoint.api_collection_id api_collection_endpoint.operation_id %}"
method="post">
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-red">Delete</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,86 @@
{% extends 'base.html' %}
{% load static i18n %}
{% block page_title %}{{ block.super }} / API Collections{% endblock page_title %}
{% block content %}
<h1>{% trans "Connector Method" %}</h1>
<div class="row">
<div class="col-xs-12 col-sm-2">
<label class="form-group">{% trans "Connector Method id" %}:</label> <br>
</div>
<div class="col-xs-12 col-sm-2">
<label class="form-group">{% trans "Method Name" %}:</label> <br>
</div>
<div class="col-xs-12 col-sm-2">
<label class="form-group">{% trans "Programming Language" %}:</label> <br>
</div>
<div class="col-xs-12 col-sm-6">
<label class="form-group">{% trans "Method Body" %}:</label> <br>
</div>
</div>
<form method="post">
{% csrf_token %}
{% for connectormethod in connectormethods %}
{% url 'connector_detail' connectormethod.connector_method_id as url_connector_detail %}
<div class="runner">
<div class="row">
<div class="col-xs-12 col-sm-2">
<div class="form-group" cols="1" rows="1">
<a class="api_collection_id" href="{{ url_collection_detail }}">{{ connectormethod.connector_method_id }}</a></div>
</div>
{% if connectormethod.connector_method_id %}
<div class="col-xs-12 col-sm-2">
<div class="form-group" cols="1" rows="1">
<div>{{ connectormethod.method_name }}</div></div>
</div>
<div class="col-xs-12 col-sm-2">
<div class="form-group" cols="1" rows="1">
<div>{{ connectormethod.programming_lang }}</div>
</div>
</div>
<div class="col-xs-12 col-sm-4">
<div cols="40" rows="1" class="form-control" style="overflow:scroll; padding:0px, 0px, 0px, 2px; height:50px;">{{connectormethod.method_body}}</div>
</div>
{% else %}
<div class="col-xs-12 col-sm-2">
<div class="form-group" cols="1" rows="1">
<input class="api_collection_name" value="Method Name">
</div>
</div>
<div class="col-xs-12 col-sm-2">
<div class="form-group" cols="1" rows="1">
<select class="api_collection_is_sharable form-control">
<option value="True">Scala</option>
<option value="False">Java</option>
<option value="False">JavaScript</option>
</select>
</div>
</div>
<div class="col-xs-12 col-sm-4">
<textarea cols="40" rows="1" class="form-control api_collection_description">{% trans "Enter Your Method Body" %}</textarea>
</div>
{% endif %}
{% if forloop.counter0 == 0 %}
<div class="col-sm-12 col-sm-2">
<div class="form-group">
<button class="btn btn-primary btn-green forSave">{% trans "Create" %}</button>
</div>
</div>
{% endif %}
{% if forloop.counter0 > 0 %}
<div class="col-sm-12 col-sm-2">
<div class="form-group">
<button class="btn btn-primary btn-red forDelete">{% trans "Update" %}</button>
</div>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</form>
{% endblock %}
{% block extrajs %}
<script type="text/javascript" src="{% static 'apicollections/js/apicollections.js' %}"></script>
{% endblock extrajs %}

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
"""
URLs for config app
"""
from django.conf.urls import url
from connectormethod.views import IndexView, connectormethod_save, DetailView
urlpatterns = [
url(r'^$',
IndexView.as_view(),
name='connectormethod'),
url(r'save/connectormethod', connectormethod_save,
name='connectormethod-save'),
url(r'^my-connectormethod-ids/(?P<connectormethod_id>[\w\@\.\+-]+)$',
DetailView.as_view(),
name='connector_detail'),
]
"""url(r'^my-connectormethod-ids/(?P<connectormethod-id>[\w\@\.\+-]+)$',
DetailView.as_view(),
name='my-api-collection-detail'),
url(r'^delete/api-collections/(?P<api_collection_id>[\w-]+)/api-collection-endpoint/(?P<operation_id>[\w\@\.\+-]+)$',
DeleteCollectionEndpointView.as_view(),
name='delete-api-collection-endpoint'),"""

View File

@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
"""
Views of config app
"""
import json
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.views.generic import FormView
from obp.api import API, APIError
from django.urls import reverse, reverse_lazy
from base.utils import exception_handle, error_once_only
from .forms import ConnectorMethodForm, ConnectorMethodEndpointForm
from django.views.decorators.csrf import csrf_exempt
class IndexView(LoginRequiredMixin, FormView):
"""Index view for config"""
template_name = "connectormethod/index.html"
form_class = ConnectorMethodForm
success_url = reverse_lazy('connectormethod-index')
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
api = API(self.request.session.get('obp'))
urlpath = '/management/connector-methods'
connectormethod =[]
try:
response = api.get(urlpath)
if 'code' in response and response['code'] >= 400:
error_once_only(self.request, response['message'])
else:
connectormethod=response['connector_methods']
except APIError as err:
messages.error(self.request, err)
#error_once_only(self.request, Exception("OBP-API server is not running or do not response properly. "
# "Please check OBP-API server. "
# "Details: " + str(err)))
except BaseException as err:
messages.error(self.request, 'KeyError: {}'.format(err))
#error_once_only(self.request, (Exception("Unknown Error. Details:" + str(err))))
else:
# set the default endpoint there, the first item will be the new endpoint.
default_api_endpoint = {
"connectormethod": "method_name",
"is_sharable": True,
"description":"Describe the purpose of the collection"
}
connectormethod.insert(0,json.dumps(default_api_endpoint))
context.update({
'connectormethods': connectormethod
})
return context
class DetailView(LoginRequiredMixin, FormView):
"""Index view for config"""
template_name = "connectormethod/detail.html"
form_class = ConnectorMethodEndpointForm
success_url = reverse_lazy('connector_detail')
def form_valid(self, form):
"""Posts api collection endpoint data to API"""
try:
data = form.cleaned_data
api = API(self.request.session.get('obp'))
connectormethod_id = super(DetailView, self).get_context_data()['view'].kwargs['connectormethod_id']
urlpath = '/my/api-collection-ids/{}/api-collection-endpoints'.format(api_collection_id)
payload = {
'operation_id': data['operation_id']
}
api_collection_endpoint = api.post(urlpath, payload=payload)
except APIError as err:
messages.error(self.request, err)
return super(DetailView, self).form_invalid(form)
except:
messages.error(self.request, 'Unknown Error')
return super(DetailView, self).form_invalid(form)
if 'code' in api_collection_endpoint and api_collection_endpoint['code']>=400:
messages.error(self.request, api_collection_endpoint['message'])
return super(DetailView, self).form_invalid(form)
else:
msg = 'Operation Id {} has been added.'.format(data['operation_id'])
messages.success(self.request, msg)
self.success_url = self.request.path
return super(DetailView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
connectormethod_id = context['view'].kwargs['connectormethod_id']
api = API(self.request.session.get('obp'))
urlpath = '/my/api-collection-ids/{}/api-collection-endpoints'.format(api_collection_id)
api_collection_endpoints =[]
try:
response = api.get(urlpath)
if 'code' in response and response['code'] >= 400:
error_once_only(self.request, response['message'])
else:
api_collection_endpoints=response['api_collection_endpoints']
except APIError as err:
error_once_only(self.request, Exception("OBP-API server is not running or do not response properly. "
"Please check OBP-API server. "
"Details: " + str(err)))
except BaseException as err:
error_once_only(self.request, (Exception("Unknown Error. Details:" + str(err))))
else:
context.update({
'api_collection_endpoints': api_collection_endpoints,
'api_collection_id': api_collection_id
})
return context
class DeleteCollectionEndpointView(LoginRequiredMixin, FormView):
"""View to delete an api collection endpoint"""
def post(self, request, *args, **kwargs):
"""Deletes api collection endpoint from API"""
api = API(self.request.session.get('obp'))
try:
urlpath = '/my/api-collections-ids/{}/api-collection-endpoints/{}'\
.format(kwargs['api_collection_id'],kwargs['operation_id'])
result = api.delete(urlpath)
if result is not None and 'code' in result and result['code']>=400:
messages.error(request, result['message'])
else:
msg = 'Operation Id {} has been deleted.'.format(kwargs['operation_id'])
messages.success(request, msg)
except APIError as err:
messages.error(request, err)
except:
messages.error(self.request, 'Unknown Error')
redirect_url = reverse('my-api-collection-detail',kwargs={"api_collection_id":kwargs['api_collection_id']})
return HttpResponseRedirect(redirect_url)
@exception_handle
@csrf_exempt
def connectormethod_save(request):
api = API(request.session.get('obp'))
urlpath = '/my/connectormethod'
payload = {
'api_collection_name': request.POST.get('api_collection_name').strip(),
'is_sharable': bool(request.POST.get('api_collection_is_sharable')),
'description': request.POST.get('api_collection_description').strip()
}
result = api.post(urlpath, payload = payload)
return result
@exception_handle
@csrf_exempt
def apicollections_delete(request):
api_collection_id = request.POST.get('api_collection_id').strip()
api = API(request.session.get('obp'))
urlpath = '/my/api-collections/{}'.format(api_collection_id)
result = api.delete(urlpath)
return result

File diff suppressed because it is too large Load Diff

View File

@ -247,7 +247,9 @@ class MyDetailView(LoginRequiredMixin, FormView):
messages.error(self.request, err)
except Exception as err:
messages.error(self.request, 'Unknown Error')
#print(user,"This is ")
#entitlements=user["entitlements"]["list"]
user["entitlements"]["list"] = sorted(user["entitlements"]["list"], key=lambda d: d['role_name'])
context.update({
'apiuser': user, # 'user' is logged-in user in template context
})
@ -416,25 +418,23 @@ class ExportCsvView(LoginRequiredMixin, View):
username = self.request.GET.get('username')
lockedstatus = self.request.GET.get('locked_status')
if lockedstatus is None: lockedstatus = "active"
if email:
urlpath = '/users/email/{}/terminator'.format(email)
elif username:
urlpath = '/users/username/{}'.format(username)
else:
urlpath = '/users?limit={}&offset={}&locked_status={}'.format(limit, offset, lockedstatus)
try:
response = api.get(urlpath)
if 'code' in response and response['code'] >= 400:
messages.error(self.request, response['message'])
else:
users = response['users']
except APIError as err:
messages.error(self.request, err)
except:
messages.error(self.request, 'Unknown Error')
response = HttpResponse(content_type = 'text/csv')
response['Content-Disposition'] = 'attachment;filename= Users'+ str(datetime.datetime.now())+'.csv'
writer = csv.writer(response)

View File

@ -29,7 +29,7 @@
<input type="hidden" class="web_ui_props_id" value="{{ webui_prop.web_ui_props_id }}"/>
<div class="col-xs-12 col-sm-3">
<div class="form-group" cols="20" rows="1">
<div class="web_ui_props_name">{{ webui_prop.name }}</div>
<div class="web_ui_props_name" >{{ webui_prop.name }}</div>
</div>
</div>
<div class="col-xs-12 col-sm-3">
@ -39,8 +39,7 @@
</div>
</div>
<div class="col-xs-12 col-sm-3">
<div class="form-group" cols="1" rows="1"><div
class="">{{ webui_prop.web_ui_props_id }}</div></div>
<div class="form-group" cols="1" rows="1"><div class="">{{ webui_prop.web_ui_props_id }}</div></div>
</div>
<div class="col-sm-12 col-sm-3">
<div class="form-group">

View File

@ -65,7 +65,8 @@ class IndexView(LoginRequiredMixin, FormView):
def webui_save(request):
web_ui_props_name = request.POST.get('web_ui_props_name')
web_ui_props_value = request.POST.get('web_ui_props_value')
print("request.POST.get", request.GET)
#print("web_ui_props_value", web_ui_props_value)
payload = {
'name': web_ui_props_name,
'value': web_ui_props_value