Skip to content

Commit

Permalink
5.3b2 (#670)
Browse files Browse the repository at this point in the history
5.3b2
  • Loading branch information
chrisclark authored Sep 10, 2024
1 parent 1c3e2ab commit d79d21c
Show file tree
Hide file tree
Showing 18 changed files with 239 additions and 166 deletions.
4 changes: 3 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Change Log
This document records all notable changes to `SQL Explorer <https://github.com/explorerhq/sql-explorer>`_.
This project adheres to `Semantic Versioning <https://semver.org/>`_.

`5.3.0 (beta)`_ (2024-08-29)
`5.3.0 (beta 2)`_ (2024-09-10)
===========================
* `#664`_: Improvements to the AI SQL Assistant:

Expand Down Expand Up @@ -41,6 +41,8 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.

* Fixed a bug when validating connections to uploaded files. Also added basic locking when downloading files from S3.

* On-boarding UI; if no connections or queries are created, the UI walks the user through it a bit.

* Keyboard shortcut for formatting the SQL in the editor.

- Cmd+Shift+F (Windows: Ctrl+Shift+F)
Expand Down
2 changes: 1 addition & 1 deletion explorer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"minor": 3,
"patch": 0,
"releaselevel": "beta",
"serial": 1
"serial": 2
}


Expand Down
2 changes: 2 additions & 0 deletions explorer/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
# 500mb default max
EXPLORER_MAX_UPLOAD_SIZE = getattr(settings, "EXPLORER_MAX_UPLOAD_SIZE", 500 * 1024 * 1024)

EXPLORER_HOSTED = getattr(settings, "EXPLORER_HOSTED", False)


def has_assistant():
return EXPLORER_AI_API_KEY is not None
Expand Down
1 change: 0 additions & 1 deletion explorer/ee/db_connections/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ def save(self, *args, **kwargs):
DatabaseConnection.objects.filter(default=True).update(default=False)
else:
# If there is no default set yet, make this newly created one the default.
# Effectively this is for first-time installations.
has_default = DatabaseConnection.objects.filter(default=True).exists()
if not has_default:
self.default = True
Expand Down
1 change: 0 additions & 1 deletion explorer/ee/db_connections/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def post(self, request): # noqa

class DatabaseConnectionsListView(PermissionRequiredMixin, ExplorerContextMixin, ListView):

context_object_name = "sqlite_uploads"
permission_required = "connections_permission"
template_name = "connections/connections.html"
model = DatabaseConnection
Expand Down
7 changes: 6 additions & 1 deletion explorer/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["database_connection"].widget.choices = self.connections
if not self.instance.database_connection:
self.initial["database_connection"] = default_db_connection().alias
default_db = default_db_connection()
self.initial["database_connection"] = default_db_connection().alias if default_db else None
self.fields["database_connection"].widget.attrs["class"] = "form-select"

def clean(self):
Expand All @@ -66,6 +67,10 @@ def created_at_time(self):

@property
def connections(self):
default_db = default_db_connection()
if default_db is None:
return []

# Ensure the default connection appears first in the dropdown in the form
result = DatabaseConnection.objects.annotate(
custom_order=Case(
Expand Down
4 changes: 2 additions & 2 deletions explorer/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def view_permission(request, **kwargs):
# And token auth does not give you permission to view the list.


def view_permission_list(request):
def view_permission_list(request, *args, **kwargs):
return app_settings.EXPLORER_PERMISSION_VIEW(request)\
or allowed_query_pks(request.user.id)

Expand All @@ -25,5 +25,5 @@ def change_permission(request, *args, **kwargs):
return app_settings.EXPLORER_PERMISSION_CHANGE(request)


def connections_permission(request, **kwargs):
def connections_permission(request, *args, **kwargs):
return app_settings.EXPLORER_PERMISSION_CONNECTIONS(request)
21 changes: 16 additions & 5 deletions explorer/src/js/assistant.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ function setupTableList() {
removeItemButton: true,
searchEnabled: true,
shouldSort: false,
position: 'bottom'
position: 'bottom',
placeholderValue: "Click to search for relevant tables"
});

// TODO - nasty. Should be refactored. Used by submitAssistantAsk to get relevant tables.
Expand All @@ -66,6 +67,16 @@ function setupTableList() {
});
});

const refreshTables = document.getElementById('refresh_tables_button');
refreshTables.addEventListener('click', (e) => {
e.preventDefault();
keys.forEach(k => {
choices.removeActiveItemsByValue(k);
});
selectRelevantTablesSql(choices, keys)
selectRelevantTablesRequest(choices, keys)
});

selectRelevantTablesSql(choices, keys);

document.addEventListener('docChanged', debounce(
Expand All @@ -81,16 +92,16 @@ function setupTableList() {
}

function selectRelevantTablesSql(choices, keys) {
const textContent = window.editor.state.doc.toString();
const textContent = window.editor.state.doc.toString().toLowerCase();
const textWords = new Set(textContent.split(/\s+/));
const hasKeys = keys.filter(key => textWords.has(key));
const hasKeys = keys.filter(key => textWords.has(key.toLowerCase()));
choices.setChoiceByValue(hasKeys);
}

function selectRelevantTablesRequest(choices, keys) {
const textContent = document.getElementById("id_assistant_input").value
const textWords = new Set(textContent.split(/\s+/));
const hasKeys = keys.filter(key => textWords.has(key));
const textWords = new Set(textContent.toLowerCase().split(/\s+/));
const hasKeys = keys.filter(key => textWords.has(key.toLowerCase()));
choices.setChoiceByValue(hasKeys);
}

Expand Down
5 changes: 3 additions & 2 deletions explorer/templates/assistant/table_description_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
{% block sql_explorer_content %}
<div class="container">
<h3>Table Annotations</h3>
<p>These will be injected into any AI assistant prompts that reference the annotated table.</p>
<p>Write some notes about your tables to help the AI Assistant do its job. Relevant annotations will be automatically injected into AI assistant requests.</p>
<p>Good annotations may describe the purposes of columns that are not obvious from their name alone, common joins to other tables, or the semantic meaning of enum values.</p>
<div class="mt-3">
<a href="{% url 'table_description_create' %}" class="btn btn-primary mb-3">Create New</a>
<a href="{% url 'table_description_create' %}" class="btn btn-primary mb-3">Create Annotation</a>
<table class="table table-striped table-hover">
<thead>
<tr>
Expand Down
13 changes: 5 additions & 8 deletions explorer/templates/connections/connection_upload.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@
{% block sql_explorer_content %}
<div class="container mt-5">
<div class="pt-3">
<h4>Upload a file</h4>
<h4>Create a connection from an uploaded file</h4>
<p>Supports .csv, .json, .db, and .sqlite files. JSON files with one JSON document per line are also supported. CSV/JSON data will be parsed and converted to SQLite. SQLite databases must <i>not</i> be password protected.</p>
<p></p>

<p>Appending to an existing connection will add a new table to the SQLite database, named after the uploaded file. If a table with the filename already exists, it will be replaced with the uploaded data.</p>
<form id="upload-form">
<div class="form-floating mb-3">
<select id="append" name="append" class="form-select">
<option value="" selected>-- Create new connection --</option>
<option value="" selected></option>
{% for connection in valid_connections %}
<option value="{{ connection.id }}">{{ connection.alias }}</option>
{% endfor %}
</select>
<label for="append">Append to existing connection:</label>
<span class="form-text text-muted">When appending, if a table with the filename already exists, it will be replaced with the uploaded data.</span>
<label for="append">Optional: Append to existing connection:</label>
</div>

<div id="drop-area" class="p-3 mb-4 bg-light border rounded" style="cursor: pointer">
<p class="lead mb-0">Drag and drop, or click to upload .csv, .json, .db, .sqlite.</p>
<p class="lead mb-0"><span class="fw-bold">Upload: </span>Drag and drop, or click to upload .csv, .json, .db, .sqlite.</p>
<input type="file" id="fileElem" style="display:none" accept=".db,.csv,.sqlite,.json">
<div class="progress mt-3" style="height: 20px;">
<div id="progress-bar" class="progress-bar" role="progressbar" style="width: 0;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
Expand Down
11 changes: 9 additions & 2 deletions explorer/templates/connections/connections.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@
<div class="container">
<h3>Connections</h3>
<div class="mt-3">
<a href="{% url 'explorer_connection_create' %}" class="btn btn-primary mb-3">Add New Connection</a>
<a href="{% url 'explorer_upload_create' %}" class="btn btn-primary mb-3">Upload File</a>
<div class="d-flex align-items-center gap-2 mb-3">
<a href="{% url 'explorer_connection_create' %}" class="btn btn-primary">Add New Connection</a>
<a href="{% url 'explorer_upload_create' %}" class="btn btn-primary">Upload File</a>
{% if object_list|length == 0 %}
<span class="text-secondary d-flex align-items-center fw-bold">
<i class="bi-arrow-left me-1"></i>Connect to an existing database, or upload a csv, json, or sqlite file.
</span>
{% endif %}
</div>
<table class="table table-striped" id="connections_table">
<thead>
<tr>
Expand Down
5 changes: 4 additions & 1 deletion explorer/templates/explorer/assistant.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
</div>
<div class="assistant-icons" style="">
<div>
<i class="bi-plus-circle" id="select_all_button" style="cursor: pointer;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Select all"></i>
<i class="bi-check-all" id="select_all_button" style="cursor: pointer;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Add all"></i>
</div>
<div>
<i class="bi-trash" id="deselect_all_button" style="cursor: pointer;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Remove all"></i>
</div>
<div>
<i class="bi-repeat" id="refresh_tables_button" style="cursor: pointer;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Refresh autodetect"></i>
</div>
<div>
<i class="bi-card-list" id="assistant_history" style="cursor: pointer;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="History"></i>
</div>
Expand Down
6 changes: 6 additions & 0 deletions explorer/templates/explorer/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ <h2>This is easy to fix, I promise!</h2>
<a class="nav-link{% if not query and view_name == 'query_favorites' %} active{% endif %}"
href="{% url 'query_favorites' %}"><i class="small me-1 bi-heart"></i>{% translate "Favorites" %}</a>
</li>
{% if hosted %}
<li class="nav-item">
<a class="nav-link"
href="/"><i class="small me-1 bi-arrow-return-left"></i>Manage</a>
</li>
{% endif %}
</ul>
</div>
</nav>
Expand Down
3 changes: 1 addition & 2 deletions explorer/templates/explorer/play.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h2>{% translate "Playground" %}</h2>
<div class="alert alert-danger db-error">{{ error|escape }}</div>
{% endif %}
{{ form.non_field_errors }}
{% if form.connections|length > 1 and can_change %}
{% if can_change %}
<div class="mb-3 form-floating">
{{ form.database_connection }}
<label for="id_database_connection" class="form-label">{% translate "Connection" %}</label>
Expand All @@ -26,7 +26,6 @@ <h2>{% translate "Playground" %}</h2>
<div class="d-none">
{{ form.database_connection }}
</div>
<div>{{ form.database_connection.value }}</div>
{% endif %}
<div class="row">
<div class="col">
Expand Down
7 changes: 5 additions & 2 deletions explorer/templates/explorer/query.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ <h2>
<div class="alert alert-danger">{{ error|escape }}</div>
{% endfor %}{% endif %}
</div>
{% if form.connections|length > 1 and can_change %}
{% if can_change %}
<div class="mb-3 form-floating">
{{ form.database_connection }}
<label for="id_database_connection" class="form-label">{% translate "Connection" %}</label>
Expand Down Expand Up @@ -96,6 +96,10 @@ <h2>
{% if query %}
<div class="position-relative float-end">
<small>
<span class="pe-3">
{% if query and can_change and assistant_enabled %}{{ form.few_shot }} {% translate "Assistant Example" %}{% endif %}
<i class="bi-question-circle" style="cursor: pointer;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Queries marked as examples will be sent, when relevant, to the AI Assistant as few-shot examples of how certain tables are used."></i>
</span>
<a href="#" title="Open in playground" id="playground_button">
<i class="bi-arrow-up-right-square"></i>
</a>
Expand Down Expand Up @@ -150,6 +154,5 @@ <h2>
</div>
<div class="container mt-1 text-end small">
{% if query and can_change and tasks_enabled %}{{ form.snapshot }} {% translate "Snapshot" %}{% endif %}
{% if query and can_change and assistant_enabled %}{{ form.few_shot }} {% translate "Assistant Example" %}{% endif %}
</div>
{% endblock %}
Loading

0 comments on commit d79d21c

Please sign in to comment.