Add configuration and scripts for linting, testing, and dependency management

- Introduced .pre-commit-config.yaml for pre-commit hooks using uv-pre-commit.
- Created lint.sh script to run Ruff and Black for linting and formatting.
- Added test.sh script to execute tests with coverage reporting.
- Configured .uv file for uv settings including lockfile management and dependency resolution.
- Updated Makefile with targets for virtual environment setup, dependency installation, linting, testing, formatting, and database migrations.
- Established requirements.txt with main and development dependencies for the project.
This commit is contained in:
2025-05-17 20:18:21 +02:00
parent d916ae2247
commit 6b19cbcb51
48 changed files with 4733 additions and 3362 deletions

View File

@ -6,192 +6,192 @@
{% block title %}Upload Data | Chat Analytics{% endblock %}
{% block content %}
<div
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"
>
<h1 class="h2">Upload Data</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="{% url 'dashboard' %}" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-arrow-left"></i> Back to Dashboard
</a>
</div>
</div>
<div
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"
>
<h1 class="h2">Upload Data</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="{% url 'dashboard' %}" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-arrow-left"></i> Back to Dashboard
</a>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Upload CSV File</h5>
</div>
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %} {{ form|crispy }}
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Upload CSV File</h5>
</div>
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %} {{ form|crispy }}
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">CSV File Format</h5>
</div>
<div class="card-body">
<p>The CSV file should contain the following columns:</p>
<table class="table table-sm">
<thead>
<tr>
<th>Column</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>session_id</td>
<td>Unique identifier for the chat session</td>
<td>String</td>
</tr>
<tr>
<td>start_time</td>
<td>When the session started</td>
<td>Datetime</td>
</tr>
<tr>
<td>end_time</td>
<td>When the session ended</td>
<td>Datetime</td>
</tr>
<tr>
<td>ip_address</td>
<td>IP address of the user</td>
<td>String</td>
</tr>
<tr>
<td>country</td>
<td>Country of the user</td>
<td>String</td>
</tr>
<tr>
<td>language</td>
<td>Language used in the conversation</td>
<td>String</td>
</tr>
<tr>
<td>messages_sent</td>
<td>Number of messages in the conversation</td>
<td>Integer</td>
</tr>
<tr>
<td>sentiment</td>
<td>Sentiment analysis of the conversation</td>
<td>String</td>
</tr>
<tr>
<td>escalated</td>
<td>Whether the conversation was escalated</td>
<td>Boolean</td>
</tr>
<tr>
<td>forwarded_hr</td>
<td>Whether the conversation was forwarded to HR</td>
<td>Boolean</td>
</tr>
<tr>
<td>full_transcript</td>
<td>Full transcript of the conversation</td>
<td>Text</td>
</tr>
<tr>
<td>avg_response_time</td>
<td>Average response time in seconds</td>
<td>Float</td>
</tr>
<tr>
<td>tokens</td>
<td>Total number of tokens used</td>
<td>Integer</td>
</tr>
<tr>
<td>tokens_eur</td>
<td>Cost of tokens in EUR</td>
<td>Float</td>
</tr>
<tr>
<td>category</td>
<td>Category of the conversation</td>
<td>String</td>
</tr>
<tr>
<td>initial_msg</td>
<td>First message from the user</td>
<td>Text</td>
</tr>
<tr>
<td>user_rating</td>
<td>User rating of the conversation</td>
<td>String</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">CSV File Format</h5>
</div>
<div class="card-body">
<p>The CSV file should contain the following columns:</p>
<table class="table table-sm">
<thead>
<tr>
<th>Column</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>session_id</td>
<td>Unique identifier for the chat session</td>
<td>String</td>
</tr>
<tr>
<td>start_time</td>
<td>When the session started</td>
<td>Datetime</td>
</tr>
<tr>
<td>end_time</td>
<td>When the session ended</td>
<td>Datetime</td>
</tr>
<tr>
<td>ip_address</td>
<td>IP address of the user</td>
<td>String</td>
</tr>
<tr>
<td>country</td>
<td>Country of the user</td>
<td>String</td>
</tr>
<tr>
<td>language</td>
<td>Language used in the conversation</td>
<td>String</td>
</tr>
<tr>
<td>messages_sent</td>
<td>Number of messages in the conversation</td>
<td>Integer</td>
</tr>
<tr>
<td>sentiment</td>
<td>Sentiment analysis of the conversation</td>
<td>String</td>
</tr>
<tr>
<td>escalated</td>
<td>Whether the conversation was escalated</td>
<td>Boolean</td>
</tr>
<tr>
<td>forwarded_hr</td>
<td>Whether the conversation was forwarded to HR</td>
<td>Boolean</td>
</tr>
<tr>
<td>full_transcript</td>
<td>Full transcript of the conversation</td>
<td>Text</td>
</tr>
<tr>
<td>avg_response_time</td>
<td>Average response time in seconds</td>
<td>Float</td>
</tr>
<tr>
<td>tokens</td>
<td>Total number of tokens used</td>
<td>Integer</td>
</tr>
<tr>
<td>tokens_eur</td>
<td>Cost of tokens in EUR</td>
<td>Float</td>
</tr>
<tr>
<td>category</td>
<td>Category of the conversation</td>
<td>String</td>
</tr>
<tr>
<td>initial_msg</td>
<td>First message from the user</td>
<td>Text</td>
</tr>
<tr>
<td>user_rating</td>
<td>User rating of the conversation</td>
<td>String</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
{% if data_sources %}
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Uploaded Data Sources</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Uploaded</th>
<th>File</th>
<th>Sessions</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for data_source in data_sources %}
<tr>
<td>{{ data_source.name }}</td>
<td>{{ data_source.description|truncatechars:50 }}</td>
<td>{{ data_source.uploaded_at|date:"M d, Y H:i" }}</td>
<td>{{ data_source.file.name|split:"/"|last }}</td>
<td>{{ data_source.chat_sessions.count }}</td>
<td>
<a
href="{% url 'data_source_detail' data_source.id %}"
class="btn btn-sm btn-outline-primary"
>
<i class="fas fa-eye"></i>
</a>
<a
href="{% url 'delete_data_source' data_source.id %}"
class="btn btn-sm btn-outline-danger"
>
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% if data_sources %}
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Uploaded Data Sources</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Uploaded</th>
<th>File</th>
<th>Sessions</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for data_source in data_sources %}
<tr>
<td>{{ data_source.name }}</td>
<td>{{ data_source.description|truncatechars:50 }}</td>
<td>{{ data_source.uploaded_at|date:"M d, Y H:i" }}</td>
<td>{{ data_source.file.name|split:"/"|last }}</td>
<td>{{ data_source.chat_sessions.count }}</td>
<td>
<a
href="{% url 'data_source_detail' data_source.id %}"
class="btn btn-sm btn-outline-primary"
>
<i class="fas fa-eye"></i>
</a>
<a
href="{% url 'delete_data_source' data_source.id %}"
class="btn btn-sm btn-outline-danger"
>
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %}