Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • kj2-drupisz/desd
1 result
Select Git revision
Show changes
{% extends "_base.html" %}
{% block content %}
<div class="container mx-auto px-4">
<h1 class="text-2xl font-bold mb-4">Model Performance</h1>
{% if metrics %}
<div class="bg-white shadow-md rounded p-6">
<p><strong>Request Count:</strong> {{ metrics.request_count }}</p>
<p><strong>Average Request Latency:</strong> {{ metrics.avg_request_latency|floatformat:6 }} seconds</p>
<p><strong>Average Runtime Latency:</strong> {{ metrics.avg_runtime_latency|floatformat:6 }} seconds</p>
<p><strong>Model Load Latency:</strong> {{ metrics.model_load_latency|floatformat:6 }} seconds</p>
</div>
{% else %}
<p>Failed to retrieve model performance metrics.</p>
{% endif %}
</div>
{% endblock content %}
\ No newline at end of file
...@@ -7,7 +7,19 @@ ...@@ -7,7 +7,19 @@
User settings User settings
</h1> </h1>
<h3 class="mb-4 text-xl font-semibold dark:text-white"> <h3 class="mb-4 text-xl font-semibold dark:text-white">
User type: {{ user_profile.user_type }} {% if user_profile.is_superuser %}
User type: Superuser
{% elif user_profile.user_type == 0 %}
User type: User
{% elif user_profile.user_type == 1 %}
User type: Admin
{% elif user_profile.user_type == 2 %}
User type: ML Engineer
{% elif user_profile.user_type == 3 %}
User type: Accountant
{% else %}
User type: Unknown
{% endif %}
</h3> </h3>
</div> </div>
<!-- Right Content --> <!-- Right Content -->
...@@ -23,7 +35,7 @@ ...@@ -23,7 +35,7 @@
</div> </div>
{% if user_profile.user_type == 3 %} {% if user_profile.user_type == 3 or user.is_superuser or user_profile.user_type == 1%}
<div <div
class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800" class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800"
> >
...@@ -76,7 +88,7 @@ ...@@ -76,7 +88,7 @@
{% comment %} REPLACE WITH LOGIC TO CHECK PROPER USER {% endcomment %} {% comment %} REPLACE WITH LOGIC TO CHECK PROPER USER {% endcomment %}
</div> </div>
{% endif %} {% endif %}
{% if 1 %} {% if user_profile.user_type == 2 or user.is_superuser or user_profile.user_type == 1%}
<div <div
class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800" class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800"
...@@ -115,8 +127,13 @@ ...@@ -115,8 +127,13 @@
</div> </div>
{% comment %} AI content {% endcomment %} {% endif%} {% comment %} AI content {% endcomment %} {% endif%}
</div> </div>
<div class="col-span-2"> <div class="col-span-2">
{% if user_profile.user_type == 2 or user.is_superuser %}
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<h3 class="mb-4 text-xl font-semibold dark:text-white">Model Performance</h3>
<a href="{% url 'model_performance' %}" class="text-blue-500 hover:underline">View Model Performance</a>
</div>
{% endif %}
<div <div
class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800" class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800"
> >
...@@ -137,8 +154,12 @@ ...@@ -137,8 +154,12 @@
class="shadow-sm bg-gray-50 border border-gray-300 text-grey-300 sm:text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" class="shadow-sm bg-gray-50 border border-gray-300 text-grey-300 sm:text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="example@gmail.com" placeholder="example@gmail.com"
required required
>{{ user.email }}</span {% if user.email %}
> <span>{{ user.email }}</span>
{% else %}
<span>No email address on record.</span>
{% endif %}
</div> </div>
<div class="col-span-6 sm:col-span-3"> <div class="col-span-6 sm:col-span-3">
<label <label
...@@ -158,6 +179,17 @@ ...@@ -158,6 +179,17 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Modal -->
<div id="myModal" class="hidden fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
<!-- Modal content with scrolling enabled -->
<div class="modal-body bg-white dark:bg-gray-800 rounded-lg p-4 md:p-6 w-full max-w-2xl">
<h3 class="text-2xl font-bold mb-4">Predictions:</h3>
<ul id="predictionList" class="space-y-2"></ul>
<button onclick="closeModal()" class="mt-4 px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600">Close</button>
</div>
</div>
<div <div
class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800" class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800"
> >
...@@ -192,61 +224,147 @@ ...@@ -192,61 +224,147 @@
class="font-medium text-blue-600 dark:text-blue-500 hover:underline" class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>{{entry.file}}</a >{{entry.file}}</a
> >
{% if entry.description %}
<button type="button" class="ml-4 px-2 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600" onclick="showModal('{{entry.description|join:'\n'}}')">
Show Results
</button>
{% endif %}
</td> </td>
</tr> </tr>
{%endfor%} {%endfor%}
</tbody> </tbody>
</table> </table>
</div> </div>
{% if 1 %} {% comment %} REPLACE WITH LOGIC TO CHECK PROPER USER
{%endcomment %}
{% if user_profile.user_type == 2 %}
<div {% if 1 %} {% comment %} REPLACE WITH LOGIC TO CHECK PROPER USER {% endcomment %}
class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800" {% if user_profile.user_type == 2 or user.is_superuser %}
> <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<h3 class="mb-4 text-xl font-semibold dark:text-white"> <h3 class="mb-4 text-xl font-semibold dark:text-white">Application Logs</h3>
Application Logs <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
</h3> <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<table
class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400"
>
<thead
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"
>
<tr> <tr>
<th scope="col" class="px-6 py-3">Date</th> <th scope="col" class="px-6 py-3">Date</th>
<th scope="col" class="px-6 py-3">Action</th> <th scope="col" class="px-6 py-3">Action</th>
<th scope="col" class="px-6 py-3">User ID</th> <th scope="col" class="px-6 py-3">User ID</th>
<th scope="col" class="px-6 py-3">status</th> <th scope="col" class="px-6 py-3">Status</th>
<th scope="col" class="px-6 py-3">Feedback</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for entry in admin_data %} {% for entry in admin_data %}
<tr <tr class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700">
class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700" <td scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
> {{entry.date}}
<td </td>
scope="row"
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
{{entry.date}} </td>
<td class="px-6 py-4"> <td class="px-6 py-4">
<a <a href="#" class="font-medium text-blue-600 dark:text-blue-500 hover:underline">{{entry.action}}</a>
href="#" {% if entry.description %}
class="font-medium text-blue-600 dark:text-blue-500 hover:underline" <button type="button" class="ml-4 px-2 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600" onclick="showModal('{{entry.description|join:'\n'}}')">
>{{entry.action}}</a Show Results
> </button>
{% endif %}
</td> </td>
<td class="px-6 py-4">{{entry.user}}</td> <td class="px-6 py-4">{{entry.user}}</td>
<td class="px-6 py-4">{{entry.status}}</td>
<td class="px-6 py-4"> <td class="px-6 py-4">
{{entry.status}}</td> {% if entry.feedback is not None %}
{% if entry.feedback %}
<span class="text-green-500">Liked</span>
{% else %}
<span class="text-red-500">Disliked</span>
{% endif %}
{% else %}
N/A
{% endif %}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
{% endif %}
{% if user.is_superuser or user_profile.user_type == 1 %}
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<h3 class="mb-4 text-xl font-semibold dark:text-white">
User Management
</h3>
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">Username</th>
<th scope="col" class="px-6 py-3">User Type</th>
<th scope="col" class="px-6 py-3">Actions</th>
</tr>
</thead>
<tbody>
{% for user_profile in all_user_profiles %}
<tr class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700">
<td class="px-6 py-4">{{ user_profile.user.username }}</td>
<td class="px-6 py-4">
{% if user_profile.is_superuser %}
Superuser
{% elif user_profile.user_type == 1 %}
Admin
{% elif user_profile.user_type == 2 %}
ML Engineer
{% elif user_profile.user_type == 3 %}
Accountant
{% else %}
User
{% endif %}
</td>
<td class="px-6 py-4">
<form action="{% url 'change_user_type' user_profile.user.id %}" method="post">
{% csrf_token %}
<select name="user_type">
<option value="0">User</option>
<option value="1">Admin</option>
<option value="2">ML Engineer</option>
<option value="3">Accountant</option>
</select>
<button type="submit" class="p-2 bg-blue-500 text-white rounded-md hover:bg-blue-600">
Change User Type
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %} {% endif %}
{% endif %} {% comment %} Admin page functionality end {% endcomment %} {% endif %} {% comment %} Admin page functionality end {% endcomment %}
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}
{% block scripts %}
<script>
function showModal(predictions, action) {
var predictionList = document.getElementById('predictionList');
predictionList.innerHTML = '';
// Split the predictions string into an array
var predictionsArray = predictions.split(', ');
// Iterate over the predictionsArray and create list items
predictionsArray.forEach(function(prediction) {
var li = document.createElement('li');
li.innerHTML = prediction;
li.className = 'bg-gray-100 dark:bg-gray-700 px-4 py-2 rounded-md';
predictionList.appendChild(li);
});
document.getElementById('myModal').classList.remove('hidden');
}
function closeModal() {
document.getElementById('myModal').classList.add('hidden');
}
</script>
{% endblock scripts %}
from django.urls import path from django.urls import path
from .views import InstrumentDetectionView, index, users, maintenance, handler404, handler500, terms_conditions, privacy_policy, handling_music_file, pricing, generate_pdf, admin_table from .views import InstrumentDetectionView, ModelPerformanceView, index, log_fileupload, users, maintenance, \
handler404, handler500, terms_conditions, privacy_policy, pricing, generate_pdf, admin_table,\
change_user_type, submit_feedback
from .payments import create_payment, execute_payment, payment_cancelled, payment_success from .payments import create_payment, execute_payment, payment_cancelled, payment_success
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
...@@ -18,19 +20,21 @@ urlpatterns = [ ...@@ -18,19 +20,21 @@ urlpatterns = [
path('terms_conditions/', terms_conditions, name='terms_conditions'), path('terms_conditions/', terms_conditions, name='terms_conditions'),
path('pricay_policy/', privacy_policy, name='privacy_policy'), path('pricay_policy/', privacy_policy, name='privacy_policy'),
path('pricing/', pricing, name='pricing'), path('pricing/', pricing, name='pricing'),
path('uploading_file/', handling_music_file, name='uploading_file'), path('submit_feedback/', submit_feedback, name='submit_feedback'),
path('generate_pdf/', generate_pdf, name='generate_pdf'), path('generate_pdf/', generate_pdf, name='generate_pdf'),
path('pricing/', pricing, name='pricing'), path('pricing/', pricing, name='pricing'),
path('generate_pdf/', generate_pdf, name='generate_pdf'), path('generate_pdf/', generate_pdf, name='generate_pdf'),
path('admin_table/', admin_table, name='admin_table'),
path('instrument_detection/', InstrumentDetectionView.as_view(), name='instrument_detection'), path('instrument_detection/', InstrumentDetectionView.as_view(), name='instrument_detection'),
path('model_performance/', ModelPerformanceView.as_view(), name='model_performance'),
path('password_change/', auth_views.PasswordChangeView.as_view(template_name='password_change_form.html'), name='password_change'), path('password_change/', auth_views.PasswordChangeView.as_view(template_name='password_change_form.html'), name='password_change'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'), path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'),
# path('user_logout/', auth_views.LogoutView.as_view(next_page='index'), name='user_logout'),
path('payment/create/', create_payment, name='create_payment'), # Logging
path('payment/execute/', execute_payment, name='execute_payment'), path('log_fileupload', log_fileupload, name='log_fileupload'),
path('payment/cancel/', payment_cancelled, name='payment_cancelled'), # Admin
path('payment_success/', payment_success, name='success'), path('change_user_type/<int:user_id>/', change_user_type, name='change_user_type'),
path('admin_table/', admin_table, name='admin_table'),
# Authentication # Authentication
path('login/', CustomLoginView.as_view(), name='login'), path('login/', CustomLoginView.as_view(), name='login'),
...@@ -42,4 +46,5 @@ urlpatterns = [ ...@@ -42,4 +46,5 @@ urlpatterns = [
path('payment/execute/', execute_payment, name='execute_payment'), path('payment/execute/', execute_payment, name='execute_payment'),
path('payment/cancel/', payment_cancelled, name='payment_cancelled'), path('payment/cancel/', payment_cancelled, name='payment_cancelled'),
path('payment_success/', payment_success, name='success') path('payment_success/', payment_success, name='success')
] ]
...@@ -4,7 +4,7 @@ from django.contrib.auth.models import User ...@@ -4,7 +4,7 @@ from django.contrib.auth.models import User
from django.contrib import messages from django.contrib import messages
from django.http import HttpResponse from django.http import HttpResponse
from django.utils import timezone from django.utils import timezone
from django.shortcuts import render, redirect from django.shortcuts import render, redirect, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
import logging import logging
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
...@@ -12,7 +12,7 @@ import json ...@@ -12,7 +12,7 @@ import json
from datetime import datetime from datetime import datetime
from .forms import InstrumentDetectionForm from .forms import InstrumentDetectionForm
from .models import Log, Action, User, UserTokenCount from .models import Log, Action, User, UserTokenCount, Profile
from django.http import JsonResponse from django.http import JsonResponse
from django.db import connection from django.db import connection
...@@ -30,38 +30,71 @@ from django.views import generic ...@@ -30,38 +30,71 @@ from django.views import generic
from .models import Profile from .models import Profile
from .forms import UserRegisterForm, LoginAuthenticationForm from .forms import UserRegisterForm, LoginAuthenticationForm
from django.contrib.auth.views import LoginView from django.contrib.auth.views import LoginView
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.mixins import UserPassesTestMixin
from django.views.generic import TemplateView
import re
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_log_data(action, status='success', file=None, description=None): def get_log_data(user, action, status='success', file=None, description=None, feedback=None):
log_data = { log_data = {
'action': action.value, 'username': user.username,
'action': action.value.format(username=user.username),
'status': status, 'status': status,
'file': file, 'file': file,
'description': description, 'description': description,
'feedback': feedback, # Add the feedback field
} }
return log_data return log_data
def create_log(user, log_data): def create_log(user, log_data):
Log.objects.create(user=user, log=log_data) Log.objects.create(user=user, log=log_data, feedback=log_data.get('feedback'))
def handling_music_file(request): @csrf_exempt
def log_fileupload(request):
if request.method == 'POST': if request.method == 'POST':
if 'audio_file' in request.FILES: data = json.loads(request.body)
log_data = { status = data.get('status')
'action': 'File uploaded', file = data.get('file')
'file': request.FILES['audio_file'].name,
} if request.user.is_authenticated:
log_data = get_log_data(Action.UPLOAD_FILE, 'success', file=request.FILES['audio_file'].name) log_data = get_log_data(request.user, Action.UPLOAD_FILE, status, file)
create_log(request.user if request.user.is_authenticated else None, log_data) create_log(request.user, log_data)
return HttpResponse('File uploaded successfully!',log_data)
log_data = get_log_data(Action.invalid_file, 'error') return JsonResponse({'message': 'Log created successfully'}, status=201)
create_log(None, log_data)
return HttpResponse('File invalid',log_data) return JsonResponse({'error': 'Invalid request'}, status=400)
def submit_feedback(request):
if request.method == 'POST' and request.user.is_authenticated:
prediction = request.POST.get('prediction')
liked = request.POST.get('feedback') == 'true'
file_name = request.POST.get('file_name') # Get the filename from the form data
# Create log data using the get_log_data function
log_data = get_log_data(
user=request.user,
action=Action.FEEDBACK_SUBMITTED,
status='success',
file=file_name, # Use the filename obtained from the form
description=prediction,
feedback=liked
)
# Create the Log entry using the create_log function
create_log(request.user, log_data)
return redirect('index')
return redirect('index')
def admin_table(request): def admin_table(request):
if request.user.is_authenticated:
if request.user.profile.user_type != 0 or request.user.is_superuser:
# Execute the query and fetch all rows # Execute the query and fetch all rows
query = """SELECT date, user, log FROM myapp_log ORDER BY date DESC""" query = """SELECT date, log, user_id, feedback FROM myapp_log ORDER BY date DESC"""
with connection.cursor() as cursor: with connection.cursor() as cursor:
cursor.execute(query) cursor.execute(query)
rows = cursor.fetchall() rows = cursor.fetchall()
...@@ -70,21 +103,30 @@ def admin_table(request): ...@@ -70,21 +103,30 @@ def admin_table(request):
data = [] data = []
for row in rows: for row in rows:
# Parse the JSON string into a dictionary # Parse the JSON string into a dictionary
log = json.loads(row[2]) log = json.loads(row[1])
# Create a dictionary with the date, user, and JSON fields # Get the user object based on the user_id
user_id = row[2]
# Get the feedback value
feedback = row[3]
# Create a dictionary with the date, user, JSON fields, and feedback
date = row[0].strftime('%Y-%m-%d %H:%M:%S') date = row[0].strftime('%Y-%m-%d %H:%M:%S')
entry = {'date': date, 'user': row[1], 'file': log['file'], 'action': log['action'], 'status': log['status']} entry = {'date': date, 'user': user_id, 'file': log['file'], 'action': log['action'], 'status': log['status'],
'description': log['description'], 'feedback': feedback}
data.append(entry) data.append(entry)
# Return the data as a JSON response # Return the data as a JSON response
return JsonResponse({'data': data}, safe=False) return JsonResponse({'data': data}, safe=False)
else:
messages.info(request, 'Must be logged in as a non-basic user to access this page.')
return redirect('index')
else:
messages.info(request, 'Must be logged in as a non-basic user to access this page.')
return redirect('login')
def user_table(request): def user_table(request):
# Execute the query and fetch all rows if request.user.is_authenticated:
query = """SELECT date, user, log FROM myapp_log ORDER BY date DESC""" user_id = request.user.id
# Only display user logs code below # Only display user logs code below
# query = """SELECT date, user, log FROM myapp_log WHERE user = '{}' ORDER BY date DESC""".format(request.user) query = """SELECT date, log, user_id, feedback FROM myapp_log WHERE user_id = {} ORDER BY date DESC""".format(user_id)
with connection.cursor() as cursor: with connection.cursor() as cursor:
cursor.execute(query) cursor.execute(query)
rows = cursor.fetchall() rows = cursor.fetchall()
...@@ -93,43 +135,54 @@ def user_table(request): ...@@ -93,43 +135,54 @@ def user_table(request):
data = [] data = []
for row in rows: for row in rows:
# Parse the JSON string into a dictionary # Parse the JSON string into a dictionary
log = json.loads(row[2]) log = json.loads(row[1])
# Create a dictionary with the date, user, and JSON fields # Get the user object based on the user_id
user_id = row[2]
# Get the feedback value
feedback = row[3]
# Create a dictionary with the date, user, JSON fields, and feedback
date = row[0].strftime('%Y-%m-%d %H:%M:%S') date = row[0].strftime('%Y-%m-%d %H:%M:%S')
entry = {'date': date, 'user': row[1], 'file': log['file'], 'action': log['action'], 'status': log['status']} entry = {'date': date, 'user': user_id, 'file': log['file'], 'action': log['action'], 'status': log['status'],
'description': log['description'], 'feedback': feedback}
data.append(entry) data.append(entry)
# Return the data as a JSON response # Return the data as a JSON response
return JsonResponse({'data': data}, safe=False) return JsonResponse({'data': data}, safe=False)
else:
messages.info(request, 'Must be logged in as a user to access this page.')
return redirect('login')
def index(request): def index(request):
# Initialize default context # Initialize default context
context = {'form': InstrumentDetectionForm(), context = {'form': InstrumentDetectionForm(), 'predictions': [], 'file_name': None}
'predictions': [],
'file_name': None
}
# Handle authenticated users # Handle authenticated users
if request.user.is_authenticated: if request.user.is_authenticated:
token_count = UserTokenCount.objects.get(user=request.user).token_count token_count = UserTokenCount.objects.get(user=request.user).token_count
context['token_count'] = token_count context['token_count'] = token_count
if request.method == 'POST': if request.method == 'POST':
form = InstrumentDetectionForm(request.POST, request.FILES) form = InstrumentDetectionForm(request.POST, request.FILES)
if form.is_valid() and 'audio_file' in request.FILES: if form.is_valid() and 'audio_file' in request.FILES:
uploaded_file = request.FILES['audio_file'] uploaded_file = request.FILES['audio_file']
context['file_name'] = uploaded_file.name context['file_name'] = uploaded_file.name
# Make a request to the InstrumentDetectionView to get the predictions # Make a request to the InstrumentDetectionView to get the predictions
view = InstrumentDetectionView().as_view() view = InstrumentDetectionView().as_view()
response = view(request) response = view(request)
# Ensure there's a response and it contains predictions before updating context # Ensure there's a response and it contains predictions before updating context
if response and hasattr(response, 'data') and 'predictions' in response.data: if response and hasattr(response, 'data') and 'predictions' in response.data:
context['predictions'] = response.data['predictions'] context['predictions'] = response.data['predictions']
if request.user.is_authenticated:
feedback = request.POST.get('feedback') # Get the user's feedback from the form
predictions_string = ', '.join(response.data['predictions'])
log_data = get_log_data(request.user, Action.RUN_ALGORITHM, 'success', file=uploaded_file.name,
description=predictions_string, feedback=feedback)
create_log(request.user, log_data)
else: else:
context['form'] = form context['form'] = form
# For GET requests or if form is not valid, render the page with the default or updated context
return render(request, 'index1.html', context)
# Handle unauthenticated users
else: else:
if request.method == 'POST': if request.method == 'POST':
# Assuming you want to do something specific with the file if it's uploaded # Assuming you want to do something specific with the file if it's uploaded
...@@ -137,8 +190,11 @@ def index(request): ...@@ -137,8 +190,11 @@ def index(request):
if uploaded_file: if uploaded_file:
# Process the uploaded file as needed # Process the uploaded file as needed
pass pass
# For now, just render the main page again, potentially after handling the uploaded file
# For GET requests or if POST doesn't involve a file, just show the main page # For GET requests or if form is not valid, render the page with the default or updated context
if request.user.is_authenticated:
return render(request, 'index1.html', context)
else:
return render(request, 'index2.html') return render(request, 'index2.html')
...@@ -146,24 +202,34 @@ def index(request): ...@@ -146,24 +202,34 @@ def index(request):
def users(request): def users(request):
if request.user.is_authenticated:
# Make a request to the admin_table view to get the data # Make a request to the admin_table view to get the data
context = {} context = {}
data_admin = admin_table(request)
data_user = user_table(request) data_user = user_table(request)
admin_dict = json.loads(data_admin.content)
user_dict = json.loads(data_user.content) user_dict = json.loads(data_user.content)
token_count = UserTokenCount.objects.get(user=request.user).token_count token_count = UserTokenCount.objects.get(user=request.user).token_count
user_profile = request.user.profile user_profile = request.user.profile
user = request.user user = request.user
all_user_profiles = Profile.objects.all() # Retrieve all Profile objects
# Pass the data as a context variable to the template # Pass the data as a context variable to the template
# !!! ADMIN DATA ONLY DISPLAYED AND GET IF USER IS ADMIN !!! # !!! ADMIN DATA ONLY DISPLAYED AND GET IF USER IS ADMIN !!!
if request.user.profile.user_type != 0 or request.user.is_superuser:
data_admin = admin_table(request)
admin_dict = json.loads(data_admin.content)
context['admin_data'] = admin_dict['data'] context['admin_data'] = admin_dict['data']
context['user_data'] = user_dict['data'] context['user_data'] = user_dict['data']
context['token_count'] = token_count context['token_count'] = token_count
context['user_profile'] = user_profile context['user_profile'] = user_profile
context['user'] = user context['user'] = user
context['all_user_profiles'] = all_user_profiles # Add all_user_profiles to the context
return render(request, 'user_page.html', context) return render(request, 'user_page.html', context)
else:
messages.info(request, 'Must be logged in as a user to access this page.')
return redirect('login')
def handler404(request, *args, **kwargs): def handler404(request, *args, **kwargs):
response = render(request, '404.html', {}) response = render(request, '404.html', {})
...@@ -178,54 +244,34 @@ def handler500(request, *args, **kwargs): ...@@ -178,54 +244,34 @@ def handler500(request, *args, **kwargs):
def maintenance(request): def maintenance(request):
return render(request, 'maintenance.html') return render(request, 'maintenance.html')
# def user_login(request):
# if request.method == 'POST':
# form = LoginForm(request.POST)
# if form.is_valid():
# username = form.cleaned_data.get('username')
# password = form.cleaned_data.get('password')
# user = authenticate(request, username=username, password=password) # Passing request along with username and password
# if user:
# login(request, user=user) # Passing request along with user
# return redirect('users')
# else:
# messages.error(request, 'Invalid username or password.')
# else:
# pass
# else:
# form = LoginForm()
# return render(request, 'login.html', {'form': form})
# def register(request):
# if request.method == 'POST':
# form = CustomRegistrationForm(request.POST)
# if form.is_valid():
# form.save()
# return redirect('user_login')
# else:
# form = CustomRegistrationForm()
# return render(request, 'register.html', {'form': form})
# def user_logout(request):
# logout(request)
# return redirect('user_login')
# Authentication # Authentication
class RegisterView(generic.CreateView): class RegisterView(generic.CreateView):
form_class = UserRegisterForm form_class = UserRegisterForm
success_url = reverse_lazy('login') success_url = reverse_lazy('index')
template_name = 'registration/register.html' template_name = 'registration/register.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
messages.info(request, 'You are already logged in.')
return redirect('index')
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form): def form_valid(self, form):
response = super().form_valid(form) response = super().form_valid(form)
Profile.objects.create(user=self.object, user_type=0) # Default user type as Basic User user = self.object # Grab the user instance
# Ensure the user is active; this line might be redundant if you're sure users are active by default
user.is_active = True
user.save()
# Check if the Profile exists, and if not, create it
if not Profile.objects.filter(user=user).exists():
Profile.objects.create(user=user, user_type=0) # Default user type as Basic User
# Log the user in
login(self.request, user)
return response return response
...@@ -233,6 +279,23 @@ class CustomLoginView(LoginView): ...@@ -233,6 +279,23 @@ class CustomLoginView(LoginView):
authentication_form = LoginAuthenticationForm authentication_form = LoginAuthenticationForm
template_name = 'registration/login.html' template_name = 'registration/login.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
messages.info(request, 'You are already logged in.')
return redirect('index')
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form):
# Create log if user is authenticated
login(self.request, form.get_user())
log_data = get_log_data(form.get_user(), Action.LOGIN, 'success')
create_log(form.get_user(), log_data)
return super().form_valid(form)
def terms_conditions(request): def terms_conditions(request):
return render(request, 'terms_conditions.html') return render(request, 'terms_conditions.html')
...@@ -257,7 +320,25 @@ def generate_pdf(request): ...@@ -257,7 +320,25 @@ def generate_pdf(request):
# Running the audio file through the model # Running the audio file through the model
class InstrumentDetectionView(APIView): class InstrumentDetectionView(APIView):
def dispatch(self, request, *args, **kwargs):
user_token_count = UserTokenCount.objects.get(user=request.user)
if request.user.is_anonymous:
messages.info(request, 'Must be logged in as a user to access this page.')
return redirect('login')
elif user_token_count.token_count < 1:
messages.info(request, 'You do not have enough tokens to make a prediction.')
return redirect('pricing')
else: return super().dispatch(request, *args, **kwargs)
def post(self, request): def post(self, request):
# Get the user's token count
user_token_count = UserTokenCount.objects.get(user=request.user)
# Decrease the user's token count by one
user_token_count.token_count -= 1
user_token_count.save()
serializer = InstrumentDetectionSerializer(data=request.data) serializer = InstrumentDetectionSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
audio_file = serializer.validated_data['audio_file'] audio_file = serializer.validated_data['audio_file']
...@@ -288,26 +369,84 @@ class InstrumentDetectionView(APIView): ...@@ -288,26 +369,84 @@ class InstrumentDetectionView(APIView):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def convert_to_percentages(self, predictions):
# Assuming predictions is a list of lists
percentage_predictions = []
for prediction in predictions:
total = sum(prediction)
# Convert each number to a percentage of the total, rounded to 2 decimal places
percentages = [round((number / total) * 100, 2) for number in prediction]
percentage_predictions.append(percentages)
return percentage_predictions
def format_predictions(self, predictions): def format_predictions(self, predictions):
instruments = ['Guitar', 'Drum', 'Violin', 'Piano'] instruments = ['Guitar', 'Drum', 'Violin', 'Piano']
formatted_predictions = [] instrument_windows = {instrument: [] for instrument in instruments}
for window_index, prediction in enumerate(predictions, start=1): for window_index, prediction in enumerate(predictions, start=1):
formatted_window = f"<strong>Window {window_index}</strong><br>" highest_score_index = prediction.index(max(prediction))
formatted_scores = "<br>".join([f"{instruments[i]} - {score:.2f}" for i, score in enumerate(prediction)]) highest_score_instrument = instruments[highest_score_index]
formatted_predictions.append(f"{formatted_window}{formatted_scores}") instrument_windows[highest_score_instrument].append(window_index)
formatted_predictions = []
for instrument, windows in instrument_windows.items():
if windows:
window_list = ', '.join(map(str, windows))
formatted_predictions.append(f"{instrument} - Windows: {window_list}")
return formatted_predictions return formatted_predictions
class ModelPerformanceView(UserPassesTestMixin, TemplateView):
template_name = 'model_performance.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_anonymous:
messages.info(request, 'Must be logged in as an ML Engineer or Admin to access this page.')
return redirect('login')
elif request.user.profile.user_type != 2 and not request.user.is_superuser:
messages.info(request, 'Must be logged in as an ML Engineer or Admin to access this page.')
return redirect('users')
else:
return super().dispatch(request, *args, **kwargs)
def test_func(self):
return self.request.user.is_authenticated and (self.request.user.is_superuser or self.request.user.profile.user_type == 2)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
metrics_url = 'http://tensorflow_serving:8501/monitoring/prometheus/metrics'
response = requests.get(metrics_url)
if response.status_code == 200:
metrics_data = response.text
# Extract metrics using regular expressions
request_count = re.search(r':tensorflow:serving:request_count{model_name="instrument_model",status="OK"} (\d+)', metrics_data)
request_latency_sum = re.search(r':tensorflow:serving:request_latency_sum{model_name="instrument_model",API="predict",entrypoint="REST"} ([\d\.e\+]+)', metrics_data)
request_latency_count = re.search(r':tensorflow:serving:request_latency_count{model_name="instrument_model",API="predict",entrypoint="REST"} (\d+)', metrics_data)
runtime_latency_sum = re.search(r':tensorflow:serving:runtime_latency_sum{model_name="instrument_model",API="Predict",runtime="TF1"} ([\d\.e\+]+)', metrics_data)
runtime_latency_count = re.search(r':tensorflow:serving:runtime_latency_count{model_name="instrument_model",API="Predict",runtime="TF1"} (\d+)', metrics_data)
model_load_latency = re.search(r':tensorflow:cc:saved_model:load_latency{model_path="/models/instrument_model/2"} (\d+)', metrics_data)
# Calculate average latencies in seconds
avg_request_latency = float(request_latency_sum.group(1)) / float(request_latency_count.group(1)) / 1e6 if request_latency_sum and request_latency_count else None
avg_runtime_latency = float(runtime_latency_sum.group(1)) / float(runtime_latency_count.group(1)) / 1e6 if runtime_latency_sum and runtime_latency_count else None
model_load_latency_seconds = float(model_load_latency.group(1)) / 1e6 if model_load_latency else None
context['metrics'] = {
'request_count': request_count.group(1) if request_count else None,
'avg_request_latency': avg_request_latency,
'avg_runtime_latency': avg_runtime_latency,
'model_load_latency': model_load_latency_seconds
}
else:
context['metrics'] = None
return context
def change_user_type(request, user_id):
if request.method == 'POST':
user_type = request.POST.get('user_type')
user_profile = get_object_or_404(Profile, user__id=user_id) # Get the user profile
user_profile.user_type = user_type
user_profile.save()
return redirect('users') # Redirect to the users page
def user_has_credits(): def user_has_credits():
has_credits = False has_credits = False
......
No preview for this file type
No preview for this file type
...@@ -26,7 +26,7 @@ SECRET_KEY = 'django-insecure-t%k1f1!c4_9f#x@r_z_k69oz21@0eadh2qb_k3pm3=gknej9f@ ...@@ -26,7 +26,7 @@ SECRET_KEY = 'django-insecure-t%k1f1!c4_9f#x@r_z_k69oz21@0eadh2qb_k3pm3=gknej9f@
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
ALLOWED_HOSTS = ["*"] ALLOWED_HOSTS = ['*']
# Application definition # Application definition
...@@ -173,10 +173,10 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' ...@@ -173,10 +173,10 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
IMAGE_URL = 'static/src/images/' IMAGE_URL = 'static/src/images/'
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
#PayPal API settings #PayPal API settings
PAYPAL_MODE = 'sandbox' PAYPAL_MODE = 'sandbox'
PAYPAL_CLIENT_ID = 'AYpHxonrFMrgnqmjii46SeNsQidn2PjJtEoIgVK0Nrda1iQFUbX28zyuMvUiJk67o_cHII3c8vCMWY-y' PAYPAL_CLIENT_ID = 'AYpHxonrFMrgnqmjii46SeNsQidn2PjJtEoIgVK0Nrda1iQFUbX28zyuMvUiJk67o_cHII3c8vCMWY-y'
PAYPAL_CLIENT_SECRET = 'EPXXK3Z7xDr4Gy_kt4OkPLbJRXd9tP62q1Dpbmj5QiwaFh7twcSUalHDRBbFRwxdX_rmHk_F6YStXa95' PAYPAL_CLIENT_SECRET = 'EPXXK3Z7xDr4Gy_kt4OkPLbJRXd9tP62q1Dpbmj5QiwaFh7twcSUalHDRBbFRwxdX_rmHk_F6YStXa95'
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'tensorflow_serving'
scrape_interval: 5s
metrics_path: /monitoring/prometheus/metrics
static_configs:
- targets: ['tensorflow_serving:8501']
\ No newline at end of file
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available
WAITFORIT_cmdname=${0##*/}
echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
usage()
{
cat << USAGE >&2
Usage:
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit 1
}
wait_for()
{
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
else
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
fi
WAITFORIT_start_ts=$(date +%s)
while :
do
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
WAITFORIT_result=$?
else
(echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
WAITFORIT_result=$?
fi
if [[ $WAITFORIT_result -eq 0 ]]; then
WAITFORIT_end_ts=$(date +%s)
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
break
fi
sleep 1
done
return $WAITFORIT_result
}
wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
WAITFORIT_PID=$!
trap "kill -INT -$WAITFORIT_PID" INT
wait $WAITFORIT_PID
WAITFORIT_RESULT=$?
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
return $WAITFORIT_RESULT
}
# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
WAITFORIT_hostport=(${1//:/ })
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
shift 1
;;
--child)
WAITFORIT_CHILD=1
shift 1
;;
-q | --quiet)
WAITFORIT_QUIET=1
shift 1
;;
-s | --strict)
WAITFORIT_STRICT=1
shift 1
;;
-h)
WAITFORIT_HOST="$2"
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
WAITFORIT_HOST="${1#*=}"
shift 1
;;
-p)
WAITFORIT_PORT="$2"
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
WAITFORIT_PORT="${1#*=}"
shift 1
;;
-t)
WAITFORIT_TIMEOUT="$2"
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
WAITFORIT_TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
WAITFORIT_CLI=("$@")
break
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done
if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
echoerr "Error: you need to provide a host and port to test."
usage
fi
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-30}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
# Check to see if timeout is from busybox?
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
WAITFORIT_ISBUSY=1
# Check if busybox timeout uses -t flag
# (recent Alpine versions don't support -t anymore)
if timeout &>/dev/stdout | grep -q -e '-t '; then
WAITFORIT_BUSYTIMEFLAG="-t"
fi
else
WAITFORIT_ISBUSY=0
fi
if [[ $WAITFORIT_CHILD -gt 0 ]]; then
wait_for
WAITFORIT_RESULT=$?
exit $WAITFORIT_RESULT
else
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
wait_for_wrapper
WAITFORIT_RESULT=$?
else
wait_for
WAITFORIT_RESULT=$?
fi
fi
if [[ $WAITFORIT_CLI != "" ]]; then
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
exit $WAITFORIT_RESULT
fi
exec "${WAITFORIT_CLI[@]}"
else
exit $WAITFORIT_RESULT
fi
\ No newline at end of file