diff options
6 files changed, 96 insertions, 50 deletions
diff --git a/kvision-modules/kvision-upload/build.gradle b/kvision-modules/kvision-upload/build.gradle index 8b90532c..21ac7eab 100644 --- a/kvision-modules/kvision-upload/build.gradle +++ b/kvision-modules/kvision-upload/build.gradle @@ -1,5 +1,9 @@ apply from: "../shared.gradle" +dependencies { + compile "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion" +} + kotlinFrontend { npm { diff --git a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt new file mode 100644 index 00000000..bdae5091 --- /dev/null +++ b/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.utils + +import kotlinx.coroutines.suspendCancellableCoroutine +import org.w3c.files.File +import org.w3c.files.FileReader +import pl.treksoft.kvision.form.Form +import pl.treksoft.kvision.form.FormPanel +import pl.treksoft.kvision.form.KFilesFormControl +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException + +/** + * Suspending extension function to get file content. + * @return file content + */ +suspend fun File.getContent(): String = suspendCancellableCoroutine { cont -> + val reader = FileReader() + reader.onload = { + @Suppress("UnsafeCastFromDynamic") + cont.resume(reader.result) + } + reader.onerror = { e -> + cont.resumeWithException(Exception(e.type)) + } + reader.readAsDataURL(this@getContent) +} + +/** + * Returns current data model with file content read for all KFiles controls. + * @return data model + */ +suspend fun <K : Any> Form<K>.getDataWithFileContent(): K { + val map = this.fields.entries.associateBy({ it.key }, { + val value = it.value + if (value is KFilesFormControl) { + value.getValue()?.map { + it.copy(content = value.getNativeFile(it)?.getContent()) + } + } else { + value.getValue() + } + }) + return this.modelFactory(map.withDefault { null }) +} + +/** + * Returns current data model with file content read for all KFiles controls. + * @return data model + */ +suspend fun <K : Any> FormPanel<K>.getDataWithFileContent(): K { + return this.form.getDataWithFileContent() +} diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FieldLabel.kt b/src/main/kotlin/pl/treksoft/kvision/form/FieldLabel.kt index e6aad194..4684b1be 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/FieldLabel.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/FieldLabel.kt @@ -21,6 +21,7 @@ */ package pl.treksoft.kvision.form +import pl.treksoft.kvision.core.Container import pl.treksoft.kvision.core.StringPair import pl.treksoft.kvision.html.TAG import pl.treksoft.kvision.html.Tag @@ -46,4 +47,19 @@ open class FieldLabel( return super.getSnAttrs() + ("for" to forId) } + companion object { + /** + * DSL builder extension function. + * + * It takes the same parameters as the constructor of the built component. + */ + fun Container.fieldLabel( + forId: String, content: String? = null, rich: Boolean = false, + classes: Set<String> = setOf("control-label"), init: (FieldLabel.() -> Unit)? = null + ): FieldLabel { + val fieldLabel = FieldLabel(forId, content, rich, classes).apply { init?.invoke(this) } + this.add(fieldLabel) + return fieldLabel + } + } } diff --git a/src/main/kotlin/pl/treksoft/kvision/form/Form.kt b/src/main/kotlin/pl/treksoft/kvision/form/Form.kt index 983b83e5..a2d6848c 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/Form.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/Form.kt @@ -32,7 +32,6 @@ import pl.treksoft.kvision.types.DateSerializer import pl.treksoft.kvision.types.KFile import pl.treksoft.kvision.types.toStringF import pl.treksoft.kvision.utils.JSON -import pl.treksoft.kvision.utils.getContent import kotlin.js.Date import kotlin.js.Json import kotlin.reflect.KProperty1 @@ -79,8 +78,8 @@ private class FormMapWrapper<out V>(private val map: Map<String, V>) : Map<Strin @Suppress("TooManyFunctions") class Form<K : Any>(private val panel: FormPanel<K>? = null, private val serializer: KSerializer<K>) { - internal val modelFactory: (Map<String, Any?>) -> K - internal val fields: MutableMap<String, FormControl> = mutableMapOf() + val modelFactory: (Map<String, Any?>) -> K + val fields: MutableMap<String, FormControl> = mutableMapOf() internal val fieldsParams: MutableMap<String, Any> = mutableMapOf() internal var validatorMessage: ((Form<K>) -> String?)? = null internal var validator: ((Form<K>) -> Boolean?)? = null @@ -279,23 +278,6 @@ class Form<K : Any>(private val panel: FormPanel<K>? = null, private val seriali return modelFactory(map.withDefault { null }) } - /** - * Returns current data model with file content read for all KFiles controls. - * @return data model - */ - suspend fun getDataWithFileContent(): K { - val map = fields.entries.associateBy({ it.key }, { - val value = it.value - if (value is KFilesFormControl) { - value.getValue()?.map { - it.copy(content = value.getNativeFile(it)?.getContent()) - } - } else { - value.getValue() - } - }) - return modelFactory(map.withDefault { null }) - } /** * Returns current data model as JSON. diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt index 10b784e0..2b51c62e 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt @@ -151,7 +151,7 @@ open class FormPanel<K : Any>( * Internal property. */ @Suppress("LeakingThis") - protected val form = Form(this, serializer) + val form = Form(this, serializer) /** * @suppress * Internal property. @@ -376,14 +376,6 @@ open class FormPanel<K : Any>( } /** - * Returns current data model with file content read for all KFiles controls. - * @return data model - */ - suspend fun getDataWithFileContent(): K { - return form.getDataWithFileContent() - } - - /** * Returns current data model as JSON. * @return data model as JSON */ diff --git a/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt index 778210ab..40891bd8 100644 --- a/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt +++ b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt @@ -23,14 +23,9 @@ package pl.treksoft.kvision.utils -import kotlinx.coroutines.suspendCancellableCoroutine -import org.w3c.files.File -import org.w3c.files.FileReader import pl.treksoft.kvision.core.CssSize import pl.treksoft.kvision.core.UNIT import kotlin.browser.window -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException /** * Extension property to convert Int to CSS px units. @@ -189,22 +184,6 @@ fun Int.toHexString(): String { fun isIE11(): Boolean = window.navigator.userAgent.matches("Trident\\/7\\.") /** - * Suspending extension function to get file content. - * @return file content - */ -suspend fun File.getContent(): String = suspendCancellableCoroutine { cont -> - val reader = FileReader() - reader.onload = { - @Suppress("UnsafeCastFromDynamic") - cont.resume(reader.result) - } - reader.onerror = { e -> - cont.resumeWithException(Exception(e.type)) - } - reader.readAsDataURL(this@getContent) -} - -/** * Utility extension function to synchronise elements of the MutableList. */ fun <T> MutableList<T>.syncWithList(list: List<T>) { |