diff options
Diffstat (limited to 'src/main/kotlin')
8 files changed, 459 insertions, 1 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt index 084b60d6..8e7fcb3b 100644 --- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt +++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt @@ -21,6 +21,8 @@ import pl.treksoft.kvision.form.text.Text import pl.treksoft.kvision.form.text.TextArea import pl.treksoft.kvision.form.text.TextAreaInput import pl.treksoft.kvision.form.text.TextInput +import pl.treksoft.kvision.form.time.DateTime +import pl.treksoft.kvision.form.time.DateTimeInput import pl.treksoft.kvision.html.* import pl.treksoft.kvision.html.TAG.DIV import pl.treksoft.kvision.html.TAG.H1 @@ -32,6 +34,8 @@ import pl.treksoft.kvision.routing.routing import pl.treksoft.kvision.snabbdom.obj import pl.treksoft.kvision.utils.perc import pl.treksoft.kvision.utils.px +import pl.treksoft.kvision.utils.toDateF +import kotlin.js.Date class Showcase : ApplicationBase() { @@ -237,6 +241,57 @@ class Showcase : ApplicationBase() { } root.add(mbuttons9) + val date = DateTimeInput().apply { + placeholder = "Wprowadź datę" + size = INPUTSIZE.LARGE + todayBtn = true + showMeridian = true + daysOfWeekDisabled = arrayOf(0, 6) + + } + root.add(date) + + val date2 = DateTimeInput(Date(), format = "DD-MM-YY").apply { + disabled = true + } + root.add(date2) + + val date3 = DateTimeInput(Date(), format = "DD-MM-YYYY hh:mm A").apply { + readonly = true + showMeridian = true + } + root.add(date3) + + val date4 = DateTime(Date(), format = "HH:mm", label = "Wprowadź datę wpływu") + date4.setEventListener<DateTime> { + showBsDateTime = { + println("show dt") + } + hideBsDateTime = { + println("hide dt") + } + } + root.add(date4) + + val mbuttons10 = Button("Sprawdz daty").setEventListener<Button> { + click = { + println(date.value) + println(date.getValueAsString()) + println(date2.value) + println(date2.getValueAsString()) + println(date3.value) + println(date3.getValueAsString()) + println(date4.value) + println(date4.getValueAsString()) + date.value = "2017-01-16".toDateF("YYYY-MM-DD") + date.showPopup() + date.weekStart = 1 + date4.format = "mm:HH" + date4.disabled = !date4.disabled + } + } + root.add(mbuttons10) + val container = SimplePanel(setOf("abc", "def")) val h1 = Tag(H1, "To jest <i>test pisania</i> tekstu", false, null, classes = setOf("test", "test2")) container.add(h1) diff --git a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt index e3c34190..65a7fe6e 100644 --- a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt +++ b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt @@ -29,6 +29,9 @@ object KVManager { private val bootstrapSelectAjaxI18n = require("./js/ajax-bootstrap-select.pl-PL.js") private val trixCss = require("trix/dist/trix.css") private val trix = require("trix") + private val bootstrapDateTimePickerCss = require("bootstrap-datetime-picker/css/bootstrap-datetimepicker.min.css") + private val bootstrapDateTimePicker = require("bootstrap-datetime-picker/js/bootstrap-datetimepicker.min.js") + internal val fecha = require("fecha") private val sdPatch = Snabbdom.init(arrayOf(classModule, attributesModule, propsModule, styleModule, eventListenersModule, datasetModule)) diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FormField.kt b/src/main/kotlin/pl/treksoft/kvision/form/FormField.kt index dd7ae745..503ee51d 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/FormField.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/FormField.kt @@ -1,5 +1,7 @@ package pl.treksoft.kvision.form +import kotlin.js.Date + enum class INPUTSIZE(val className: String) { LARGE("input-lg"), SMALL("input-sm") @@ -25,3 +27,8 @@ interface BoolFormField : FormField { var value: Boolean override fun getValueAsString(): String? = value.toString() } + +interface DateFormField : FormField { + var value: Date? + override fun getValueAsString(): String? = value?.toString() +} diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt index 4d0ebf51..0b50cbab 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt @@ -1,9 +1,9 @@ package pl.treksoft.kvision.form.text -import pl.treksoft.kvision.panel.SimplePanel import pl.treksoft.kvision.core.Widget import pl.treksoft.kvision.form.FieldLabel import pl.treksoft.kvision.form.StringFormField +import pl.treksoft.kvision.panel.SimplePanel import pl.treksoft.kvision.snabbdom.SnOn abstract class AbstractText(label: String? = null, rich: Boolean = false) : @@ -39,6 +39,16 @@ abstract class AbstractText(label: String? = null, rich: Boolean = false) : set(value) { input.disabled = value } + var autofocus + get() = input.autofocus + set(value) { + input.autofocus = value + } + var readonly + get() = input.readonly + set(value) { + input.readonly = value + } var label get() = flabel.text set(value) { diff --git a/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt new file mode 100644 index 00000000..ae732030 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt @@ -0,0 +1,142 @@ +package pl.treksoft.kvision.form.time + +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.form.DateFormField +import pl.treksoft.kvision.form.FieldLabel +import pl.treksoft.kvision.panel.SimplePanel +import pl.treksoft.kvision.snabbdom.SnOn +import kotlin.js.Date + +open class DateTime(value: Date? = null, format: String = "YYYY-MM-DD HH:mm", label: String? = null, + rich: Boolean = false) : SimplePanel(setOf("form-group")), DateFormField { + + override var value + get() = input.value + set(value) { + input.value = value + } + var format + get() = input.format + set(value) { + input.format = value + } + var placeholder + get() = input.placeholder + set(value) { + input.placeholder = value + } + var name + get() = input.name + set(value) { + input.name = value + } + override var disabled + get() = input.disabled + set(value) { + input.disabled = value + } + var autofocus + get() = input.autofocus + set(value) { + input.autofocus = value + } + var readonly + get() = input.readonly + set(value) { + input.readonly = value + } + var weekStart + get() = input.weekStart + set(value) { + input.weekStart = value + } + var daysOfWeekDisabled + get() = input.daysOfWeekDisabled + set(value) { + input.daysOfWeekDisabled = value + } + var clearBtn + get() = input.clearBtn + set(value) { + input.clearBtn = value + } + var todayBtn + get() = input.todayBtn + set(value) { + input.todayBtn = value + } + var todayHighlight + get() = input.todayHighlight + set(value) { + input.todayHighlight = value + } + var minuteStep + get() = input.minuteStep + set(value) { + input.minuteStep = value + } + var showMeridian + get() = input.showMeridian + set(value) { + input.showMeridian = value + } + var label + get() = flabel.text + set(value) { + flabel.text = value + } + var rich + get() = flabel.rich + set(value) { + flabel.rich = value + } + override var size + get() = input.size + set(value) { + input.size = value + } + + protected val idc = "kv_form_time_" + counter + internal val input: DateTimeInput = DateTimeInput(value, format).apply { id = idc } + internal val flabel: FieldLabel = FieldLabel(idc, label, rich) + + init { + this.addInternal(flabel) + @Suppress("LeakingThis") + input.eventTarget = this + this.addInternal(input) + counter++ + } + + companion object { + var counter = 0 + } + + @Suppress("UNCHECKED_CAST") + override fun <T : Widget> setEventListener(block: SnOn<T>.() -> Unit): Widget { + input.setEventListener(block) + return this + } + + override fun setEventListener(block: SnOn<Widget>.() -> Unit): Widget { + input.setEventListener(block) + return this + } + + override fun removeEventListeners(): Widget { + input.removeEventListeners() + return this + } + + open fun showPopup() { + input.showPopup() + } + + open fun hidePopup() { + input.hidePopup() + } + + override fun getValueAsString(): String? { + return input.getValueAsString() + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt new file mode 100644 index 00000000..78321c10 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt @@ -0,0 +1,226 @@ +package pl.treksoft.kvision.form.time + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.form.DateFormField +import pl.treksoft.kvision.form.INPUTSIZE +import pl.treksoft.kvision.snabbdom.StringBoolPair +import pl.treksoft.kvision.snabbdom.StringPair +import pl.treksoft.kvision.snabbdom.obj +import pl.treksoft.kvision.utils.toDateF +import pl.treksoft.kvision.utils.toStringF +import kotlin.js.Date + +const val DEFAULT_MINUTE_STEP = 5 +const val MAX_VIEW = 4 + +@Suppress("TooManyFunctions") +open class DateTimeInput(value: Date? = null, format: String = "YYYY-MM-DD HH:mm", + classes: Set<String> = setOf()) : Widget(classes + "form-control"), DateFormField { + + + init { + this.setInternalEventListener<DateTimeInput> { + change = { + self.changeValue() + } + } + } + + override var value: Date? = value + set(value) { + field = value + refreshState() + } + var format: String = format + set(value) { + field = value + refreshDatePicker() + } + var placeholder: String? = null + set(value) { + field = value + refresh() + } + var name: String? = null + set(value) { + field = value + refresh() + } + override var disabled: Boolean = false + set(value) { + field = value + refresh() + } + var autofocus: Boolean? = null + set(value) { + field = value + refresh() + } + var readonly: Boolean? = null + set(value) { + field = value + refresh() + } + override var size: INPUTSIZE? = null + set(value) { + field = value + refresh() + } + var weekStart: Int = 0 + set(value) { + field = value + refreshDatePicker() + } + var daysOfWeekDisabled: Array<Int> = arrayOf() + set(value) { + field = value + refreshDatePicker() + } + var clearBtn: Boolean = true + set(value) { + field = value + refreshDatePicker() + } + var todayBtn: Boolean = false + set(value) { + field = value + refreshDatePicker() + } + var todayHighlight: Boolean = false + set(value) { + field = value + refreshDatePicker() + } + var minuteStep: Int = DEFAULT_MINUTE_STEP + set(value) { + field = value + refreshDatePicker() + } + var showMeridian: Boolean = false + set(value) { + field = value + refreshDatePicker() + } + + override fun render(): VNode { + return kvh("input") + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + size?.let { + cl.add(it.className to true) + } + return cl + } + + override fun getSnAttrs(): List<StringPair> { + val sn = super.getSnAttrs().toMutableList() + sn.add("type" to "text") + placeholder?.let { + sn.add("placeholder" to it) + } + name?.let { + sn.add("name" to it) + } + autofocus?.let { + if (it) { + sn.add("autofocus" to "autofocus") + } + } + readonly?.let { + if (it) { + sn.add("readonly" to "readonly") + } + } + if (disabled) { + sn.add("disabled" to "true") + value?.let { + sn.add("value" to it.toStringF(format)) + } + } + return sn + } + + @Suppress("UnsafeCastFromDynamic") + protected open fun refreshState() { + value?.let { + getElementJQueryD()?.datetimepicker("update", it) + } ?: getElementJQueryD()?.datetimepicker("update", null) + } + + protected open fun refreshDatePicker() { + getElementJQueryD()?.`val`(null) + getElementJQueryD()?.datetimepicker("remove") + initDateTimePicker() + refreshState() + } + + protected open fun changeValue() { + val v = getElementJQuery()?.`val`() as String? + if (v != null && v.isNotEmpty()) { + this.value = v.toDateF(format) + } else { + this.value = null + } + } + + open fun showPopup() { + getElementJQueryD()?.datetimepicker("show") + } + + open fun hidePopup() { + getElementJQueryD()?.datetimepicker("hide") + } + + @Suppress("UnsafeCastFromDynamic") + override fun afterInsert(node: VNode) { + if (!this.disabled) { + this.initDateTimePicker() + this.getElementJQuery()?.on("changeDate", { e, _ -> + this.dispatchEvent("change", obj { detail = e }) + }) + this.getElementJQuery()?.on("show", { e, _ -> + this.dispatchEvent("showBsDateTime", obj { detail = e }) + }) + this.getElementJQuery()?.on("hide", { e, _ -> + this.dispatchEvent("hideBsDateTime", obj { detail = e }) + }) + refreshState() + } + } + + private fun initDateTimePicker() { + val datePickerFormat = format.toDatePickerFormat() + val minView = if (format.contains("HH") || format.contains("mm")) 0 else 2 + val maxView = if (format.contains("YY") || format.contains("M") || format.contains("D")) MAX_VIEW else 1 + val startView = if (maxView < 2) maxView else 2 + getElementJQueryD()?.datetimepicker(obj { + this.format = datePickerFormat + this.startView = startView + this.minView = minView + this.maxView = maxView + this.minuteStep = minuteStep + this.todayHighlight = todayHighlight + this.clearBtn = clearBtn + this.todayBtn = todayBtn + this.weekStart = weekStart + this.showMeridian = showMeridian + this.daysOfWeekDisabled = daysOfWeekDisabled + this.autoclose = true + }) + } + + override fun getValueAsString(): String? { + return value?.toStringF(format) + } + + companion object { + private fun String.toDatePickerFormat(): String { + return this.replace("YY", "yy").replace("m", "i").replace("MMMM", "{----}").replace("MMM", "{---}") + .replace("M", "m").replace("{----}", "MM").replace("{---}", "M").replace("H", "{-}") + .replace("h", "H").replace("{-}", "h").replace("D", "d").replace("a", "p").replace("A", "P") + } + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt b/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt index 3ed50967..1606e83a 100644 --- a/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt +++ b/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt @@ -49,6 +49,9 @@ interface BtOn : On { var renderedBsSelect: ((KvEvent) -> kotlin.Unit)? var refreshedBsSelect: ((KvEvent) -> kotlin.Unit)? var changedBsSelect: ((KvEvent) -> kotlin.Unit)? + var changeDate: ((KvEvent) -> kotlin.Unit)? + var showBsDateTime: ((KvEvent) -> kotlin.Unit)? + var hideBsDateTime: ((KvEvent) -> kotlin.Unit)? } interface SnOn<T> : BtOn { diff --git a/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt index e2396868..b426e432 100644 --- a/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt +++ b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt @@ -3,7 +3,9 @@ package pl.treksoft.kvision.utils import pl.treksoft.kvision.core.CssSize +import pl.treksoft.kvision.core.KVManager import pl.treksoft.kvision.core.UNIT +import kotlin.js.Date fun Int.px(): CssSize = Pair(this, UNIT.px) fun Int.em(): CssSize = Pair(this, UNIT.em) @@ -34,3 +36,13 @@ fun Int.toHexString(): String { } return result } + +@Suppress("UnsafeCastFromDynamic") +fun String.toDateF(format: String = "YYYY-MM-DD HH:mm:ss"): Date { + return KVManager.fecha.parse(this, format) +} + +@Suppress("UnsafeCastFromDynamic") +fun Date.toStringF(format: String = "YYYY-MM-DD HH:mm:ss"): String { + return KVManager.fecha.format(this, format) +} |