total rework
@ -7,6 +7,9 @@ plugins {
|
|||||||
apply from: "$mppProjectWithSerializationPresetPath"
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
js (IR) {
|
||||||
|
binaries.executable()
|
||||||
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -17,10 +20,27 @@ kotlin {
|
|||||||
api(compose.runtime)
|
api(compose.runtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
jsMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(compose.web.core)
|
||||||
|
api libs.ktor.client.js
|
||||||
|
api libs.jsuikit
|
||||||
|
}
|
||||||
|
}
|
||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(compose.desktop.currentOs)
|
implementation(compose.desktop.currentOs)
|
||||||
|
api libs.ktor.client.cio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
compose {
|
||||||
|
desktop {
|
||||||
|
application {
|
||||||
|
mainClass = "dev.inmo.kmppscriptbuilder.desktop.BuilderKt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,18 +5,26 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultDivider
|
||||||
|
|
||||||
expect object BuilderViewDrawer : Drawer<BuilderView>
|
@Composable
|
||||||
|
expect fun TopAppBar(
|
||||||
|
config: Config,
|
||||||
|
saveAvailable: Boolean,
|
||||||
|
onSaveAvailable: (Boolean) -> Unit,
|
||||||
|
onNewConfig: (Config) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
class BuilderView : View() {
|
class BuilderView : View() {
|
||||||
internal val projectTypeView = ProjectTypeView()
|
internal val projectTypeView by mutableStateOf(ProjectTypeView())
|
||||||
internal val mavenInfoView = MavenInfoView()
|
internal val mavenInfoView by mutableStateOf(MavenInfoView())
|
||||||
internal val licensesView = LicensesView()
|
internal val licensesView by mutableStateOf(LicensesView())
|
||||||
|
|
||||||
internal var saveAvailableState by mutableStateOf(false)
|
internal var saveAvailableState by mutableStateOf(false)
|
||||||
var config: Config
|
var config: Config
|
||||||
get() = Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
get() {
|
||||||
|
return Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
||||||
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
licensesView.licenses = value.licenses
|
licensesView.licenses = value.licenses
|
||||||
mavenInfoView.mavenConfig = value.mavenConfig
|
mavenInfoView.mavenConfig = value.mavenConfig
|
||||||
@ -26,6 +34,20 @@ class BuilderView : View() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun build() {
|
override fun build() {
|
||||||
with(BuilderViewDrawer) { draw() }
|
TopAppBar(
|
||||||
|
config,
|
||||||
|
saveAvailableState,
|
||||||
|
{
|
||||||
|
saveAvailableState = it
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
config = it
|
||||||
|
}
|
||||||
|
|
||||||
|
projectTypeView.build()
|
||||||
|
DefaultDivider()
|
||||||
|
licensesView.build()
|
||||||
|
DefaultDivider()
|
||||||
|
mavenInfoView.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.core.ui
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
|
||||||
class DeveloperState(
|
class DeveloperState(
|
||||||
id: String = "",
|
id: String = "",
|
||||||
@ -21,11 +23,32 @@ class DeveloperState(
|
|||||||
private fun Developer.toDeveloperState() = DeveloperState(id, name, eMail)
|
private fun Developer.toDeveloperState() = DeveloperState(id, name, eMail)
|
||||||
|
|
||||||
class DevelopersView : ListView<DeveloperState>("Developers info") {
|
class DevelopersView : ListView<DeveloperState>("Developers info") {
|
||||||
var developers = mutableStateListOf<Developer>()
|
var developers: List<Developer>
|
||||||
|
get() = itemsList.map { it.toDeveloper() }
|
||||||
|
set(value) {
|
||||||
|
itemsList.apply {
|
||||||
|
clear()
|
||||||
|
addAll(value.map { it.toDeveloperState() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val addItemText: String = "Add developer"
|
override val addItemText: String = "Add developer"
|
||||||
override val removeItemText: String = "Remove developer"
|
override val removeItemText: String = "Remove developer"
|
||||||
|
|
||||||
override fun createItem(): DeveloperState = DeveloperState()
|
override fun createItem(): DeveloperState = DeveloperState()
|
||||||
|
@Composable
|
||||||
|
override fun buildView(item: DeveloperState) {
|
||||||
|
CommonTextField(
|
||||||
|
item.id,
|
||||||
|
"Developer username",
|
||||||
|
) { item.id = it }
|
||||||
|
CommonTextField(
|
||||||
|
item.name,
|
||||||
|
"Developer name",
|
||||||
|
) { item.name = it }
|
||||||
|
CommonTextField(
|
||||||
|
item.eMail,
|
||||||
|
"Developer E-Mail",
|
||||||
|
) { item.eMail = it }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.core.ui
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.License
|
import dev.inmo.kmppscriptbuilder.core.models.License
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -38,8 +41,14 @@ class LicensesView: VerticalView("Licenses") {
|
|||||||
licensesListState.addAll(value.map { it.toLicenseState() })
|
licensesListState.addAll(value.map { it.toLicenseState() })
|
||||||
}
|
}
|
||||||
internal val availableLicensesState = mutableStateListOf<License>()
|
internal val availableLicensesState = mutableStateListOf<License>()
|
||||||
internal val licensesOffersToShow = mutableStateListOf<License>()
|
|
||||||
internal var licenseSearchFilter by mutableStateOf("")
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
@ -50,6 +59,16 @@ class LicensesView: VerticalView("Licenses") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val content: @Composable () -> Unit = {
|
override val content: @Composable () -> Unit = {
|
||||||
|
CommonTextField(
|
||||||
|
licenseSearchFilter,
|
||||||
|
"Search filter",
|
||||||
|
onFocusChanged = {
|
||||||
|
searchFieldFocused.value = it
|
||||||
|
}
|
||||||
|
) { filterText ->
|
||||||
|
licenseSearchFilter = filterText
|
||||||
|
}
|
||||||
|
|
||||||
with(LicensesDrawer) { draw() }
|
with(LicensesDrawer) { draw() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ abstract class ListView<T>(title: String) : VerticalView(title) {
|
|||||||
|
|
||||||
protected val drawer = ListViewDrawer<T>()
|
protected val drawer = ListViewDrawer<T>()
|
||||||
|
|
||||||
override val content: () -> Unit = {
|
override val content: @Composable () -> Unit = {
|
||||||
with(drawer) {
|
with(drawer) {
|
||||||
draw()
|
draw()
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,17 @@ package dev.inmo.kmppscriptbuilder.core.ui
|
|||||||
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
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.CommonTextField
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
|
||||||
|
|
||||||
expect object MavenInfoDrawer : Drawer<MavenInfoView>
|
expect class GpgSigningOptionDrawer : Drawer<GpgSigning>
|
||||||
|
expect fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer
|
||||||
|
|
||||||
class MavenInfoView : VerticalView("Project information") {
|
class MavenInfoView : VerticalView("Project information") {
|
||||||
internal var projectNameProperty by mutableStateOf("")
|
internal var projectNameProperty by mutableStateOf("")
|
||||||
@ -43,10 +51,46 @@ class MavenInfoView : VerticalView("Project information") {
|
|||||||
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
|
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
|
||||||
developersView.developers = value.developers
|
developersView.developers = value.developers
|
||||||
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
|
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
|
||||||
// developersView.developers = value.developers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val gpgSigningDrawer = GpgSigningOptionDrawerWithView(this)
|
||||||
|
|
||||||
override val content: @Composable () -> Unit = {
|
override val content: @Composable () -> Unit = {
|
||||||
with (MavenInfoDrawer) { draw() }
|
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 }
|
||||||
|
|
||||||
|
ButtonsPanel(
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,31 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
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.MultiplatformProjectType
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
expect object ProjectTypeDrawer : Drawer<ProjectTypeView>
|
expect class ProjectTypeDrawer : Drawer<ProjectType>
|
||||||
|
expect fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer
|
||||||
|
|
||||||
class ProjectTypeView : VerticalView("Project type") {
|
class ProjectTypeView : VerticalView("Project type") {
|
||||||
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
|
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
|
||||||
|
private val typeDrawer = ProjectTypeDrawerWithView(this)
|
||||||
|
|
||||||
override val content: @Composable () -> Unit = {
|
override val content: @Composable () -> Unit = {
|
||||||
with(ProjectTypeDrawer) { draw() }
|
ButtonsPanel(
|
||||||
|
MultiplatformProjectType,
|
||||||
|
JVMProjectType,
|
||||||
|
JSProjectType
|
||||||
|
) {
|
||||||
|
with(typeDrawer) {
|
||||||
|
with (it) {
|
||||||
|
draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ package dev.inmo.kmppscriptbuilder.core.ui
|
|||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
class RepositoryState(
|
class RepositoryState(
|
||||||
@ -19,8 +21,6 @@ class RepositoryState(
|
|||||||
|
|
||||||
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url)
|
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url)
|
||||||
|
|
||||||
expect object RepositoryStateDrawer : Drawer<RepositoryState>
|
|
||||||
|
|
||||||
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
||||||
var repositories: List<MavenPublishingRepository>
|
var repositories: List<MavenPublishingRepository>
|
||||||
get() = itemsList.map { it.toRepository() }
|
get() = itemsList.map { it.toRepository() }
|
||||||
@ -38,7 +38,14 @@ class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun buildView(item: RepositoryState) {
|
override fun buildView(item: RepositoryState) {
|
||||||
with(RepositoryStateDrawer) { with(item) { draw() } }
|
CommonTextField(
|
||||||
|
item.name,
|
||||||
|
"Repository name",
|
||||||
|
) { item.name = it }
|
||||||
|
CommonTextField(
|
||||||
|
item.url,
|
||||||
|
"Repository url",
|
||||||
|
) { item.url = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package dev.inmo.kmppscriptbuilder.core.ui.utils
|
|||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
interface Drawer<T> {
|
fun interface Drawer<T> {
|
||||||
@Composable
|
@Composable
|
||||||
fun T.draw()
|
fun T.draw()
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,12 @@ expect fun TitleText(text: String)
|
|||||||
expect fun CommonText(text: String, onClick: (() -> Unit)? = null)
|
expect fun CommonText(text: String, onClick: (() -> Unit)? = null)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit)
|
expect fun CommonTextField(
|
||||||
|
presetText: String,
|
||||||
|
hint: String,
|
||||||
|
onFocusChanged: (Boolean) -> Unit = {},
|
||||||
|
onChange: (String) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun SwitchWithLabel(
|
expect fun SwitchWithLabel(
|
||||||
@ -19,3 +24,18 @@ expect fun SwitchWithLabel(
|
|||||||
switchEnabled: Boolean = true,
|
switchEnabled: Boolean = true,
|
||||||
onCheckedChange: (Boolean) -> Unit
|
onCheckedChange: (Boolean) -> Unit
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun <T> ButtonsPanel(
|
||||||
|
data: Iterable<T>,
|
||||||
|
itemDrawer: @Composable (T) -> Unit
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T> ButtonsPanel(
|
||||||
|
vararg data: T,
|
||||||
|
itemDrawer: @Composable (T) -> Unit
|
||||||
|
) = ButtonsPanel(data.toList(), itemDrawer)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun DefaultDivider()
|
||||||
|
@ -5,16 +5,7 @@ import dev.inmo.micro_utils.common.MPPFile
|
|||||||
|
|
||||||
internal const val appExtension = "kpsb"
|
internal const val appExtension = "kpsb"
|
||||||
|
|
||||||
private var lastFile: MPPFile? = null
|
expect fun openNewConfig(onParsed: (Config) -> Unit)
|
||||||
|
|
||||||
fun loadConfigFile(file: MPPFile): Config {
|
|
||||||
lastFile = file
|
|
||||||
return serialFormat.decodeFromString(Config.serializer(), file.text())
|
|
||||||
}
|
|
||||||
|
|
||||||
expect fun MPPFile.text(): String
|
|
||||||
|
|
||||||
expect fun loadConfig(): Config?
|
|
||||||
|
|
||||||
expect fun saveConfig(config: Config): Boolean
|
expect fun saveConfig(config: Config): 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,25 @@
|
|||||||
|
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.kmppscriptbuilder.core.models.GpgSigning
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
actual class GpgSigningOptionDrawer(
|
||||||
|
private val mavenInfoView: MavenInfoView
|
||||||
|
) : Drawer<GpgSigning> {
|
||||||
|
@Composable
|
||||||
|
override fun GpgSigning.draw() {
|
||||||
|
if (mavenInfoView.gpgSignProperty == this) {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Primary)
|
||||||
|
} else {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Default) {
|
||||||
|
mavenInfoView.gpgSignProperty = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
|
@ -0,0 +1,59 @@
|
|||||||
|
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.builder
|
||||||
|
import dev.inmo.jsuikit.utils.Attrs
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
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
|
||||||
|
) { _ ->
|
||||||
|
licensesListState.add(it.toLicenseState())
|
||||||
|
licenseSearchFilter = ""
|
||||||
|
}
|
||||||
|
Divider.Common()
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultButton("Add empty license", UIKitButton.Type.Primary, UIKitMargin.Small) {
|
||||||
|
licensesListState.add(LicenseState())
|
||||||
|
}
|
||||||
|
|
||||||
|
licensesListState.forEach { license ->
|
||||||
|
Div(UIKitMargin.Small.builder()) {
|
||||||
|
CommonTextField(
|
||||||
|
license.id,
|
||||||
|
"License ID",
|
||||||
|
) { license.id = it }
|
||||||
|
CommonTextField(
|
||||||
|
license.title,
|
||||||
|
"License title",
|
||||||
|
) { license.title = it }
|
||||||
|
CommonTextField(
|
||||||
|
license.url ?: "",
|
||||||
|
"License URL",
|
||||||
|
) { license.url = it }
|
||||||
|
DefaultButton("Remove", UIKitButton.Type.Danger, UIKitMargin.Small) {
|
||||||
|
licensesListState.remove(license)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
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.builder
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import org.jetbrains.compose.web.dom.Div
|
||||||
|
|
||||||
|
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||||
|
@Composable
|
||||||
|
override fun ListView<T>.draw() {
|
||||||
|
DefaultButton(addItemText, UIKitButton.Type.Primary ) { itemsList.add(createItem()) }
|
||||||
|
itemsList.forEach { item ->
|
||||||
|
Div(UIKitMargin.Small.builder()) {
|
||||||
|
buildView(item)
|
||||||
|
DefaultButton(removeItemText, UIKitButton.Type.Danger, UIKitMargin.Small) {
|
||||||
|
itemsList.remove(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
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.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) {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Primary)
|
||||||
|
} else {
|
||||||
|
DefaultButton(name, UIKitButton.Type.Default) {
|
||||||
|
projectTypeView.projectType = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
|
@ -0,0 +1,82 @@
|
|||||||
|
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.UIKitMargin
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitPadding
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitText
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitTooltipModifier
|
||||||
|
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.Text
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun TopAppBar(
|
||||||
|
config: Config,
|
||||||
|
saveAvailable: Boolean,
|
||||||
|
onSaveAvailable: (Boolean) -> Unit,
|
||||||
|
onNewConfig: (Config) -> Unit
|
||||||
|
) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.core.ui
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitForm
|
||||||
|
import dev.inmo.jsuikit.modifiers.builder
|
||||||
|
import org.jetbrains.compose.web.dom.Legend
|
||||||
|
import org.jetbrains.compose.web.dom.Text
|
||||||
|
|
||||||
actual abstract class View {
|
actual abstract class View {
|
||||||
@Composable
|
@Composable
|
||||||
@ -9,4 +13,8 @@ actual abstract class View {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun View.DrawVertically(title: String, block: @Composable () -> Unit) {
|
actual fun View.DrawVertically(title: String, block: @Composable () -> Unit) {
|
||||||
|
Legend(UIKitForm.Legend.builder()) {
|
||||||
|
Text(title)
|
||||||
|
}
|
||||||
|
block()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
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.Label
|
||||||
|
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.UIKitText
|
||||||
|
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||||
|
import dev.inmo.jsuikit.modifiers.builder
|
||||||
|
import dev.inmo.jsuikit.modifiers.include
|
||||||
|
import dev.inmo.jsuikit.utils.Attrs
|
||||||
|
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 { onFocusChanged(false) }
|
||||||
|
},
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (checked) {
|
||||||
|
Icon.App.Check.drawAsFormInputPart(UIKitInverse.Light)
|
||||||
|
}
|
||||||
|
Text(label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun <T> ButtonsPanel(data: Iterable<T>, itemDrawer: @Composable (T) -> Unit) {
|
||||||
|
Flex(UIKitFlex.Alignment.Vertical.Middle, UIKitMargin.Small) {
|
||||||
|
data.forEach { itemDrawer(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultDivider() {
|
||||||
|
Divider.Common()
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
1
core/src/jsMain/resources/css/uikit.min.css
vendored
Normal file
72
core/src/jsMain/resources/index.html
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<!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" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- <form class="uk-padding-small">-->
|
||||||
|
<!-- <fieldset class="uk-fieldset">-->
|
||||||
|
<!-- <legend class="uk-legend">Project type</legend>-->
|
||||||
|
<!-- <div class="uk-padding-small">-->
|
||||||
|
<!-- <ul class="uk-subnav uk-subnav-pill">-->
|
||||||
|
<!-- <li id="mppProjectType" class="uk-active"><a href="#">Multiplatform</a></li>-->
|
||||||
|
<!-- <li id="jvmProjectType"><a href="#">JVM</a></li>-->
|
||||||
|
<!-- <li id="jsProjectType"><a href="#">JS</a></li>-->
|
||||||
|
<!-- </ul>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <legend class="uk-legend">Licenses</legend>-->
|
||||||
|
<!-- <div id="licensesListDiv" class="uk-padding-small"></div>-->
|
||||||
|
|
||||||
|
<!-- <legend class="uk-legend">Project information</legend>-->
|
||||||
|
|
||||||
|
<!-- <div class="uk-padding-small">-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectNameInput">Public project name</label>-->
|
||||||
|
<!-- <input id="projectNameInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectDescriptionInput">Public project description</label>-->
|
||||||
|
<!-- <input id="projectDescriptionInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectUrlInput">Public project URL</label>-->
|
||||||
|
<!-- <input id="projectUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github or other source with readme">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||||
|
<!-- <label class="uk-form-label" for="projectVCSUrlInput">Public project VCS URL (with .git)</label>-->
|
||||||
|
<!-- <input id="projectVCSUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github .git file">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="uk-margin">-->
|
||||||
|
<!-- <label>GPG Signing</label>-->
|
||||||
|
|
||||||
|
<!-- <div class="uk-padding-small">-->
|
||||||
|
<!-- <ul class="uk-subnav uk-subnav-pill">-->
|
||||||
|
<!-- <li id="disableGpgSigning" class="uk-active" uk-tooltip="title: Signing will not be added"><a href="#">Disabled</a></li>-->
|
||||||
|
<!-- <li id="optionalGpgSigning" uk-tooltip="title: Signing will be added, but disabled in case of absence 'signatory.keyId'"><a href="#">Optional</a></li>-->
|
||||||
|
<!-- <li id="enableGpgSigning" uk-tooltip="title: Signing will be always enabled"><a href="#">Enabled</a></li>-->
|
||||||
|
<!-- </ul>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="uk-margin">-->
|
||||||
|
<!-- <label><input id="includeMavenCentralTargetRepoToggle" class="uk-checkbox" type="checkbox"> Include publication to MavenCentral</label>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <legend class="uk-legend">Developers info</legend>-->
|
||||||
|
<!-- <div id="developersListDiv" class="uk-padding-small"></div>-->
|
||||||
|
|
||||||
|
<!-- <legend class="uk-legend">Repositories info</legend>-->
|
||||||
|
<!-- <div id="repositoriesListDiv" class="uk-padding-small"></div>-->
|
||||||
|
<!-- </fieldset>-->
|
||||||
|
<!-- </form>-->
|
||||||
|
<!-- UIkit JS -->
|
||||||
|
<script src="./js/uikit.min.js"></script>
|
||||||
|
<script src="./js/uikit-icons.min.js"></script>
|
||||||
|
<!-- Internal JS -->
|
||||||
|
<script src="kmppscriptbuilder.core.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
core/src/jsMain/resources/js/uikit-icons.min.js
vendored
Normal file
1
core/src/jsMain/resources/js/uikit.min.js
vendored
Normal file
@ -1,4 +1,4 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop
|
package dev.inmo.kmppscriptbuilder.core
|
||||||
|
|
||||||
import androidx.compose.foundation.*
|
import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
@ -9,9 +9,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.window.Window
|
import androidx.compose.ui.window.Window
|
||||||
import androidx.compose.ui.window.application
|
import androidx.compose.ui.window.application
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.init
|
import dev.inmo.kmppscriptbuilder.core.ui.BuilderView
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.loadConfigFile
|
import dev.inmo.kmppscriptbuilder.core.utils.loadConfigFile
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.views.BuilderView
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
|
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
|
||||||
@ -48,7 +47,9 @@ fun main(args: Array<String>) = application {
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(stateVertical)
|
.verticalScroll(stateVertical)
|
||||||
) {
|
) {
|
||||||
builder.init()
|
Column {
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,65 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.core.ui
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.Divider
|
|
||||||
import androidx.compose.material.Text
|
|
||||||
import androidx.compose.material.TopAppBar
|
|
||||||
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.Drawer
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.loadConfig
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.saveAs
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
|
|
||||||
|
|
||||||
actual object BuilderViewDrawer : Drawer<BuilderView> {
|
|
||||||
override fun BuilderView.draw() {
|
|
||||||
Box(Modifier.fillMaxSize()) {
|
|
||||||
Column() {
|
|
||||||
TopAppBar(
|
|
||||||
@Composable {
|
|
||||||
Text("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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OutlinedButton(
|
||||||
|
{
|
||||||
|
mavenInfoView.gpgSignProperty = this
|
||||||
|
},
|
||||||
|
Modifier.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Text(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
|
@ -4,6 +4,9 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.Button
|
import androidx.compose.material.Button
|
||||||
import androidx.compose.material.Divider
|
import androidx.compose.material.Divider
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
@ -11,44 +14,39 @@ import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
|||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
actual object LicensesDrawer : Drawer<LicensesView> {
|
actual object LicensesDrawer : Drawer<LicensesView> {
|
||||||
|
@Composable
|
||||||
override fun LicensesView.draw() {
|
override fun LicensesView.draw() {
|
||||||
CommonTextField(licenseSearchFilter, "Search filter") { filterText ->
|
if (searchFieldFocused.value) {
|
||||||
licenseSearchFilter = filterText
|
|
||||||
licensesOffersToShow.clear()
|
|
||||||
if (licenseSearchFilter.isNotEmpty()) {
|
|
||||||
licensesOffersToShow.addAll(
|
|
||||||
availableLicensesState.filter { filterText.all { symbol -> symbol.lowercaseChar() in it.title } }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Column {
|
Column {
|
||||||
licensesOffersToShow.forEach {
|
licensesOffersToShow.value.forEach {
|
||||||
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
|
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
|
||||||
CommonText(it.title) {
|
CommonText(it.title) {
|
||||||
licensesListState.add(it.toLicenseState())
|
licensesListState.add(it.toLicenseState())
|
||||||
licenseSearchFilter = ""
|
licenseSearchFilter = ""
|
||||||
licensesOffersToShow.clear()
|
|
||||||
}
|
}
|
||||||
Divider()
|
Divider()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
|
|
||||||
CommonText("Add empty license",)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
|
||||||
|
CommonText("Add empty license")
|
||||||
|
}
|
||||||
|
|
||||||
licensesListState.forEach { license ->
|
licensesListState.forEach { license ->
|
||||||
Column(Modifier.padding(8.dp)) {
|
Column(Modifier.padding(8.dp)) {
|
||||||
CommonTextField(
|
CommonTextField(
|
||||||
license.id,
|
license.id,
|
||||||
"License ID"
|
"License ID",
|
||||||
) { license.id = it }
|
) { license.id = it }
|
||||||
CommonTextField(
|
CommonTextField(
|
||||||
license.title,
|
license.title,
|
||||||
"License title"
|
"License title",
|
||||||
) { license.title = it }
|
) { license.title = it }
|
||||||
CommonTextField(
|
CommonTextField(
|
||||||
license.url ?: "",
|
license.url ?: "",
|
||||||
"License URL"
|
"License URL",
|
||||||
) { license.url = it }
|
) { license.url = it }
|
||||||
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
|
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
|
||||||
CommonText("Remove",)
|
CommonText("Remove",)
|
||||||
|
@ -3,12 +3,14 @@ package dev.inmo.kmppscriptbuilder.core.ui
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.Button
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||||
|
@Composable
|
||||||
override fun ListView<T>.draw() {
|
override fun ListView<T>.draw() {
|
||||||
Button({ itemsList.add(createItem()) }) {
|
Button({ itemsList.add(createItem()) }) {
|
||||||
CommonText(addItemText,)
|
CommonText(addItemText,)
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
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 object MavenInfoDrawer : Drawer<MavenInfoView> {
|
|
||||||
@Composable
|
|
||||||
private fun MavenInfoView.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 fun MavenInfoView.draw() {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,30 +15,26 @@ import dev.inmo.kmppscriptbuilder.core.models.MultiplatformProjectType
|
|||||||
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
actual object ProjectTypeDrawer : Drawer<ProjectTypeView> {
|
actual class ProjectTypeDrawer(
|
||||||
|
private val projectTypeView: ProjectTypeView
|
||||||
|
) : Drawer<ProjectType> {
|
||||||
@Composable
|
@Composable
|
||||||
private fun ProjectTypeView.addProjectTypeButton(newProjectType: ProjectType) {
|
override fun ProjectType.draw() {
|
||||||
if (projectType == newProjectType) {
|
if (projectTypeView.projectType == this) {
|
||||||
Button({}, Modifier.padding(8.dp)) {
|
Button({}, Modifier.padding(8.dp)) {
|
||||||
Text(newProjectType.name)
|
Text(name)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
{
|
{
|
||||||
projectType = newProjectType
|
projectTypeView.projectType = this
|
||||||
},
|
},
|
||||||
Modifier.padding(8.dp)
|
Modifier.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
Text(newProjectType.name)
|
Text(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ProjectTypeView.draw() {
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
addProjectTypeButton(MultiplatformProjectType)
|
|
||||||
addProjectTypeButton(JVMProjectType)
|
|
||||||
addProjectTypeButton(JSProjectType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.core.ui
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
|
||||||
|
|
||||||
actual object RepositoryStateDrawer : Drawer<RepositoriesView> {
|
|
||||||
override fun RepositoriesView.draw() {
|
|
||||||
CommonTextField(
|
|
||||||
item.name,
|
|
||||||
"Repository name"
|
|
||||||
) { item.name = it }
|
|
||||||
CommonTextField(
|
|
||||||
item.url,
|
|
||||||
"Repository url"
|
|
||||||
) { item.url = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -6,12 +6,14 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Divider
|
||||||
import androidx.compose.material.OutlinedTextField
|
import androidx.compose.material.OutlinedTextField
|
||||||
import androidx.compose.material.Switch
|
import androidx.compose.material.Switch
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@ -29,15 +31,15 @@ actual fun SwitchWithLabel(
|
|||||||
switchEnabled: Boolean,
|
switchEnabled: Boolean,
|
||||||
onCheckedChange: (Boolean) -> Unit
|
onCheckedChange: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
Row(Modifier.padding(0.dp, 8.dp), Arrangement.Start, Alignment.Top) {
|
Row(Modifier.padding(0.dp, 8.dp).clickable { onCheckedChange(!checked) }, Arrangement.Start, Alignment.Top) {
|
||||||
val switchCreator = @Composable {
|
val switchCreator = @Composable {
|
||||||
Switch(checked, onCheckedChange, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
|
Switch(checked, null, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
|
||||||
}
|
}
|
||||||
if (placeSwitchAtTheStart) {
|
if (placeSwitchAtTheStart) {
|
||||||
switchCreator()
|
switchCreator()
|
||||||
}
|
}
|
||||||
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically).clickable { }) {
|
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically)) {
|
||||||
CommonText(label,)
|
CommonText(label)
|
||||||
}
|
}
|
||||||
if (!placeSwitchAtTheStart) {
|
if (!placeSwitchAtTheStart) {
|
||||||
switchCreator()
|
switchCreator()
|
||||||
@ -46,11 +48,18 @@ actual fun SwitchWithLabel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit) {
|
actual fun CommonTextField(
|
||||||
|
presetText: String,
|
||||||
|
hint: String,
|
||||||
|
onFocusChanged: (Boolean) -> Unit,
|
||||||
|
onChange: (String) -> Unit
|
||||||
|
) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
presetText,
|
presetText,
|
||||||
onChange,
|
onChange,
|
||||||
Modifier.fillMaxWidth(),
|
Modifier.fillMaxWidth().onFocusChanged {
|
||||||
|
onFocusChanged(it.isFocused)
|
||||||
|
},
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
label = {
|
label = {
|
||||||
CommonText(hint,)
|
CommonText(hint,)
|
||||||
@ -69,3 +78,15 @@ actual fun TitleText(text: String) {
|
|||||||
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
|
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun <T> ButtonsPanel(data: Iterable<T>, itemDrawer: @Composable (T) -> Unit) {
|
||||||
|
Row {
|
||||||
|
data.forEach { itemDrawer(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DefaultDivider() {
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
@ -2,33 +2,29 @@ package dev.inmo.kmppscriptbuilder.core.utils
|
|||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
|
||||||
import dev.inmo.micro_utils.common.MPPFile
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.swing.JFileChooser
|
import javax.swing.JFileChooser
|
||||||
|
|
||||||
private const val appExtension = "kpsb"
|
fun MPPFile.text() = readText()
|
||||||
|
|
||||||
private var lastFile: File? = null
|
internal var lastFile: MPPFile? = null
|
||||||
|
|
||||||
fun loadConfigFile(file: File): Config {
|
fun loadConfigFile(file: MPPFile): Config {
|
||||||
lastFile = file
|
lastFile = file
|
||||||
return serialFormat.decodeFromString(Config.serializer(), file.readText())
|
return serialFormat.decodeFromString(Config.serializer(), file.text())
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun MPPFile.text() = readText()
|
actual fun openNewConfig(onParsed: (Config) -> Unit) {
|
||||||
|
|
||||||
actual fun loadConfig(): Config? {
|
|
||||||
val fc = JFileChooser(lastFile ?.parent)
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||||
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
||||||
return when (fc.showOpenDialog(null)) {
|
when (fc.showOpenDialog(null)) {
|
||||||
JFileChooser.APPROVE_OPTION -> {
|
JFileChooser.APPROVE_OPTION -> {
|
||||||
val file = fc.selectedFile
|
val file = fc.selectedFile
|
||||||
lastFile = file
|
lastFile = file
|
||||||
return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
|
onParsed(serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText()))
|
||||||
}
|
}
|
||||||
else -> null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
|
||||||
alias(libs.plugins.jb.compose)
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$mppJavaProjectPresetPath"
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvm()
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
implementation project(":kmppscriptbuilder.core")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jvmMain {
|
|
||||||
dependencies {
|
|
||||||
implementation(compose.desktop.currentOs)
|
|
||||||
implementation libs.ktor.client.cio
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compose.desktop {
|
|
||||||
application {
|
|
||||||
mainClass = "dev.inmo.kmppscriptbuilder.desktop.BuilderKt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
|
||||||
import java.io.File
|
|
||||||
import javax.swing.JFileChooser
|
|
||||||
|
|
||||||
private const val appExtension = "kpsb"
|
|
||||||
|
|
||||||
private var lastFile: File? = null
|
|
||||||
|
|
||||||
fun loadConfigFile(file: File): Config {
|
|
||||||
lastFile = file
|
|
||||||
return serialFormat.decodeFromString(Config.serializer(), file.readText())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadConfig(): Config? {
|
|
||||||
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)) {
|
|
||||||
JFileChooser.APPROVE_OPTION -> {
|
|
||||||
val file = fc.selectedFile
|
|
||||||
lastFile = file
|
|
||||||
return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveConfig(config: Config): Boolean {
|
|
||||||
return lastFile ?.also {
|
|
||||||
it.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
|
||||||
} != null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun exportGradle(config: Config): Boolean {
|
|
||||||
val fc = JFileChooser(lastFile ?.parent)
|
|
||||||
fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
|
||||||
return when (fc.showSaveDialog(null)) {
|
|
||||||
JFileChooser.APPROVE_OPTION -> {
|
|
||||||
val file = fc.selectedFile
|
|
||||||
val mavenConfigContent = config.type.buildMavenGradleConfig(
|
|
||||||
config.mavenConfig,
|
|
||||||
config.licenses
|
|
||||||
)
|
|
||||||
File(file, "publish.gradle").apply {
|
|
||||||
delete()
|
|
||||||
createNewFile()
|
|
||||||
writeText(mavenConfigContent)
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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")))
|
|
||||||
return when (fc.showSaveDialog(null)) {
|
|
||||||
JFileChooser.APPROVE_OPTION -> {
|
|
||||||
val file = fc.selectedFile
|
|
||||||
val resultFile = if (file.extension == "") {
|
|
||||||
File(file.parentFile, "${file.name}.$appExtension")
|
|
||||||
} else {
|
|
||||||
file
|
|
||||||
}
|
|
||||||
resultFile.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
|
||||||
lastFile = resultFile
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
@ -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,51 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
|
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
|
||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
|
|
||||||
|
|
||||||
class DeveloperState(
|
|
||||||
id: String = "",
|
|
||||||
name: String = "",
|
|
||||||
eMail: String = ""
|
|
||||||
) {
|
|
||||||
var id: String by mutableStateOf(id)
|
|
||||||
var name: String by mutableStateOf(name)
|
|
||||||
var eMail: String by mutableStateOf(eMail)
|
|
||||||
|
|
||||||
fun toDeveloper() = Developer(id, name, eMail)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Developer.toDeveloperState() = DeveloperState(id, name, eMail)
|
|
||||||
|
|
||||||
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() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val addItemText: String = "Add developer"
|
|
||||||
override val removeItemText: String = "Remove developer"
|
|
||||||
|
|
||||||
override fun createItem(): DeveloperState = DeveloperState()
|
|
||||||
@Composable
|
|
||||||
override fun buildView(item: DeveloperState) {
|
|
||||||
CommonTextField(
|
|
||||||
item.id,
|
|
||||||
"Developer username"
|
|
||||||
) { item.id = it }
|
|
||||||
CommonTextField(
|
|
||||||
item.name,
|
|
||||||
"Developer name"
|
|
||||||
) { item.name = it }
|
|
||||||
CommonTextField(
|
|
||||||
item.eMail,
|
|
||||||
"Developer E-Mail"
|
|
||||||
) { item.eMail = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -7,6 +7,7 @@ kt-coroutines = "1.6.4"
|
|||||||
jb-compose = "1.2.1"
|
jb-compose = "1.2.1"
|
||||||
jb-dokka = "1.7.20"
|
jb-dokka = "1.7.20"
|
||||||
microutils = "0.14.2"
|
microutils = "0.14.2"
|
||||||
|
kjsuikit = "0.4.1"
|
||||||
|
|
||||||
ktor = "2.1.3"
|
ktor = "2.1.3"
|
||||||
|
|
||||||
@ -22,10 +23,13 @@ kt-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", vers
|
|||||||
|
|
||||||
ktor-client = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
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-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-common = { module = "dev.inmo:micro_utils.common", version.ref = "microutils" }
|
||||||
microutils-coroutines = { module = "dev.inmo:micro_utils.coroutines", 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-js = { module = "org.jetbrains.kotlin:kotlin-test-js", version.ref = "kt" }
|
||||||
kt-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kt" }
|
kt-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kt" }
|
||||||
|
@ -9,8 +9,8 @@ rootProject.name = 'kmppscriptbuilder'
|
|||||||
|
|
||||||
String[] includes = [
|
String[] includes = [
|
||||||
":core",
|
":core",
|
||||||
":desktop",
|
// ":desktop",
|
||||||
":web"
|
// ":web"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$mppJsProjectPresetPath"
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
implementation project(":kmppscriptbuilder.core")
|
|
||||||
implementation "dev.inmo:micro_utils.common:$micro_utils_version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.views.*
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.*
|
|
||||||
import org.w3c.dom.url.URL
|
|
||||||
import org.w3c.files.*
|
|
||||||
|
|
||||||
fun saveFile(content: String, filename: String) {
|
|
||||||
val a = document.body!!.appendElement("a") {
|
|
||||||
setAttribute("style", "visibility:hidden; display: none")
|
|
||||||
} as HTMLAnchorElement
|
|
||||||
val blob = Blob(arrayOf(content), BlobPropertyBag(
|
|
||||||
"application/*;charset=utf-8"
|
|
||||||
))
|
|
||||||
val url = URL.createObjectURL(blob)
|
|
||||||
a.href = url
|
|
||||||
a.download = filename
|
|
||||||
a.click()
|
|
||||||
URL.revokeObjectURL(url)
|
|
||||||
a.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
document.addEventListener(
|
|
||||||
"DOMContentLoaded",
|
|
||||||
{
|
|
||||||
val builderView = BuilderView()
|
|
||||||
|
|
||||||
(document.getElementById("openConfig") as HTMLElement).onclick = {
|
|
||||||
val targetInput = document.body!!.appendElement("input") {
|
|
||||||
setAttribute("style", "visibility:hidden; display: none")
|
|
||||||
} as HTMLInputElement
|
|
||||||
targetInput.type = "file"
|
|
||||||
targetInput.onchange = {
|
|
||||||
targetInput.files ?.also { files ->
|
|
||||||
for (i in (0 until files.length) ) {
|
|
||||||
files[i] ?.also { file ->
|
|
||||||
val reader = FileReader()
|
|
||||||
|
|
||||||
reader.onload = {
|
|
||||||
val content = it.target.asDynamic().result as String
|
|
||||||
builderView.config = serialFormat.decodeFromString(Config.serializer(), content)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.readAsText(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
targetInput.click()
|
|
||||||
targetInput.remove()
|
|
||||||
false
|
|
||||||
}
|
|
||||||
(document.getElementById("saveConfig") as HTMLElement).onclick = {
|
|
||||||
val filename = "publish.kpsb"
|
|
||||||
val content = serialFormat.encodeToString(Config.serializer(), builderView.config)
|
|
||||||
|
|
||||||
saveFile(content, filename)
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
(document.getElementById("exportScript") as HTMLElement).onclick = {
|
|
||||||
val filename = "publish.gradle"
|
|
||||||
|
|
||||||
val content = builderView.config.run {
|
|
||||||
type.buildMavenGradleConfig(
|
|
||||||
mavenConfig,
|
|
||||||
licenses
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
saveFile(content, filename)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.utils
|
|
||||||
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
var HTMLElement.ukActive: Boolean
|
|
||||||
get() = classList.contains("uk-active")
|
|
||||||
set(value) {
|
|
||||||
if (value) {
|
|
||||||
classList.add("uk-active")
|
|
||||||
} else {
|
|
||||||
classList.remove("uk-active")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.utils
|
|
||||||
|
|
||||||
import kotlinx.browser.document
|
|
||||||
|
|
||||||
inline fun <R> keepScrolling(crossinline block: () -> R): R = document.body ?.let {
|
|
||||||
val (x, y) = (it.scrollLeft to it.scrollTop)
|
|
||||||
return block().also { _ ->
|
|
||||||
it.scrollTo(x, y)
|
|
||||||
}
|
|
||||||
} ?: block()
|
|
@ -1,23 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
class BuilderView : View {
|
|
||||||
private val projectTypeView = ProjectTypeView()
|
|
||||||
private val licensesView = LicensesView(document.getElementById("licensesListDiv") as HTMLElement)
|
|
||||||
private val mavenInfoTypeView = MavenProjectInfoView()
|
|
||||||
|
|
||||||
var config: Config
|
|
||||||
get() = Config(
|
|
||||||
licensesView.licenses,
|
|
||||||
mavenInfoTypeView.mavenConfig,
|
|
||||||
projectTypeView.projectType
|
|
||||||
)
|
|
||||||
set(value) {
|
|
||||||
licensesView.licenses = value.licenses
|
|
||||||
mavenInfoTypeView.mavenConfig = value.mavenConfig
|
|
||||||
projectTypeView.projectType = value.type
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
class DevelopersView(rootElement: HTMLElement) : MutableListView<Developer>(rootElement, "Add developer", "Remove developer") {
|
|
||||||
private val HTMLElement.usernameElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[0] as HTMLInputElement
|
|
||||||
private val HTMLElement.nameElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[1] as HTMLInputElement
|
|
||||||
private val HTMLElement.emailElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[2] as HTMLInputElement
|
|
||||||
|
|
||||||
var developers: List<Developer>
|
|
||||||
get() = elements.map {
|
|
||||||
Developer(it.usernameElement.value, it.nameElement.value, it.emailElement.value)
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
data = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPlainObject(): Developer = Developer("", "", "")
|
|
||||||
|
|
||||||
override fun HTMLElement.addContentBeforeRemoveButton(value: Developer) {
|
|
||||||
createTextField("Developer ID", "Developer username").value = value.id
|
|
||||||
createTextField("Developer name", "").value = value.name
|
|
||||||
createTextField("Developer E-Mail", "").value = value.eMail
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: Developer, to: Developer) {
|
|
||||||
usernameElement.value = to.id
|
|
||||||
nameElement.value = to.name
|
|
||||||
emailElement.value = to.eMail
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.License
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
|
||||||
import dev.inmo.micro_utils.coroutines.safeActor
|
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.channels.Channel
|
|
||||||
import kotlinx.coroutines.channels.SendChannel
|
|
||||||
import kotlinx.coroutines.flow.consumeAsFlow
|
|
||||||
import kotlinx.coroutines.flow.debounce
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
class LicensesView(
|
|
||||||
rootElement: HTMLElement,
|
|
||||||
client: HttpClient = HttpClient(),
|
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
|
||||||
) : MutableListView<License>(rootElement, "Add empty license", "Remove license") {
|
|
||||||
private val HTMLElement.idElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[0] as HTMLInputElement
|
|
||||||
private val HTMLElement.titleElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[1] as HTMLInputElement
|
|
||||||
private val HTMLElement.urlElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[2] as HTMLInputElement
|
|
||||||
|
|
||||||
private class LicenseOfferList(
|
|
||||||
rootElement: HTMLElement,
|
|
||||||
private val licensesView: LicensesView,
|
|
||||||
client: HttpClient,
|
|
||||||
scope: CoroutineScope
|
|
||||||
) : ListView<License>(rootElement, useSimpleDiffStrategy = true) {
|
|
||||||
private var licensesTemplates: List<License> = emptyList()
|
|
||||||
|
|
||||||
init {
|
|
||||||
scope.launch {
|
|
||||||
licensesTemplates = client.getLicenses().values.toList()
|
|
||||||
changeActor.send(Unit) // update list of searches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val changeActor: SendChannel<Unit> = scope.run {
|
|
||||||
val onChangeActor = Channel<Unit>(Channel.CONFLATED)
|
|
||||||
onChangeActor.consumeAsFlow().subscribeSafelyWithoutExceptions(scope) {
|
|
||||||
val lowercased = searchString
|
|
||||||
data = if (lowercased.isEmpty()) {
|
|
||||||
emptyList()
|
|
||||||
} else {
|
|
||||||
licensesTemplates.filter {
|
|
||||||
val lowercasedTitle = it.title.lowercase()
|
|
||||||
lowercased.all { it in lowercasedTitle }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onChangeActor
|
|
||||||
}
|
|
||||||
private val searchElement = rootElement.createTextField("Quick add", "Type some license name part to find it").apply {
|
|
||||||
oninput = {
|
|
||||||
changeActor.trySend(Unit)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private var searchString: String
|
|
||||||
get() = searchElement.value.lowercase()
|
|
||||||
set(value) {
|
|
||||||
searchElement.value = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.placeElement(value: License) {
|
|
||||||
createCommonButton(value.title).onclick = {
|
|
||||||
searchString = ""
|
|
||||||
licensesView.licenses += value
|
|
||||||
changeActor.trySend(Unit)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: License, to: License) {
|
|
||||||
getElementsByTagName("button")[0] ?.remove()
|
|
||||||
placeElement(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val licensesOffersList = LicenseOfferList(
|
|
||||||
rootElement.appendElement("div") { classList.add("uk-padding-small") } as HTMLElement,
|
|
||||||
this,
|
|
||||||
client,
|
|
||||||
scope
|
|
||||||
)
|
|
||||||
|
|
||||||
var licenses: List<License>
|
|
||||||
get() = elements.map {
|
|
||||||
License(it.idElement.value, it.titleElement.value, it.urlElement.value)
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
data = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPlainObject(): License = License("", "", "")
|
|
||||||
|
|
||||||
override fun HTMLElement.addContentBeforeRemoveButton(value: License) {
|
|
||||||
createTextField("License Id", "Short name like \"Apache-2.0\"").value = value.id
|
|
||||||
createTextField("License Title", "Official title of license (like \"Apache Software License 2.0\")").value = value.title
|
|
||||||
createTextField("License URL", "Link to your LICENSE file OR official license file (like \"https://opensource.org/licenses/Apache-2.0\")").value = value.url ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: License, to: License) {
|
|
||||||
idElement.value = to.id
|
|
||||||
titleElement.value = to.title
|
|
||||||
urlElement.value = to.url ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.common.calculateStrictDiff
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
abstract class ListView<T>(
|
|
||||||
protected val rootElement: HTMLElement,
|
|
||||||
useSimpleDiffStrategy: Boolean = false
|
|
||||||
) : View {
|
|
||||||
protected val elements = mutableListOf<HTMLElement>()
|
|
||||||
private val diffHandling: (old: List<T>, new: List<T>) -> Unit = if (useSimpleDiffStrategy) {
|
|
||||||
{ _, new ->
|
|
||||||
elements.forEach { it.remove() }
|
|
||||||
elements.clear()
|
|
||||||
new.forEach {
|
|
||||||
val element = instantiateElement()
|
|
||||||
elements.add(element)
|
|
||||||
element.placeElement(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
{ old, new ->
|
|
||||||
val diff = old.calculateStrictDiff(new)
|
|
||||||
diff.removed.forEach {
|
|
||||||
elements[it.index].remove()
|
|
||||||
elements.removeAt(it.index)
|
|
||||||
println(it.value)
|
|
||||||
}
|
|
||||||
diff.added.forEach {
|
|
||||||
val element = instantiateElement()
|
|
||||||
elements.add(element)
|
|
||||||
element.placeElement(it.value)
|
|
||||||
}
|
|
||||||
diff.replaced.forEach { (old, new) ->
|
|
||||||
val element = elements.getOrNull(old.index) ?.also { it.updateElement(old.value, new.value) }
|
|
||||||
if (element == null) {
|
|
||||||
val newElement = instantiateElement()
|
|
||||||
newElement.placeElement(new.value)
|
|
||||||
elements[new.index] = newElement
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected var data: List<T> = emptyList()
|
|
||||||
set(value) {
|
|
||||||
val old = field
|
|
||||||
field = value
|
|
||||||
diffHandling(old, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun HTMLElement.placeElement(value: T)
|
|
||||||
protected abstract fun HTMLElement.updateElement(from: T, to: T)
|
|
||||||
|
|
||||||
private fun instantiateElement() = rootElement.appendElement("div") {
|
|
||||||
classList.add("uk-padding-small")
|
|
||||||
} as HTMLElement
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.utils.ukActive
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
import org.w3c.dom.HTMLInputElement
|
|
||||||
|
|
||||||
class MavenProjectInfoView : View {
|
|
||||||
private val nameElement = document.getElementById("projectNameInput") as HTMLInputElement
|
|
||||||
private val descriptionElement = document.getElementById("projectDescriptionInput") as HTMLInputElement
|
|
||||||
private val urlElement = document.getElementById("projectUrlInput") as HTMLInputElement
|
|
||||||
private val vcsUrlElement = document.getElementById("projectVCSUrlInput") as HTMLInputElement
|
|
||||||
private val disableGpgSigningElement = document.getElementById("disableGpgSigning") as HTMLElement
|
|
||||||
private val optionalGpgSigningElement = document.getElementById("optionalGpgSigning") as HTMLElement
|
|
||||||
private val enableGpgSigningElement = document.getElementById("enableGpgSigning") as HTMLElement
|
|
||||||
private val includeMavenCentralElement = document.getElementById("includeMavenCentralTargetRepoToggle") as HTMLInputElement
|
|
||||||
private val developersView = DevelopersView(document.getElementById("developersListDiv") as HTMLElement)
|
|
||||||
private val repositoriesView = RepositoriesView(document.getElementById("repositoriesListDiv") as HTMLElement)
|
|
||||||
|
|
||||||
private var gpgSignMode: GpgSigning = GpgSigning.Disabled
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
when (value) {
|
|
||||||
GpgSigning.Enabled -> {
|
|
||||||
enableGpgSigningElement.ukActive = true
|
|
||||||
disableGpgSigningElement.ukActive = false
|
|
||||||
optionalGpgSigningElement.ukActive = false
|
|
||||||
}
|
|
||||||
GpgSigning.Optional -> {
|
|
||||||
enableGpgSigningElement.ukActive = false
|
|
||||||
disableGpgSigningElement.ukActive = false
|
|
||||||
optionalGpgSigningElement.ukActive = true
|
|
||||||
}
|
|
||||||
GpgSigning.Disabled -> {
|
|
||||||
enableGpgSigningElement.ukActive = false
|
|
||||||
disableGpgSigningElement.ukActive = true
|
|
||||||
optionalGpgSigningElement.ukActive = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mavenConfig: MavenConfig
|
|
||||||
get() = MavenConfig(
|
|
||||||
nameElement.value.ifBlank { defaultProjectName },
|
|
||||||
descriptionElement.value.ifBlank { defaultProjectDescription },
|
|
||||||
urlElement.value,
|
|
||||||
vcsUrlElement.value,
|
|
||||||
developersView.developers,
|
|
||||||
repositoriesView.repositories + if (includeMavenCentralElement.checked) {
|
|
||||||
listOf(SonatypeRepository)
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
},
|
|
||||||
when {
|
|
||||||
optionalGpgSigningElement.ukActive -> GpgSigning.Optional
|
|
||||||
enableGpgSigningElement.ukActive -> GpgSigning.Enabled
|
|
||||||
else -> GpgSigning.Disabled
|
|
||||||
}
|
|
||||||
)
|
|
||||||
set(value) {
|
|
||||||
nameElement.value = value.name
|
|
||||||
descriptionElement.value = value.description
|
|
||||||
urlElement.value = value.url
|
|
||||||
vcsUrlElement.value = value.vcsUrl
|
|
||||||
gpgSignMode = if (value.includeGpgSigning) {
|
|
||||||
GpgSigning.Enabled
|
|
||||||
} else {
|
|
||||||
value.gpgSigning
|
|
||||||
}
|
|
||||||
developersView.developers = value.developers
|
|
||||||
val reposWithoutSonatype = value.repositories.filter { it != SonatypeRepository }
|
|
||||||
includeMavenCentralElement.checked = value.repositories.size != reposWithoutSonatype.size
|
|
||||||
repositoriesView.repositories = reposWithoutSonatype
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
enableGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Enabled; Unit }
|
|
||||||
disableGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Disabled; Unit }
|
|
||||||
optionalGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Optional; Unit }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.utils.keepScrolling
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
abstract class MutableListView<T>(
|
|
||||||
rootElement: HTMLElement,
|
|
||||||
addButtonText: String = "Add",
|
|
||||||
private val removeButtonText: String = "Remove"
|
|
||||||
) : ListView<T>(rootElement) {
|
|
||||||
init {
|
|
||||||
rootElement.createPrimaryButton(addButtonText).apply {
|
|
||||||
onclick = {
|
|
||||||
keepScrolling {
|
|
||||||
val newObject = createPlainObject()
|
|
||||||
data += newObject
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun createPlainObject(): T
|
|
||||||
protected open fun HTMLElement.addContentBeforeRemoveButton(value: T) {}
|
|
||||||
protected open fun HTMLElement.addContentAfterRemoveButton(value: T) {}
|
|
||||||
final override fun HTMLElement.placeElement(value: T) {
|
|
||||||
addContentBeforeRemoveButton(value)
|
|
||||||
addRemoveButton()
|
|
||||||
addContentAfterRemoveButton(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun HTMLElement.addRemoveButton() {
|
|
||||||
val button = createPrimaryButton(removeButtonText)
|
|
||||||
button.onclick = {
|
|
||||||
elements.indexOf(button.parentElement).takeIf { it > -1 } ?.also {
|
|
||||||
data -= data[it]
|
|
||||||
} ?: rootElement.removeChild(this@addRemoveButton)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.*
|
|
||||||
import dev.inmo.kmppscriptbuilder.web.utils.ukActive
|
|
||||||
import kotlinx.browser.document
|
|
||||||
import org.w3c.dom.HTMLElement
|
|
||||||
|
|
||||||
class ProjectTypeView : View {
|
|
||||||
private val mppProjectTypeElement = document.getElementById("mppProjectType") as HTMLElement
|
|
||||||
private val jvmProjectTypeElement = document.getElementById("jvmProjectType") as HTMLElement
|
|
||||||
private val jsProjectTypeElement = document.getElementById("jsProjectType") as HTMLElement
|
|
||||||
|
|
||||||
var projectType: ProjectType
|
|
||||||
get() = when {
|
|
||||||
jvmProjectTypeElement.ukActive -> JVMProjectType
|
|
||||||
jsProjectTypeElement.ukActive -> JSProjectType
|
|
||||||
else -> MultiplatformProjectType
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
mppProjectTypeElement.ukActive = value == MultiplatformProjectType
|
|
||||||
jvmProjectTypeElement.ukActive = value == JVMProjectType
|
|
||||||
jsProjectTypeElement.ukActive = value == JSProjectType
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
mppProjectTypeElement.onclick = {
|
|
||||||
projectType = MultiplatformProjectType
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
jvmProjectTypeElement.onclick = {
|
|
||||||
projectType = JVMProjectType
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
jsProjectTypeElement.onclick = {
|
|
||||||
projectType = JSProjectType
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
class RepositoriesView(rootElement: HTMLElement) : MutableListView<MavenPublishingRepository>(rootElement, "Add repository", "Remove repository") {
|
|
||||||
private val HTMLElement.nameElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[0] as HTMLInputElement
|
|
||||||
private val HTMLElement.urlElement: HTMLInputElement
|
|
||||||
get() = getElementsByTagName("input")[1] as HTMLInputElement
|
|
||||||
|
|
||||||
var repositories: List<MavenPublishingRepository>
|
|
||||||
get() = elements.map {
|
|
||||||
MavenPublishingRepository(it.nameElement.value, it.urlElement.value)
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
data = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPlainObject(): MavenPublishingRepository = MavenPublishingRepository("", "")
|
|
||||||
|
|
||||||
override fun HTMLElement.addContentBeforeRemoveButton(value: MavenPublishingRepository) {
|
|
||||||
createTextField("Repository name", "This name will be used to identify repository in grade").value = value.name
|
|
||||||
createTextField("Repository URL", "For example: https://repo.maven.apache.org/maven2/").value = value.url
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun HTMLElement.updateElement(from: MavenPublishingRepository, to: MavenPublishingRepository) {
|
|
||||||
nameElement.value = to.name
|
|
||||||
urlElement.value = to.url
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
interface View
|
|
@ -1,35 +0,0 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.web.views
|
|
||||||
|
|
||||||
import kotlinx.dom.appendElement
|
|
||||||
import org.w3c.dom.*
|
|
||||||
|
|
||||||
fun HTMLElement.createTextField(
|
|
||||||
label: String,
|
|
||||||
placeholder: String
|
|
||||||
): HTMLInputElement {
|
|
||||||
return appendElement("div") {
|
|
||||||
classList.add("uk-margin", "uk-width-1-1")
|
|
||||||
}.appendElement("label") {
|
|
||||||
classList.add("uk-form-label")
|
|
||||||
innerHTML = label
|
|
||||||
}.run {
|
|
||||||
val input = appendElement("input") {
|
|
||||||
classList.add("uk-input", "uk-width-expand")
|
|
||||||
setAttribute("type", "text")
|
|
||||||
setAttribute("placeholder", placeholder)
|
|
||||||
} as HTMLInputElement
|
|
||||||
input
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun HTMLElement.createPrimaryButton(text: String): HTMLButtonElement = (appendElement("button") {
|
|
||||||
classList.add("uk-button", "uk-button-primary")
|
|
||||||
} as HTMLButtonElement).apply {
|
|
||||||
innerText = text
|
|
||||||
}
|
|
||||||
|
|
||||||
fun HTMLElement.createCommonButton(text: String): HTMLButtonElement = (appendElement("button") {
|
|
||||||
classList.add("uk-button", "uk-button-default")
|
|
||||||
} as HTMLButtonElement).apply {
|
|
||||||
innerText = text
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Kotlin Publication Scripts Builder</title>
|
|
||||||
<!-- UIkit CSS -->
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/css/uikit.min.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class="uk-navbar-container" uk-navbar>
|
|
||||||
<div class="uk-navbar-left">
|
|
||||||
<div class="uk-padding-small uk-text-lead">Kotlin Publication Scripts Builder</div>
|
|
||||||
<div class="uk-padding-small"><a href="https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder"><img src="https://img.shields.io/github/stars/InsanusMokrassar/KotlinPublicationScriptsBuilder?label=Github&style=plastic"/></a></div>
|
|
||||||
</div>
|
|
||||||
<div class="uk-navbar-right">
|
|
||||||
<ul class="uk-navbar-nav">
|
|
||||||
<li uk-tooltip="title: Open config" id="openConfig"><a href="#"><span uk-icon="icon: pull"></span></a></li><!--Open file-->
|
|
||||||
<li uk-tooltip="title: Save config" id="saveConfig"><a href="#"><span uk-icon="icon: push"></span></a></li><!--Save file-->
|
|
||||||
<li uk-tooltip="title: Export script" id="exportScript"><a href="#"><span uk-icon="icon: upload"></span></a></li><!--Save file-->
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<form class="uk-padding-small">
|
|
||||||
<fieldset class="uk-fieldset">
|
|
||||||
<legend class="uk-legend">Project type</legend>
|
|
||||||
<div class="uk-padding-small">
|
|
||||||
<ul class="uk-subnav uk-subnav-pill">
|
|
||||||
<li id="mppProjectType" class="uk-active"><a href="#">Multiplatform</a></li>
|
|
||||||
<li id="jvmProjectType"><a href="#">JVM</a></li>
|
|
||||||
<li id="jsProjectType"><a href="#">JS</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<legend class="uk-legend">Licenses</legend>
|
|
||||||
<div id="licensesListDiv" class="uk-padding-small"></div>
|
|
||||||
|
|
||||||
<legend class="uk-legend">Project information</legend>
|
|
||||||
|
|
||||||
<div class="uk-padding-small">
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectNameInput">Public project name</label>
|
|
||||||
<input id="projectNameInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectDescriptionInput">Public project description</label>
|
|
||||||
<input id="projectDescriptionInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectUrlInput">Public project URL</label>
|
|
||||||
<input id="projectUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github or other source with readme">
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin uk-width-1-1">
|
|
||||||
<label class="uk-form-label" for="projectVCSUrlInput">Public project VCS URL (with .git)</label>
|
|
||||||
<input id="projectVCSUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github .git file">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="uk-margin">
|
|
||||||
<label>GPG Signing</label>
|
|
||||||
|
|
||||||
<div class="uk-padding-small">
|
|
||||||
<ul class="uk-subnav uk-subnav-pill">
|
|
||||||
<li id="disableGpgSigning" class="uk-active" uk-tooltip="title: Signing will not be added"><a href="#">Disabled</a></li>
|
|
||||||
<li id="optionalGpgSigning" uk-tooltip="title: Signing will be added, but disabled in case of absence 'signatory.keyId'"><a href="#">Optional</a></li>
|
|
||||||
<li id="enableGpgSigning" uk-tooltip="title: Signing will be always enabled"><a href="#">Enabled</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="uk-margin">
|
|
||||||
<label><input id="includeMavenCentralTargetRepoToggle" class="uk-checkbox" type="checkbox"> Include publication to MavenCentral</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<legend class="uk-legend">Developers info</legend>
|
|
||||||
<div id="developersListDiv" class="uk-padding-small"></div>
|
|
||||||
|
|
||||||
<legend class="uk-legend">Repositories info</legend>
|
|
||||||
<div id="repositoriesListDiv" class="uk-padding-small"></div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
<!-- UIkit JS -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/js/uikit.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/js/uikit-icons.min.js"></script>
|
|
||||||
<!-- Internal JS -->
|
|
||||||
<script src="kmppscriptbuilder.web.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|