Merge pull request #6 from InsanusMokrassar/different_credentials_support
Different credentials support
6
.github/workflows/commit-release.yml
vendored
@ -38,12 +38,12 @@ jobs:
|
|||||||
draft: false
|
draft: false
|
||||||
prerelease: true
|
prerelease: true
|
||||||
- name: Upload Ubuntu Release Asset
|
- name: Upload Ubuntu Release Asset
|
||||||
id: upload-ubuntu-release-asset
|
id: upload-ubuntu-release-asset
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||||
asset_path: "./desktop/build/compose/jars/kmppscriptbuilder.desktop-linux-x64-${{ env.version }}${{ env.additional_version }}.jar"
|
asset_path: "./core/build/compose/jars/kmppscriptbuilder.desktop-linux-x64-${{ env.version }}${{ env.additional_version }}.jar"
|
||||||
asset_name: KotlinPublicationScriptsBuilder-linux-x64.jar
|
asset_name: KotlinPublicationScriptsBuilder-linux-x64.jar
|
||||||
asset_content_type: application/java-archive
|
asset_content_type: application/java-archive
|
||||||
|
@ -7,11 +7,10 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
classpath libs.buildscript.kt.gradle
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath libs.buildscript.kt.serialization
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath libs.buildscript.jb.dokka
|
||||||
classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$dexcount_version"
|
classpath libs.buildscript.gh.release
|
||||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,46 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
id "com.android.library"
|
alias(libs.plugins.jb.compose)
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$mppProjectWithSerializationPresetPath"
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
js (IR) {
|
||||||
|
binaries.executable()
|
||||||
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
api libs.kt.coroutines
|
||||||
api "dev.inmo:micro_utils.coroutines:$micro_utils_version"
|
api libs.microutils.common
|
||||||
|
api libs.microutils.coroutines
|
||||||
api "io.ktor:ktor-client-core:$ktor_version"
|
api libs.ktor.client
|
||||||
|
api(compose.runtime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jsMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(compose.web.core)
|
||||||
|
api libs.ktor.client.js
|
||||||
|
api libs.jsuikit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jvmMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(compose.desktop.currentOs)
|
||||||
|
api libs.ktor.client.cio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
compose {
|
||||||
|
desktop {
|
||||||
|
application {
|
||||||
|
mainClass = "dev.inmo.kmppscriptbuilder.desktop.BuilderKt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@ import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
|||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.url
|
import io.ktor.client.request.url
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.builtins.MapSerializer
|
import kotlinx.serialization.builtins.MapSerializer
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
@ -20,9 +21,9 @@ private val commonLicensesListDeserializer = MapSerializer(String.serializer(),
|
|||||||
private var licenses: Map<String, License>? = null
|
private var licenses: Map<String, License>? = null
|
||||||
|
|
||||||
suspend fun HttpClient.getLicenses(): Map<String, License> {
|
suspend fun HttpClient.getLicenses(): Map<String, License> {
|
||||||
val answer = get<String> {
|
val answer = get {
|
||||||
url("https://licenses.opendefinition.org/licenses/groups/all.json")
|
url("https://licenses.opendefinition.org/licenses/groups/all.json")
|
||||||
}
|
}.bodyAsText()
|
||||||
return serialFormat.decodeFromString(commonLicensesListDeserializer, answer).also { gotLicenses ->
|
return serialFormat.decodeFromString(commonLicensesListDeserializer, answer).also { gotLicenses ->
|
||||||
licenses = gotLicenses
|
licenses = gotLicenses
|
||||||
}
|
}
|
||||||
|
@ -31,23 +31,84 @@ data class MavenConfig(
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class MavenPublishingRepository(
|
data class MavenPublishingRepository(
|
||||||
val name: String,
|
val name: String,
|
||||||
val url: String
|
val url: String,
|
||||||
|
val credsType: CredentialsType = CredentialsType.UsernameAndPassword(
|
||||||
|
CredentialsType.UsernameAndPassword.defaultUsernameProperty(name),
|
||||||
|
CredentialsType.UsernameAndPassword.defaultPasswordProperty(name),
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
private val nameCapitalized by lazy {
|
|
||||||
name.toUpperCase()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun build(indent: String): String {
|
@Serializable
|
||||||
val usernameProperty = "${nameCapitalized}_USER"
|
sealed interface CredentialsType {
|
||||||
val passwordProperty = "${nameCapitalized}_PASSWORD"
|
@Serializable
|
||||||
return """if ((project.hasProperty('${usernameProperty}') || System.getenv('${usernameProperty}') != null) && (project.hasProperty('${passwordProperty}') || System.getenv('${passwordProperty}') != null)) {
|
object Nothing: CredentialsType {
|
||||||
maven {
|
override fun buildCheckPart(): String = "true"
|
||||||
name = "$name"
|
override fun buildCredsPart(): String = ""
|
||||||
url = uri("$url")
|
}
|
||||||
|
@Serializable
|
||||||
|
data class UsernameAndPassword(
|
||||||
|
val usernameProperty: String,
|
||||||
|
val passwordProperty: String
|
||||||
|
): CredentialsType {
|
||||||
|
constructor(baseParameter: String) : this(
|
||||||
|
defaultUsernameProperty(baseParameter),
|
||||||
|
defaultPasswordProperty(baseParameter)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun buildCheckPart(): String = "(project.hasProperty('${usernameProperty}') || System.getenv('${usernameProperty}') != null) && (project.hasProperty('${passwordProperty}') || System.getenv('${passwordProperty}') != null)"
|
||||||
|
override fun buildCredsPart(): String {
|
||||||
|
return """
|
||||||
credentials {
|
credentials {
|
||||||
username = project.hasProperty('${usernameProperty}') ? project.property('${usernameProperty}') : System.getenv('${usernameProperty}')
|
username = project.hasProperty('${usernameProperty}') ? project.property('${usernameProperty}') : System.getenv('${usernameProperty}')
|
||||||
password = project.hasProperty('${passwordProperty}') ? project.property('${passwordProperty}') : System.getenv('${passwordProperty}')
|
password = project.hasProperty('${passwordProperty}') ? project.property('${passwordProperty}') : System.getenv('${passwordProperty}')
|
||||||
}
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun defaultUsernameProperty(name: String): String {
|
||||||
|
return "${name.uppercase()}_USER"
|
||||||
|
}
|
||||||
|
fun defaultPasswordProperty(name: String): String {
|
||||||
|
return "${name.uppercase()}_PASSWORD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Serializable
|
||||||
|
data class HttpHeaderCredentials(
|
||||||
|
val headerName: String,
|
||||||
|
val headerValueProperty: String
|
||||||
|
): CredentialsType {
|
||||||
|
override fun buildCheckPart(): String = "project.hasProperty('${headerValueProperty}') || System.getenv('${headerValueProperty}') != null"
|
||||||
|
override fun buildCredsPart(): String {
|
||||||
|
return """
|
||||||
|
credentials(HttpHeaderCredentials) {
|
||||||
|
name = "$headerName"
|
||||||
|
value = project.hasProperty('${headerValueProperty}') ? project.property('${headerValueProperty}') : System.getenv('${headerValueProperty}')
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun defaultValueProperty(name: String): String {
|
||||||
|
return "${name.uppercase()}_TOKEN"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildCheckPart(): String
|
||||||
|
fun buildCredsPart(): String
|
||||||
|
}
|
||||||
|
private val nameCapitalized by lazy {
|
||||||
|
name.uppercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(indent: String): String {
|
||||||
|
return """if (${credsType.buildCheckPart()}) {
|
||||||
|
maven {
|
||||||
|
name = "$name"
|
||||||
|
url = uri("$url")
|
||||||
|
${credsType.buildCredsPart()}
|
||||||
}
|
}
|
||||||
}""".replace("\n", "\n$indent")
|
}""".replace("\n", "\n$indent")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultDivider
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun TopAppBar(
|
||||||
|
config: Config,
|
||||||
|
saveAvailable: Boolean,
|
||||||
|
onSaveAvailable: (Boolean) -> Unit,
|
||||||
|
onNewConfig: (Config) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
|
class BuilderView : View() {
|
||||||
|
internal val projectTypeView by mutableStateOf(ProjectTypeView())
|
||||||
|
internal val mavenInfoView by mutableStateOf(MavenInfoView())
|
||||||
|
internal val licensesView by mutableStateOf(LicensesView())
|
||||||
|
|
||||||
|
internal var saveAvailableState by mutableStateOf(false)
|
||||||
|
var config: Config
|
||||||
|
get() {
|
||||||
|
return Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
licensesView.licenses = value.licenses
|
||||||
|
mavenInfoView.mavenConfig = value.mavenConfig
|
||||||
|
projectTypeView.projectType = value.type
|
||||||
|
saveAvailableState = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun build() {
|
||||||
|
TopAppBar(
|
||||||
|
config,
|
||||||
|
saveAvailableState,
|
||||||
|
{
|
||||||
|
saveAvailableState = it
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
config = it
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultContentColumn {
|
||||||
|
projectTypeView.build()
|
||||||
|
DefaultDivider()
|
||||||
|
licensesView.build()
|
||||||
|
DefaultDivider()
|
||||||
|
mavenInfoView.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,13 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
|
||||||
class DeveloperState(
|
class DeveloperState(
|
||||||
id: String = "",
|
id: String = "",
|
||||||
@ -22,10 +27,10 @@ class DevelopersView : ListView<DeveloperState>("Developers info") {
|
|||||||
var developers: List<Developer>
|
var developers: List<Developer>
|
||||||
get() = itemsList.map { it.toDeveloper() }
|
get() = itemsList.map { it.toDeveloper() }
|
||||||
set(value) {
|
set(value) {
|
||||||
itemsList.clear()
|
itemsList.apply {
|
||||||
itemsList.addAll(
|
clear()
|
||||||
value.map { it.toDeveloperState() }
|
addAll(value.map { it.toDeveloperState() })
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val addItemText: String = "Add developer"
|
override val addItemText: String = "Add developer"
|
||||||
@ -34,18 +39,19 @@ class DevelopersView : ListView<DeveloperState>("Developers info") {
|
|||||||
override fun createItem(): DeveloperState = DeveloperState()
|
override fun createItem(): DeveloperState = DeveloperState()
|
||||||
@Composable
|
@Composable
|
||||||
override fun buildView(item: DeveloperState) {
|
override fun buildView(item: DeveloperState) {
|
||||||
|
CommonText("Developer username")
|
||||||
CommonTextField(
|
CommonTextField(
|
||||||
item.id,
|
item.id,
|
||||||
"Developer username"
|
|
||||||
) { item.id = it }
|
) { item.id = it }
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
CommonText("Developer name")
|
||||||
CommonTextField(
|
CommonTextField(
|
||||||
item.name,
|
item.name,
|
||||||
"Developer name"
|
|
||||||
) { item.name = it }
|
) { item.name = it }
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
CommonText("Developer E-Mail")
|
||||||
CommonTextField(
|
CommonTextField(
|
||||||
item.eMail,
|
item.eMail,
|
||||||
"Developer E-Mail"
|
|
||||||
) { item.eMail = it }
|
) { item.eMail = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.License
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class LicenseState(
|
||||||
|
id: String = "",
|
||||||
|
title: String = "",
|
||||||
|
url: String? = null
|
||||||
|
) {
|
||||||
|
var id: String by mutableStateOf(id)
|
||||||
|
var title: String by mutableStateOf(title)
|
||||||
|
var url: String? by mutableStateOf(url)
|
||||||
|
|
||||||
|
fun toLicense() = License(id, title, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun License.toLicenseState() = LicenseState(id, title, url)
|
||||||
|
|
||||||
|
expect object LicensesDrawer : Drawer<LicensesView>
|
||||||
|
|
||||||
|
class LicensesView : ListView<LicenseState>("Licenses") {
|
||||||
|
var licenses: List<License>
|
||||||
|
get() = itemsList.map { it.toLicense() }
|
||||||
|
set(value) {
|
||||||
|
itemsList.clear()
|
||||||
|
itemsList.addAll(value.map { it.toLicenseState() })
|
||||||
|
}
|
||||||
|
internal val availableLicensesState = mutableStateListOf<License>()
|
||||||
|
internal var licenseSearchFilter by mutableStateOf("")
|
||||||
|
internal val searchFieldFocused = mutableStateOf(false)
|
||||||
|
internal val licensesOffersToShow = derivedStateOf {
|
||||||
|
val query = licenseSearchFilter.lowercase()
|
||||||
|
availableLicensesState.filter {
|
||||||
|
it.title.lowercase().contains(query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val addItemText: String
|
||||||
|
get() = "Add empty license"
|
||||||
|
|
||||||
|
init {
|
||||||
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
|
val client = HttpClient()
|
||||||
|
availableLicensesState.addAll(client.getLicenses().values)
|
||||||
|
client.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createItem(): LicenseState = LicenseState()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun buildView(item: LicenseState) {
|
||||||
|
CommonText("License ID")
|
||||||
|
CommonTextField(
|
||||||
|
item.id,
|
||||||
|
"Short name like \"Apache-2.0\"",
|
||||||
|
) { item.id = it }
|
||||||
|
CommonText("License title")
|
||||||
|
CommonTextField(
|
||||||
|
item.title,
|
||||||
|
"Official title of license (like \"Apache Software License 2.0\")",
|
||||||
|
) { item.title = it }
|
||||||
|
CommonText("License URL")
|
||||||
|
CommonTextField(
|
||||||
|
item.url ?: "",
|
||||||
|
"Link to your LICENSE file OR official license file (like \"https://opensource.org/licenses/Apache-2.0\")",
|
||||||
|
) { item.url = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val content: @Composable () -> Unit = {
|
||||||
|
CommonTextField(
|
||||||
|
licenseSearchFilter,
|
||||||
|
"Search filter",
|
||||||
|
onFocusChanged = {
|
||||||
|
searchFieldFocused.value = it
|
||||||
|
}
|
||||||
|
) { filterText ->
|
||||||
|
licenseSearchFilter = filterText
|
||||||
|
}
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
|
||||||
|
with(LicensesDrawer) { draw() }
|
||||||
|
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
|
||||||
|
super.content()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
expect class ListViewDrawer<T>() : Drawer<ListView<T>>
|
||||||
|
|
||||||
|
abstract class ListView<T>(title: String) : VerticalView(title) {
|
||||||
|
internal val itemsList = mutableStateListOf<T>()
|
||||||
|
|
||||||
|
internal open val addItemText: String = "Add"
|
||||||
|
internal open val removeItemText: String = "Remove"
|
||||||
|
|
||||||
|
internal abstract fun createItem(): T
|
||||||
|
@Composable
|
||||||
|
internal abstract fun buildView(item: T)
|
||||||
|
|
||||||
|
protected val drawer = ListViewDrawer<T>()
|
||||||
|
|
||||||
|
override val content: @Composable () -> Unit = {
|
||||||
|
with(drawer) {
|
||||||
|
draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MavenConfig
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.SonatypeRepository
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.defaultProjectDescription
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.defaultProjectName
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
|
||||||
|
|
||||||
|
expect class GpgSigningOptionDrawer : Drawer<GpgSigning>
|
||||||
|
expect fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer
|
||||||
|
|
||||||
|
class MavenInfoView : VerticalView("Project information") {
|
||||||
|
internal var projectNameProperty by mutableStateOf("")
|
||||||
|
internal var projectDescriptionProperty by mutableStateOf("")
|
||||||
|
internal var projectUrlProperty by mutableStateOf("")
|
||||||
|
internal var projectVcsUrlProperty by mutableStateOf("")
|
||||||
|
internal var gpgSignProperty by mutableStateOf<GpgSigning>(GpgSigning.Disabled)
|
||||||
|
internal var publishToMavenCentralProperty by mutableStateOf(false)
|
||||||
|
internal val developersView = DevelopersView()
|
||||||
|
internal val repositoriesView = RepositoriesView()
|
||||||
|
|
||||||
|
var mavenConfig: MavenConfig
|
||||||
|
get() = MavenConfig(
|
||||||
|
projectNameProperty.ifBlank { defaultProjectName },
|
||||||
|
projectDescriptionProperty.ifBlank { defaultProjectDescription },
|
||||||
|
projectUrlProperty,
|
||||||
|
projectVcsUrlProperty,
|
||||||
|
developersView.developers,
|
||||||
|
repositoriesView.repositories + if (publishToMavenCentralProperty) {
|
||||||
|
listOf(SonatypeRepository)
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
},
|
||||||
|
gpgSignProperty
|
||||||
|
)
|
||||||
|
set(value) {
|
||||||
|
projectNameProperty = value.name
|
||||||
|
projectDescriptionProperty = value.description
|
||||||
|
projectUrlProperty = value.url
|
||||||
|
projectVcsUrlProperty = value.vcsUrl
|
||||||
|
gpgSignProperty = if (value.includeGpgSigning) {
|
||||||
|
GpgSigning.Enabled
|
||||||
|
} else {
|
||||||
|
value.gpgSigning
|
||||||
|
}
|
||||||
|
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
|
||||||
|
developersView.developers = value.developers
|
||||||
|
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gpgSigningDrawer = GpgSigningOptionDrawerWithView(this)
|
||||||
|
|
||||||
|
override val content: @Composable () -> Unit = {
|
||||||
|
CommonText("Public project name")
|
||||||
|
CommonTextField(
|
||||||
|
projectNameProperty,
|
||||||
|
"\${project.name}",
|
||||||
|
) { projectNameProperty = it }
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
CommonText("Public project description")
|
||||||
|
CommonTextField(
|
||||||
|
projectDescriptionProperty,
|
||||||
|
"\${project.name}",
|
||||||
|
) { projectDescriptionProperty = it }
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
CommonText("Public project URL")
|
||||||
|
CommonTextField(
|
||||||
|
projectUrlProperty,
|
||||||
|
"Type url to github or other source with readme",
|
||||||
|
) { projectUrlProperty = it }
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
CommonText("Public project VCS URL (with .git)")
|
||||||
|
CommonTextField(
|
||||||
|
projectVcsUrlProperty,
|
||||||
|
"Type url to github .git file"
|
||||||
|
) { projectVcsUrlProperty = it }
|
||||||
|
|
||||||
|
ButtonsPanel(
|
||||||
|
"Gpg signing",
|
||||||
|
GpgSigning.Disabled,
|
||||||
|
GpgSigning.Optional,
|
||||||
|
GpgSigning.Enabled
|
||||||
|
) {
|
||||||
|
with(gpgSigningDrawer) {
|
||||||
|
with (it) {
|
||||||
|
draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitchWithLabel(
|
||||||
|
"Include publication to MavenCentral",
|
||||||
|
publishToMavenCentralProperty,
|
||||||
|
placeSwitchAtTheStart = true
|
||||||
|
) { publishToMavenCentralProperty = it }
|
||||||
|
developersView.build()
|
||||||
|
repositoriesView.build()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.JSProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.JVMProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MultiplatformProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
expect class ProjectTypeDrawer : Drawer<ProjectType>
|
||||||
|
expect fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer
|
||||||
|
|
||||||
|
class ProjectTypeView : VerticalView("Project type") {
|
||||||
|
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
|
||||||
|
private val typeDrawer = ProjectTypeDrawerWithView(this)
|
||||||
|
|
||||||
|
override val content: @Composable () -> Unit = {
|
||||||
|
ButtonsPanel(
|
||||||
|
"Project type",
|
||||||
|
MultiplatformProjectType,
|
||||||
|
JVMProjectType,
|
||||||
|
JSProjectType
|
||||||
|
) {
|
||||||
|
with(typeDrawer) {
|
||||||
|
with (it) {
|
||||||
|
draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
class RepositoryState(
|
||||||
|
name: String = "",
|
||||||
|
url: String = "",
|
||||||
|
credsType: MavenPublishingRepository.CredentialsType = MavenPublishingRepository.CredentialsType.UsernameAndPassword(name)
|
||||||
|
) {
|
||||||
|
var name: String by mutableStateOf(name)
|
||||||
|
var url: String by mutableStateOf(url)
|
||||||
|
var credsType by mutableStateOf(credsType)
|
||||||
|
|
||||||
|
fun toRepository() = MavenPublishingRepository(name, url, credsType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url, credsType)
|
||||||
|
|
||||||
|
expect class RepositoryCredentialTypeDrawer : Drawer<MavenPublishingRepository.CredentialsType>
|
||||||
|
expect fun RepositoryCredentialTypeDrawerWithState(repositoryState: RepositoryState): RepositoryCredentialTypeDrawer
|
||||||
|
|
||||||
|
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
||||||
|
var repositories: List<MavenPublishingRepository>
|
||||||
|
get() = itemsList.map { it.toRepository() }
|
||||||
|
set(value) {
|
||||||
|
itemsList.clear()
|
||||||
|
itemsList.addAll(
|
||||||
|
value.map { it.toRepositoryState() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val addItemText: String = "Add repository"
|
||||||
|
override val removeItemText: String = "Remove repository"
|
||||||
|
|
||||||
|
override fun createItem(): RepositoryState = RepositoryState()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun buildView(item: RepositoryState) {
|
||||||
|
val credsTypesDrawer = remember {
|
||||||
|
RepositoryCredentialTypeDrawerWithState(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonText("Repository name")
|
||||||
|
CommonTextField(
|
||||||
|
item.name,
|
||||||
|
"This name will be used to identify repository in gradle"
|
||||||
|
) {
|
||||||
|
val previous = item.name
|
||||||
|
item.name = it
|
||||||
|
when (val currentCredsType = item.credsType) {
|
||||||
|
is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> {
|
||||||
|
if (MavenPublishingRepository.CredentialsType.HttpHeaderCredentials.defaultValueProperty(previous) == currentCredsType.headerValueProperty) {
|
||||||
|
item.credsType = currentCredsType.copy(
|
||||||
|
headerValueProperty = MavenPublishingRepository.CredentialsType.HttpHeaderCredentials.defaultValueProperty(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MavenPublishingRepository.CredentialsType.Nothing -> {}
|
||||||
|
is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> {
|
||||||
|
var current: MavenPublishingRepository.CredentialsType.UsernameAndPassword = currentCredsType
|
||||||
|
if (MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultUsernameProperty(previous) == currentCredsType.usernameProperty) {
|
||||||
|
current = current.copy(
|
||||||
|
usernameProperty = MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultUsernameProperty(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultPasswordProperty(previous) == currentCredsType.passwordProperty) {
|
||||||
|
current = current.copy(
|
||||||
|
passwordProperty = MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultPasswordProperty(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
item.credsType = current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
CommonText("Repository url")
|
||||||
|
CommonTextField(
|
||||||
|
item.url,
|
||||||
|
"For example: https://repo.maven.apache.org/maven2/"
|
||||||
|
) { item.url = it }
|
||||||
|
|
||||||
|
ButtonsPanel(
|
||||||
|
"Credentials type",
|
||||||
|
MavenPublishingRepository.CredentialsType.Nothing.takeIf { item.credsType != it } ?: item.credsType,
|
||||||
|
MavenPublishingRepository.CredentialsType.UsernameAndPassword(item.name).takeIf { item.credsType !is MavenPublishingRepository.CredentialsType.UsernameAndPassword } ?: item.credsType,
|
||||||
|
MavenPublishingRepository.CredentialsType.HttpHeaderCredentials(
|
||||||
|
"Authorization",
|
||||||
|
MavenPublishingRepository.CredentialsType.HttpHeaderCredentials.defaultValueProperty(item.name)
|
||||||
|
).takeIf { item.credsType !is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials } ?: item.credsType,
|
||||||
|
) {
|
||||||
|
with(credsTypesDrawer) {
|
||||||
|
with(it) {
|
||||||
|
draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultContentColumn {
|
||||||
|
when (val credsType = item.credsType) {
|
||||||
|
is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> {
|
||||||
|
CommonText("Header name")
|
||||||
|
CommonTextField(credsType.headerName) {
|
||||||
|
item.credsType = credsType.copy(headerName = it)
|
||||||
|
}
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
|
||||||
|
CommonText("Property name")
|
||||||
|
CommonTextField(credsType.headerValueProperty) {
|
||||||
|
item.credsType = credsType.copy(headerValueProperty = it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MavenPublishingRepository.CredentialsType.Nothing -> {
|
||||||
|
CommonText("No parameters for absence of credentials")
|
||||||
|
}
|
||||||
|
is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> {
|
||||||
|
CommonText("Username property name")
|
||||||
|
CommonTextField(credsType.usernameProperty) {
|
||||||
|
item.credsType = credsType.copy(usernameProperty = it)
|
||||||
|
}
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
|
||||||
|
CommonText("Password property name")
|
||||||
|
CommonTextField(credsType.passwordProperty) {
|
||||||
|
item.credsType = credsType.copy(passwordProperty = it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
|
||||||
|
|
||||||
|
abstract class VerticalView(protected val title: String) : View() {
|
||||||
|
abstract val content: @Composable () -> Unit
|
||||||
|
@Composable
|
||||||
|
override fun build() {
|
||||||
|
DefaultContentColumn {
|
||||||
|
DrawVertically(title, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
expect abstract class View() {
|
||||||
|
@Composable
|
||||||
|
abstract fun build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun View.DrawVertically(title: String, block: @Composable () -> Unit)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T : View> T.init(): T = apply {
|
||||||
|
build()
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
fun interface Drawer<T> {
|
||||||
|
@Composable
|
||||||
|
fun T.draw()
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun TitleText(text: String)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun CommonText(text: String, onClick: (() -> Unit)? = null)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun CommonTextField(
|
||||||
|
presetText: String,
|
||||||
|
hint: String? = null,
|
||||||
|
onFocusChanged: (Boolean) -> Unit = {},
|
||||||
|
onChange: (String) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun SwitchWithLabel(
|
||||||
|
label: String,
|
||||||
|
checked: Boolean,
|
||||||
|
placeSwitchAtTheStart: Boolean = false,
|
||||||
|
switchEnabled: Boolean = true,
|
||||||
|
onCheckedChange: (Boolean) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun <T> ButtonsPanel(
|
||||||
|
title: String,
|
||||||
|
data: Iterable<T>,
|
||||||
|
itemDrawer: @Composable (T) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T> ButtonsPanel(
|
||||||
|
title: String,
|
||||||
|
vararg data: T,
|
||||||
|
itemDrawer: @Composable (T) -> Unit
|
||||||
|
) = ButtonsPanel(title, data.toList(), itemDrawer)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun DefaultDivider()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun DefaultSmallVerticalMargin()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun DefaultContentColumn(block: @Composable () -> Unit)
|
@ -0,0 +1,14 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
|
|
||||||
|
internal const val appExtension = "kpsb"
|
||||||
|
|
||||||
|
expect fun openNewConfig(onParsed: (Config) -> Unit)
|
||||||
|
|
||||||
|
expect fun saveConfig(config: Config): Boolean
|
||||||
|
|
||||||
|
expect fun exportGradle(config: Config): Boolean
|
||||||
|
|
||||||
|
expect fun saveAs(config: Config): Boolean
|
@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
expect fun openLink(link: String): Boolean
|
Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 452 B After Width: | Height: | Size: 452 B |
Before Width: | Height: | Size: 744 B After Width: | Height: | Size: 744 B |
Before Width: | Height: | Size: 502 B After Width: | Height: | Size: 502 B |
@ -0,0 +1,14 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core
|
||||||
|
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.BuilderView
|
||||||
|
import kotlinx.browser.window
|
||||||
|
import org.jetbrains.compose.web.renderComposableInBody
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
window.addEventListener("load", {
|
||||||
|
val builder = BuilderView()
|
||||||
|
renderComposableInBody {
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitTooltipModifier
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
|
||||||
|
|
||||||
|
actual class GpgSigningOptionDrawer(
|
||||||
|
private val mavenInfoView: MavenInfoView
|
||||||
|
) : Drawer<GpgSigning> {
|
||||||
|
@Composable
|
||||||
|
override fun GpgSigning.draw() {
|
||||||
|
val tooltipModifier = UIKitTooltipModifier(
|
||||||
|
when (this) {
|
||||||
|
GpgSigning.Disabled -> "Signing will not be added"
|
||||||
|
GpgSigning.Enabled -> "Signing will be always enabled"
|
||||||
|
GpgSigning.Optional -> "Signing will be added, but disabled in case of absence 'signatory.keyId'"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (mavenInfoView.gpgSignProperty == this) {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Primary, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded, tooltipModifier)
|
||||||
|
} else {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Default, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded, tooltipModifier) {
|
||||||
|
mavenInfoView.gpgSignProperty = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
|
@ -0,0 +1,37 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultButton
|
||||||
|
import dev.inmo.jsuikit.elements.Divider
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.jsuikit.modifiers.builder
|
||||||
|
import dev.inmo.jsuikit.utils.Attrs
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
|
||||||
|
import org.jetbrains.compose.web.dom.Div
|
||||||
|
|
||||||
|
actual object LicensesDrawer : Drawer<LicensesView> {
|
||||||
|
@Composable
|
||||||
|
override fun LicensesView.draw() {
|
||||||
|
dev.inmo.jsuikit.elements.List(
|
||||||
|
licensesOffersToShow.value,
|
||||||
|
Attrs {
|
||||||
|
if (!searchFieldFocused.value) {
|
||||||
|
hidden()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
DefaultButton(
|
||||||
|
it.title,
|
||||||
|
UIKitButton.Type.Text
|
||||||
|
) { _ ->
|
||||||
|
itemsList.add(it.toLicenseState())
|
||||||
|
licenseSearchFilter = ""
|
||||||
|
}
|
||||||
|
Divider.Common()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
|
||||||
|
|
||||||
|
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||||
|
@Composable
|
||||||
|
override fun ListView<T>.draw() {
|
||||||
|
itemsList.forEach { item ->
|
||||||
|
DefaultContentColumn {
|
||||||
|
buildView(item)
|
||||||
|
DefaultButton(removeItemText, UIKitButton.Type.Default, UIKitMargin.Small, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded) {
|
||||||
|
itemsList.remove(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefaultButton(addItemText, UIKitButton.Type.Primary, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded ) { itemsList.add(createItem()) }
|
||||||
|
}
|
||||||
|
if (itemsList.isEmpty()) {
|
||||||
|
DefaultButton(addItemText, UIKitButton.Type.Primary, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded ) { itemsList.add(createItem()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitText
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
|
||||||
|
|
||||||
|
actual class ProjectTypeDrawer(
|
||||||
|
private val projectTypeView: ProjectTypeView
|
||||||
|
) : Drawer<ProjectType> {
|
||||||
|
@Composable
|
||||||
|
override fun ProjectType.draw() {
|
||||||
|
if (projectTypeView.projectType == this) {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Primary, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded)
|
||||||
|
} else {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Default, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded) {
|
||||||
|
projectTypeView.projectType = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
|
@ -0,0 +1,32 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
|
||||||
|
|
||||||
|
actual class RepositoryCredentialTypeDrawer(
|
||||||
|
private val state: RepositoryState
|
||||||
|
) : Drawer<MavenPublishingRepository.CredentialsType> {
|
||||||
|
@Composable
|
||||||
|
override fun MavenPublishingRepository.CredentialsType.draw() {
|
||||||
|
val name = when (this@draw) {
|
||||||
|
is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> "Headers"
|
||||||
|
MavenPublishingRepository.CredentialsType.Nothing -> "No"
|
||||||
|
is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> "Username and password"
|
||||||
|
}
|
||||||
|
if (state.credsType == this) {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Primary, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded)
|
||||||
|
} else {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Default, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded) {
|
||||||
|
state.credsType = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun RepositoryCredentialTypeDrawerWithState(repositoryState: RepositoryState): RepositoryCredentialTypeDrawer = RepositoryCredentialTypeDrawer(repositoryState)
|
@ -0,0 +1,92 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.Icon
|
||||||
|
import dev.inmo.jsuikit.elements.NavItemElement
|
||||||
|
import dev.inmo.jsuikit.elements.Navbar
|
||||||
|
import dev.inmo.jsuikit.elements.NavbarNav
|
||||||
|
import dev.inmo.jsuikit.elements.drawAsLink
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitBackground
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitInverse
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitModifier
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitNavbar
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitPadding
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitSection
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitText
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitTooltipModifier
|
||||||
|
import dev.inmo.jsuikit.modifiers.attrsBuilder
|
||||||
|
import dev.inmo.jsuikit.modifiers.builder
|
||||||
|
import dev.inmo.jsuikit.modifiers.include
|
||||||
|
import dev.inmo.jsuikit.utils.AttrsWithContentBuilder
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.openNewConfig
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
|
||||||
|
import org.jetbrains.compose.web.dom.A
|
||||||
|
import org.jetbrains.compose.web.dom.Div
|
||||||
|
import org.jetbrains.compose.web.dom.Img
|
||||||
|
import org.jetbrains.compose.web.dom.Section
|
||||||
|
import org.jetbrains.compose.web.dom.Text
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun TopAppBar(
|
||||||
|
config: Config,
|
||||||
|
saveAvailable: Boolean,
|
||||||
|
onSaveAvailable: (Boolean) -> Unit,
|
||||||
|
onNewConfig: (Config) -> Unit
|
||||||
|
) {
|
||||||
|
Section(attrsBuilder(UIKitSection.Style.Primary, UIKitInverse.Light)) {
|
||||||
|
Navbar(
|
||||||
|
leftBuilder = AttrsWithContentBuilder {
|
||||||
|
Div(
|
||||||
|
{
|
||||||
|
onClick {
|
||||||
|
console.log(config)
|
||||||
|
}
|
||||||
|
include(UIKitPadding.Size.Small, UIKitText.Style.Lead)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Kotlin publication scripts builder")
|
||||||
|
}
|
||||||
|
Div(UIKitMargin.Small.builder()) {
|
||||||
|
A("https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder") {
|
||||||
|
Img("https://img.shields.io/github/stars/InsanusMokrassar/KotlinPublicationScriptsBuilder?label=Github&style=plastic")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rightBuilder = AttrsWithContentBuilder {
|
||||||
|
NavbarNav(
|
||||||
|
AttrsWithContentBuilder {
|
||||||
|
NavItemElement(
|
||||||
|
UIKitTooltipModifier("Open file")
|
||||||
|
) {
|
||||||
|
Icon.Storage.Pull.drawAsLink {
|
||||||
|
openNewConfig(onNewConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AttrsWithContentBuilder {
|
||||||
|
NavItemElement(
|
||||||
|
UIKitTooltipModifier("Save config")
|
||||||
|
) {
|
||||||
|
Icon.Storage.Push.drawAsLink {
|
||||||
|
saveConfig(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AttrsWithContentBuilder {
|
||||||
|
NavItemElement(
|
||||||
|
UIKitTooltipModifier("Export gradle script")
|
||||||
|
) {
|
||||||
|
Icon.Storage.Upload.drawAsLink {
|
||||||
|
exportGradle(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navModifiers = arrayOf(UIKitNavbar.Transparent)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitForm
|
||||||
|
import dev.inmo.jsuikit.modifiers.builder
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
import org.jetbrains.compose.web.dom.Legend
|
||||||
|
import org.jetbrains.compose.web.dom.Text
|
||||||
|
|
||||||
|
actual abstract class View {
|
||||||
|
@Composable
|
||||||
|
actual abstract fun build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun View.DrawVertically(title: String, block: @Composable () -> Unit) {
|
||||||
|
Legend(UIKitForm.Legend.builder()) {
|
||||||
|
Text(title)
|
||||||
|
}
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
block()
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultButton
|
||||||
|
import dev.inmo.jsuikit.elements.DefaultInput
|
||||||
|
import dev.inmo.jsuikit.elements.Divider
|
||||||
|
import dev.inmo.jsuikit.elements.Flex
|
||||||
|
import dev.inmo.jsuikit.elements.Icon
|
||||||
|
import dev.inmo.jsuikit.elements.drawAsFormInputPart
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitFlex
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitForm
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitInverse
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.jsuikit.modifiers.attrsBuilder
|
||||||
|
import dev.inmo.jsuikit.modifiers.builder
|
||||||
|
import dev.inmo.jsuikit.modifiers.include
|
||||||
|
import kotlinx.browser.window
|
||||||
|
import org.jetbrains.compose.web.attributes.InputType
|
||||||
|
import org.jetbrains.compose.web.dom.Div
|
||||||
|
import org.jetbrains.compose.web.dom.Legend
|
||||||
|
import org.jetbrains.compose.web.dom.Text
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun TitleText(text: String) {
|
||||||
|
Legend(UIKitForm.Legend.builder()) {
|
||||||
|
Text(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun CommonText(text: String, onClick: (() -> Unit)?) {
|
||||||
|
Div(
|
||||||
|
{
|
||||||
|
onClick ?.let {
|
||||||
|
this.onClick { _ ->
|
||||||
|
it()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun CommonTextField(
|
||||||
|
presetText: String,
|
||||||
|
hint: String?,
|
||||||
|
onFocusChanged: (Boolean) -> Unit,
|
||||||
|
onChange: (String) -> Unit
|
||||||
|
) {
|
||||||
|
DefaultInput(
|
||||||
|
InputType.Text,
|
||||||
|
presetText,
|
||||||
|
false,
|
||||||
|
placeholder = hint,
|
||||||
|
attributesCustomizer = {
|
||||||
|
onFocusIn { onFocusChanged(true) }
|
||||||
|
onFocusOut {
|
||||||
|
window.setTimeout( // avoid immediate hiding of potential interface data with additional delay
|
||||||
|
{ onFocusChanged(false) },
|
||||||
|
100
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChange = onChange
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun SwitchWithLabel(
|
||||||
|
label: String,
|
||||||
|
checked: Boolean,
|
||||||
|
placeSwitchAtTheStart: Boolean,
|
||||||
|
switchEnabled: Boolean,
|
||||||
|
onCheckedChange: (Boolean) -> Unit
|
||||||
|
) {
|
||||||
|
DefaultButton(
|
||||||
|
if (checked) {
|
||||||
|
UIKitButton.Type.Primary
|
||||||
|
} else {
|
||||||
|
UIKitButton.Type.Default
|
||||||
|
},
|
||||||
|
disabled = !switchEnabled,
|
||||||
|
onClick = {
|
||||||
|
onCheckedChange(!checked)
|
||||||
|
},
|
||||||
|
attributesCustomizer = {
|
||||||
|
include(UIKitUtility.Inline, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (checked) {
|
||||||
|
Icon.App.Check.drawAsFormInputPart(UIKitInverse.Light)
|
||||||
|
}
|
||||||
|
Text(label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun <T> ButtonsPanel(
|
||||||
|
title: String,
|
||||||
|
data: Iterable<T>,
|
||||||
|
itemDrawer: @Composable (T) -> Unit
|
||||||
|
) {
|
||||||
|
Flex(UIKitFlex.Alignment.Vertical.Middle, UIKitMargin.Small) {
|
||||||
|
Div(UIKitMargin.Small.Horizontal.builder()) { Text(title) }
|
||||||
|
data.forEach { itemDrawer(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultDivider() {
|
||||||
|
Divider.Common()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultSmallVerticalMargin() {
|
||||||
|
Div(UIKitMargin.Small.Top.builder())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultContentColumn(block: @Composable () -> Unit) {
|
||||||
|
Div(attrsBuilder(UIKitMargin.Small.Horizontal, UIKitMargin.Small.Vertical)) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitCustom
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
|
||||||
|
val ClassNoTransform = UIKitCustom(arrayOf("no-transform"))
|
||||||
|
|
||||||
|
val UIKitUtility.Companion.NoTransform
|
||||||
|
get() = ClassNoTransform
|
@ -0,0 +1,83 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.dom.appendElement
|
||||||
|
import org.w3c.dom.HTMLAnchorElement
|
||||||
|
import org.w3c.dom.HTMLInputElement
|
||||||
|
import org.w3c.dom.url.URL
|
||||||
|
import org.w3c.files.Blob
|
||||||
|
import org.w3c.files.BlobPropertyBag
|
||||||
|
import org.w3c.files.FileReader
|
||||||
|
import org.w3c.files.get
|
||||||
|
|
||||||
|
fun saveFile(content: String, filename: String) {
|
||||||
|
val a = document.body!!.appendElement("a") {
|
||||||
|
setAttribute("style", "visibility:hidden; display: none")
|
||||||
|
} as HTMLAnchorElement
|
||||||
|
val blob = Blob(arrayOf(content), BlobPropertyBag(
|
||||||
|
"application/*;charset=utf-8"
|
||||||
|
))
|
||||||
|
val url = URL.createObjectURL(blob)
|
||||||
|
a.href = url
|
||||||
|
a.download = filename
|
||||||
|
a.click()
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
a.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openNewConfig(onParsed: (Config) -> Unit) {
|
||||||
|
val targetInput = document.body!!.appendElement("input") {
|
||||||
|
setAttribute("style", "visibility:hidden; display: none")
|
||||||
|
} as HTMLInputElement
|
||||||
|
targetInput.type = "file"
|
||||||
|
targetInput.onchange = {
|
||||||
|
targetInput.files ?.also { files ->
|
||||||
|
for (i in (0 until files.length) ) {
|
||||||
|
files[i] ?.also { file ->
|
||||||
|
val reader = FileReader()
|
||||||
|
|
||||||
|
reader.onload = {
|
||||||
|
val content = it.target.asDynamic().result as String
|
||||||
|
onParsed(serialFormat.decodeFromString(Config.serializer(), content))
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsText(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetInput.click()
|
||||||
|
targetInput.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun saveConfig(config: Config): Boolean {
|
||||||
|
saveFile(
|
||||||
|
serialFormat.encodeToString(Config.serializer(), config),
|
||||||
|
"publish.kpsb"
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun exportGradle(config: Config): Boolean {
|
||||||
|
val filename = "publish.gradle"
|
||||||
|
|
||||||
|
val content = config.run {
|
||||||
|
type.buildMavenGradleConfig(
|
||||||
|
mavenConfig,
|
||||||
|
licenses
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFile(content, filename)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun saveAs(config: Config): Boolean {
|
||||||
|
saveFile(
|
||||||
|
serialFormat.encodeToString(Config.serializer(), config),
|
||||||
|
"publish.kpsb"
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
actual fun openLink(link: String): Boolean {
|
||||||
|
dev.inmo.micro_utils.common.openLink(link)
|
||||||
|
return true
|
||||||
|
}
|
4
core/src/jsMain/resources/css/internal.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.no-transform {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
1
core/src/jsMain/resources/css/uikit.min.css
vendored
Normal file
73
core/src/jsMain/resources/index.html
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Kotlin Publication Scripts Builder</title>
|
||||||
|
<!-- UIkit CSS -->
|
||||||
|
<link rel="stylesheet" href="./css/uikit.min.css" />
|
||||||
|
<link rel="stylesheet" href="./css/internal.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- <form class="uk-padding-small">-->
|
||||||
|
<!-- <fieldset class="uk-fieldset">-->
|
||||||
|
<!-- <legend class="uk-legend">Project type</legend>-->
|
||||||
|
<!-- <div class="uk-padding-small">-->
|
||||||
|
<!-- <ul class="uk-subnav uk-subnav-pill">-->
|
||||||
|
<!-- <li id="mppProjectType" class="uk-active"><a href="#">Multiplatform</a></li>-->
|
||||||
|
<!-- <li id="jvmProjectType"><a href="#">JVM</a></li>-->
|
||||||
|
<!-- <li id="jsProjectType"><a href="#">JS</a></li>-->
|
||||||
|
<!-- </ul>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <legend class="uk-legend">Licenses</legend>-->
|
||||||
|
<!-- <div id="licensesListDiv" class="uk-padding-small"></div>-->
|
||||||
|
|
||||||
|
<!-- <legend class="uk-legend">Project information</legend>-->
|
||||||
|
|
||||||
|
<!-- <div class="uk-padding-small">-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectNameInput">Public project name</label>-->
|
||||||
|
<!-- <input id="projectNameInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectDescriptionInput">Public project description</label>-->
|
||||||
|
<!-- <input id="projectDescriptionInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectUrlInput">Public project URL</label>-->
|
||||||
|
<!-- <input id="projectUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github or other source with readme">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectVCSUrlInput">Public project VCS URL (with .git)</label>-->
|
||||||
|
<!-- <input id="projectVCSUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github .git file">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="uk-margin">-->
|
||||||
|
<!-- <label>GPG Signing</label>-->
|
||||||
|
|
||||||
|
<!-- <div class="uk-padding-small">-->
|
||||||
|
<!-- <ul class="uk-subnav uk-subnav-pill">-->
|
||||||
|
<!-- <li id="disableGpgSigning" class="uk-active" uk-tooltip="title: Signing will not be added"><a href="#">Disabled</a></li>-->
|
||||||
|
<!-- <li id="optionalGpgSigning" uk-tooltip="title: Signing will be added, but disabled in case of absence 'signatory.keyId'"><a href="#">Optional</a></li>-->
|
||||||
|
<!-- <li id="enableGpgSigning" uk-tooltip="title: Signing will be always enabled"><a href="#">Enabled</a></li>-->
|
||||||
|
<!-- </ul>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin">-->
|
||||||
|
<!-- <label><input id="includeMavenCentralTargetRepoToggle" class="uk-checkbox" type="checkbox"> Include publication to MavenCentral</label>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <legend class="uk-legend">Developers info</legend>-->
|
||||||
|
<!-- <div id="developersListDiv" class="uk-padding-small"></div>-->
|
||||||
|
|
||||||
|
<!-- <legend class="uk-legend">Repositories info</legend>-->
|
||||||
|
<!-- <div id="repositoriesListDiv" class="uk-padding-small"></div>-->
|
||||||
|
<!-- </fieldset>-->
|
||||||
|
<!-- </form>-->
|
||||||
|
<!-- UIkit JS -->
|
||||||
|
<script src="./js/uikit.min.js"></script>
|
||||||
|
<script src="./js/uikit-icons.min.js"></script>
|
||||||
|
<!-- Internal JS -->
|
||||||
|
<script src="kmppscriptbuilder.core.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
core/src/jsMain/resources/js/uikit-icons.min.js
vendored
Normal file
1
core/src/jsMain/resources/js/uikit.min.js
vendored
Normal file
@ -1,4 +1,4 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop
|
package dev.inmo.kmppscriptbuilder.core
|
||||||
|
|
||||||
import androidx.compose.foundation.*
|
import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
@ -9,9 +9,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.window.Window
|
import androidx.compose.ui.window.Window
|
||||||
import androidx.compose.ui.window.application
|
import androidx.compose.ui.window.application
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.init
|
import dev.inmo.kmppscriptbuilder.core.ui.BuilderView
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.loadConfigFile
|
import dev.inmo.kmppscriptbuilder.core.utils.loadConfigFile
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.views.BuilderView
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
|
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
|
||||||
@ -48,7 +47,9 @@ fun main(args: Array<String>) = application {
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(stateVertical)
|
.verticalScroll(stateVertical)
|
||||||
) {
|
) {
|
||||||
builder.init()
|
Column {
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.TitleText
|
||||||
|
|
||||||
|
actual abstract class View {
|
||||||
|
internal open val defaultModifier = Modifier.fillMaxWidth()
|
||||||
|
@Composable
|
||||||
|
actual abstract fun build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun View.DrawVertically(
|
||||||
|
title: String,
|
||||||
|
block: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
TitleText(title)
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
|
||||||
|
Column(defaultModifier) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultSmallVerticalMargin()
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.OutlinedButton
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
|
||||||
|
|
||||||
|
actual class GpgSigningOptionDrawer(
|
||||||
|
private val mavenInfoView: MavenInfoView
|
||||||
|
) : Drawer<GpgSigning> {
|
||||||
|
@Composable
|
||||||
|
override fun GpgSigning.draw() {
|
||||||
|
if (mavenInfoView.gpgSignProperty == this) {
|
||||||
|
Button({}, Modifier.padding(8.dp, 0.dp)) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OutlinedButton(
|
||||||
|
{
|
||||||
|
mavenInfoView.gpgSignProperty = this
|
||||||
|
},
|
||||||
|
Modifier.padding(8.dp, 0.dp)
|
||||||
|
) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
|
@ -0,0 +1,31 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.Divider
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
actual object LicensesDrawer : Drawer<LicensesView> {
|
||||||
|
@Composable
|
||||||
|
override fun LicensesView.draw() {
|
||||||
|
if (searchFieldFocused.value) {
|
||||||
|
Column {
|
||||||
|
licensesOffersToShow.value.forEach {
|
||||||
|
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
|
||||||
|
CommonText(it.title) {
|
||||||
|
itemsList.add(it.toLicenseState())
|
||||||
|
licenseSearchFilter = ""
|
||||||
|
}
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.OutlinedButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||||
|
@Composable
|
||||||
|
override fun ListView<T>.draw() {
|
||||||
|
itemsList.forEach { item ->
|
||||||
|
DefaultContentColumn {
|
||||||
|
buildView(item)
|
||||||
|
OutlinedButton({ itemsList.remove(item) }, Modifier.padding(8.dp)) {
|
||||||
|
CommonText(removeItemText,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button({ itemsList.add(createItem()) }) {
|
||||||
|
CommonText(addItemText,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemsList.isEmpty()) {
|
||||||
|
Button({ itemsList.add(createItem()) }) {
|
||||||
|
CommonText(addItemText,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.OutlinedButton
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.JSProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.JVMProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MultiplatformProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
actual class ProjectTypeDrawer(
|
||||||
|
private val projectTypeView: ProjectTypeView
|
||||||
|
) : Drawer<ProjectType> {
|
||||||
|
@Composable
|
||||||
|
override fun ProjectType.draw() {
|
||||||
|
if (projectTypeView.projectType == this) {
|
||||||
|
Button({}, Modifier.padding(8.dp, 0.dp)) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OutlinedButton(
|
||||||
|
{
|
||||||
|
projectTypeView.projectType = this
|
||||||
|
},
|
||||||
|
Modifier.padding(8.dp, 0.dp)
|
||||||
|
) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
|
@ -0,0 +1,40 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.OutlinedButton
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
actual class RepositoryCredentialTypeDrawer(
|
||||||
|
private val state: RepositoryState
|
||||||
|
) : Drawer<MavenPublishingRepository.CredentialsType> {
|
||||||
|
@Composable
|
||||||
|
override fun MavenPublishingRepository.CredentialsType.draw() {
|
||||||
|
val name = when (this@draw) {
|
||||||
|
is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> "Headers"
|
||||||
|
MavenPublishingRepository.CredentialsType.Nothing -> "No"
|
||||||
|
is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> "Username and password"
|
||||||
|
}
|
||||||
|
if (state.credsType == this) {
|
||||||
|
Button({}, Modifier.padding(8.dp, 0.dp)) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OutlinedButton(
|
||||||
|
{
|
||||||
|
state.credsType = this
|
||||||
|
},
|
||||||
|
Modifier.padding(8.dp, 0.dp)
|
||||||
|
) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun RepositoryCredentialTypeDrawerWithState(repositoryState: RepositoryState): RepositoryCredentialTypeDrawer = RepositoryCredentialTypeDrawer(repositoryState)
|
@ -0,0 +1,88 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.TooltipArea
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.IconButton
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Surface
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.TopAppBar
|
||||||
|
import androidx.compose.material.primarySurface
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.openNewConfig
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.saveAs
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun createIcon(
|
||||||
|
tooltip: String,
|
||||||
|
resource: String,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
TooltipArea(
|
||||||
|
tooltip = {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.shadow(4.dp),
|
||||||
|
color = MaterialTheme.colors.primarySurface,
|
||||||
|
shape = RoundedCornerShape(4.dp)
|
||||||
|
) {
|
||||||
|
Text(tooltip, modifier = Modifier.padding(10.dp), color = MaterialTheme.colors.onPrimary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
IconButton(onClick) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(resource),
|
||||||
|
contentDescription = tooltip
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun TopAppBar(
|
||||||
|
config: Config,
|
||||||
|
saveAvailable: Boolean,
|
||||||
|
onSaveAvailable: (Boolean) -> Unit,
|
||||||
|
onNewConfig: (Config) -> Unit
|
||||||
|
) {
|
||||||
|
TopAppBar(
|
||||||
|
@Composable {
|
||||||
|
Text("Kotlin publication scripts builder", Modifier.clickable { println(config) })
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
createIcon("Open file", "images/open_file.svg") {
|
||||||
|
openNewConfig(onNewConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAvailable) {
|
||||||
|
createIcon("Save", "images/save_file.svg") {
|
||||||
|
saveConfig(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAvailable) {
|
||||||
|
createIcon("Export Gradle script", "images/export_gradle.svg") {
|
||||||
|
exportGradle(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createIcon("Save as", "images/save_as.svg") {
|
||||||
|
if (saveAs(config)) {
|
||||||
|
onSaveAvailable(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Divider
|
||||||
|
import androidx.compose.material.OutlinedTextField
|
||||||
|
import androidx.compose.material.Switch
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
|
||||||
|
val commonTextFieldTextStyle = TextStyle(
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun SwitchWithLabel(
|
||||||
|
label: String,
|
||||||
|
checked: Boolean,
|
||||||
|
placeSwitchAtTheStart: Boolean,
|
||||||
|
switchEnabled: Boolean,
|
||||||
|
onCheckedChange: (Boolean) -> Unit
|
||||||
|
) {
|
||||||
|
Row(Modifier.padding(0.dp, 8.dp).clickable { onCheckedChange(!checked) }, Arrangement.Start, Alignment.Top) {
|
||||||
|
val switchCreator = @Composable {
|
||||||
|
Switch(checked, null, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
|
||||||
|
}
|
||||||
|
if (placeSwitchAtTheStart) {
|
||||||
|
switchCreator()
|
||||||
|
}
|
||||||
|
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically)) {
|
||||||
|
CommonText(label)
|
||||||
|
}
|
||||||
|
if (!placeSwitchAtTheStart) {
|
||||||
|
switchCreator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun CommonTextField(
|
||||||
|
presetText: String,
|
||||||
|
hint: String?,
|
||||||
|
onFocusChanged: (Boolean) -> Unit,
|
||||||
|
onChange: (String) -> Unit
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
presetText,
|
||||||
|
onChange,
|
||||||
|
Modifier.fillMaxWidth().onFocusChanged {
|
||||||
|
onFocusChanged(it.isFocused)
|
||||||
|
},
|
||||||
|
singleLine = true,
|
||||||
|
label = hint ?.let {
|
||||||
|
{
|
||||||
|
CommonText(hint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun CommonText(text: String, onClick: (() -> Unit)?) {
|
||||||
|
Text(text, modifier = Modifier.run { onClick ?.let { clickable(onClick = it) } ?: this })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun TitleText(text: String) {
|
||||||
|
Text(
|
||||||
|
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun <T> ButtonsPanel(
|
||||||
|
title: String,
|
||||||
|
data: Iterable<T>,
|
||||||
|
itemDrawer: @Composable (T) -> Unit
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Text(title, Modifier.padding(8.dp))
|
||||||
|
data.forEach { itemDrawer(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultDivider() {
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultSmallVerticalMargin() {
|
||||||
|
Spacer(Modifier.padding(0.dp, 4.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultContentColumn(block: @Composable () -> Unit) {
|
||||||
|
Column(Modifier.padding(8.dp)) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.swing.filechooser.FileFilter
|
import javax.swing.filechooser.FileFilter
|
@ -1,40 +1,40 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
||||||
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.swing.JFileChooser
|
import javax.swing.JFileChooser
|
||||||
|
|
||||||
private const val appExtension = "kpsb"
|
fun MPPFile.text() = readText()
|
||||||
|
|
||||||
private var lastFile: File? = null
|
internal var lastFile: MPPFile? = null
|
||||||
|
|
||||||
fun loadConfigFile(file: File): Config {
|
fun loadConfigFile(file: MPPFile): Config {
|
||||||
lastFile = file
|
lastFile = file
|
||||||
return serialFormat.decodeFromString(Config.serializer(), file.readText())
|
return serialFormat.decodeFromString(Config.serializer(), file.text())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadConfig(): Config? {
|
actual fun openNewConfig(onParsed: (Config) -> Unit) {
|
||||||
val fc = JFileChooser(lastFile ?.parent)
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||||
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
||||||
return when (fc.showOpenDialog(null)) {
|
when (fc.showOpenDialog(null)) {
|
||||||
JFileChooser.APPROVE_OPTION -> {
|
JFileChooser.APPROVE_OPTION -> {
|
||||||
val file = fc.selectedFile
|
val file = fc.selectedFile
|
||||||
lastFile = file
|
lastFile = file
|
||||||
return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
|
onParsed(serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText()))
|
||||||
}
|
}
|
||||||
else -> null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveConfig(config: Config): Boolean {
|
actual fun saveConfig(config: Config): Boolean {
|
||||||
return lastFile ?.also {
|
return lastFile ?.also {
|
||||||
it.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
it.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
||||||
} != null
|
} != null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportGradle(config: Config): Boolean {
|
actual fun exportGradle(config: Config): Boolean {
|
||||||
val fc = JFileChooser(lastFile ?.parent)
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
||||||
return when (fc.showSaveDialog(null)) {
|
return when (fc.showSaveDialog(null)) {
|
||||||
@ -55,7 +55,7 @@ fun exportGradle(config: Config): Boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveAs(config: Config): Boolean {
|
actual fun saveAs(config: Config): Boolean {
|
||||||
val fc = JFileChooser(lastFile ?.parent)
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||||
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
@ -1,9 +1,9 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
fun openLink(link: String): Boolean {
|
actual fun openLink(link: String): Boolean {
|
||||||
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
|
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
|
||||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||||
try {
|
try {
|
@ -0,0 +1,2 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
<manifest package="dev.inmo.KotlinPublicationScriptsBuilder.core"/>
|
|
@ -1,40 +0,0 @@
|
|||||||
apply plugin: 'com.getkeepsafe.dexcount'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion "$android_compileSdkVersion".toInteger()
|
|
||||||
buildToolsVersion "$android_buildToolsVersion"
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion "$android_minSdkVersion".toInteger()
|
|
||||||
targetSdkVersion "$android_compileSdkVersion".toInteger()
|
|
||||||
versionCode "${android_code_version}".toInteger()
|
|
||||||
versionName "$version"
|
|
||||||
}
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
}
|
|
||||||
debug {
|
|
||||||
debuggable true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
packagingOptions {
|
|
||||||
exclude 'META-INF/kotlinx-serialization-runtime.kotlin_module'
|
|
||||||
exclude 'META-INF/kotlinx-serialization-cbor.kotlin_module'
|
|
||||||
exclude 'META-INF/kotlinx-serialization-properties.kotlin_module'
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
|
||||||
id("org.jetbrains.compose") version "$compose_version"
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$mppJavaProjectPresetPath"
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvm {
|
|
||||||
compilations.main.kotlinOptions {
|
|
||||||
jvmTarget = "11"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
implementation project(":kmppscriptbuilder.core")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jvmMain {
|
|
||||||
dependencies {
|
|
||||||
implementation(compose.desktop.currentOs)
|
|
||||||
api "io.ktor:ktor-client-cio:$ktor_version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compose.desktop {
|
|
||||||
application {
|
|
||||||
mainClass = "dev.inmo.kmppscriptbuilder.desktop.BuilderKt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.material.*
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
|
|
||||||
val commonTextFieldTextStyle = TextStyle(
|
|
||||||
fontSize = 12.sp
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
inline fun TitleText(text: String) = Text(
|
|
||||||
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
inline fun CommonText(text: String, modifier: Modifier = Modifier) = Text(
|
|
||||||
text, modifier = modifier
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
inline fun CommonTextField(presetText: String, hint: String, noinline onChange: (String) -> Unit) = OutlinedTextField(
|
|
||||||
presetText,
|
|
||||||
onChange,
|
|
||||||
Modifier.fillMaxWidth(),
|
|
||||||
singleLine = true,
|
|
||||||
label = {
|
|
||||||
CommonText(hint)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
inline fun SwitchWithLabel(
|
|
||||||
label: String,
|
|
||||||
checked: Boolean,
|
|
||||||
placeSwitchAtTheStart: Boolean = false,
|
|
||||||
switchEnabled: Boolean = true,
|
|
||||||
modifier: Modifier = Modifier.padding(0.dp, 8.dp),
|
|
||||||
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
|
||||||
verticalAlignment: Alignment.Vertical = Alignment.Top,
|
|
||||||
switchModifier: Modifier = Modifier.padding(8.dp, 0.dp),
|
|
||||||
noinline onCheckedChange: (Boolean) -> Unit
|
|
||||||
) = Row(modifier, horizontalArrangement, verticalAlignment) {
|
|
||||||
val switchCreator = @Composable {
|
|
||||||
Switch(checked, onCheckedChange, switchModifier, enabled = switchEnabled)
|
|
||||||
}
|
|
||||||
if (placeSwitchAtTheStart) {
|
|
||||||
switchCreator()
|
|
||||||
}
|
|
||||||
CommonText(label, Modifier.align(Alignment.CenterVertically).clickable { })
|
|
||||||
if (!placeSwitchAtTheStart) {
|
|
||||||
switchCreator()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
|
|
||||||
abstract class View {
|
|
||||||
protected open val defaultModifier = Modifier.fillMaxWidth().padding(8.dp)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
abstract fun build()
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class VerticalView(val title: String) : View() {
|
|
||||||
abstract val content: @Composable ColumnScope.() -> Unit
|
|
||||||
@Composable
|
|
||||||
override fun build() {
|
|
||||||
TitleText(title)
|
|
||||||
|
|
||||||
Column(
|
|
||||||
defaultModifier
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(Modifier.fillMaxWidth().height(8.dp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun <T : View> T.init(): T = apply {
|
|
||||||
build()
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.foundation.*
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.*
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
|
|
||||||
|
|
||||||
class BuilderView : View() {
|
|
||||||
private val projectTypeView = ProjectTypeView()
|
|
||||||
private val mavenInfoView = MavenInfoView()
|
|
||||||
private val licensesView = LicensesView()
|
|
||||||
private var saveAvailableState by mutableStateOf(false)
|
|
||||||
|
|
||||||
override val defaultModifier: Modifier = Modifier.fillMaxSize()
|
|
||||||
|
|
||||||
var config: Config
|
|
||||||
get() = Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
|
||||||
set(value) {
|
|
||||||
licensesView.licenses = value.licenses
|
|
||||||
mavenInfoView.mavenConfig = value.mavenConfig
|
|
||||||
projectTypeView.projectType = value.type
|
|
||||||
saveAvailableState = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
private fun createIcon(
|
|
||||||
tooltip: String,
|
|
||||||
resource: String,
|
|
||||||
onClick: () -> Unit
|
|
||||||
) {
|
|
||||||
TooltipArea(
|
|
||||||
tooltip = {
|
|
||||||
Surface(
|
|
||||||
modifier = Modifier.shadow(4.dp),
|
|
||||||
color = MaterialTheme.colors.primarySurface,
|
|
||||||
shape = RoundedCornerShape(4.dp)
|
|
||||||
) {
|
|
||||||
Text(tooltip, modifier = Modifier.padding(10.dp), color = MaterialTheme.colors.onPrimary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
IconButton(onClick) {
|
|
||||||
Image(
|
|
||||||
painter = painterResource(resource),
|
|
||||||
contentDescription = tooltip
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
override fun build() {
|
|
||||||
Box(Modifier.fillMaxSize()) {
|
|
||||||
Column() {
|
|
||||||
TopAppBar(
|
|
||||||
@Composable {
|
|
||||||
CommonText("Kotlin publication scripts builder", Modifier.clickable { println(config) })
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
createIcon("Open file", "images/open_file.svg") {
|
|
||||||
loadConfig()?.also {
|
|
||||||
config = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saveAvailableState) {
|
|
||||||
createIcon("Save", "images/save_file.svg") {
|
|
||||||
saveConfig(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saveAvailableState) {
|
|
||||||
createIcon("Export Gradle script", "images/export_gradle.svg") {
|
|
||||||
exportGradle(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createIcon("Save as", "images/save_as.svg") {
|
|
||||||
if (saveAs(config)) {
|
|
||||||
saveAvailableState = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Column(Modifier.padding(8.dp)) {
|
|
||||||
projectTypeView.init()
|
|
||||||
Divider()
|
|
||||||
licensesView.init()
|
|
||||||
Divider()
|
|
||||||
mavenInfoView.init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.material.Button
|
|
||||||
import androidx.compose.material.Divider
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.License
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
|
|
||||||
private class LicenseState(
|
|
||||||
id: String = "",
|
|
||||||
title: String = "",
|
|
||||||
url: String? = null
|
|
||||||
) {
|
|
||||||
var id: String by mutableStateOf(id)
|
|
||||||
var title: String by mutableStateOf(title)
|
|
||||||
var url: String? by mutableStateOf(url)
|
|
||||||
|
|
||||||
fun toLicense() = License(id, title, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun License.toLicenseState() = LicenseState(id, title, url)
|
|
||||||
|
|
||||||
class LicensesView: VerticalView("Licenses") {
|
|
||||||
private var licensesListState = mutableStateListOf<LicenseState>()
|
|
||||||
var licenses: List<License>
|
|
||||||
get() = licensesListState.map { it.toLicense() }
|
|
||||||
set(value) {
|
|
||||||
licensesListState.clear()
|
|
||||||
licensesListState.addAll(value.map { it.toLicenseState() })
|
|
||||||
}
|
|
||||||
private val availableLicensesState = mutableStateListOf<License>()
|
|
||||||
private val licensesOffersToShow = mutableStateListOf<License>()
|
|
||||||
private var licenseSearchFilter by mutableStateOf("")
|
|
||||||
|
|
||||||
init {
|
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
|
||||||
val client = HttpClient()
|
|
||||||
availableLicensesState.addAll(client.getLicenses().values)
|
|
||||||
client.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val content: @Composable ColumnScope.() -> Unit = {
|
|
||||||
CommonTextField(licenseSearchFilter, "Search filter") { filterText ->
|
|
||||||
licenseSearchFilter = filterText
|
|
||||||
licensesOffersToShow.clear()
|
|
||||||
if (licenseSearchFilter.isNotEmpty()) {
|
|
||||||
licensesOffersToShow.addAll(
|
|
||||||
availableLicensesState.filter { filterText.all { symbol -> symbol.lowercaseChar() in it.title } }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Column {
|
|
||||||
licensesOffersToShow.forEach {
|
|
||||||
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
|
|
||||||
CommonText(it.title, Modifier.clickable {
|
|
||||||
licensesListState.add(it.toLicenseState())
|
|
||||||
licenseSearchFilter = ""
|
|
||||||
licensesOffersToShow.clear()
|
|
||||||
})
|
|
||||||
Divider()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
|
|
||||||
CommonText("Add empty license")
|
|
||||||
}
|
|
||||||
licensesListState.forEach { license ->
|
|
||||||
Column(Modifier.padding(8.dp)) {
|
|
||||||
CommonTextField(
|
|
||||||
license.id,
|
|
||||||
"License ID"
|
|
||||||
) { license.id = it }
|
|
||||||
CommonTextField(
|
|
||||||
license.title,
|
|
||||||
"License title"
|
|
||||||
) { license.title = it }
|
|
||||||
CommonTextField(
|
|
||||||
license.url ?: "",
|
|
||||||
"License URL"
|
|
||||||
) { license.url = it }
|
|
||||||
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
|
|
||||||
CommonText("Remove")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.material.Button
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonText
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.VerticalView
|
|
||||||
|
|
||||||
abstract class ListView<T>(title: String) : VerticalView(title) {
|
|
||||||
protected val itemsList = mutableStateListOf<T>()
|
|
||||||
|
|
||||||
protected open val addItemText: String = "Add"
|
|
||||||
protected open val removeItemText: String = "Remove"
|
|
||||||
|
|
||||||
protected abstract fun createItem(): T
|
|
||||||
@Composable
|
|
||||||
protected abstract fun buildView(item: T)
|
|
||||||
|
|
||||||
override val content: @Composable ColumnScope.() -> Unit = {
|
|
||||||
Button({ itemsList.add(createItem()) }) {
|
|
||||||
CommonText(addItemText)
|
|
||||||
}
|
|
||||||
itemsList.forEach { item ->
|
|
||||||
Column(Modifier.padding(8.dp)) {
|
|
||||||
buildView(item)
|
|
||||||
Button({ itemsList.remove(item) }, Modifier.padding(8.dp)) {
|
|
||||||
CommonText(removeItemText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.material.*
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.layout.VerticalAlignmentLine
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
|
|
||||||
|
|
||||||
class MavenInfoView : VerticalView("Project information") {
|
|
||||||
private var projectNameProperty by mutableStateOf("")
|
|
||||||
private var projectDescriptionProperty by mutableStateOf("")
|
|
||||||
private var projectUrlProperty by mutableStateOf("")
|
|
||||||
private var projectVcsUrlProperty by mutableStateOf("")
|
|
||||||
private var gpgSignProperty by mutableStateOf<GpgSigning>(GpgSigning.Disabled)
|
|
||||||
private var publishToMavenCentralProperty by mutableStateOf(false)
|
|
||||||
private val developersView = DevelopersView()
|
|
||||||
private val repositoriesView = RepositoriesView()
|
|
||||||
|
|
||||||
var mavenConfig: MavenConfig
|
|
||||||
get() = MavenConfig(
|
|
||||||
projectNameProperty.ifBlank { defaultProjectName },
|
|
||||||
projectDescriptionProperty.ifBlank { defaultProjectDescription },
|
|
||||||
projectUrlProperty,
|
|
||||||
projectVcsUrlProperty,
|
|
||||||
developersView.developers,
|
|
||||||
repositoriesView.repositories + if (publishToMavenCentralProperty) {
|
|
||||||
listOf(SonatypeRepository)
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
},
|
|
||||||
gpgSignProperty
|
|
||||||
)
|
|
||||||
set(value) {
|
|
||||||
projectNameProperty = value.name
|
|
||||||
projectDescriptionProperty = value.description
|
|
||||||
projectUrlProperty = value.url
|
|
||||||
projectVcsUrlProperty = value.vcsUrl
|
|
||||||
gpgSignProperty = if (value.includeGpgSigning) {
|
|
||||||
GpgSigning.Enabled
|
|
||||||
} else {
|
|
||||||
value.gpgSigning
|
|
||||||
}
|
|
||||||
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
|
|
||||||
developersView.developers = value.developers
|
|
||||||
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
|
|
||||||
// developersView.developers = value.developers
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun addGpgSigningButton(gpgSigning: GpgSigning) {
|
|
||||||
if (gpgSignProperty == gpgSigning) {
|
|
||||||
Button({}, Modifier.padding(8.dp)) {
|
|
||||||
Text(gpgSigning.name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OutlinedButton(
|
|
||||||
{
|
|
||||||
gpgSignProperty = gpgSigning
|
|
||||||
},
|
|
||||||
Modifier.padding(8.dp)
|
|
||||||
) {
|
|
||||||
Text(gpgSigning.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val content: @Composable ColumnScope.() -> Unit = {
|
|
||||||
CommonTextField(
|
|
||||||
projectNameProperty,
|
|
||||||
"Public project name"
|
|
||||||
) { projectNameProperty = it }
|
|
||||||
CommonTextField(
|
|
||||||
projectDescriptionProperty,
|
|
||||||
"Public project description"
|
|
||||||
) { projectDescriptionProperty = it }
|
|
||||||
CommonTextField(
|
|
||||||
projectUrlProperty,
|
|
||||||
"Public project URL"
|
|
||||||
) { projectUrlProperty = it }
|
|
||||||
CommonTextField(
|
|
||||||
projectVcsUrlProperty,
|
|
||||||
"Public project VCS URL (with .git)"
|
|
||||||
) { projectVcsUrlProperty = it }
|
|
||||||
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
Text("Gpg Signing: ")
|
|
||||||
addGpgSigningButton(GpgSigning.Disabled)
|
|
||||||
addGpgSigningButton(GpgSigning.Optional)
|
|
||||||
addGpgSigningButton(GpgSigning.Enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitchWithLabel(
|
|
||||||
"Include publication to MavenCentral",
|
|
||||||
publishToMavenCentralProperty,
|
|
||||||
placeSwitchAtTheStart = true
|
|
||||||
) { publishToMavenCentralProperty = it }
|
|
||||||
developersView.init()
|
|
||||||
repositoriesView.init()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.material.*
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.VerticalView
|
|
||||||
|
|
||||||
class ProjectTypeView : VerticalView("Project type") {
|
|
||||||
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun addProjectTypeButton(newProjectType: ProjectType) {
|
|
||||||
if (projectType == newProjectType) {
|
|
||||||
Button({}, Modifier.padding(8.dp)) {
|
|
||||||
Text(newProjectType.name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OutlinedButton(
|
|
||||||
{
|
|
||||||
projectType = newProjectType
|
|
||||||
},
|
|
||||||
Modifier.padding(8.dp)
|
|
||||||
) {
|
|
||||||
Text(newProjectType.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val content: @Composable ColumnScope.() -> Unit = {
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
addProjectTypeButton(MultiplatformProjectType)
|
|
||||||
addProjectTypeButton(JVMProjectType)
|
|
||||||
addProjectTypeButton(JSProjectType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
|
|
||||||
|
|
||||||
class RepositoryState(
|
|
||||||
name: String = "",
|
|
||||||
url: String = ""
|
|
||||||
) {
|
|
||||||
var name: String by mutableStateOf(name)
|
|
||||||
var url: String by mutableStateOf(url)
|
|
||||||
|
|
||||||
fun toRepository() = MavenPublishingRepository(name, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url)
|
|
||||||
|
|
||||||
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
|
||||||
var repositories: List<MavenPublishingRepository>
|
|
||||||
get() = itemsList.map { it.toRepository() }
|
|
||||||
set(value) {
|
|
||||||
itemsList.clear()
|
|
||||||
itemsList.addAll(
|
|
||||||
value.map { it.toRepositoryState() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val addItemText: String = "Add repository"
|
|
||||||
override val removeItemText: String = "Remove repository"
|
|
||||||
|
|
||||||
override fun createItem(): RepositoryState = RepositoryState()
|
|
||||||
@Composable
|
|
||||||
override fun buildView(item: RepositoryState) {
|
|
||||||
CommonTextField(
|
|
||||||
item.name,
|
|
||||||
"Repository name"
|
|
||||||
) { item.name = it }
|
|
||||||
CommonTextField(
|
|
||||||
item.url,
|
|
||||||
"Repository url"
|
|
||||||
) { item.url = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ allprojects {
|
|||||||
mppProjectWithSerializationPresetPath = "${rootProject.projectDir.absolutePath}/mppProjectWithSerialization.gradle"
|
mppProjectWithSerializationPresetPath = "${rootProject.projectDir.absolutePath}/mppProjectWithSerialization.gradle"
|
||||||
mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
|
mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
|
||||||
mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"
|
mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"
|
||||||
mppAndroidProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppAndroidProject.gradle"
|
|
||||||
|
|
||||||
defaultAndroidSettingsPresetPath = "${rootProject.projectDir.absolutePath}/defaultAndroidSettings.gradle"
|
defaultAndroidSettingsPresetPath = "${rootProject.projectDir.absolutePath}/defaultAndroidSettings.gradle"
|
||||||
|
|
||||||
|
@ -3,30 +3,18 @@ org.gradle.parallel=true
|
|||||||
kotlin.js.generate.externals=true
|
kotlin.js.generate.externals=true
|
||||||
kotlin.incremental=true
|
kotlin.incremental=true
|
||||||
kotlin.incremental.js=true
|
kotlin.incremental.js=true
|
||||||
android.useAndroidX=true
|
|
||||||
android.enableJetifier=true
|
|
||||||
|
|
||||||
kotlin_version=1.6.10
|
kotlin_version=1.7.20
|
||||||
kotlin_coroutines_version=1.6.0
|
kotlin_coroutines_version=1.6.4
|
||||||
kotlin_serialisation_core_version=1.3.2
|
kotlin_serialisation_core_version=1.4.1
|
||||||
ktor_version=1.6.7
|
ktor_version=2.1.3
|
||||||
micro_utils_version=0.9.0
|
micro_utils_version=0.14.2
|
||||||
|
|
||||||
compose_version=1.0.1
|
compose_version=1.2.1
|
||||||
|
|
||||||
# ANDROID
|
|
||||||
|
|
||||||
android_minSdkVersion=21
|
|
||||||
android_compileSdkVersion=32
|
|
||||||
android_buildToolsVersion=32.0.0
|
|
||||||
dexcount_version=3.0.1
|
|
||||||
junit_version=4.12
|
|
||||||
test_ext_junit_version=1.1.2
|
|
||||||
espresso_core=3.3.0
|
|
||||||
|
|
||||||
# Dokka
|
# Dokka
|
||||||
|
|
||||||
dokka_version=1.6.0
|
dokka_version=1.7.20
|
||||||
|
|
||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
|
45
gradle/libs.versions.toml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
[versions]
|
||||||
|
|
||||||
|
kt = "1.7.20"
|
||||||
|
kt-serialization = "1.4.1"
|
||||||
|
kt-coroutines = "1.6.4"
|
||||||
|
|
||||||
|
jb-compose = "1.2.1"
|
||||||
|
jb-dokka = "1.7.20"
|
||||||
|
microutils = "0.14.2"
|
||||||
|
kjsuikit = "0.4.1"
|
||||||
|
|
||||||
|
ktor = "2.1.3"
|
||||||
|
|
||||||
|
gh-release = "2.4.1"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
|
||||||
|
kt-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kt" }
|
||||||
|
|
||||||
|
kt-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kt-serialization" }
|
||||||
|
|
||||||
|
kt-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kt-coroutines" }
|
||||||
|
|
||||||
|
ktor-client = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
||||||
|
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
|
||||||
|
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
|
||||||
|
|
||||||
|
microutils-common = { module = "dev.inmo:micro_utils.common", version.ref = "microutils" }
|
||||||
|
microutils-coroutines = { module = "dev.inmo:micro_utils.coroutines", version.ref = "microutils" }
|
||||||
|
|
||||||
|
jsuikit = { module = "dev.inmo:kjsuikit", version.ref = "kjsuikit" }
|
||||||
|
|
||||||
|
|
||||||
|
kt-test-js = { module = "org.jetbrains.kotlin:kotlin-test-js", version.ref = "kt" }
|
||||||
|
kt-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kt" }
|
||||||
|
|
||||||
|
|
||||||
|
buildscript-kt-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kt" }
|
||||||
|
buildscript-kt-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kt" }
|
||||||
|
buildscript-jb-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "jb-dokka" }
|
||||||
|
buildscript-gh-release = { module = "com.github.breadmoirai:github-release", version.ref = "gh-release" }
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
|
||||||
|
jb-compose = { id = "org.jetbrains.compose", version.ref = "jb-compose" }
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
|
@ -4,9 +4,7 @@ project.group = "$group"
|
|||||||
// apply from: "$publishGradlePath"
|
// apply from: "$publishGradlePath"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm {
|
jvm()
|
||||||
compilations.main.kotlinOptions.useIR = true
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
|
@ -5,10 +5,8 @@ project.group = "$group"
|
|||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
js (IR) {
|
js (IR) {
|
||||||
browser {
|
browser()
|
||||||
binaries.executable()
|
binaries.executable()
|
||||||
}
|
|
||||||
nodejs()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
@ -4,16 +4,11 @@ project.group = "$group"
|
|||||||
// apply from: "$publishGradlePath"
|
// apply from: "$publishGradlePath"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm {
|
jvm()
|
||||||
compilations.main.kotlinOptions.useIR = true
|
|
||||||
}
|
|
||||||
js (IR) {
|
js (IR) {
|
||||||
browser()
|
browser()
|
||||||
nodejs()
|
nodejs()
|
||||||
}
|
}
|
||||||
android {
|
|
||||||
publishAllLibraryVariants()
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
@ -39,14 +34,5 @@ kotlin {
|
|||||||
implementation kotlin('test-junit')
|
implementation kotlin('test-junit')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
androidTest {
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin('test-junit')
|
|
||||||
implementation "androidx.test.ext:junit:$test_ext_junit_version"
|
|
||||||
implementation "androidx.test.espresso:espresso-core:$espresso_core"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$defaultAndroidSettingsPresetPath"
|
|
||||||
|
@ -9,8 +9,8 @@ rootProject.name = 'kmppscriptbuilder'
|
|||||||
|
|
||||||
String[] includes = [
|
String[] includes = [
|
||||||
":core",
|
":core",
|
||||||
":desktop",
|
// ":desktop",
|
||||||
":web"
|
// ":web"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$mppJsProjectPresetPath"
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
implementation project(":kmppscriptbuilder.core")
|
|
||||||
implementation "dev.inmo:micro_utils.common:$micro_utils_version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.views.*
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.*
|
|
||||||
import org.w3c.dom.url.URL
|
|
||||||
import org.w3c.files.*
|
|
||||||
|
|
||||||
fun saveFile(content: String, filename: String) {
|
|
||||||
val a = document.body!!.appendElement("a") {
|
|
||||||
setAttribute("style", "visibility:hidden; display: none")
|
|
||||||
} as HTMLAnchorElement
|
|
||||||
val blob = Blob(arrayOf(content), BlobPropertyBag(
|
|
||||||
"application/*;charset=utf-8"
|
|
||||||
))
|
|
||||||
val url = URL.createObjectURL(blob)
|
|
||||||
a.href = url
|
|
||||||
a.download = filename
|
|
||||||
a.click()
|
|
||||||
URL.revokeObjectURL(url)
|
|
||||||
a.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
document.addEventListener(
|
|
||||||
"DOMContentLoaded",
|
|
||||||
{
|
|
||||||
val builderView = BuilderView()
|
|
||||||
|
|
||||||
(document.getElementById("openConfig") as HTMLElement).onclick = {
|
|
||||||
val targetInput = document.body!!.appendElement("input") {
|
|
||||||
setAttribute("style", "visibility:hidden; display: none")
|
|
||||||
} as HTMLInputElement
|
|
||||||
targetInput.type = "file"
|
|
||||||
targetInput.onchange = {
|
|
||||||
targetInput.files ?.also { files ->
|
|
||||||
for (i in (0 until files.length) ) {
|
|
||||||
files[i] ?.also { file ->
|
|
||||||
val reader = FileReader()
|
|
||||||
|
|
||||||
reader.onload = {
|
|
||||||
val content = it.target.asDynamic().result as String
|
|
||||||
builderView.config = serialFormat.decodeFromString(Config.serializer(), content)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.readAsText(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
targetInput.click()
|
|
||||||
targetInput.remove()
|
|
||||||
false
|
|
||||||
}
|
|
||||||
(document.getElementById("saveConfig") as HTMLElement).onclick = {
|
|
||||||
val filename = "publish.kpsb"
|
|
||||||
val content = serialFormat.encodeToString(Config.serializer(), builderView.config)
|
|
||||||
|
|
||||||
saveFile(content, filename)
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
(document.getElementById("exportScript") as HTMLElement).onclick = {
|
|
||||||
val filename = "publish.gradle"
|
|
||||||
|
|
||||||
val content = builderView.config.run {
|
|
||||||
type.buildMavenGradleConfig(
|
|
||||||
mavenConfig,
|
|
||||||
licenses
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
saveFile(content, filename)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.utils
|
|
||||||
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
var HTMLElement.ukActive: Boolean
|
|
||||||
get() = classList.contains("uk-active")
|
|
||||||
set(value) {
|
|
||||||
if (value) {
|
|
||||||
classList.add("uk-active")
|
|
||||||
} else {
|
|
||||||
classList.remove("uk-active")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.utils
|
|
||||||
|
|
||||||
import kotlinx.browser.document
|
|
||||||
|
|
||||||
inline fun <R> keepScrolling(crossinline block: () -> R): R = document.body ?.let {
|
|
||||||
val (x, y) = (it.scrollLeft to it.scrollTop)
|
|
||||||
return block().also { _ ->
|
|
||||||
it.scrollTo(x, y)
|
|
||||||
}
|
|
||||||
} ?: block()
|
|
@ -1,23 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
class BuilderView : View {
|
|
||||||
private val projectTypeView = ProjectTypeView()
|
|
||||||
private val licensesView = LicensesView(document.getElementById("licensesListDiv") as HTMLElement)
|
|
||||||
private val mavenInfoTypeView = MavenProjectInfoView()
|
|
||||||
|
|
||||||
var config: Config
|
|
||||||
get() = Config(
|
|
||||||
licensesView.licenses,
|
|
||||||
mavenInfoTypeView.mavenConfig,
|
|
||||||
projectTypeView.projectType
|
|
||||||
)
|
|
||||||
set(value) {
|
|
||||||
licensesView.licenses = value.licenses
|
|
||||||
mavenInfoTypeView.mavenConfig = value.mavenConfig
|
|
||||||
projectTypeView.projectType = value.type
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
class DevelopersView(rootElement: HTMLElement) : MutableListView<Developer>(rootElement, "Add developer", "Remove developer") {
|
|
||||||
private val HTMLElement.usernameElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[0] as HTMLInputElement
|
|
||||||
private val HTMLElement.nameElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[1] as HTMLInputElement
|
|
||||||
private val HTMLElement.emailElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[2] as HTMLInputElement
|
|
||||||
|
|
||||||
var developers: List<Developer>
|
|
||||||
get() = elements.map {
|
|
||||||
Developer(it.usernameElement.value, it.nameElement.value, it.emailElement.value)
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
data = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPlainObject(): Developer = Developer("", "", "")
|
|
||||||
|
|
||||||
override fun HTMLElement.addContentBeforeRemoveButton(value: Developer) {
|
|
||||||
createTextField("Developer ID", "Developer username").value = value.id
|
|
||||||
createTextField("Developer name", "").value = value.name
|
|
||||||
createTextField("Developer E-Mail", "").value = value.eMail
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: Developer, to: Developer) {
|
|
||||||
usernameElement.value = to.id
|
|
||||||
nameElement.value = to.name
|
|
||||||
emailElement.value = to.eMail
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.License
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
|
||||||
import dev.inmo.micro_utils.coroutines.safeActor
|
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.channels.Channel
|
|
||||||
import kotlinx.coroutines.channels.SendChannel
|
|
||||||
import kotlinx.coroutines.flow.consumeAsFlow
|
|
||||||
import kotlinx.coroutines.flow.debounce
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
class LicensesView(
|
|
||||||
rootElement: HTMLElement,
|
|
||||||
client: HttpClient = HttpClient(),
|
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
|
||||||
) : MutableListView<License>(rootElement, "Add empty license", "Remove license") {
|
|
||||||
private val HTMLElement.idElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[0] as HTMLInputElement
|
|
||||||
private val HTMLElement.titleElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[1] as HTMLInputElement
|
|
||||||
private val HTMLElement.urlElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[2] as HTMLInputElement
|
|
||||||
|
|
||||||
private class LicenseOfferList(
|
|
||||||
rootElement: HTMLElement,
|
|
||||||
private val licensesView: LicensesView,
|
|
||||||
client: HttpClient,
|
|
||||||
scope: CoroutineScope
|
|
||||||
) : ListView<License>(rootElement, useSimpleDiffStrategy = true) {
|
|
||||||
private var licensesTemplates: List<License> = emptyList()
|
|
||||||
|
|
||||||
init {
|
|
||||||
scope.launch {
|
|
||||||
licensesTemplates = client.getLicenses().values.toList()
|
|
||||||
changeActor.send(Unit) // update list of searches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val changeActor: SendChannel<Unit> = scope.run {
|
|
||||||
val onChangeActor = Channel<Unit>(Channel.CONFLATED)
|
|
||||||
onChangeActor.consumeAsFlow().subscribeSafelyWithoutExceptions(scope) {
|
|
||||||
val lowercased = searchString
|
|
||||||
data = if (lowercased.isEmpty()) {
|
|
||||||
emptyList()
|
|
||||||
} else {
|
|
||||||
licensesTemplates.filter {
|
|
||||||
val lowercasedTitle = it.title.lowercase()
|
|
||||||
lowercased.all { it in lowercasedTitle }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onChangeActor
|
|
||||||
}
|
|
||||||
private val searchElement = rootElement.createTextField("Quick add", "Type some license name part to find it").apply {
|
|
||||||
oninput = {
|
|
||||||
changeActor.trySend(Unit)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private var searchString: String
|
|
||||||
get() = searchElement.value.lowercase()
|
|
||||||
set(value) {
|
|
||||||
searchElement.value = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.placeElement(value: License) {
|
|
||||||
createCommonButton(value.title).onclick = {
|
|
||||||
searchString = ""
|
|
||||||
licensesView.licenses += value
|
|
||||||
changeActor.trySend(Unit)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: License, to: License) {
|
|
||||||
getElementsByTagName("button")[0] ?.remove()
|
|
||||||
placeElement(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val licensesOffersList = LicenseOfferList(
|
|
||||||
rootElement.appendElement("div") { classList.add("uk-padding-small") } as HTMLElement,
|
|
||||||
this,
|
|
||||||
client,
|
|
||||||
scope
|
|
||||||
)
|
|
||||||
|
|
||||||
var licenses: List<License>
|
|
||||||
get() = elements.map {
|
|
||||||
License(it.idElement.value, it.titleElement.value, it.urlElement.value)
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
data = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPlainObject(): License = License("", "", "")
|
|
||||||
|
|
||||||
override fun HTMLElement.addContentBeforeRemoveButton(value: License) {
|
|
||||||
createTextField("License Id", "Short name like \"Apache-2.0\"").value = value.id
|
|
||||||
createTextField("License Title", "Official title of license (like \"Apache Software License 2.0\")").value = value.title
|
|
||||||
createTextField("License URL", "Link to your LICENSE file OR official license file (like \"https://opensource.org/licenses/Apache-2.0\")").value = value.url ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: License, to: License) {
|
|
||||||
idElement.value = to.id
|
|
||||||
titleElement.value = to.title
|
|
||||||
urlElement.value = to.url ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.common.calculateStrictDiff
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
abstract class ListView<T>(
|
|
||||||
protected val rootElement: HTMLElement,
|
|
||||||
useSimpleDiffStrategy: Boolean = false
|
|
||||||
) : View {
|
|
||||||
protected val elements = mutableListOf<HTMLElement>()
|
|
||||||
private val diffHandling: (old: List<T>, new: List<T>) -> Unit = if (useSimpleDiffStrategy) {
|
|
||||||
{ _, new ->
|
|
||||||
elements.forEach { it.remove() }
|
|
||||||
elements.clear()
|
|
||||||
new.forEach {
|
|
||||||
val element = instantiateElement()
|
|
||||||
elements.add(element)
|
|
||||||
element.placeElement(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
{ old, new ->
|
|
||||||
val diff = old.calculateStrictDiff(new)
|
|
||||||
diff.removed.forEach {
|
|
||||||
elements[it.index].remove()
|
|
||||||
elements.removeAt(it.index)
|
|
||||||
println(it.value)
|
|
||||||
}
|
|
||||||
diff.added.forEach {
|
|
||||||
val element = instantiateElement()
|
|
||||||
elements.add(element)
|
|
||||||
element.placeElement(it.value)
|
|
||||||
}
|
|
||||||
diff.replaced.forEach { (old, new) ->
|
|
||||||
val element = elements.getOrNull(old.index) ?.also { it.updateElement(old.value, new.value) }
|
|
||||||
if (element == null) {
|
|
||||||
val newElement = instantiateElement()
|
|
||||||
newElement.placeElement(new.value)
|
|
||||||
elements[new.index] = newElement
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected var data: List<T> = emptyList()
|
|
||||||
set(value) {
|
|
||||||
val old = field
|
|
||||||
field = value
|
|
||||||
diffHandling(old, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun HTMLElement.placeElement(value: T)
|
|
||||||
protected abstract fun HTMLElement.updateElement(from: T, to: T)
|
|
||||||
|
|
||||||
private fun instantiateElement() = rootElement.appendElement("div") {
|
|
||||||
classList.add("uk-padding-small")
|
|
||||||
} as HTMLElement
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.utils.ukActive
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
import org.w3c.dom.HTMLInputElement
|
|
||||||
|
|
||||||
class MavenProjectInfoView : View {
|
|
||||||
private val nameElement = document.getElementById("projectNameInput") as HTMLInputElement
|
|
||||||
private val descriptionElement = document.getElementById("projectDescriptionInput") as HTMLInputElement
|
|
||||||
private val urlElement = document.getElementById("projectUrlInput") as HTMLInputElement
|
|
||||||
private val vcsUrlElement = document.getElementById("projectVCSUrlInput") as HTMLInputElement
|
|
||||||
private val disableGpgSigningElement = document.getElementById("disableGpgSigning") as HTMLElement
|
|
||||||
private val optionalGpgSigningElement = document.getElementById("optionalGpgSigning") as HTMLElement
|
|
||||||
private val enableGpgSigningElement = document.getElementById("enableGpgSigning") as HTMLElement
|
|
||||||
private val includeMavenCentralElement = document.getElementById("includeMavenCentralTargetRepoToggle") as HTMLInputElement
|
|
||||||
private val developersView = DevelopersView(document.getElementById("developersListDiv") as HTMLElement)
|
|
||||||
private val repositoriesView = RepositoriesView(document.getElementById("repositoriesListDiv") as HTMLElement)
|
|
||||||
|
|
||||||
private var gpgSignMode: GpgSigning = GpgSigning.Disabled
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
when (value) {
|
|
||||||
GpgSigning.Enabled -> {
|
|
||||||
enableGpgSigningElement.ukActive = true
|
|
||||||
disableGpgSigningElement.ukActive = false
|
|
||||||
optionalGpgSigningElement.ukActive = false
|
|
||||||
}
|
|
||||||
GpgSigning.Optional -> {
|
|
||||||
enableGpgSigningElement.ukActive = false
|
|
||||||
disableGpgSigningElement.ukActive = false
|
|
||||||
optionalGpgSigningElement.ukActive = true
|
|
||||||
}
|
|
||||||
GpgSigning.Disabled -> {
|
|
||||||
enableGpgSigningElement.ukActive = false
|
|
||||||
disableGpgSigningElement.ukActive = true
|
|
||||||
optionalGpgSigningElement.ukActive = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mavenConfig: MavenConfig
|
|
||||||
get() = MavenConfig(
|
|
||||||
nameElement.value.ifBlank { defaultProjectName },
|
|
||||||
descriptionElement.value.ifBlank { defaultProjectDescription },
|
|
||||||
urlElement.value,
|
|
||||||
vcsUrlElement.value,
|
|
||||||
developersView.developers,
|
|
||||||
repositoriesView.repositories + if (includeMavenCentralElement.checked) {
|
|
||||||
listOf(SonatypeRepository)
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
},
|
|
||||||
when {
|
|
||||||
optionalGpgSigningElement.ukActive -> GpgSigning.Optional
|
|
||||||
enableGpgSigningElement.ukActive -> GpgSigning.Enabled
|
|
||||||
else -> GpgSigning.Disabled
|
|
||||||
}
|
|
||||||
)
|
|
||||||
set(value) {
|
|
||||||
nameElement.value = value.name
|
|
||||||
descriptionElement.value = value.description
|
|
||||||
urlElement.value = value.url
|
|
||||||
vcsUrlElement.value = value.vcsUrl
|
|
||||||
gpgSignMode = if (value.includeGpgSigning) {
|
|
||||||
GpgSigning.Enabled
|
|
||||||
} else {
|
|
||||||
value.gpgSigning
|
|
||||||
}
|
|
||||||
developersView.developers = value.developers
|
|
||||||
val reposWithoutSonatype = value.repositories.filter { it != SonatypeRepository }
|
|
||||||
includeMavenCentralElement.checked = value.repositories.size != reposWithoutSonatype.size
|
|
||||||
repositoriesView.repositories = reposWithoutSonatype
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
enableGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Enabled; Unit }
|
|
||||||
disableGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Disabled; Unit }
|
|
||||||
optionalGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Optional; Unit }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.utils.keepScrolling
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
abstract class MutableListView<T>(
|
|
||||||
rootElement: HTMLElement,
|
|
||||||
addButtonText: String = "Add",
|
|
||||||
private val removeButtonText: String = "Remove"
|
|
||||||
) : ListView<T>(rootElement) {
|
|
||||||
init {
|
|
||||||
rootElement.createPrimaryButton(addButtonText).apply {
|
|
||||||
onclick = {
|
|
||||||
keepScrolling {
|
|
||||||
val newObject = createPlainObject()
|
|
||||||
data += newObject
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun createPlainObject(): T
|
|
||||||
protected open fun HTMLElement.addContentBeforeRemoveButton(value: T) {}
|
|
||||||
protected open fun HTMLElement.addContentAfterRemoveButton(value: T) {}
|
|
||||||
final override fun HTMLElement.placeElement(value: T) {
|
|
||||||
addContentBeforeRemoveButton(value)
|
|
||||||
addRemoveButton()
|
|
||||||
addContentAfterRemoveButton(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun HTMLElement.addRemoveButton() {
|
|
||||||
val button = createPrimaryButton(removeButtonText)
|
|
||||||
button.onclick = {
|
|
||||||
elements.indexOf(button.parentElement).takeIf { it > -1 } ?.also {
|
|
||||||
data -= data[it]
|
|
||||||
} ?: rootElement.removeChild(this@addRemoveButton)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.utils.ukActive
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
class ProjectTypeView : View {
|
|
||||||
private val mppProjectTypeElement = document.getElementById("mppProjectType") as HTMLElement
|
|
||||||
private val jvmProjectTypeElement = document.getElementById("jvmProjectType") as HTMLElement
|
|
||||||
private val jsProjectTypeElement = document.getElementById("jsProjectType") as HTMLElement
|
|
||||||
|
|
||||||
var projectType: ProjectType
|
|
||||||
get() = when {
|
|
||||||
jvmProjectTypeElement.ukActive -> JVMProjectType
|
|
||||||
jsProjectTypeElement.ukActive -> JSProjectType
|
|
||||||
else -> MultiplatformProjectType
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
mppProjectTypeElement.ukActive = value == MultiplatformProjectType
|
|
||||||
jvmProjectTypeElement.ukActive = value == JVMProjectType
|
|
||||||
jsProjectTypeElement.ukActive = value == JSProjectType
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
mppProjectTypeElement.onclick = {
|
|
||||||
projectType = MultiplatformProjectType
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
jvmProjectTypeElement.onclick = {
|
|
||||||
projectType = JVMProjectType
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
jsProjectTypeElement.onclick = {
|
|
||||||
projectType = JSProjectType
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
class RepositoriesView(rootElement: HTMLElement) : MutableListView<MavenPublishingRepository>(rootElement, "Add repository", "Remove repository") {
|
|
||||||
private val HTMLElement.nameElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[0] as HTMLInputElement
|
|
||||||
private val HTMLElement.urlElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[1] as HTMLInputElement
|
|
||||||
|
|
||||||
var repositories: List<MavenPublishingRepository>
|
|
||||||
get() = elements.map {
|
|
||||||
MavenPublishingRepository(it.nameElement.value, it.urlElement.value)
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
data = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPlainObject(): MavenPublishingRepository = MavenPublishingRepository("", "")
|
|
||||||
|
|
||||||
override fun HTMLElement.addContentBeforeRemoveButton(value: MavenPublishingRepository) {
|
|
||||||
createTextField("Repository name", "This name will be used to identify repository in grade").value = value.name
|
|
||||||
createTextField("Repository URL", "For example: https://repo.maven.apache.org/maven2/").value = value.url
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: MavenPublishingRepository, to: MavenPublishingRepository) {
|
|
||||||
nameElement.value = to.name
|
|
||||||
urlElement.value = to.url
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
interface View
|
|
@ -1,35 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
fun HTMLElement.createTextField(
|
|
||||||
label: String,
|
|
||||||
placeholder: String
|
|
||||||
): HTMLInputElement {
|
|
||||||
return appendElement("div") {
|
|
||||||
classList.add("uk-margin", "uk-width-1-1")
|
|
||||||
}.appendElement("label") {
|
|
||||||
classList.add("uk-form-label")
|
|
||||||
innerHTML = label
|
|
||||||
}.run {
|
|
||||||
val input = appendElement("input") {
|
|
||||||
classList.add("uk-input", "uk-width-expand")
|
|
||||||
setAttribute("type", "text")
|
|
||||||
setAttribute("placeholder", placeholder)
|
|
||||||
} as HTMLInputElement
|
|
||||||
input
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun HTMLElement.createPrimaryButton(text: String): HTMLButtonElement = (appendElement("button") {
|
|
||||||
classList.add("uk-button", "uk-button-primary")
|
|
||||||
} as HTMLButtonElement).apply {
|
|
||||||
innerText = text
|
|
||||||
}
|
|
||||||
|
|
||||||
fun HTMLElement.createCommonButton(text: String): HTMLButtonElement = (appendElement("button") {
|
|
||||||
classList.add("uk-button", "uk-button-default")
|
|
||||||
} as HTMLButtonElement).apply {
|
|
||||||
innerText = text
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Kotlin Publication Scripts Builder</title>
|
|
||||||
<!-- UIkit CSS -->
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/css/uikit.min.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class="uk-navbar-container" uk-navbar>
|
|
||||||
<div class="uk-navbar-left">
|
|
||||||
<div class="uk-padding-small uk-text-lead">Kotlin Publication Scripts Builder</div>
|
|
||||||
<div class="uk-padding-small"><a href="https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder"><img src="https://img.shields.io/github/stars/InsanusMokrassar/KotlinPublicationScriptsBuilder?label=Github&style=plastic"/></a></div>
|
|
||||||
</div>
|
|
||||||
<div class="uk-navbar-right">
|
|
||||||
<ul class="uk-navbar-nav">
|
|
||||||
<li uk-tooltip="title: Open config" id="openConfig"><a href="#"><span uk-icon="icon: pull"></span></a></li><!--Open file-->
|
|
||||||
<li uk-tooltip="title: Save config" id="saveConfig"><a href="#"><span uk-icon="icon: push"></span></a></li><!--Save file-->
|
|
||||||
<li uk-tooltip="title: Export script" id="exportScript"><a href="#"><span uk-icon="icon: upload"></span></a></li><!--Save file-->
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<form class="uk-padding-small">
|
|
||||||
<fieldset class="uk-fieldset">
|
|
||||||
<legend class="uk-legend">Project type</legend>
|
|
||||||
<div class="uk-padding-small">
|
|
||||||
<ul class="uk-subnav uk-subnav-pill">
|
|
||||||
<li id="mppProjectType" class="uk-active"><a href="#">Multiplatform</a></li>
|
|
||||||
<li id="jvmProjectType"><a href="#">JVM</a></li>
|
|
||||||
<li id="jsProjectType"><a href="#">JS</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<legend class="uk-legend">Licenses</legend>
|
|
||||||
<div id="licensesListDiv" class="uk-padding-small"></div>
|
|
||||||
|
|
||||||
<legend class="uk-legend">Project information</legend>
|
|
||||||
|
|
||||||
<div class="uk-padding-small">
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectNameInput">Public project name</label>
|
|
||||||
<input id="projectNameInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectDescriptionInput">Public project description</label>
|
|
||||||
<input id="projectDescriptionInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectUrlInput">Public project URL</label>
|
|
||||||
<input id="projectUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github or other source with readme">
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectVCSUrlInput">Public project VCS URL (with .git)</label>
|
|
||||||
<input id="projectVCSUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github .git file">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="uk-margin">
|
|
||||||
<label>GPG Signing</label>
|
|
||||||
|
|
||||||
<div class="uk-padding-small">
|
|
||||||
<ul class="uk-subnav uk-subnav-pill">
|
|
||||||
<li id="disableGpgSigning" class="uk-active" uk-tooltip="title: Signing will not be added"><a href="#">Disabled</a></li>
|
|
||||||
<li id="optionalGpgSigning" uk-tooltip="title: Signing will be added, but disabled in case of absence 'signatory.keyId'"><a href="#">Optional</a></li>
|
|
||||||
<li id="enableGpgSigning" uk-tooltip="title: Signing will be always enabled"><a href="#">Enabled</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin">
|
|
||||||
<label><input id="includeMavenCentralTargetRepoToggle" class="uk-checkbox" type="checkbox"> Include publication to MavenCentral</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<legend class="uk-legend">Developers info</legend>
|
|
||||||
<div id="developersListDiv" class="uk-padding-small"></div>
|
|
||||||
|
|
||||||
<legend class="uk-legend">Repositories info</legend>
|
|
||||||
<div id="repositoriesListDiv" class="uk-padding-small"></div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
<!-- UIkit JS -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/js/uikit.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/js/uikit-icons.min.js"></script>
|
|
||||||
<!-- Internal JS -->
|
|
||||||
<script src="kmppscriptbuilder.web.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|