Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into feat/refresh-file
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcinVaadin committed Apr 24, 2024
2 parents abf9329 + 22956c9 commit c3c655b
Show file tree
Hide file tree
Showing 17 changed files with 644 additions and 4 deletions.
32 changes: 29 additions & 3 deletions .github/workflows/validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ on:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true

jobs:
validate:
buildPlugin:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -23,4 +23,30 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Build with Gradle
run: ./gradlew --no-configuration-cache build test
run: ./gradlew --no-configuration-cache buildPlugin
- uses: actions/[email protected]
id: artifact
with:
name: distributions
path: build/distributions
- uses: mshick/add-pr-comment@v2
with:
refresh-message-position: true
message: |
Artifact build on last commit: [distributions.zip](${{ steps.artifact.outputs.artifact-url }}).
For MacOS users: there is a zip inside this zip and Finder unzips them both at once. Use `unzip distributions.zip` from Terminal or [check solution for Archive Manager](https://apple.stackexchange.com/questions/443607/is-there-a-way-to-prevent-macoss-archive-utility-from-unarchiving-inner-zip-fil).
runPluginVerifier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Build with Gradle
run: ./gradlew --no-configuration-cache runPluginVerifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.vaadin.plugin.module

import com.intellij.notification.NotificationType
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.ProjectActivity
import com.intellij.openapi.vfs.VfsUtil
import com.vaadin.plugin.utils.VaadinProjectUtil
import java.io.File

class PostModuleCreatedActivity : ProjectActivity {

override suspend fun execute(project: Project) {
project.getUserData(VaadinProjectUtil.PROJECT_DOWNLOADED_PROP_KEY)?.afterChange {
VaadinProjectUtil.notify("Vaadin project created", NotificationType.INFORMATION, project)
VfsUtil.findFileByIoFile(File(project.basePath, "README.md"), true)?.let {
val descriptor = OpenFileDescriptor(project, it)
descriptor.setUsePreviewTab(true)
FileEditorManager.getInstance(project).openEditor(descriptor, true)
}
}
}

}
28 changes: 28 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/module/QuickStarterPanel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.vaadin.plugin.module

import com.intellij.ui.dsl.builder.panel
import com.vaadin.plugin.starter.QuickStarterModel

class QuickStarterPanel {

val model = QuickStarterModel("Flow (Java)", false, "Stable")

val root = panel {
row("Example views") {
segmentedButton(setOf("Flow (Java)", "Hilla (React)", "None")) { it }.whenItemSelected {
model.views = it
}.selectedItem = model.views
}
row("Use authentication") {
checkBox("").onChanged {
model.authentication = it.isSelected
}.component.isSelected = model.authentication
}
row("Version") {
segmentedButton(setOf("Stable", "Prerelease")) { it }.whenItemSelected {
model.version = it
}.selectedItem = model.version
}
}

}
120 changes: 120 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/module/SkeletonStarterPanel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package com.vaadin.plugin.module

import com.intellij.openapi.ui.DialogPanel
import com.intellij.ui.dsl.builder.TopGap
import com.intellij.ui.dsl.builder.bind
import com.intellij.ui.dsl.builder.panel
import com.jetbrains.rd.util.first
import com.vaadin.plugin.starter.StarterModel
import com.vaadin.plugin.starter.StarterSupport
import javax.swing.JEditorPane
import javax.swing.JRadioButton

class SkeletonStarterPanel {

private val all = mapOf(
"frameworks" to HashMap<JRadioButton, String>(),
"languages" to HashMap(),
"buildTools" to HashMap(),
"architectures" to HashMap(),
)

private var kotlinInfo: JEditorPane? = null
private var notAllArchitecturesSupportedMessage: JEditorPane? = null

val model = StarterModel(
StarterSupport.frameworks.keys.first(),
StarterSupport.languages.keys.first(),
StarterSupport.buildTools.keys.first(),
StarterSupport.architectures.keys.first()
)

val root: DialogPanel = panel {
buttonsGroup {
row("Framework") {
for (el in StarterSupport.frameworks.entries) {
val r = radioButton(el.value, el.key).onChanged { refreshSupport() }
all["frameworks"]!![r.component] = el.key
}
}
}.bind(model::framework)
buttonsGroup {
row("Language") {
for (el in StarterSupport.languages) {
val r = radioButton(el.value, el.key).onChanged { refreshSupport() }
all["languages"]!![r.component] = el.key
}
}.topGap(TopGap.SMALL)
row("") {
kotlinInfo = text("<i>Kotlin support uses a community add-on.</i>").component
}
}.bind(model::language)
buttonsGroup {
row("Build tool") {
for (el in StarterSupport.buildTools) {
val r = radioButton(el.value, el.key).onChanged { refreshSupport() }
all["buildTools"]!![r.component] = el.key
}
}.topGap(TopGap.SMALL)
}.bind(model::buildTool)
buttonsGroup {
row("Architecture") {
for (el in StarterSupport.architectures.entries) {
val r = radioButton(el.value, el.key).onChanged { refreshSupport() }
all["architectures"]!![r.component] = el.key
}
}
row("") {
notAllArchitecturesSupportedMessage = text("").component
}
}.bind(model::architecture)
}

/**
* Enable / disable radio buttons depending on support matrix
*/
private fun refreshSupport() {
// apply model updates
root?.apply() ?: null
refreshGroup(all["frameworks"]!!, StarterSupport::isSupportedFramework)
refreshGroup(all["languages"]!!, StarterSupport::isSupportedLanguage)
refreshGroup(all["buildTools"]!!, StarterSupport::isSupportedBuildTool)
refreshGroup(all["architectures"]!!, StarterSupport::isSupportedArchitecture)
refreshKotlinMessage()
refreshArchitecturesSupportedMessage()
}

private fun refreshArchitecturesSupportedMessage() {
if (StarterSupport.supportsAllArchitectures(model)) {
notAllArchitecturesSupportedMessage?.isVisible = false
} else {
notAllArchitecturesSupportedMessage?.isVisible = true
val frameworkName = StarterSupport.frameworks[model.framework]
notAllArchitecturesSupportedMessage?.text = "<i>$frameworkName does not support all architectures.</i>"
}
}

private fun refreshKotlinMessage() {
kotlinInfo!!.isVisible = model.language == "kotlin"
}

/**
* Checks all JRadioButtons in given group if they should be disabled, fallbacks to first enabled
*/
private fun refreshGroup(
group: HashMap<JRadioButton, String>,
supportCheck: (model: StarterModel, framework: String) -> Boolean
) {
var selectFirstEnabled = false
group.forEach {
it.key.isEnabled = supportCheck(model, it.value)
if (!it.key.isEnabled && it.key.isSelected) {
selectFirstEnabled = true
}
}
if (selectFirstEnabled) {
group.filterKeys { it.isEnabled }.first().key.isSelected = true
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.vaadin.plugin.module

import com.intellij.ide.util.projectWizard.ModuleWizardStep
import javax.swing.JComponent

class VaadinCustomOptionsStep(private val builder: VaadinModuleBuilder) : ModuleWizardStep() {

private val panel = VaadinPanel()

override fun getComponent(): JComponent {
return panel.getComponent()
}

override fun updateDataModel() {
builder.setModel(panel.getModel())
}

}
50 changes: 50 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/module/VaadinModuleBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.vaadin.plugin.module

import com.intellij.ide.util.projectWizard.ModuleBuilder
import com.intellij.ide.util.projectWizard.ModuleWizardStep
import com.intellij.ide.util.projectWizard.WizardContext
import com.intellij.openapi.Disposable
import com.intellij.openapi.module.ModifiableModuleModel
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.observable.properties.PropertyGraph
import com.intellij.openapi.project.ProjectType
import com.vaadin.plugin.starter.DownloadableModel
import com.vaadin.plugin.utils.VaadinProjectUtil

class VaadinModuleBuilder : ModuleBuilder() {

private val propertyGraph = PropertyGraph()

private val projectDownloadedProperty = propertyGraph.property(false)

private var model: DownloadableModel? = null

override fun getBuilderId(): String {
return "vaadin"
}

override fun getModuleType(): ModuleType<*> {
return VaadinModuleType("VaadinModule")
}

override fun getCustomOptionsStep(context: WizardContext?, parentDisposable: Disposable?): ModuleWizardStep {
return VaadinCustomOptionsStep(this)
}

fun setModel(model: DownloadableModel) {
this.model = model
}

override fun createModule(moduleModel: ModifiableModuleModel): Module {
val project = moduleModel.project
project.putUserData(VaadinProjectUtil.PROJECT_DOWNLOADED_PROP_KEY, projectDownloadedProperty)
VaadinProjectUtil.downloadAndExtract(project, this.model!!.getDownloadLink(project))
return super.createModule(moduleModel)
}

override fun getProjectType(): ProjectType? {
return this.model?.let { ProjectType.create(it.getProjectType()) }
}

}
26 changes: 26 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/module/VaadinModuleType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.vaadin.plugin.module

import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.util.IconLoader
import org.jetbrains.annotations.NonNls
import javax.swing.Icon

class VaadinModuleType(id: @NonNls String) : ModuleType<VaadinModuleBuilder>(id) {

override fun createModuleBuilder(): VaadinModuleBuilder {
return VaadinModuleBuilder()
}

override fun getName(): String {
return "Vaadin"
}

override fun getDescription(): String {
return "Create Vaadin application"
}

override fun getNodeIcon(isOpened: Boolean): Icon {
return IconLoader.getIcon("/META-INF/pluginIcon.svg", javaClass.classLoader)
}

}
59 changes: 59 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/module/VaadinPanel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.vaadin.plugin.module

import com.intellij.ide.wizard.withVisualPadding
import com.intellij.openapi.ui.DialogPanel
import com.intellij.ui.dsl.builder.CollapsibleRow
import com.intellij.ui.dsl.builder.panel
import com.vaadin.plugin.starter.DownloadableModel

class VaadinPanel {

private var dialogPanel: DialogPanel? = null

private var quickStarterGroup: CollapsibleRow? = null
private var skeletonStarterGroup: CollapsibleRow? = null

private val quickStarterPanel = QuickStarterPanel()
private val skeletonStarterPanel = SkeletonStarterPanel()

init {
dialogPanel = panel {
quickStarterGroup = collapsibleGroup("Project Settings") {
row {}.cell(quickStarterPanel.root)
}

skeletonStarterGroup = collapsibleGroup("Hello World Projects") {
row {}.cell(skeletonStarterPanel.root)
}
row {
text(
"<a href=\"https://vaadin.com/flow\">Flow framework</a> is the most productive" +
" choice, allowing 100% of the user<br>interface to be coded in server-side Java."
)
}
row {
text(
"<a href=\"https://hilla.dev/\">Hilla framework</a>, on the other hand, enables" +
" implementation of your user<br>interface with React while automatically connecting it to your" +
" Java backend."
)
}
row {
text("For more configuration options, visit <a href=\"https://start.vaadin.com\">start.vaadin.com</a>")
}
}.withVisualPadding(true)

quickStarterGroup!!.expanded = true
quickStarterGroup!!.addExpandedListener { if (it) skeletonStarterGroup!!.expanded = false }
skeletonStarterGroup!!.addExpandedListener { if (it) quickStarterGroup!!.expanded = false }
}

fun getComponent(): DialogPanel {
return dialogPanel!!
}

fun getModel(): DownloadableModel {
return if (quickStarterGroup!!.expanded) quickStarterPanel.model else skeletonStarterPanel.model
}

}
11 changes: 11 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/starter/DownloadableModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.vaadin.plugin.starter

import com.intellij.openapi.project.Project

interface DownloadableModel {

fun getDownloadLink(project: Project): String

fun getProjectType(): String

}
Loading

0 comments on commit c3c655b

Please sign in to comment.