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
|
||||
prerelease: true
|
||||
- name: Upload Ubuntu Release Asset
|
||||
id: upload-ubuntu-release-asset
|
||||
id: upload-ubuntu-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
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
|
||||
asset_path: "./desktop/build/compose/jars/kmppscriptbuilder.desktop-linux-x64-${{ env.version }}${{ env.additional_version }}.jar"
|
||||
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: "./core/build/compose/jars/kmppscriptbuilder.desktop-linux-x64-${{ env.version }}${{ env.additional_version }}.jar"
|
||||
asset_name: KotlinPublicationScriptsBuilder-linux-x64.jar
|
||||
asset_content_type: application/java-archive
|
||||
|
@ -7,11 +7,10 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$dexcount_version"
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
|
||||
classpath libs.buildscript.kt.gradle
|
||||
classpath libs.buildscript.kt.serialization
|
||||
classpath libs.buildscript.jb.dokka
|
||||
classpath libs.buildscript.gh.release
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,46 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
kotlin {
|
||||
js (IR) {
|
||||
binaries.executable()
|
||||
}
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
api "dev.inmo:micro_utils.coroutines:$micro_utils_version"
|
||||
|
||||
api "io.ktor:ktor-client-core:$ktor_version"
|
||||
api libs.kt.coroutines
|
||||
api libs.microutils.common
|
||||
api libs.microutils.coroutines
|
||||
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.request.get
|
||||
import io.ktor.client.request.url
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.builtins.MapSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
@ -20,9 +21,9 @@ private val commonLicensesListDeserializer = MapSerializer(String.serializer(),
|
||||
private var licenses: Map<String, License>? = null
|
||||
|
||||
suspend fun HttpClient.getLicenses(): Map<String, License> {
|
||||
val answer = get<String> {
|
||||
val answer = get {
|
||||
url("https://licenses.opendefinition.org/licenses/groups/all.json")
|
||||
}
|
||||
}.bodyAsText()
|
||||
return serialFormat.decodeFromString(commonLicensesListDeserializer, answer).also { gotLicenses ->
|
||||
licenses = gotLicenses
|
||||
}
|
||||
|
@ -31,23 +31,84 @@ data class MavenConfig(
|
||||
@Serializable
|
||||
data class MavenPublishingRepository(
|
||||
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 {
|
||||
val usernameProperty = "${nameCapitalized}_USER"
|
||||
val passwordProperty = "${nameCapitalized}_PASSWORD"
|
||||
return """if ((project.hasProperty('${usernameProperty}') || System.getenv('${usernameProperty}') != null) && (project.hasProperty('${passwordProperty}') || System.getenv('${passwordProperty}') != null)) {
|
||||
maven {
|
||||
name = "$name"
|
||||
url = uri("$url")
|
||||
@Serializable
|
||||
sealed interface CredentialsType {
|
||||
@Serializable
|
||||
object Nothing: CredentialsType {
|
||||
override fun buildCheckPart(): String = "true"
|
||||
override fun buildCredsPart(): String = ""
|
||||
}
|
||||
@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 {
|
||||
username = project.hasProperty('${usernameProperty}') ? project.property('${usernameProperty}') : System.getenv('${usernameProperty}')
|
||||
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")
|
||||
}
|
||||
|
@ -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.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(
|
||||
id: String = "",
|
||||
@ -22,10 +27,10 @@ class DevelopersView : ListView<DeveloperState>("Developers info") {
|
||||
var developers: List<Developer>
|
||||
get() = itemsList.map { it.toDeveloper() }
|
||||
set(value) {
|
||||
itemsList.clear()
|
||||
itemsList.addAll(
|
||||
value.map { it.toDeveloperState() }
|
||||
)
|
||||
itemsList.apply {
|
||||
clear()
|
||||
addAll(value.map { it.toDeveloperState() })
|
||||
}
|
||||
}
|
||||
|
||||
override val addItemText: String = "Add developer"
|
||||
@ -34,18 +39,19 @@ class DevelopersView : ListView<DeveloperState>("Developers info") {
|
||||
override fun createItem(): DeveloperState = DeveloperState()
|
||||
@Composable
|
||||
override fun buildView(item: DeveloperState) {
|
||||
CommonText("Developer username")
|
||||
CommonTextField(
|
||||
item.id,
|
||||
"Developer username"
|
||||
) { item.id = it }
|
||||
DefaultSmallVerticalMargin()
|
||||
CommonText("Developer name")
|
||||
CommonTextField(
|
||||
item.name,
|
||||
"Developer name"
|
||||
) { item.name = it }
|
||||
DefaultSmallVerticalMargin()
|
||||
CommonText("Developer E-Mail")
|
||||
CommonTextField(
|
||||
item.eMail,
|
||||
"Developer E-Mail"
|
||||
) { 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.layout.*
|
||||
@ -9,9 +9,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import dev.inmo.kmppscriptbuilder.desktop.utils.init
|
||||
import dev.inmo.kmppscriptbuilder.desktop.utils.loadConfigFile
|
||||
import dev.inmo.kmppscriptbuilder.desktop.views.BuilderView
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.BuilderView
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.loadConfigFile
|
||||
import java.io.File
|
||||
|
||||
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
|
||||
@ -48,7 +47,9 @@ fun main(args: Array<String>) = application {
|
||||
.fillMaxSize()
|
||||
.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 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.utils.serialFormat
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import java.io.File
|
||||
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
|
||||
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)
|
||||
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
||||
return when (fc.showOpenDialog(null)) {
|
||||
when (fc.showOpenDialog(null)) {
|
||||
JFileChooser.APPROVE_OPTION -> {
|
||||
val file = fc.selectedFile
|
||||
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 {
|
||||
it.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
||||
} != null
|
||||
}
|
||||
|
||||
fun exportGradle(config: Config): Boolean {
|
||||
actual fun exportGradle(config: Config): Boolean {
|
||||
val fc = JFileChooser(lastFile ?.parent)
|
||||
fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
||||
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)
|
||||
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||
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.net.URI
|
||||
|
||||
fun openLink(link: String): Boolean {
|
||||
actual fun openLink(link: String): Boolean {
|
||||
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
|
||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||
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"
|
||||
mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
|
||||
mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"
|
||||
mppAndroidProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppAndroidProject.gradle"
|
||||
|
||||
defaultAndroidSettingsPresetPath = "${rootProject.projectDir.absolutePath}/defaultAndroidSettings.gradle"
|
||||
|
||||
|
@ -3,30 +3,18 @@ org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
kotlin.incremental.js=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
kotlin_version=1.6.10
|
||||
kotlin_coroutines_version=1.6.0
|
||||
kotlin_serialisation_core_version=1.3.2
|
||||
ktor_version=1.6.7
|
||||
micro_utils_version=0.9.0
|
||||
kotlin_version=1.7.20
|
||||
kotlin_coroutines_version=1.6.4
|
||||
kotlin_serialisation_core_version=1.4.1
|
||||
ktor_version=2.1.3
|
||||
micro_utils_version=0.14.2
|
||||
|
||||
compose_version=1.0.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
|
||||
compose_version=1.2.1
|
||||
|
||||
# Dokka
|
||||
|
||||
dokka_version=1.6.0
|
||||
dokka_version=1.7.20
|
||||
|
||||
# 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
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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"
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations.main.kotlinOptions.useIR = true
|
||||
}
|
||||
jvm()
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
|
@ -5,10 +5,8 @@ project.group = "$group"
|
||||
|
||||
kotlin {
|
||||
js (IR) {
|
||||
browser {
|
||||
binaries.executable()
|
||||
}
|
||||
nodejs()
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
@ -4,16 +4,11 @@ project.group = "$group"
|
||||
// apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations.main.kotlinOptions.useIR = true
|
||||
}
|
||||
jvm()
|
||||
js (IR) {
|
||||
browser()
|
||||
nodejs()
|
||||
}
|
||||
android {
|
||||
publishAllLibraryVariants()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
@ -39,14 +34,5 @@ kotlin {
|
||||
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 = [
|
||||
":core",
|
||||
":desktop",
|
||||
":web"
|
||||
// ":desktop",
|
||||
// ":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>
|