Skip to content

Commit

Permalink
Merge pull request #147 from frappe/script-query
Browse files Browse the repository at this point in the history
feat: new script query
  • Loading branch information
nextchamp-saqib authored Aug 6, 2023
2 parents 983843a + 692a4c3 commit 4b91ef3
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 38 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"dependencies": {
"@codemirror/lang-javascript": "^6.0.2",
"@codemirror/lang-python": "^6.1.3",
"@codemirror/lang-sql": "^6.4.0",
"@playwright/test": "^1.32.1",
"@vitejs/plugin-vue": "^4.2.3",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/Controls/Code.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { autocompletion, closeBrackets } from '@codemirror/autocomplete'
import { javascript } from '@codemirror/lang-javascript'
import { MySQL, sql } from '@codemirror/lang-sql'
import { python } from '@codemirror/lang-python'
import { HighlightStyle, syntaxHighlighting, syntaxTree } from '@codemirror/language'
import { EditorView } from '@codemirror/view'
import { tags } from '@lezer/highlight'
Expand Down Expand Up @@ -72,6 +73,8 @@ watch(code, (value, oldValue) => {
const language =
props.language === 'javascript'
? javascript()
: props.language === 'python'
? python()
: sql({
dialect: MySQL,
upperCaseKeywords: true,
Expand Down
16 changes: 11 additions & 5 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@
/* Code Control */

.cm-gutters {
display: none !important;
@apply !bg-gray-50 !text-sm !leading-6;
}
.cm-activeLine {
padding-left: 10px !important;
margin-left: -4px !important;
@apply !bg-gray-50;
}
.cm-activeLineGutter {
@apply !bg-gray-300;
}
.cm-editor {
height: 100%;
Expand All @@ -34,11 +42,9 @@
@apply !text-gray-600;
}
.cm-content {
padding: 0px !important;
}
.cm-activeLine {
@apply !bg-transparent;
padding: 6px 0px 6px 4px !important;
}

.cm-scroller {
font-family: 'Fira Code' !important;
line-height: 1.5rem !important;
Expand Down
55 changes: 30 additions & 25 deletions frontend/src/query/Query.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,35 @@
</div>
<div class="flex flex-1 flex-shrink-0 flex-col overflow-y-scroll">
<template v-if="activeTab == buildTabLabel">
<template v-if="query.doc.is_native_query">
<div
class="flex min-h-[20rem] flex-1 flex-shrink-0 gap-4 overflow-hidden px-2 py-1"
>
<NativeQueryEditor />
</div>
</template>
<template v-else>
<div
class="flex min-h-[20rem] flex-1 flex-shrink-0 gap-4 overflow-hidden px-2 py-1"
>
<template v-if="!query.doc.is_assisted_query">
<TablePanel />
<ColumnPanel />
<FilterPanel />
</template>
<template v-else>
<div class="flex min-h-[20rem] w-full flex-1 rounded border py-2">
<Suspense>
<VisualQuery :name="query.doc.name" />
</Suspense>
</div>
</template>
</div>
</template>
<div
v-if="query.doc.is_native_query"
class="flex min-h-[20rem] flex-1 flex-shrink-0 gap-4 overflow-hidden px-2 py-1"
>
<NativeQueryEditor />
</div>
<div
v-else-if="query.doc.is_script_query"
class="flex min-h-[20rem] flex-1 flex-shrink-0 gap-4 overflow-hidden px-2 py-1"
>
<ScriptQueryEditor />
</div>
<div
v-else
class="flex min-h-[20rem] flex-1 flex-shrink-0 gap-4 overflow-hidden px-2 py-1"
>
<template v-if="!query.doc.is_assisted_query">
<TablePanel />
<ColumnPanel />
<FilterPanel />
</template>
<template v-else>
<div class="flex min-h-[20rem] w-full flex-1 rounded border py-2">
<Suspense>
<VisualQuery :name="query.doc.name" />
</Suspense>
</div>
</template>
</div>
<QueryResult class="min-h-[20rem] flex-1" />
</template>

Expand All @@ -47,6 +51,7 @@ import { default as VisualQuery } from '@/notebook/blocks/query/builder/QueryBui
import ColumnPanel from '@/query/Column/ColumnPanel.vue'
import FilterPanel from '@/query/Filter/FilterPanel.vue'
import NativeQueryEditor from '@/query/NativeQueryEditor.vue'
import ScriptQueryEditor from '@/query/ScriptQueryEditor.vue'
import QueryHeader from '@/query/QueryHeader.vue'
import QueryVisualizer from '@/query/QueryVisualizer.vue'
import QueryResult from '@/query/Result/QueryResult.vue'
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/query/QueryList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ async function openQueryEditor(type) {
if (type === 'visual') new_query.is_assisted_query = 1
if (type === 'classic') new_query.is_assisted_query = 0
if (type === 'sql') new_query.is_native_query = 1
if (type === 'script') new_query.is_script_query = 1
const query = await queries.create(new_query)
router.push({
name: 'Query',
Expand Down Expand Up @@ -111,6 +112,13 @@ const queryBuilderTypes = ref([
icon: 'code',
onClick: () => openQueryEditor('sql'),
},
{
label: 'Script',
description: 'Create a query using a script',
icon: 'code',
tag: 'beta',
onClick: () => openQueryEditor('script'),
},
])
</script>

Expand Down
38 changes: 38 additions & 0 deletions frontend/src/query/ScriptQueryEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script setup>
import Code from '@/components/Controls/Code.vue'
import { inject, ref, watch } from 'vue'
const query = inject('query')
const script = ref(query.doc.script)
watch(
() => query.doc.script,
(value) => (script.value = value)
)
function runQuery() {
query.setValue.submit({ script: script.value }).then(() => {
query.run.submit()
})
}
</script>

<template>
<div class="flex w-full flex-1 flex-shrink-0 flex-col">
<div class="flex-shrink-0 text-sm uppercase leading-7 tracking-wide text-gray-600">
Script Query
</div>
<div class="flex flex-1 overflow-y-scroll rounded border">
<Code language="python" v-model="script" placeholder="Enter your script here...">
</Code>
</div>
<div class="mt-2 flex-shrink-0 space-x-2">
<Button
iconLeft="play"
variant="outline"
@click="runQuery"
:loading="query.run.loading"
>
Run
</Button>
</div>
</div>
</template>
1 change: 1 addition & 0 deletions insights/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def create_query(**query):
doc.data_source = query.get("data_source")
doc.is_assisted_query = query.get("is_assisted_query")
doc.is_native_query = query.get("is_native_query")
doc.is_script_query = query.get("is_script_query")
if table := query.get("table") and not doc.is_assisted_query:
doc.append(
"tables",
Expand Down
22 changes: 18 additions & 4 deletions insights/insights/doctype/insights_query/insights_query.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"is_native_query",
"is_assisted_query",
"is_saved_as_table",
"is_script_query",
"column_break_3",
"data_source",
"is_stored",
Expand All @@ -25,6 +26,7 @@
"limit",
"section_break_cnma",
"json",
"script",
"query_and_result_tab",
"section_break_11",
"sql",
Expand Down Expand Up @@ -109,7 +111,7 @@
"fieldtype": "Column Break"
},
{
"depends_on": "eval: !doc.is_native_query",
"depends_on": "eval: !doc.is_assisted_query && !doc.is_native_query",
"fieldname": "section_break_3",
"fieldtype": "Section Break"
},
Expand All @@ -120,7 +122,6 @@
"in_standard_filter": 1,
"label": "Data Source",
"options": "Insights Data Source",
"reqd": 1,
"search_index": 1
},
{
Expand Down Expand Up @@ -160,7 +161,7 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
"options": "Pending Execution\nExecution Successful",
"options": "Pending Execution\nExecution Successful\nExecution Failed",
"read_only": 1
},
{
Expand Down Expand Up @@ -219,11 +220,24 @@
"fieldtype": "Check",
"is_virtual": 1,
"label": "Is Saved as Table"
},
{
"default": "0",
"fieldname": "is_script_query",
"fieldtype": "Check",
"label": "Is Script Query"
},
{
"depends_on": "eval: doc.is_script_query",
"fieldname": "script",
"fieldtype": "Code",
"label": "Script",
"options": "Python"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-07-22 23:42:07.915992",
"modified": "2023-08-06 11:19:07.413824",
"modified_by": "Administrator",
"module": "Insights",
"name": "Insights Query",
Expand Down
14 changes: 11 additions & 3 deletions insights/insights/doctype/insights_query/insights_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
)
from .insights_query_client import InsightsQueryClient
from .insights_raw_query import InsightsRawQueryController
from .insights_script_query import InsightsScriptQueryController
from .utils import (
CachedResults,
InsightsTableColumn,
Expand Down Expand Up @@ -60,7 +61,10 @@ def is_saved_as_table(self):
def results(self):
fetch_if_not_cached = self.status == Status.SUCCESS.value
limit = InsightsSettings.get("query_result_limit") or 1000
results = self.retrieve_results(fetch_if_not_cached)
try:
results = self.retrieve_results(fetch_if_not_cached)
except Exception:
results = []
return frappe.as_json(results[:limit])

@property
Expand All @@ -73,6 +77,8 @@ def variant_controller(self):
return InsightsRawQueryController(self)
if self.is_assisted_query:
return InsightsAssistedQueryController(self)
if self.is_script_query:
return InsightsScriptQueryController(self)
return InsightsLegacyQueryController(self)

def validate(self):
Expand All @@ -85,6 +91,7 @@ def reset(self):
new_query.data_source = self.data_source
new_query.is_native_query = self.is_native_query
new_query.is_assisted_query = self.is_assisted_query
new_query.is_script_query = self.is_script_query
new_query_dict = new_query.as_dict(no_default_fields=True)
self.update(new_query_dict)
self.status = Status.SUCCESS.value
Expand Down Expand Up @@ -164,10 +171,11 @@ def fetch_results(self):
self._results = self.process_results_columns(self._results)
self.execution_time = flt(time.monotonic() - start, 3)
self.last_execution = frappe.utils.now()
self.status = Status.SUCCESS.value
self.db_set("status", Status.SUCCESS.value)
except Exception as e:
self.status = Status.FAILED.value
frappe.db.rollback()
frappe.log_error(e)
self.db_set("status", Status.FAILED.value, commit=True)
raise
finally:
CachedResults.set(self.name, self._results)
Expand Down
Loading

0 comments on commit 4b91ef3

Please sign in to comment.