Skip to content

Commit

Permalink
Merge pull request #47 from ramonvermeulen/ramon/compiled-sql
Browse files Browse the repository at this point in the history
Compiled SQL panel
  • Loading branch information
ramonvermeulen authored Aug 2, 2024
2 parents 3228bc6 + eb354eb commit 08899d2
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 35 deletions.
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ updates:
directory: "/"
schedule:
interval: "daily"
# Maintain dependencies for npm in lineage-panel
- package-ecosystem: "npm"
directory: "/lineage-panel"
schedule:
interval: "daily"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
build
**/lineage-panel-dist/**
.kotlin
**/.kotlin/**
**/.kotlin/**
.salive
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ This feature helps you understand the impact of changes and the flow of data in
quicker way to navigate through your dbt project.
* **dbt Documentation**: Access your dbt documentation within your IDE, eliminating the need to switch between different
tools and platforms. This feature supports a more efficient workflow and keeps essential information at your fingertips.
* **Preview compiled SQL**: Preview the compiled SQL of a dbt model quickly in your IDE, and recompile a single model on
the fly.

## Upcoming Features
*These are features I am planning to implement in the future, however this list might change overtime*
* **Full Jinja support in SQL files**: Highlight Jinja syntax in SQL files and navigate through files by clicking
through `{{ ref() }}` and `{{ source() }}` tags.
* **Preview compiled SQL**: Preview the compiled SQL of a dbt model quickly in your IDE, and recompile a single model on
the fly.
* **Preview data**: Preview the output data of a dbt model directly in your IDE.
* **... More**: I am open to suggestions and feedback, so feel free to reach out to me with your ideas!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package com.github.ramonvermeulen.dbtToolkit.ui

import com.github.ramonvermeulen.dbtToolkit.services.DbtToolkitSettingsService
import com.github.ramonvermeulen.dbtToolkit.ui.console.ConsoleOutputPanel
import com.github.ramonvermeulen.dbtToolkit.ui.docs.DocsPanel
import com.github.ramonvermeulen.dbtToolkit.ui.lineage.LineagePanel
import com.github.ramonvermeulen.dbtToolkit.ui.panels.CompiledSqlPanel
import com.github.ramonvermeulen.dbtToolkit.ui.panels.DocsPanel
import com.github.ramonvermeulen.dbtToolkit.ui.panels.LineagePanel
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
Expand Down Expand Up @@ -31,8 +32,9 @@ class DbtToolkitMainToolWindow : ToolWindowFactory, DumbAware {

val panelCreators =
mapOf(
"dbt lineage" to PanelInfo({ LineagePanel(project) }, false),
"dbt docs" to PanelInfo({ DocsPanel(project) }, true),
"lineage" to PanelInfo({ LineagePanel(project) }, false),
"docs" to PanelInfo({ DocsPanel(project) }, true),
"compiled sql" to PanelInfo({ CompiledSqlPanel(project) }, true),
"console (read-only)" to PanelInfo({ ConsoleOutputPanel(project) }, false),
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.github.ramonvermeulen.dbtToolkit.ui.panels

import com.github.ramonvermeulen.dbtToolkit.services.ActiveFileListener
import com.github.ramonvermeulen.dbtToolkit.services.ActiveFileService
import com.github.ramonvermeulen.dbtToolkit.services.DbtCommandExecutorService
import com.github.ramonvermeulen.dbtToolkit.services.DbtToolkitSettingsService
import com.github.ramonvermeulen.dbtToolkit.ui.IdeaPanel
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.service
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import java.awt.BorderLayout
import java.io.File
import javax.swing.JButton
import javax.swing.JComponent
import javax.swing.JPanel
import javax.swing.SwingUtilities

class CompiledSqlPanel(project: Project) : IdeaPanel, Disposable, ActiveFileListener {
private val settings = project.service<DbtToolkitSettingsService>()
private val dbtCommandExecutorService = project.service<DbtCommandExecutorService>()
private val mainPanel = JPanel(BorderLayout())
private val recompileButton = JButton("Re-compile model")
private var document: Document? = null
private var activeFile: VirtualFile? = null

init {
project.messageBus.connect().subscribe(ActiveFileService.TOPIC, this)
val fileType = FileTypeManager.getInstance().getFileTypeByExtension("sql")
document = EditorFactory.getInstance().createDocument("")
val editor = EditorFactory.getInstance().createEditor(document!!, project, fileType, false)
val editorTextField = editor.component
// to set the initial file, since the subscription is only set-up after
// opening the panel (lazy) for the first time
activeFileChanged(FileEditorManager.getInstance(project).selectedFiles.firstOrNull())
recompileButton.addActionListener { handleRecompileButtonClick() }
mainPanel.add(recompileButton, BorderLayout.NORTH)
mainPanel.add(editorTextField, BorderLayout.CENTER)
}

private fun handleRecompileButtonClick() {
SwingUtilities.invokeLater {
recompileButton.isEnabled = false
recompileButton.text = "Re-compiling..."
}
ApplicationManager.getApplication().executeOnPooledThread {
try {
if (activeFile != null) {
// save the active file on disk before recompiling, IDE can have an open buffer
ApplicationManager.getApplication().invokeLater {
ApplicationManager.getApplication().runWriteAction {
FileDocumentManager.getInstance().getDocument(activeFile!!).let {
FileDocumentManager.getInstance().saveDocument(it!!)
}
}
}
dbtCommandExecutorService.executeCommand(
listOf("compile", "--no-populate-cache", "--select", activeFile!!.nameWithoutExtension),
)
activeFileChanged(activeFile)
}
} finally {
SwingUtilities.invokeLater {
recompileButton.isEnabled = true
recompileButton.text = "Re-compile model"
}
}
}
}

override fun activeFileChanged(file: VirtualFile?) {
activeFile = file
val compiledFile = findCompiledFile(file)
displayCompiledFile(compiledFile)
}

private fun findCompiledFile(file: VirtualFile?): VirtualFile? {
val relativePathFromDbtProjectRoot = file?.path?.replace(File(settings.state.dbtProjectsDir).parentFile.path, "")
val targetPath = "${settings.state.dbtTargetDir}/compiled$relativePathFromDbtProjectRoot"
return VirtualFileManager.getInstance().findFileByUrl("file://$targetPath")
}

private fun displayCompiledFile(file: VirtualFile?) {
if (file != null && file.exists()) {
// VirtualFiles are cached by default, so we need to refresh the file to get the latest contents
file.refresh(false, false)
SwingUtilities.invokeLater {
ApplicationManager.getApplication().runWriteAction {
document?.setText(file.contentsToByteArray().toString(Charsets.UTF_8))
}
}
}
}

override fun getContent(): JComponent {
return mainPanel
}

override fun dispose() {
// Implement your dispose logic here
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.github.ramonvermeulen.dbtToolkit.ui.docs
package com.github.ramonvermeulen.dbtToolkit.ui.panels

import com.github.ramonvermeulen.dbtToolkit.DBT_CATALOG_FILE
import com.github.ramonvermeulen.dbtToolkit.DBT_DOCS_FILE
Expand Down Expand Up @@ -37,32 +37,7 @@ class DocsPanel(project: Project) : IdeaPanel, Disposable {
private val browser: JBCefBrowser = JBCefBrowserBuilder().setClient(ourCefClient).setEnableOpenDevToolsMenuItem(isDebug).build()
private val mainPanel: JPanel = JPanel()
private val buttonPanel = JPanel(FlowLayout(FlowLayout.LEFT))
private val regenerateButton =
object : JButton("Regenerate Docs") {
init {
addActionListener {
SwingUtilities.invokeLater {
isEnabled = false
text = "Loading..."
}
ApplicationManager.getApplication().executeOnPooledThread {
try {
val docs = docsService.getDocs(forceRegen = true)
docs.lastModified().let {
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
lastModifiedLabel.text = "Last modified: ${sdf.format(it)}"
}
browser.loadURL(docs.absolutePath)
} finally {
SwingUtilities.invokeLater {
isEnabled = true
text = "Regenerate Docs"
}
}
}
}
}
}
private val regenerateButton = JButton("Regenerate Docs")
private val lastModifiedLabel = JLabel()

init {
Expand Down Expand Up @@ -90,13 +65,36 @@ class DocsPanel(project: Project) : IdeaPanel, Disposable {
mainPanel.layout = BoxLayout(mainPanel, BoxLayout.Y_AXIS)
regenerateButton.isEnabled = false
regenerateButton.text = "Loading..."
regenerateButton.addActionListener { handleRegenerateButtonClick() }
buttonPanel.add(regenerateButton)
buttonPanel.add(lastModifiedLabel)
mainPanel.add(buttonPanel)
mainPanel.add(browser.component)
}
}

private fun handleRegenerateButtonClick() {
SwingUtilities.invokeLater {
regenerateButton.isEnabled = false
regenerateButton.text = "Loading..."
}
ApplicationManager.getApplication().executeOnPooledThread {
try {
val docs = docsService.getDocs(forceRegen = true)
docs.lastModified().let {
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
lastModifiedLabel.text = "Last modified: ${sdf.format(it)}"
}
browser.loadURL(docs.absolutePath)
} finally {
SwingUtilities.invokeLater {
regenerateButton.isEnabled = true
regenerateButton.text = "Regenerate Docs"
}
}
}
}

private fun initiateCefRequestHandler() {
val myRequestHandler = CefLocalRequestHandler()
val docs = docsService.getDocs()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.github.ramonvermeulen.dbtToolkit.ui.lineage
package com.github.ramonvermeulen.dbtToolkit.ui.panels

import com.github.ramonvermeulen.dbtToolkit.JS_TRIGGERED_KEY
import com.github.ramonvermeulen.dbtToolkit.LINEAGE_PANEL_APP_DIR_NAME
Expand Down

0 comments on commit 08899d2

Please sign in to comment.