aboutsummaryrefslogtreecommitdiff
path: root/kvision-modules
diff options
context:
space:
mode:
Diffstat (limited to 'kvision-modules')
-rw-r--r--kvision-modules/kvision-bootstrap-css/build.gradle9
-rw-r--r--kvision-modules/kvision-bootstrap-css/package.json.d/project.info3
-rw-r--r--kvision-modules/kvision-bootstrap-css/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrapCss.kt35
-rw-r--r--kvision-modules/kvision-bootstrap-css/webpack.config.d/bootstrap.js4
-rw-r--r--kvision-modules/kvision-bootstrap-css/webpack.config.d/css.js (renamed from kvision-modules/kvision-datetime/webpack.config.d/css.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-css/webpack.config.d/jquery.js (renamed from kvision-modules/kvision-spinner/webpack.config.d/jquery.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/build.gradle13
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/package.json.d/project.info (renamed from kvision-modules/kvision-datetime/package.json.d/project.info)0
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt36
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt (renamed from kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt)99
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt377
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt (renamed from kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeInputSpec.kt (renamed from kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeInputSpec.kt)8
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeSpec.kt (renamed from kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeSpec.kt)4
-rw-r--r--kvision-modules/kvision-bootstrap-datetime/webpack.config.d/css.js (renamed from kvision-modules/kvision-select/webpack.config.d/css.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-dialog/build.gradle6
-rw-r--r--kvision-modules/kvision-bootstrap-dialog/package.json.d/project.info (renamed from kvision-modules/kvision-dialog/package.json.d/project.info)0
-rw-r--r--kvision-modules/kvision-bootstrap-dialog/src/main/kotlin/pl/treksoft/kvision/modal/Dialog.kt (renamed from kvision-modules/kvision-dialog/src/main/kotlin/pl/treksoft/kvision/modal/Dialog.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-dialog/webpack.config.d/css.js (renamed from kvision-modules/kvision-spinner/webpack.config.d/css.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select-remote/build.gradle (renamed from kvision-modules/kvision-select-remote/build.gradle)2
-rw-r--r--kvision-modules/kvision-bootstrap-select-remote/package.json.d/project.info (renamed from kvision-modules/kvision-select-remote/package.json.d/project.info)0
-rw-r--r--kvision-modules/kvision-bootstrap-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemote.kt (renamed from kvision-modules/kvision-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemote.kt)8
-rw-r--r--kvision-modules/kvision-bootstrap-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemoteInput.kt (renamed from kvision-modules/kvision-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemoteInput.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-select-remote/webpack.config.d/css.js (renamed from kvision-modules/kvision-upload/webpack.config.d/css.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/build.gradle14
-rw-r--r--kvision-modules/kvision-bootstrap-select/package.json.d/project.info (renamed from kvision-modules/kvision-select/package.json.d/project.info)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/KVManagerSelect.kt (renamed from kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/KVManagerSelect.kt)21
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/AjaxOptions.kt (renamed from kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/AjaxOptions.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt (renamed from kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt)8
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt (renamed from kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt)8
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOptGroup.kt (renamed from kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOptGroup.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOption.kt (renamed from kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOption.kt)6
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.cs-CZ.min.js23
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.en-US.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.en-US.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.it-IT.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.it-IT.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ja-JP.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ja-JP.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ko-KR.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ko-KR.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.nl-NL.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.nl-NL.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.sr-SP.min.js23
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/bootstrap-select/bootstrap-select-i18n.min.js (renamed from kvision-modules/kvision-select/src/main/resources/js/locales/bootstrap-select/bootstrap-select-i18n.min.js)2
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt (renamed from kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectInputSpec.kt (renamed from kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectInputSpec.kt)2
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptGroupSpec.kt (renamed from kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptGroupSpec.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptionSpec.kt (renamed from kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptionSpec.kt)4
-rw-r--r--kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectSpec.kt (renamed from kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectSpec.kt)6
-rw-r--r--kvision-modules/kvision-bootstrap-select/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-bootstrap-select/webpack.config.d/jquery.js5
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/build.gradle13
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/package.json.d/project.info (renamed from kvision-modules/kvision-spinner/package.json.d/project.info)0
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/KVManagerSpinner.kt (renamed from kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/KVManagerSpinner.kt)10
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt (renamed from kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt)72
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt (renamed from kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt)86
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt (renamed from kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerInputSpec.kt (renamed from kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerInputSpec.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerSpec.kt (renamed from kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerSpec.kt)4
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-bootstrap-spinner/webpack.config.d/jquery.js5
-rw-r--r--kvision-modules/kvision-bootstrap-upload/build.gradle14
-rw-r--r--kvision-modules/kvision-bootstrap-upload/package.json.d/project.info (renamed from kvision-modules/kvision-upload/package.json.d/project.info)0
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/KVManagerUpload.kt (renamed from kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/KVManagerUpload.kt)22
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/Upload.kt (renamed from kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/Upload.kt)8
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt (renamed from kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt)12
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt (renamed from kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ar.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ar.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/az.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/az.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/bg.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/bg.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ca.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ca.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/cr.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/cr.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/cs.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/cs.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/da.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/da.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/de.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/de.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/el.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/el.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/es.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/es.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/et.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/et.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fa.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fa.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fi.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fi.js)14
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fr.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fr.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/gl.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/gl.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/he.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/he.js)11
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/hu.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/hu.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/id.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/id.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/it.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/it.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ja.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ja.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ka.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ka.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/kr.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ko.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/kz.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/kz.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/lt.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/lt.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/nl.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/nl.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/no.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/no.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pl.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pl.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt-BR.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt-BR.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js111
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ro.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ro.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ru.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ru.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sk.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sk.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sl.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sl.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sv.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sv.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/th.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/th.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/tr.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/tr.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/uk.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/uk.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/uz.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/uz.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/vi.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/vi.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/zh-TW.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/zh-TW.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/zh.js (renamed from kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/zh.js)15
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt (renamed from kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadInputSpec.kt (renamed from kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadInputSpec.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadSpec.kt (renamed from kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadSpec.kt)0
-rw-r--r--kvision-modules/kvision-bootstrap-upload/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-bootstrap-upload/webpack.config.d/file.js (renamed from kvision-modules/kvision-upload/webpack.config.d/file.js)0
-rw-r--r--kvision-modules/kvision-bootstrap-upload/webpack.config.d/jquery.js5
-rw-r--r--kvision-modules/kvision-bootstrap/build.gradle14
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrap.kt54
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/core/Component.kt133
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt112
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt417
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt61
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt57
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Alert.kt121
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/CloseIcon.kt48
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Confirm.kt176
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt292
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Nav.kt110
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/NavForm.kt72
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Navbar.kt229
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt185
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt273
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressBar.kt162
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressIndicator.kt125
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/ButtonGroup.kt109
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/Toolbar.kt63
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt48
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt48
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/Window.kt449
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/resources/css/paper.css16
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/resources/css/style.css226
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.js64
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.less0
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt4
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/ContextMenuSpec.kt76
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt29
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/HeaderSpec.kt46
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/SeparatorSpec.kt46
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/modal/AlertSpec.kt16
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavFormSpec.kt54
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavSpec.kt54
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavbarSpec.kt71
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/ResponsiveGridPanelSpec.kt50
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt117
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressBarSpec.kt56
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressIndicatorSpec.kt55
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ButtonGroupSpec.kt56
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ToolbarSpec.kt47
-rw-r--r--kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/window/WindowSpec.kt11
-rw-r--r--kvision-modules/kvision-chart/build.gradle4
-rw-r--r--kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt6
-rw-r--r--kvision-modules/kvision-chart/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-cordova/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-datacontainer/build.gradle11
-rw-r--r--kvision-modules/kvision-datacontainer/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-datetime/build.gradle13
-rw-r--r--kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt81
-rw-r--r--kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt320
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ar.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.az.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bg.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bn.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ca.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.cs.js20
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.da.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.de.js19
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ee.js19
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.el.js16
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.es.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fi.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fr.js19
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.he.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hr.js16
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hu.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hy.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.id.js20
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.is.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.it.js19
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ja.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ka.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ko.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lt.js19
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lv.js19
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ms.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nb.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nl.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.no.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pl.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt-BR.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ro.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs-latin.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ru.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sk.js20
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sl.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sv.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sw.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.th.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.tr.js18
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ua.js16
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.uk.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh-TW.js17
-rw-r--r--kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh.js17
-rw-r--r--kvision-modules/kvision-dialog/build.gradle16
-rw-r--r--kvision-modules/kvision-fontawesome/build.gradle9
-rw-r--r--kvision-modules/kvision-fontawesome/package.json.d/project.info3
-rw-r--r--kvision-modules/kvision-fontawesome/src/main/kotlin/pl/treksoft/kvision/KVManagerFontAwesome.kt35
-rw-r--r--kvision-modules/kvision-fontawesome/webpack.config.d/bootstrap.js4
-rw-r--r--kvision-modules/kvision-fontawesome/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-fontawesome/webpack.config.d/jquery.js5
-rw-r--r--kvision-modules/kvision-handlebars/build.gradle6
-rw-r--r--kvision-modules/kvision-handlebars/src/main/kotlin/pl/treksoft/kvision/KVManagerHandlebars.kt6
-rw-r--r--kvision-modules/kvision-i18n/build.gradle4
-rw-r--r--kvision-modules/kvision-i18n/src/main/kotlin/pl/treksoft/kvision/KVManagerI18n.kt6
-rw-r--r--kvision-modules/kvision-i18n/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-moment/src/main/kotlin/pl/treksoft/kvision/KVManagerMoment.kt8
-rw-r--r--kvision-modules/kvision-pace/build.gradle4
-rw-r--r--kvision-modules/kvision-pace/src/main/kotlin/pl/treksoft/kvision/KVManagerPace.kt8
-rw-r--r--kvision-modules/kvision-redux-kotlin/build.gradle11
-rw-r--r--kvision-modules/kvision-redux-kotlin/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-redux/build.gradle8
-rw-r--r--kvision-modules/kvision-redux/src/main/kotlin/pl/treksoft/kvision/KVManagerRedux.kt14
-rw-r--r--kvision-modules/kvision-redux/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/Profile.kt8
-rw-r--r--kvision-modules/kvision-richtext/build.gradle6
-rw-r--r--kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt10
-rw-r--r--kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt2
-rw-r--r--kvision-modules/kvision-richtext/webpack.config.d/jquery.js5
-rw-r--r--kvision-modules/kvision-select/build.gradle14
-rw-r--r--kvision-modules/kvision-spinner/build.gradle13
-rw-r--r--kvision-modules/kvision-tabulator-remote/webpack.config.d/css.js2
-rw-r--r--kvision-modules/kvision-tabulator/build.gradle4
-rw-r--r--kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/KVManagerTabulator.kt14
-rw-r--r--kvision-modules/kvision-upload/build.gradle17
-rw-r--r--kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js100
-rw-r--r--kvision-modules/shared.gradle7
248 files changed, 5638 insertions, 2111 deletions
diff --git a/kvision-modules/kvision-bootstrap-css/build.gradle b/kvision-modules/kvision-bootstrap-css/build.gradle
new file mode 100644
index 00000000..1aca3288
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-css/build.gradle
@@ -0,0 +1,9 @@
+apply from: "../shared.gradle"
+
+kotlinFrontend {
+
+ npm {
+ dependency("bootstrap", "4.3.1")
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap-css/package.json.d/project.info b/kvision-modules/kvision-bootstrap-css/package.json.d/project.info
new file mode 100644
index 00000000..b990974a
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-css/package.json.d/project.info
@@ -0,0 +1,3 @@
+{
+ "description": "KVision Bootstrap CSS module"
+}
diff --git a/kvision-modules/kvision-bootstrap-css/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrapCss.kt b/kvision-modules/kvision-bootstrap-css/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrapCss.kt
new file mode 100644
index 00000000..ec131d5d
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-css/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrapCss.kt
@@ -0,0 +1,35 @@
+/*
+ * 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
+
+internal val kVManagerBootstrapCssInit = KVManagerBootstrapCss.init()
+
+/**
+ * Internal singleton object which initializes and configures KVision Bootstrap CSS module.
+ */
+internal object KVManagerBootstrapCss {
+ init {
+ require("bootstrap/dist/css/bootstrap.min.css")
+ }
+
+ internal fun init() {}
+}
diff --git a/kvision-modules/kvision-bootstrap-css/webpack.config.d/bootstrap.js b/kvision-modules/kvision-bootstrap-css/webpack.config.d/bootstrap.js
new file mode 100644
index 00000000..32a7c4d0
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-css/webpack.config.d/bootstrap.js
@@ -0,0 +1,4 @@
+config.module.rules.push({test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'});
+config.module.rules.push({test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'});
+config.module.rules.push({test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'});
+config.module.rules.push({test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'});
diff --git a/kvision-modules/kvision-datetime/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-css/webpack.config.d/css.js
index 5d710d35..5d710d35 100644
--- a/kvision-modules/kvision-datetime/webpack.config.d/css.js
+++ b/kvision-modules/kvision-bootstrap-css/webpack.config.d/css.js
diff --git a/kvision-modules/kvision-spinner/webpack.config.d/jquery.js b/kvision-modules/kvision-bootstrap-css/webpack.config.d/jquery.js
index bf5a1a20..bf5a1a20 100644
--- a/kvision-modules/kvision-spinner/webpack.config.d/jquery.js
+++ b/kvision-modules/kvision-bootstrap-css/webpack.config.d/jquery.js
diff --git a/kvision-modules/kvision-bootstrap-datetime/build.gradle b/kvision-modules/kvision-bootstrap-datetime/build.gradle
new file mode 100644
index 00000000..8cb14799
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-datetime/build.gradle
@@ -0,0 +1,13 @@
+apply from: "../shared.gradle"
+
+dependencies {
+ compile project(":kvision-modules:kvision-bootstrap")
+}
+
+kotlinFrontend {
+
+ npm {
+ dependency("pc-bootstrap4-datetimepicker", "4.17.50")
+ }
+
+}
diff --git a/kvision-modules/kvision-datetime/package.json.d/project.info b/kvision-modules/kvision-bootstrap-datetime/package.json.d/project.info
index 3d332806..3d332806 100644
--- a/kvision-modules/kvision-datetime/package.json.d/project.info
+++ b/kvision-modules/kvision-bootstrap-datetime/package.json.d/project.info
diff --git a/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt b/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt
new file mode 100644
index 00000000..c02a116d
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt
@@ -0,0 +1,36 @@
+/*
+ * 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
+
+internal val kVManagerDatetimeInit = KVManagerDatetime.init()
+
+/**
+ * Internal singleton object which initializes and configures KVision datetime module.
+ */
+internal object KVManagerDatetime {
+ init {
+ require("pc-bootstrap4-datetimepicker/build/css/bootstrap-datetimepicker.min.css")
+ require("pc-bootstrap4-datetimepicker/build/js/bootstrap-datetimepicker.min.js")
+ }
+
+ internal fun init() {}
+}
diff --git a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt b/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt
index 3d32fd8c..b7cf18ec 100644
--- a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt
+++ b/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt
@@ -26,7 +26,7 @@ import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.DateFormControl
import pl.treksoft.kvision.form.FieldLabel
-import pl.treksoft.kvision.form.HelpBlock
+import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.panel.SimplePanel
import pl.treksoft.kvision.utils.SnOn
import kotlin.js.Date
@@ -87,14 +87,6 @@ open class DateTime(
input.readonly = value
}
/**
- * Day of the week start. 0 (Sunday) to 6 (Saturday).
- */
- var weekStart
- get() = input.weekStart
- set(value) {
- input.weekStart = value
- }
- /**
* Days of the week that should be disabled. Multiple values should be comma separated.
*/
var daysOfWeekDisabled
@@ -105,42 +97,82 @@ open class DateTime(
/**
* Determines if *Clear* button should be visible.
*/
- var clearBtn
- get() = input.clearBtn
+ var showClear
+ get() = input.showClear
set(value) {
- input.clearBtn = value
+ input.showClear = value
}
/**
- * Determines if *Today* button should be visible.
+ * Determines if *Close* button should be visible.
*/
- var todayBtn
- get() = input.todayBtn
+ var showClose
+ get() = input.showClose
set(value) {
- input.todayBtn = value
+ input.showClose = value
}
/**
- * Determines if the current day should be highlighted.
+ * Determines if *Today* button should be visible.
*/
- var todayHighlight
- get() = input.todayHighlight
+ var showTodayButton
+ get() = input.showTodayButton
set(value) {
- input.todayHighlight = value
+ input.showTodayButton = value
}
/**
* The increment used to build the hour view.
*/
- var minuteStep
- get() = input.minuteStep
+ var stepping
+ get() = input.stepping
+ set(value) {
+ input.stepping = value
+ }
+ /**
+ * Prevents date selection before this date.
+ */
+ var minDate
+ get() = input.minDate
+ set(value) {
+ input.minDate = value
+ }
+ /**
+ * Prevents date selection after this date.
+ */
+ var maxDate
+ get() = input.maxDate
+ set(value) {
+ input.maxDate = value
+ }
+ /**
+ * Shows date and time pickers side by side.
+ */
+ var sideBySide
+ get() = input.sideBySide
+ set(value) {
+ input.sideBySide = value
+ }
+ /**
+ * An array of enabled dates.
+ */
+ var enabledDates
+ get() = input.enabledDates
set(value) {
- input.minuteStep = value
+ input.enabledDates = value
}
/**
- * Determines if meridian views are visible in day and hour views.
+ * An array of disabled dates.
*/
- var showMeridian
- get() = input.showMeridian
+ var disabledDates
+ get() = input.disabledDates
set(value) {
- input.showMeridian = value
+ input.disabledDates = value
+ }
+ /**
+ * Allow date picker for readonly component..
+ */
+ var ignoreReadonly
+ get() = input.ignoreReadonly
+ set(value) {
+ input.ignoreReadonly = value
}
/**
* The label text bound to the input element.
@@ -165,21 +197,21 @@ open class DateTime(
this.name = name
}
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
- final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
+ final override val invalidFeedback: InvalidFeedback = InvalidFeedback().apply { visible = false }
init {
@Suppress("LeakingThis")
input.eventTarget = this
this.addInternal(flabel)
this.addInternal(input)
- this.addInternal(validationInfo)
+ this.addInternal(invalidFeedback)
counter++
}
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
if (validatorError != null) {
- cl.add("has-error" to true)
+ cl.add("text-danger" to true)
}
return cl
}
@@ -214,6 +246,13 @@ open class DateTime(
input.hidePopup()
}
+ /**
+ * Toggle date/time chooser popup.
+ */
+ open fun togglePopup() {
+ input.togglePopup()
+ }
+
override fun getValueAsString(): String? {
return input.getValueAsString()
}
diff --git a/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt b/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
new file mode 100644
index 00000000..626346b1
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
@@ -0,0 +1,377 @@
+/*
+ * 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.form.time
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.form.FormInput
+import pl.treksoft.kvision.form.text.TextInput
+import pl.treksoft.kvision.html.Div
+import pl.treksoft.kvision.html.Icon
+import pl.treksoft.kvision.html.Icon.Companion.icon
+import pl.treksoft.kvision.html.Span.Companion.span
+import pl.treksoft.kvision.i18n.I18n
+import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.types.toDateF
+import pl.treksoft.kvision.types.toStringF
+import pl.treksoft.kvision.utils.obj
+import kotlin.js.Date
+
+internal const val DEFAULT_STEPPING = 5
+
+/**
+ * Basic date/time chooser component.
+ *
+ * @constructor
+ * @param value date/time input value
+ * @param format date/time format (default YYYY-MM-DD HH:mm)
+ * @param classes a set of CSS class names
+ */
+@Suppress("TooManyFunctions")
+open class DateTimeInput(
+ value: Date? = null, format: String = "YYYY-MM-DD HH:mm",
+ classes: Set<String> = setOf()
+) : SimplePanel(classes + "input-group" + "date"), FormInput {
+
+ private var initialized = false
+
+ internal val input = TextInput(value = value?.toStringF(format))
+ private lateinit var icon: Icon
+ private val addon = Div(classes = setOf("input-group-append")) {
+ span(classes = setOf("input-group-text", "datepickerbutton")) {
+ icon = icon(getIconClass(format))
+ }
+ }
+
+ init {
+ addInternal(input)
+ addInternal(addon)
+ }
+
+ /**
+ * Date/time input value.
+ */
+ var value
+ get() = input.value?.toDateF(format)
+ set(value) {
+ input.value = value?.toStringF(format)
+ refreshState()
+ }
+ /**
+ * Date/time format.
+ */
+ var format by refreshOnUpdate(format) { refreshDatePicker() }
+ /**
+ * The placeholder for the date/time input.
+ */
+ var placeholder
+ get() = input.placeholder
+ set(value) {
+ input.placeholder = value
+ }
+ /**
+ * The name attribute of the generated HTML input element.
+ */
+ override var name
+ get() = input.name
+ set(value) {
+ input.name = value
+ }
+ /**
+ * Determines if the field is disabled.
+ */
+ override var disabled
+ get() = input.disabled
+ set(value) {
+ input.disabled = value
+ }
+ /**
+ * Determines if the text input is automatically focused.
+ */
+ var autofocus
+ get() = input.autofocus
+ set(value) {
+ input.autofocus = value
+ }
+ /**
+ * Determines if the date/time input is read-only.
+ */
+ var readonly
+ get() = input.readonly
+ set(value) {
+ input.readonly = value
+ }
+ /**
+ * The size of the input.
+ */
+ override var size
+ get() = input.size
+ set(value) {
+ input.size = value
+ }
+ /**
+ * The validation status of the input.
+ */
+ override var validationStatus
+ get() = input.validationStatus
+ set(value) {
+ input.validationStatus = value
+ refresh()
+ }
+ /**
+ * Days of the week that should be disabled. Multiple values should be comma separated.
+ */
+ var daysOfWeekDisabled by refreshOnUpdate(arrayOf<Int>()) { refreshDatePicker() }
+ /**
+ * Determines if *Clear* button should be visible.
+ */
+ var showClear by refreshOnUpdate(true) { refreshDatePicker() }
+ /**
+ * Determines if *Close* button should be visible.
+ */
+ var showClose by refreshOnUpdate(true) { refreshDatePicker() }
+ /**
+ * Determines if *Today* button should be visible.
+ */
+ var showTodayButton by refreshOnUpdate(true) { refreshDatePicker() }
+ /**
+ * The increment used to build the hour view.
+ */
+ var stepping by refreshOnUpdate(DEFAULT_STEPPING) { refreshDatePicker() }
+ /**
+ * Prevents date selection before this date.
+ */
+ var minDate: Date? by refreshOnUpdate { refreshDatePicker() }
+ /**
+ * Prevents date selection after this date.
+ */
+ var maxDate: Date? by refreshOnUpdate { refreshDatePicker() }
+ /**
+ * Shows date and time pickers side by side.
+ */
+ var sideBySide by refreshOnUpdate(false) { refreshDatePicker() }
+ /**
+ * An array of enabled dates.
+ */
+ var enabledDates by refreshOnUpdate(arrayOf<Date>()) { refreshDatePicker() }
+ /**
+ * An array of disabled dates.
+ */
+ var disabledDates by refreshOnUpdate(arrayOf<Date>()) { refreshDatePicker() }
+ /**
+ * Allow date picker for readonly component.
+ */
+ var ignoreReadonly by refreshOnUpdate(false) { refreshDatePicker() }
+
+ private fun refreshState() {
+ if (initialized) getElementJQueryD().data("DateTimePicker").date(value)
+ }
+
+ private fun getIconClass(format: String): String {
+ return if (format.contains("YYYY") || format.contains("MM") || format.contains("DD")) {
+ "fas fa-calendar-alt"
+ } else {
+ "fas fa-clock"
+ }
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ validationStatus?.let {
+ cl.add(it.className to true)
+ }
+ return cl
+ }
+
+ protected open fun refreshDatePicker() {
+ if (initialized) {
+ getElementJQueryD()?.data("DateTimePicker").destroy()
+ }
+ initDateTimePicker()
+ icon.icon = getIconClass(format)
+ }
+
+ /**
+ * Open date/time chooser popup.
+ */
+ open fun showPopup() {
+ if (initialized) getElementJQueryD()?.data("DateTimePicker").show()
+ }
+
+ /**
+ * Hides date/time chooser popup.
+ */
+ open fun hidePopup() {
+ if (initialized) getElementJQueryD()?.data("DateTimePicker").hide()
+ }
+
+ /**
+ * Toggles date/time chooser popup.
+ */
+ open fun togglePopup() {
+ if (initialized) getElementJQueryD()?.data("DateTimePicker").toggle()
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ override fun afterInsert(node: VNode) {
+ this.initDateTimePicker()
+ this.initEventHandlers()
+ initialized = true
+ }
+
+ override fun afterDestroy() {
+ if (initialized) {
+ val comp = getElementJQueryD()?.data("DateTimePicker")
+ if (comp != null) comp.destroy()
+ initialized = false
+ }
+ }
+
+ private fun initDateTimePicker() {
+ val language = I18n.language
+ val self = this
+ getElementJQueryD()?.datetimepicker(obj {
+ this.useCurrent = false
+ this.format = format
+ this.stepping = stepping
+ this.showClear = showClear
+ this.showClose = showClose
+ this.showTodayButton = showTodayButton
+ this.sideBySide = sideBySide
+ this.ignoreReadonly = ignoreReadonly
+ if (minDate != null) this.minDate = minDate
+ if (maxDate != null) this.maxDate = maxDate
+ if (daysOfWeekDisabled.isNotEmpty()) this.daysOfWeekDisabled = daysOfWeekDisabled
+ if (enabledDates.isNotEmpty()) this.enabledDates = enabledDates
+ if (disabledDates.isNotEmpty()) this.disabledDates = disabledDates
+ this.locale = language
+ this.icons = obj {
+ this.time = "far fa-clock"
+ this.date = "far fa-calendar"
+ this.up = "fas fa-arrow-up"
+ this.down = "fas fa-arrow-down"
+ this.previous = "fas fa-chevron-left"
+ this.next = "fas fa-chevron-right"
+ this.today = "fas fa-calendar-check"
+ this.clear = "far fa-trash-alt"
+ this.close = "far fa-times-circle"
+ }
+ this.tooltips = obj {
+ this.today = ""
+ this.clear = ""
+ this.close = ""
+ this.selectMonth = ""
+ this.prevMonth = ""
+ this.nextMonth = ""
+ this.selectYear = ""
+ this.prevYear = ""
+ this.nextYear = ""
+ this.selectDecade = ""
+ this.prevDecade = ""
+ this.nextDecade = ""
+ this.prevCentury = ""
+ this.nextCentury = ""
+ this.pickHour = ""
+ this.incrementHour = ""
+ this.decrementHour = ""
+ this.pickMinute = ""
+ this.incrementMinute = ""
+ this.decrementMinute = ""
+ this.pickSecond = ""
+ this.incrementSecond = ""
+ this.decrementSecond = ""
+ this.togglePeriod = ""
+ this.selectTime = ""
+ }
+ this.keyBinds = obj {
+ enter = {
+ self.togglePopup()
+ }
+ }
+ })
+ }
+
+ private fun initEventHandlers() {
+ this.getElementJQuery()?.on("dp.change") { e, _ ->
+ val moment = e.asDynamic().date
+ if (moment) {
+ this.value = moment.toDate()
+ } else {
+ this.value = null
+ }
+ @Suppress("UnsafeCastFromDynamic")
+ this.dispatchEvent("change", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("dp.error") { e, _ ->
+ this.value = null
+ @Suppress("UnsafeCastFromDynamic")
+ this.dispatchEvent("change", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("dp.show") { e, _ ->
+ @Suppress("UnsafeCastFromDynamic")
+ this.dispatchEvent("showBsDateTime", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("dp.hide") { e, _ ->
+ @Suppress("UnsafeCastFromDynamic")
+ this.dispatchEvent("hideBsDateTime", obj { detail = e })
+ }
+ }
+
+ /**
+ * Get value of date/time input control as String
+ * @return value as a String
+ */
+ fun getValueAsString(): String? {
+ return value?.toStringF(format)
+ }
+
+ /**
+ * Makes the input element focused.
+ */
+ override fun focus() {
+ input.focus()
+ }
+
+ /**
+ * Makes the input element blur.
+ */
+ override fun blur() {
+ input.blur()
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.dateTimeInput(
+ value: Date? = null, format: String = "YYYY-MM-DD HH:mm", classes: Set<String> = setOf(),
+ init: (DateTimeInput.() -> Unit)? = null
+ ): DateTimeInput {
+ val dateTimeInput = DateTimeInput(value, format, classes).apply { init?.invoke(this) }
+ this.add(dateTimeInput)
+ return dateTimeInput
+ }
+ }
+}
diff --git a/kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt b/kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
index 13c8531b..13c8531b 100644
--- a/kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
+++ b/kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
diff --git a/kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeInputSpec.kt b/kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeInputSpec.kt
index 877cf650..5cdb68c9 100644
--- a/kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeInputSpec.kt
+++ b/kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeInputSpec.kt
@@ -25,6 +25,7 @@ import pl.treksoft.kvision.form.time.DateTimeInput
import pl.treksoft.kvision.panel.Root
import pl.treksoft.kvision.types.toStringF
import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
import kotlin.js.Date
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -41,10 +42,11 @@ class DateTimeInputSpec : DomSpec {
id = "idti"
}
root.add(dti)
- val value = dti.getElementJQuery()?.`val`()
+ val element = document.getElementById("test")
+ val datastr = data.toStringF(dti.format)
assertEquals(
- data.toStringF(dti.format),
- value,
+ "<div class=\"input-group date\" id=\"idti\"><input class=\"form-control\" placeholder=\"place\" type=\"text\" value=\"$datastr\"><div class=\"input-group-append\"><span class=\"input-group-text datepickerbutton\"><span class=\"fas fa-calendar-alt\"></span></span></div></div>",
+ element?.innerHTML,
"Should render date time input with correctly formatted value"
)
}
diff --git a/kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeSpec.kt b/kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeSpec.kt
index b5e393bb..a6714f0c 100644
--- a/kvision-modules/kvision-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeSpec.kt
+++ b/kvision-modules/kvision-bootstrap-datetime/src/test/kotlin/test/pl/treksoft/kvision/form/time/DateTimeSpec.kt
@@ -46,13 +46,13 @@ class DateTimeSpec : DomSpec {
val id = ti.input.id
val datastr = data.toStringF(ti.format)
assertEqualsHtml(
- "<div class=\"form-group\"><label class=\"control-label\" for=\"$id\">Label</label><input class=\"form-control\" id=\"$id\" type=\"text\" placeholder=\"place\" name=\"name\" disabled=\"disabled\" value=\"$datastr\"></div>",
+ "<div class=\"form-group\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"input-group date\" id=\"$id\"><input class=\"form-control\" placeholder=\"place\" name=\"name\" disabled=\"\" type=\"text\" value=\"$datastr\"><div class=\"input-group-append\"><span class=\"input-group-text datepickerbutton\"><span class=\"fas fa-calendar-alt\"></span></span></div></div></div>",
element?.innerHTML,
"Should render correct date time input form control"
)
ti.validatorError = "Validation Error"
assertEqualsHtml(
- "<div class=\"form-group has-error\"><label class=\"control-label\" for=\"$id\">Label</label><input class=\"form-control\" id=\"$id\" type=\"text\" placeholder=\"place\" name=\"name\" disabled=\"disabled\" value=\"$datastr\"><span class=\"help-block small\">Validation Error</span></div>",
+ "<div class=\"form-group text-danger\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"input-group date is-invalid\" id=\"$id\"><input class=\"form-control is-invalid\" placeholder=\"place\" name=\"name\" disabled=\"\" type=\"text\" value=\"$datastr\"><div class=\"input-group-append\"><span class=\"input-group-text datepickerbutton\"><span class=\"fas fa-calendar-alt\"></span></span></div></div><div class=\"invalid-feedback\">Validation Error</div></div>",
element?.innerHTML,
"Should render correct date time input form control with validation error"
)
diff --git a/kvision-modules/kvision-select/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-datetime/webpack.config.d/css.js
index 5d710d35..5d710d35 100644
--- a/kvision-modules/kvision-select/webpack.config.d/css.js
+++ b/kvision-modules/kvision-bootstrap-datetime/webpack.config.d/css.js
diff --git a/kvision-modules/kvision-bootstrap-dialog/build.gradle b/kvision-modules/kvision-bootstrap-dialog/build.gradle
new file mode 100644
index 00000000..652d14d6
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-dialog/build.gradle
@@ -0,0 +1,6 @@
+apply from: "../shared.gradle"
+
+dependencies {
+ compile project(":kvision-modules:kvision-bootstrap")
+ compile "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion"
+}
diff --git a/kvision-modules/kvision-dialog/package.json.d/project.info b/kvision-modules/kvision-bootstrap-dialog/package.json.d/project.info
index 416cd4a7..416cd4a7 100644
--- a/kvision-modules/kvision-dialog/package.json.d/project.info
+++ b/kvision-modules/kvision-bootstrap-dialog/package.json.d/project.info
diff --git a/kvision-modules/kvision-dialog/src/main/kotlin/pl/treksoft/kvision/modal/Dialog.kt b/kvision-modules/kvision-bootstrap-dialog/src/main/kotlin/pl/treksoft/kvision/modal/Dialog.kt
index e67a6f17..e67a6f17 100644
--- a/kvision-modules/kvision-dialog/src/main/kotlin/pl/treksoft/kvision/modal/Dialog.kt
+++ b/kvision-modules/kvision-bootstrap-dialog/src/main/kotlin/pl/treksoft/kvision/modal/Dialog.kt
diff --git a/kvision-modules/kvision-spinner/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-dialog/webpack.config.d/css.js
index 5d710d35..5d710d35 100644
--- a/kvision-modules/kvision-spinner/webpack.config.d/css.js
+++ b/kvision-modules/kvision-bootstrap-dialog/webpack.config.d/css.js
diff --git a/kvision-modules/kvision-select-remote/build.gradle b/kvision-modules/kvision-bootstrap-select-remote/build.gradle
index 739c7a53..7a4dc8fa 100644
--- a/kvision-modules/kvision-select-remote/build.gradle
+++ b/kvision-modules/kvision-bootstrap-select-remote/build.gradle
@@ -1,6 +1,6 @@
apply from: "../shared.gradle"
dependencies {
- compile project(":kvision-modules:kvision-select")
+ compile project(":kvision-modules:kvision-bootstrap-select")
compile project(":kvision-modules:kvision-remote")
}
diff --git a/kvision-modules/kvision-select-remote/package.json.d/project.info b/kvision-modules/kvision-bootstrap-select-remote/package.json.d/project.info
index 5685d581..5685d581 100644
--- a/kvision-modules/kvision-select-remote/package.json.d/project.info
+++ b/kvision-modules/kvision-bootstrap-select-remote/package.json.d/project.info
diff --git a/kvision-modules/kvision-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemote.kt b/kvision-modules/kvision-bootstrap-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemote.kt
index ea9d369b..de823280 100644
--- a/kvision-modules/kvision-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemote.kt
+++ b/kvision-modules/kvision-bootstrap-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemote.kt
@@ -26,7 +26,7 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FieldLabel
-import pl.treksoft.kvision.form.HelpBlock
+import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.StringFormControl
import pl.treksoft.kvision.panel.SimplePanel
import pl.treksoft.kvision.remote.KVServiceManager
@@ -155,21 +155,21 @@ open class SelectRemote<T : Any>(
this.name = name
}
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
- final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
+ final override val invalidFeedback: InvalidFeedback = InvalidFeedback().apply { visible = false }
init {
@Suppress("LeakingThis")
input.eventTarget = this
this.addInternal(flabel)
this.addInternal(input)
- this.addInternal(validationInfo)
+ this.addInternal(invalidFeedback)
counter++
}
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
if (validatorError != null) {
- cl.add("has-error" to true)
+ cl.add("text-danger" to true)
}
return cl
}
diff --git a/kvision-modules/kvision-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemoteInput.kt b/kvision-modules/kvision-bootstrap-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemoteInput.kt
index 4c891d30..4c891d30 100644
--- a/kvision-modules/kvision-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemoteInput.kt
+++ b/kvision-modules/kvision-bootstrap-select-remote/src/main/kotlin/pl/treksoft/kvision/form/select/SelectRemoteInput.kt
diff --git a/kvision-modules/kvision-upload/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-select-remote/webpack.config.d/css.js
index 5d710d35..5d710d35 100644
--- a/kvision-modules/kvision-upload/webpack.config.d/css.js
+++ b/kvision-modules/kvision-bootstrap-select-remote/webpack.config.d/css.js
diff --git a/kvision-modules/kvision-bootstrap-select/build.gradle b/kvision-modules/kvision-bootstrap-select/build.gradle
new file mode 100644
index 00000000..7c10515f
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-select/build.gradle
@@ -0,0 +1,14 @@
+apply from: "../shared.gradle"
+
+dependencies {
+ compile project(":kvision-modules:kvision-bootstrap")
+}
+
+kotlinFrontend {
+
+ npm {
+ dependency("bootstrap-select", "1.13.11")
+ dependency("ajax-bootstrap-select", "1.4.5")
+ }
+
+}
diff --git a/kvision-modules/kvision-select/package.json.d/project.info b/kvision-modules/kvision-bootstrap-select/package.json.d/project.info
index 80e675b0..80e675b0 100644
--- a/kvision-modules/kvision-select/package.json.d/project.info
+++ b/kvision-modules/kvision-bootstrap-select/package.json.d/project.info
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/KVManagerSelect.kt b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/KVManagerSelect.kt
index e2c556c1..09f92a0d 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/KVManagerSelect.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/KVManagerSelect.kt
@@ -26,28 +26,17 @@ internal val kVManagerSelectInit = KVManagerSelect.init()
/**
* Internal singleton object which initializes and configures KVision select module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerSelect {
internal const val AJAX_REQUEST_DELAY = 300
internal const val KVNULL = "#kvnull"
- fun init() {}
-
- private val bootstrapSelectCss = try {
+ init {
require("bootstrap-select/dist/css/bootstrap-select.min.css")
- } catch (e: Throwable) {
- }
- private val bootstrapSelect = try {
require("bootstrap-select/dist/js/bootstrap-select.min.js")
require("./js/locales/bootstrap-select/bootstrap-select-i18n.min.js")
- } catch (e: Throwable) {
- }
- private val bootstrapSelectAjaxCss = try {
require("ajax-bootstrap-select/dist/css/ajax-bootstrap-select.min.css")
- } catch (e: Throwable) {
- }
- private val bootstrapSelectAjax = try {
require("ajax-bootstrap-select/dist/js/ajax-bootstrap-select.min.js")
+ require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.cs-CZ.min.js")
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js")
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js")
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js")
@@ -58,8 +47,12 @@ internal object KVManagerSelect {
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js")
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js")
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js")
+ require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.sr-SP.min.js")
require("./js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js")
- } catch (e: Throwable) {
+ js("$.fn.selectpicker.Constructor.BootstrapVersion = '4';")
+ js("$.fn.selectpicker.Constructor.DEFAULTS.styleBase = 'form-control';");
+ js("$.fn.selectpicker.Constructor.DEFAULTS.style = '';")
}
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/AjaxOptions.kt b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/AjaxOptions.kt
index c088f68d..c088f68d 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/AjaxOptions.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/AjaxOptions.kt
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt
index db8a5b3b..4b2505d2 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt
@@ -27,7 +27,7 @@ import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FieldLabel
-import pl.treksoft.kvision.form.HelpBlock
+import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.StringFormControl
import pl.treksoft.kvision.panel.SimplePanel
import pl.treksoft.kvision.utils.SnOn
@@ -176,21 +176,21 @@ open class Select(
this.name = name
}
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
- final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
+ final override val invalidFeedback: InvalidFeedback = InvalidFeedback().apply { visible = false }
init {
@Suppress("LeakingThis")
input.eventTarget = this
this.addInternal(flabel)
this.addInternal(input)
- this.addInternal(validationInfo)
+ this.addInternal(invalidFeedback)
counter++
}
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
if (validatorError != null) {
- cl.add("has-error" to true)
+ cl.add("text-danger" to true)
}
return cl
}
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
index e0a49326..84eccaf7 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
@@ -30,6 +30,7 @@ import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
+import pl.treksoft.kvision.form.ValidationStatus
import pl.treksoft.kvision.html.ButtonStyle
import pl.treksoft.kvision.panel.SimplePanel
import pl.treksoft.kvision.utils.asString
@@ -128,6 +129,10 @@ open class SelectInput(
* The size of the input.
*/
override var size: InputSize? by refreshOnUpdate()
+ /**
+ * The validation status of the input.
+ */
+ override var validationStatus: ValidationStatus? by refreshOnUpdate()
init {
setChildrenFromOptions()
@@ -228,6 +233,9 @@ open class SelectInput(
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
cl.add("selectpicker" to true)
+ validationStatus?.let {
+ cl.add(it.className to true)
+ }
size?.let {
cl.add(it.className to true)
}
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOptGroup.kt b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOptGroup.kt
index 3f07a9bf..3f07a9bf 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOptGroup.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOptGroup.kt
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOption.kt b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOption.kt
index 3977776b..91c269a8 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOption.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectOption.kt
@@ -91,11 +91,7 @@ open class SelectOption(
sn.add("data-subtext" to translate(it))
}
icon?.let {
- if (it.startsWith("fa-")) {
- sn.add("data-icon" to "fa $it")
- } else {
- sn.add("data-icon" to "glyphicon-$it")
- }
+ sn.add("data-icon" to it)
}
if (disabled) {
sn.add("disabled" to "disabled")
diff --git a/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.cs-CZ.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.cs-CZ.min.js
new file mode 100644
index 00000000..994014a9
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.cs-CZ.min.js
@@ -0,0 +1,23 @@
+/*!
+ * Ajax Bootstrap Select
+ *
+ * Extends existing [Bootstrap Select] implementations by adding the ability to search via AJAX requests as you type. Originally for CROSCON.
+ *
+ * @version 1.4.5
+ * @author Adam Heim - https://github.com/truckingsim
+ * @link https://github.com/truckingsim/Ajax-Bootstrap-Select
+ * @copyright 2019 Adam Heim
+ * @license Released under the MIT license.
+ *
+ * Contributors:
+ * Mark Carver - https://github.com/markcarver
+ *
+ * Last build: 2019-04-23 12:18:55 PM EDT
+ */
+!(function ($) {
+
+/*!
+ * Czech translation for the "cs-CZ" and "cs" language codes.
+ * Martin Brettschneider <martin.brettschneider@gmail.com>
+ */
+$.fn.ajaxSelectPicker.locale["cs-CZ"]={currentlySelected:"Aktuálně vybrané",emptyTitle:"Vyberte a začněte psát",errorText:"Výsledky nelze načíst",searchPlaceholder:"Vyhledat...",statusInitialized:"Začněte psát hledaný výraz",statusNoResults:"Žádné výsledky",statusSearching:"Vyhledávání...",statusTooShort:"Zadejte více znaků"},$.fn.ajaxSelectPicker.locale.cs=$.fn.ajaxSelectPicker.locale["cs-CZ"];})(jQuery);
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js
index 08b38207..08b38207 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.de-DE.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.en-US.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.en-US.min.js
index 8b130b97..8b130b97 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.en-US.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.en-US.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js
index bbe3fe45..bbe3fe45 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.es-ES.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js
index 1d86582f..1d86582f 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.fr-FR.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.it-IT.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.it-IT.min.js
index b30deb3e..b30deb3e 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.it-IT.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.it-IT.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ja-JP.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ja-JP.min.js
index 23a9a348..23a9a348 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ja-JP.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ja-JP.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ko-KR.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ko-KR.min.js
index 2fd5299b..2fd5299b 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ko-KR.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ko-KR.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.nl-NL.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.nl-NL.min.js
index 6c6a16f2..6c6a16f2 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.nl-NL.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.nl-NL.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js
index f104f491..f104f491 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pl-PL.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js
index 2a6e743d..2a6e743d 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.pt-BR.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js
index aa6d4d06..aa6d4d06 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.ru-RU.min.js
diff --git a/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.sr-SP.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.sr-SP.min.js
new file mode 100644
index 00000000..4536c620
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.sr-SP.min.js
@@ -0,0 +1,23 @@
+/*!
+ * Ajax Bootstrap Select
+ *
+ * Extends existing [Bootstrap Select] implementations by adding the ability to search via AJAX requests as you type. Originally for CROSCON.
+ *
+ * @version 1.4.5
+ * @author Adam Heim - https://github.com/truckingsim
+ * @link https://github.com/truckingsim/Ajax-Bootstrap-Select
+ * @copyright 2019 Adam Heim
+ * @license Released under the MIT license.
+ *
+ * Contributors:
+ * Mark Carver - https://github.com/markcarver
+ *
+ * Last build: 2019-04-23 12:18:55 PM EDT
+ */
+!(function ($) {
+
+/*!
+ * Serbian translation for the "sr-SP" and "sr" language codes.
+ * Miroslav Maksimovic <miroslavmaksimovic95@gmail.com>
+ */
+$.fn.ajaxSelectPicker.locale["sr-SP"]={currentlySelected:"Trenutno izabrano",emptyTitle:"Izaberite i pocnite kucati",errorText:"Nemoguce dobiti rezultate",searchPlaceholder:"Pretrazi...",statusInitialized:"Pocnite kucati kljucnu rijec",statusNoResults:"Nema rezultata",statusSearching:"Trazim...",statusTooShort:"Molimo unesite vise znakova"},$.fn.ajaxSelectPicker.locale.ru=$.fn.ajaxSelectPicker.locale["sr-SP"];})(jQuery);
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js
index 6af588f4..6af588f4 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/ajax-bootstrap-select/ajax-bootstrap-select.tr-TR.min.js
diff --git a/kvision-modules/kvision-select/src/main/resources/js/locales/bootstrap-select/bootstrap-select-i18n.min.js b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/bootstrap-select/bootstrap-select-i18n.min.js
index 4428d3c0..877071ce 100644
--- a/kvision-modules/kvision-select/src/main/resources/js/locales/bootstrap-select/bootstrap-select-i18n.min.js
+++ b/kvision-modules/kvision-bootstrap-select/src/main/resources/js/locales/bootstrap-select/bootstrap-select-i18n.min.js
@@ -1 +1 @@
-!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function(a){!function(a){a.fn.selectpicker.defaults={noneSelectedText:"",noneResultsText:"",countSelectedText:function(a,b){return 1==a?"... ({n})":"... ({n})"},maxOptionsText:function(a,b){return[1==a?"🛇":"🛇",1==b?"🛇":"🛇"]},selectAllText:"++",deselectAllText:"--",multipleSeparator:", "}}(a)}); \ No newline at end of file
+!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function(a){!function(a){a.fn.selectpicker.defaults={noneSelectedText:" ",noneResultsText:"",countSelectedText:function(a,b){return 1==a?"... ({n})":"... ({n})"},maxOptionsText:function(a,b){return[1==a?"🛇":"🛇",1==b?"🛇":"🛇"]},selectAllText:"++",deselectAllText:"--",multipleSeparator:", "}}(a)}); \ No newline at end of file
diff --git a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
index 13c8531b..13c8531b 100644
--- a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
diff --git a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectInputSpec.kt b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectInputSpec.kt
index bfd93900..0e759896 100644
--- a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectInputSpec.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectInputSpec.kt
@@ -44,7 +44,7 @@ class SelectInputSpec : DomSpec {
root.add(selectInput)
val element = document.getElementById("test")
assertTrue(
- true == element?.innerHTML?.endsWith("<select class=\"selectpicker\" multiple=\"multiple\" data-live-search=\"true\" title=\"Choose ...\" data-style=\"btn-default\" data-width=\"fit\" tabindex=\"-98\"><option value=\"#kvnull\"></option><option value=\"test1\">Test 1</option><option value=\"test2\">Test 2</option></select></div>"),
+ true == element?.innerHTML?.startsWith("<div class=\"dropdown bootstrap-select show-tick fit-width\"><select class=\"selectpicker\" multiple=\"multiple\" data-live-search=\"true\" title=\"Choose ...\" data-style=\"btn-default\" data-width=\"fit\" tabindex=\"-98\"><option value=\"#kvnull\"></option><option value=\"test1\">Test 1</option><option value=\"test2\">Test 2</option></select>"),
"Should render correct select input"
)
}
diff --git a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptGroupSpec.kt b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptGroupSpec.kt
index 33ccc843..33ccc843 100644
--- a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptGroupSpec.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptGroupSpec.kt
diff --git a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptionSpec.kt b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptionSpec.kt
index 33c36576..d711301a 100644
--- a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptionSpec.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectOptionSpec.kt
@@ -41,9 +41,9 @@ class SelectOptionSpec : DomSpec {
element?.innerHTML,
"Should render correct select option"
)
- selectOption.icon = "fa-flag"
+ selectOption.icon = "fas fa-flag"
assertEqualsHtml(
- "<option value=\"testValue\" data-icon=\"fa fa-flag\">testLabel</option>",
+ "<option value=\"testValue\" data-icon=\"fas fa-flag\">testLabel</option>",
element?.innerHTML,
"Should render correct select option with icon"
)
diff --git a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectSpec.kt b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectSpec.kt
index 9eddff81..9ed44f82 100644
--- a/kvision-modules/kvision-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectSpec.kt
+++ b/kvision-modules/kvision-bootstrap-select/src/test/kotlin/test/pl/treksoft/kvision/form/select/SelectSpec.kt
@@ -45,11 +45,7 @@ class SelectSpec : DomSpec {
val element = document.getElementById("test")
val id = select.input.id
assertTrue(
- true == element?.innerHTML?.startsWith("<div class=\"form-group\"><label class=\"control-label\" for=\"$id\">Label</label>"),
- "Should render correct select form control"
- )
- assertTrue(
- true == element?.innerHTML?.endsWith("<select class=\"form-control selectpicker\" id=\"$id\" multiple=\"multiple\" data-live-search=\"true\" title=\"Choose ...\" data-style=\"btn-default\" data-width=\"fit\" tabindex=\"-98\"><option value=\"#kvnull\"></option><option value=\"test1\">Test 1</option><option value=\"test2\">Test 2</option></select></div></div>"),
+ true == element?.innerHTML?.startsWith("<div class=\"form-group\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"dropdown bootstrap-select show-tick form-control fit-width\"><select class=\"form-control selectpicker\" id=\"$id\" multiple=\"multiple\" data-live-search=\"true\" title=\"Choose ...\" data-style=\"btn-default\" data-width=\"fit\" tabindex=\"-98\"><option value=\"#kvnull\"></option><option value=\"test1\">Test 1</option><option value=\"test2\">Test 2</option></select>"),
"Should render correct select form control"
)
}
diff --git a/kvision-modules/kvision-bootstrap-select/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-select/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-select/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-bootstrap-select/webpack.config.d/jquery.js b/kvision-modules/kvision-bootstrap-select/webpack.config.d/jquery.js
new file mode 100644
index 00000000..bf5a1a20
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-select/webpack.config.d/jquery.js
@@ -0,0 +1,5 @@
+config.plugins.push(new webpack.ProvidePlugin({
+ $: "jquery",
+ jQuery: "jquery",
+ "window.jQuery": "jquery"
+}));
diff --git a/kvision-modules/kvision-bootstrap-spinner/build.gradle b/kvision-modules/kvision-bootstrap-spinner/build.gradle
new file mode 100644
index 00000000..02d4e9e5
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-spinner/build.gradle
@@ -0,0 +1,13 @@
+apply from: "../shared.gradle"
+
+dependencies {
+ compile project(":kvision-modules:kvision-bootstrap")
+}
+
+kotlinFrontend {
+
+ npm {
+ dependency("bootstrap-touchspin", "4.2.5")
+ }
+
+}
diff --git a/kvision-modules/kvision-spinner/package.json.d/project.info b/kvision-modules/kvision-bootstrap-spinner/package.json.d/project.info
index fb0c7956..fb0c7956 100644
--- a/kvision-modules/kvision-spinner/package.json.d/project.info
+++ b/kvision-modules/kvision-bootstrap-spinner/package.json.d/project.info
diff --git a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/KVManagerSpinner.kt b/kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/KVManagerSpinner.kt
index ca4d3764..de406845 100644
--- a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/KVManagerSpinner.kt
+++ b/kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/KVManagerSpinner.kt
@@ -26,17 +26,11 @@ internal val kVManagerSpinnerInit = KVManagerSpinner.init()
/**
* Internal singleton object which initializes and configures KVision spinner module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerSpinner {
- fun init() {}
-
- private val bootstrapTouchspinCss = try {
+ init {
require("bootstrap-touchspin/dist/jquery.bootstrap-touchspin.min.css")
- } catch (e: Throwable) {
- }
- private val bootstrapTouchspin = try {
require("bootstrap-touchspin/dist/jquery.bootstrap-touchspin.min.js")
- } catch (e: Throwable) {
}
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt b/kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt
index 31c6ceb8..7e3048d1 100644
--- a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt
+++ b/kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt
@@ -25,8 +25,9 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FieldLabel
-import pl.treksoft.kvision.form.HelpBlock
+import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.NumberFormControl
+import pl.treksoft.kvision.html.ButtonStyle
import pl.treksoft.kvision.panel.SimplePanel
import pl.treksoft.kvision.utils.SnOn
@@ -47,8 +48,8 @@ import pl.treksoft.kvision.utils.SnOn
*/
open class Spinner(
value: Number? = null, name: String? = null, min: Int? = null, max: Int? = null, step: Double = DEFAULT_STEP,
- decimals: Int = 0, buttonsType: ButtonsType = ButtonsType.VERTICAL,
- forceType: ForceType = ForceType.NONE, label: String? = null,
+ decimals: Int = 0, val buttonsType: ButtonsType = ButtonsType.VERTICAL,
+ forceType: ForceType = ForceType.NONE, buttonStyle: ButtonStyle? = null, label: String? = null,
rich: Boolean = false
) : SimplePanel(setOf("form-group")), NumberFormControl {
@@ -104,14 +105,6 @@ open class Spinner(
input.decimals = value
}
/**
- * Spinner buttons type.
- */
- var buttonsType
- get() = input.buttonsType
- set(value) {
- input.buttonsType = value
- }
- /**
* Spinner force rounding type.
*/
var forceType
@@ -120,6 +113,14 @@ open class Spinner(
input.forceType = value
}
/**
+ * The style of the up/down buttons.
+ */
+ var buttonStyle
+ get() = input.buttonStyle
+ set(value) {
+ input.buttonStyle = value
+ }
+ /**
* The placeholder for the spinner input.
*/
var placeholder
@@ -160,28 +161,40 @@ open class Spinner(
flabel.rich = value
}
- protected val idc = "kv_form_spinner_$counter"
- final override val input: SpinnerInput = SpinnerInput(value, min, max, step, decimals, buttonsType, forceType)
- .apply {
- this.id = idc
- this.name = name
+ override var validatorError: String?
+ get() = super.validatorError
+ set(value) {
+ super.validatorError = value
+ if (value != null) {
+ input.addSurroundingCssClass("is-invalid")
+ } else {
+ input.removeSurroundingCssClass("is-invalid")
+ }
}
+
+ protected val idc = "kv_form_spinner_$counter"
+ final override val input: SpinnerInput =
+ SpinnerInput(value, min, max, step, decimals, buttonsType, forceType, buttonStyle)
+ .apply {
+ this.id = idc
+ this.name = name
+ }
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
- final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
+ final override val invalidFeedback: InvalidFeedback = InvalidFeedback().apply { visible = false }
init {
@Suppress("LeakingThis")
input.eventTarget = this
this.addInternal(flabel)
this.addInternal(input)
- this.addInternal(validationInfo)
+ this.addInternal(invalidFeedback)
counter++
}
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
if (validatorError != null) {
- cl.add("has-error" to true)
+ cl.add("text-danger" to true)
}
return cl
}
@@ -230,6 +243,15 @@ open class Spinner(
input.blur()
}
+ override fun styleForHorizontalFormPanel() {
+ addCssClass("row")
+ flabel.addCssClass("col-sm-2")
+ flabel.addCssClass("col-form-label")
+ input.addSurroundingCssClass("col-sm-10")
+ invalidFeedback.addCssClass("offset-sm-2")
+ invalidFeedback.addCssClass("col-sm-10")
+ }
+
companion object {
internal var counter = 0
@@ -247,15 +269,17 @@ open class Spinner(
decimals: Int = 0,
buttonsType: ButtonsType = ButtonsType.VERTICAL,
forceType: ForceType = ForceType.NONE,
+ buttonStyle: ButtonStyle? = null,
label: String? = null,
rich: Boolean = false,
init: (Spinner.() -> Unit)? = null
): Spinner {
- val spinner = Spinner(value, name, min, max, step, decimals, buttonsType, forceType, label, rich).apply {
- init?.invoke(
- this
- )
- }
+ val spinner =
+ Spinner(value, name, min, max, step, decimals, buttonsType, forceType, buttonStyle, label, rich).apply {
+ init?.invoke(
+ this
+ )
+ }
this.add(spinner)
return spinner
}
diff --git a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt b/kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
index 18df26fa..c75bbfc4 100644
--- a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
+++ b/kvision-modules/kvision-bootstrap-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
@@ -29,6 +29,8 @@ import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
+import pl.treksoft.kvision.form.ValidationStatus
+import pl.treksoft.kvision.html.ButtonStyle
import pl.treksoft.kvision.utils.obj
/**
@@ -63,37 +65,17 @@ internal const val DEFAULT_STEP = 1.0
* @param decimals number of decimal digits (default 0)
* @param buttonsType spinner buttons type
* @param forceType spinner force rounding type
+ * @param buttonStyle the style of the up/down buttons
* @param classes a set of CSS class names
*/
@Suppress("TooManyFunctions")
open class SpinnerInput(
value: Number? = null, min: Int? = null, max: Int? = null, step: Double = DEFAULT_STEP,
- decimals: Int = 0, buttonsType: ButtonsType = ButtonsType.VERTICAL,
- forceType: ForceType = ForceType.NONE,
+ decimals: Int = 0, val buttonsType: ButtonsType = ButtonsType.VERTICAL,
+ forceType: ForceType = ForceType.NONE, buttonStyle: ButtonStyle? = null,
classes: Set<String> = setOf()
) : Widget(classes + "form-control"), FormInput {
- init {
- this.addSurroundingCssClass("input-group")
- if (buttonsType == ButtonsType.NONE) {
- this.addSurroundingCssClass("kv-spinner-btn-none")
- } else {
- this.removeSurroundingCssClass("kv-spinner-btn-none")
- }
- if (buttonsType == ButtonsType.VERTICAL) {
- this.addSurroundingCssClass("kv-spinner-btn-vertical")
- } else {
- this.removeSurroundingCssClass("kv-spinner-btn-vertical")
- }
- this.surroundingSpan = true
- this.refreshSpinner()
- this.setInternalEventListener<SpinnerInput> {
- change = {
- self.changeValue()
- }
- }
- }
-
/**
* Spinner value.
*/
@@ -122,14 +104,14 @@ open class SpinnerInput(
*/
var decimals by refreshOnUpdate(decimals) { refreshSpinner() }
/**
- * Spinner buttons type.
- */
- var buttonsType by refreshOnUpdate(buttonsType) { refreshSpinner() }
- /**
* Spinner force rounding type.
*/
var forceType by refreshOnUpdate(forceType) { refreshSpinner() }
/**
+ * The style of the up/down buttons.
+ */
+ var buttonStyle by refreshOnUpdate(buttonStyle) { refreshSpinner() }
+ /**
* The placeholder for the spinner input.
*/
var placeholder: String? by refreshOnUpdate()
@@ -153,15 +135,38 @@ open class SpinnerInput(
* The size of the input.
*/
override var size: InputSize? by refreshOnUpdate()
+ /**
+ * The validation status of the input.
+ */
+ override var validationStatus: ValidationStatus? by refreshOnUpdate()
private var siblings: JQuery? = null
+ init {
+ this.addSurroundingCssClass("input-group")
+ this.addSurroundingCssClass("kv-spinner")
+ when (buttonsType) {
+ ButtonsType.NONE -> this.addSurroundingCssClass("kv-spinner-btn-none")
+ ButtonsType.VERTICAL -> this.addSurroundingCssClass("kv-spinner-btn-vertical")
+ ButtonsType.HORIZONTAL -> this.addSurroundingCssClass("kv-spinner-btn-horizontal")
+ }
+ this.surroundingSpan = true
+ this.setInternalEventListener<SpinnerInput> {
+ change = {
+ self.changeValue()
+ }
+ }
+ }
+
override fun render(): VNode {
return render("input")
}
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
+ validationStatus?.let {
+ cl.add(it.className to true)
+ }
size?.let {
cl.add(it.className to true)
}
@@ -273,6 +278,7 @@ open class SpinnerInput(
private fun getSettingsObj(): dynamic {
val verticalbuttons = buttonsType == ButtonsType.VERTICAL || buttonsType == ButtonsType.NONE
+ val style = buttonStyle
return obj {
this.min = min
this.max = max
@@ -280,12 +286,17 @@ open class SpinnerInput(
this.decimals = decimals
this.verticalbuttons = verticalbuttons
this.forcestepdivisibility = forceType.value
+ if (style != null) {
+ this.buttonup_class = "btn ${style.className}"
+ this.buttondown_class = "btn ${style.className}"
+ } else {
+ this.buttonup_class = "btn btn-secondary"
+ this.buttondown_class = "btn btn-secondary"
+ }
if (verticalbuttons) {
- this.verticalup = "<i class=\"fa fa-caret-up\"></i>"
- this.verticaldown = "<i class=\"fa fa-caret-down\"></i>"
+ this.verticalup = "<i class=\"fas fa-caret-up\"></i>"
+ this.verticaldown = "<i class=\"fas fa-caret-down\"></i>"
}
- this.buttondown_class = "btn btn-default"
- this.buttonup_class = "btn btn-default"
}
}
@@ -313,14 +324,15 @@ open class SpinnerInput(
fun Container.spinnerInput(
value: Number? = null, min: Int? = null, max: Int? = null, step: Double = DEFAULT_STEP,
decimals: Int = 0, buttonsType: ButtonsType = ButtonsType.VERTICAL,
- forceType: ForceType = ForceType.NONE, classes: Set<String> = setOf(),
+ forceType: ForceType = ForceType.NONE, buttonStyle: ButtonStyle? = null, classes: Set<String> = setOf(),
init: (SpinnerInput.() -> Unit)? = null
): SpinnerInput {
- val spinnerInput = SpinnerInput(value, min, max, step, decimals, buttonsType, forceType, classes).apply {
- init?.invoke(
- this
- )
- }
+ val spinnerInput =
+ SpinnerInput(value, min, max, step, decimals, buttonsType, forceType, buttonStyle, classes).apply {
+ init?.invoke(
+ this
+ )
+ }
this.add(spinnerInput)
return spinnerInput
}
diff --git a/kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt b/kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
index 13c8531b..13c8531b 100644
--- a/kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
+++ b/kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
diff --git a/kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerInputSpec.kt b/kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerInputSpec.kt
index 467e48db..467e48db 100644
--- a/kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerInputSpec.kt
+++ b/kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerInputSpec.kt
diff --git a/kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerSpec.kt b/kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerSpec.kt
index 928fe0b1..bb090b61 100644
--- a/kvision-modules/kvision-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerSpec.kt
+++ b/kvision-modules/kvision-bootstrap-spinner/src/test/kotlin/test/pl/treksoft/kvision/form/spinner/SpinnerSpec.kt
@@ -43,13 +43,13 @@ class SpinnerSpec : DomSpec {
val element = document.getElementById("test")
val id = ti.input.id
assertEqualsHtml(
- "<div class=\"form-group\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"input-group kv-spinner-btn-vertical\"><span><div class=\"input-group bootstrap-touchspin bootstrap-touchspin-injected\"><input class=\"form-control\" id=\"$id\" type=\"text\" value=\"13\" placeholder=\"place\" name=\"name\" disabled=\"disabled\"><span class=\"input-group-btn-vertical\"><button class=\"btn btn-default bootstrap-touchspin-up \" type=\"button\"><i class=\"fa fa-caret-up\"></i></button><button class=\"btn btn-default bootstrap-touchspin-down \" type=\"button\"><i class=\"fa fa-caret-down\"></i></button></span></div></span></div></div>",
+ "<div class=\"form-group\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"input-group kv-spinner kv-spinner-btn-vertical\"><span><div class=\"input-group bootstrap-touchspin bootstrap-touchspin-injected\"><input class=\"form-control\" id=\"$id\" type=\"text\" value=\"13\" placeholder=\"place\" name=\"name\" disabled=\"disabled\"><span class=\"input-group-btn-vertical\"><button class=\"btn btn-secondary bootstrap-touchspin-up \" type=\"button\"><i class=\"fas fa-caret-up\"></i></button><button class=\"btn btn-secondary bootstrap-touchspin-down \" type=\"button\"><i class=\"fas fa-caret-down\"></i></button></span></div></span></div></div>",
element?.innerHTML,
"Should render correct spinner input form control"
)
ti.validatorError = "Validation Error"
assertEqualsHtml(
- "<div class=\"form-group has-error\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"input-group kv-spinner-btn-vertical\"><span><div class=\"input-group bootstrap-touchspin bootstrap-touchspin-injected\"><input class=\"form-control\" id=\"$id\" type=\"text\" value=\"13\" placeholder=\"place\" name=\"name\" disabled=\"disabled\"><span class=\"input-group-btn-vertical\"><button class=\"btn btn-default bootstrap-touchspin-up \" type=\"button\"><i class=\"fa fa-caret-up\"></i></button><button class=\"btn btn-default bootstrap-touchspin-down \" type=\"button\"><i class=\"fa fa-caret-down\"></i></button></span></div></span></div><span class=\"help-block small\">Validation Error</span></div>",
+ "<div class=\"form-group text-danger\"><label class=\"control-label\" for=\"$id\">Label</label><div class=\"input-group kv-spinner kv-spinner-btn-vertical is-invalid\"><span><div class=\"input-group bootstrap-touchspin bootstrap-touchspin-injected\"><input class=\"form-control is-invalid\" id=\"$id\" type=\"text\" value=\"13\" placeholder=\"place\" name=\"name\" disabled=\"disabled\"><span class=\"input-group-btn-vertical\"><button class=\"btn btn-secondary bootstrap-touchspin-up \" type=\"button\"><i class=\"fas fa-caret-up\"></i></button><button class=\"btn btn-secondary bootstrap-touchspin-down \" type=\"button\"><i class=\"fas fa-caret-down\"></i></button></span></div></span></div><div class=\"invalid-feedback\">Validation Error</div></div>",
element?.innerHTML,
"Should render correct spinner input form control with validation error"
)
diff --git a/kvision-modules/kvision-bootstrap-spinner/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-spinner/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-spinner/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-bootstrap-spinner/webpack.config.d/jquery.js b/kvision-modules/kvision-bootstrap-spinner/webpack.config.d/jquery.js
new file mode 100644
index 00000000..bf5a1a20
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-spinner/webpack.config.d/jquery.js
@@ -0,0 +1,5 @@
+config.plugins.push(new webpack.ProvidePlugin({
+ $: "jquery",
+ jQuery: "jquery",
+ "window.jQuery": "jquery"
+}));
diff --git a/kvision-modules/kvision-bootstrap-upload/build.gradle b/kvision-modules/kvision-bootstrap-upload/build.gradle
new file mode 100644
index 00000000..a47a110a
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-upload/build.gradle
@@ -0,0 +1,14 @@
+apply from: "../shared.gradle"
+
+dependencies {
+ compile project(":kvision-modules:kvision-bootstrap")
+ compile "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion"
+}
+
+kotlinFrontend {
+
+ npm {
+ dependency("bootstrap-fileinput", "5.0.6")
+ }
+
+}
diff --git a/kvision-modules/kvision-upload/package.json.d/project.info b/kvision-modules/kvision-bootstrap-upload/package.json.d/project.info
index d789d81b..d789d81b 100644
--- a/kvision-modules/kvision-upload/package.json.d/project.info
+++ b/kvision-modules/kvision-bootstrap-upload/package.json.d/project.info
diff --git a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/KVManagerUpload.kt b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/KVManagerUpload.kt
index af0950eb..1d8f05b0 100644
--- a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/KVManagerUpload.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/KVManagerUpload.kt
@@ -26,19 +26,11 @@ internal val kVManagerUploadInit = KVManagerUpload.init()
/**
* Internal singleton object which initializes and configures KVision upload module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerUpload {
- fun init() {}
- private val bootstrapFileinputCss = try {
+ init {
require("bootstrap-fileinput/css/fileinput.min.css")
- } catch (e: Throwable) {
- }
- private val bootstrapFileinputCssFa = try {
- require("bootstrap-fileinput/themes/explorer-fa/theme.min.css")
- } catch (e: Throwable) {
- }
- private val bootstrapFileinput = try {
+ require("bootstrap-fileinput/themes/explorer-fas/theme.min.css")
require("bootstrap-fileinput")
require("./js/locales/bootstrap-fileinput/ar.js")
require("./js/locales/bootstrap-fileinput/az.js")
@@ -59,7 +51,7 @@ internal object KVManagerUpload {
require("./js/locales/bootstrap-fileinput/it.js")
require("./js/locales/bootstrap-fileinput/ja.js")
require("./js/locales/bootstrap-fileinput/ka.js")
- require("./js/locales/bootstrap-fileinput/ko.js")
+ require("./js/locales/bootstrap-fileinput/kr.js")
require("./js/locales/bootstrap-fileinput/kz.js")
require("./js/locales/bootstrap-fileinput/lt.js")
require("./js/locales/bootstrap-fileinput/nl.js")
@@ -76,11 +68,9 @@ internal object KVManagerUpload {
require("./js/locales/bootstrap-fileinput/uk.js")
require("./js/locales/bootstrap-fileinput/vi.js")
require("./js/locales/bootstrap-fileinput/zh.js")
- } catch (e: Throwable) {
- }
- private val bootstrapFileinputFa = try {
- require("bootstrap-fileinput/themes/explorer-fa/theme.min.js")
- } catch (e: Throwable) {
+ require("bootstrap-fileinput/themes/explorer-fas/theme.min.js")
+ require("bootstrap-fileinput/themes/fas/theme.min.js")
}
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/Upload.kt b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/Upload.kt
index 971ce186..bd931127 100644
--- a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/Upload.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/Upload.kt
@@ -26,7 +26,7 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FieldLabel
-import pl.treksoft.kvision.form.HelpBlock
+import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.KFilesFormControl
import pl.treksoft.kvision.panel.SimplePanel
import pl.treksoft.kvision.types.KFile
@@ -208,21 +208,21 @@ open class Upload(
this.name = name
}
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
- final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
+ final override val invalidFeedback: InvalidFeedback = InvalidFeedback().apply { visible = false }
init {
@Suppress("LeakingThis")
input.eventTarget = this
this.addInternal(flabel)
this.addInternal(input)
- this.addInternal(validationInfo)
+ this.addInternal(invalidFeedback)
counter++
}
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
if (validatorError != null) {
- cl.add("has-error" to true)
+ cl.add("text-danger" to true)
}
return cl
}
diff --git a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt
index 21073e61..faae5274 100644
--- a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt
@@ -31,6 +31,7 @@ import pl.treksoft.kvision.form.Form
import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.FormPanel
import pl.treksoft.kvision.form.InputSize
+import pl.treksoft.kvision.form.ValidationStatus
import pl.treksoft.kvision.i18n.I18n
import pl.treksoft.kvision.types.KFile
import pl.treksoft.kvision.utils.getContent
@@ -135,6 +136,10 @@ open class UploadInput(uploadUrl: String? = null, multiple: Boolean = false, cla
* The size of the input (currently not working)
*/
override var size: InputSize? by refreshOnUpdate()
+ /**
+ * The validation status of the input.
+ */
+ override var validationStatus: ValidationStatus? by refreshOnUpdate()
private val nativeFiles: MutableMap<KFile, File> = mutableMapOf()
@@ -144,6 +149,9 @@ open class UploadInput(uploadUrl: String? = null, multiple: Boolean = false, cla
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
+ validationStatus?.let {
+ cl.add(it.className to true)
+ }
size?.let {
cl.add(it.className to true)
}
@@ -290,7 +298,7 @@ open class UploadInput(uploadUrl: String? = null, multiple: Boolean = false, cla
return obj {
this.uploadUrl = uploadUrl
this.uploadExtraData = uploadExtraData ?: undefined
- this.theme = if (explorerTheme) "explorer-fa" else null
+ this.theme = if (explorerTheme) "explorer-fas" else "fas"
this.required = required
this.showCaption = showCaption
this.showPreview = showPreview
@@ -307,6 +315,8 @@ open class UploadInput(uploadUrl: String? = null, multiple: Boolean = false, cla
this.showUpload = showUpload
this.showRemove = showRemove
}
+ this.autoOrientImage = false
+ this.purifyHtml = false
this.language = language
}
}
diff --git a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt
index bdae5091..bdae5091 100644
--- a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ar.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ar.js
index 92d32d28..2245b633 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ar.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ar.js
@@ -20,10 +20,13 @@
removeTitle: 'إزالة الملفات المختارة',
cancelLabel: 'إلغاء',
cancelTitle: 'إنهاء الرفع الحالي',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'رفع',
uploadTitle: 'رفع الملفات المختارة',
msgNo: 'لا',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'ألغيت',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'معاينة تفصيلية',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'خطأ التحقق من صحة',
msgLoading: 'تحميل ملف {index} من {files} &hellip;',
msgProgress: 'تحميل ملف {index} من {files} - {name} - {percent}% منتهي.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'حدث خطأ أثناء تغيير أبعاد الصورة.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'لم يتم الرفع بعد',
indicatorSuccessTitle: 'تم الرفع',
indicatorErrorTitle: 'خطأ بالرفع',
- indicatorLoadingTitle: 'جارٍ الرفع ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'جارٍ الرفع ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/az.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/az.js
index 5a9c6440..c3efafaa 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/az.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/az.js
@@ -20,10 +20,13 @@
removeTitle: 'Seçilmiş faylları təmizlə',
cancelLabel: 'İmtina et',
cancelTitle: 'Cari yükləməni dayandır',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Yüklə',
uploadTitle: 'Seçilmiş faylları yüklə',
msgNo: 'xeyir',
msgNoFilesSelected: 'Heç bir fayl seçilməmişdir',
+ msgPaused: 'Paused',
msgCancelled: 'İmtina edildi',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'İlkin baxış',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Yükləmə...',
msgUploadBegin: 'Yoxlama...',
msgUploadEnd: 'Fayl(lar) yükləndi',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Yükləmə üçün verilmiş məlumatlar yanlışdır',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Yoxlama nəticəsi səhvir',
msgLoading: '{files} fayldan {index} yüklənir &hellip;',
msgProgress: '{files} fayldan {index} - {name} - {percent}% yükləndi.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Faylın ölçülərini dəyişmək mümkün olmadı.<pre>{errors}</pre>',
msgAjaxError: '{operation} əməliyyatı zamanı səhv baş verdi. Təkrar yoxlayın!',
msgAjaxProgressError: '{operation} əməliyyatı yerinə yetirmək mümkün olmadı.',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'faylı sil',
uploadThumb: 'faylı yüklə',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Davam edir',
indicatorSuccessTitle: 'Tamamlandı',
indicatorErrorTitle: 'Yükləmə xətası',
- indicatorLoadingTitle: 'Yükləmə ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Yükləmə ...'
},
previewZoomButtonTitles: {
prev: 'Əvvəlki fayla bax',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/bg.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/bg.js
index cf75d1ab..537932d0 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/bg.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/bg.js
@@ -19,10 +19,13 @@
removeTitle: 'Изчисти избраните',
cancelLabel: 'Откажи',
cancelTitle: 'Откажи качването',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Качи',
uploadTitle: 'Качи избраните файлове',
msgNo: 'Не',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Отменен',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Детайлен преглед',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'утвърждаване грешка',
msgLoading: 'Зареждане на файл {index} от общо {files} &hellip;',
msgProgress: 'Зареждане на файл {index} от общо {files} - {name} - {percent}% завършени.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Грешка при промяна на размера на изображението.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Все още не е качил',
indicatorSuccessTitle: 'Качено',
indicatorErrorTitle: 'Качи Error',
- indicatorLoadingTitle: 'Качва се ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Качва се ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ca.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ca.js
index 16514535..b8410975 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ca.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ca.js
@@ -19,10 +19,13 @@
removeTitle: 'Treure arxius seleccionats',
cancelLabel: 'Cancel',
cancelTitle: 'Avortar la pujada en curs',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Pujar arxiu',
uploadTitle: 'Pujar arxius seleccionats',
msgNo: 'No',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'cancel·lat',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Vista prèvia detallada',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Error de validació',
msgLoading: 'Pujant fitxer {index} de {files} &hellip;',
msgProgress: 'Pujant fitxer {index} de {files} - {name} - {percent}% completat.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Error en canviar la mida de la imatge.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'No pujat encara',
indicatorSuccessTitle: 'Subido',
indicatorErrorTitle: 'Pujar Error',
- indicatorLoadingTitle: 'Pujant ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Pujant ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/cr.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/cr.js
index 685da85d..d6c9f420 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/cr.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/cr.js
@@ -20,10 +20,13 @@
removeTitle: 'Ukloni označene datoteke',
cancelLabel: 'Odustani',
cancelTitle: 'Prekini trenutno otpremanje',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Otpremi',
uploadTitle: 'Otpremi označene datoteke',
msgNo: 'Ne',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Otkazan',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Detaljni pregled',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Provjera pogrešaka',
msgLoading: 'Učitavanje datoteke {index} od {files} &hellip;',
msgProgress: 'Učitavanje datoteke {index} od {files} - {name} - {percent}% završeno.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Greška prilikom promjene veličine slike.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Još nije učitao',
indicatorSuccessTitle: 'Preneseno',
indicatorErrorTitle: 'Postavi Greška',
- indicatorLoadingTitle: 'Prijenos ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Prijenos ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/cs.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/cs.js
index f5e8b723..e3989943 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/cs.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/cs.js
@@ -19,10 +19,13 @@
removeTitle: 'Vyčistit vybrané soubory',
cancelLabel: 'Storno',
cancelTitle: 'Přerušit nahrávání',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Nahrát',
uploadTitle: 'Nahrát vybrané soubory',
msgNo: 'Ne',
msgNoFilesSelected: 'Nevybrány žádné soubory',
+ msgPaused: 'Paused',
msgCancelled: 'Zrušeno',
msgPlaceholder: 'Vybrat {files}...',
msgZoomModalHeading: 'Detailní náhled',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Zpracovávám...',
msgUploadBegin: 'Inicializujem...',
msgUploadEnd: 'Hotovo',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Pro nahrávání nejsou k dispozici žádné platné údaje.',
- msgUploadError: 'Chyba',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Chyba',
msgValidationError: 'Chyba ověření',
msgLoading: 'Nahrávání souboru {index} z {files} &hellip;',
msgProgress: 'Nahrávání souboru {index} z {files} - {name} - {percent}% dokončeno.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Chyba při změně velikosti obrázku.<pre>{errors}</pre>',
msgAjaxError: 'Došlo k chybě v {operation}. Prosím zkuste to znovu později!',
msgAjaxProgressError: '{operation} - neúspěšné',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'odstranit soubor',
uploadThumb: 'nahrát soubor',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Ještě nenahrál',
indicatorSuccessTitle: 'Nahraný',
indicatorErrorTitle: 'Chyba nahrávání',
- indicatorLoadingTitle: 'Nahrávání ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Nahrávání ...'
},
previewZoomButtonTitles: {
prev: 'Zobrazit předchozí soubor',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/da.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/da.js
index 11a13892..27d57db5 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/da.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/da.js
@@ -19,10 +19,13 @@
removeTitle: 'Fjern valgte filer',
cancelLabel: 'Fortryd',
cancelTitle: 'Afbryd nuv&aelig;rende upload',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Upload',
uploadTitle: 'Upload valgte filer',
msgNo: 'Ingen',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'aflyst',
msgPlaceholder: 'V&aelig;lg {files}...',
msgZoomModalHeading: 'Detaljeret visning',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Arbejder...',
msgUploadBegin: 'Initialiserer...',
msgUploadEnd: 'Udf&oslash;rt',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Ingen gyldig data tilg&aelig;ngelig til upload.',
- msgUploadError: 'Fejl',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Fejl',
msgValidationError: 'Valideringsfejl',
msgLoading: 'Henter fil {index} af {files} &hellip;',
msgProgress: 'Henter fil {index} af {files} - {name} - {percent}% f&aelig;rdiggjort.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Fejl ved at &aelig;ndre st&oslash;rrelsen p&aring; billedet.<pre>{errors}</pre>',
msgAjaxError: 'Noget gik galt med {operation} operationen. Fors&oslash;g venligst senere!',
msgAjaxProgressError: '{operation} fejlede',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'fil slet',
uploadThumb: 'fil upload',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Ikke uploadet endnu',
indicatorSuccessTitle: 'Uploadet',
indicatorErrorTitle: 'Upload fejl',
- indicatorLoadingTitle: 'Uploader ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Uploader ...'
},
previewZoomButtonTitles: {
prev: 'Se forrige fil',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/de.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/de.js
index 56ee854b..c1bb4797 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/de.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/de.js
@@ -17,10 +17,13 @@
removeTitle: 'Ausgewählte löschen',
cancelLabel: 'Abbrechen',
cancelTitle: 'Hochladen abbrechen',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Hochladen',
uploadTitle: 'Hochladen der ausgewählten Dateien',
msgNo: 'Keine',
msgNoFilesSelected: 'Keine Dateien ausgewählt',
+ msgPaused: 'Paused',
msgCancelled: 'Abgebrochen',
msgPlaceholder: '{files} auswählen...',
msgZoomModalHeading: 'ausführliche Vorschau',
@@ -51,8 +54,11 @@
msgUploadThreshold: 'Wird bearbeitet ...',
msgUploadBegin: 'Wird initialisiert ...',
msgUploadEnd: 'Erledigt',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Keine gültigen Daten zum Hochladen verfügbar.',
- msgUploadError: 'Fehler',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Fehler',
msgValidationError: 'Validierungsfehler',
msgLoading: 'Lade Datei {index} von {files} hoch&hellip;',
msgProgress: 'Datei {index} von {files} - {name} - zu {percent}% fertiggestellt.',
@@ -66,6 +72,10 @@
msgImageResizeException: 'Fehler beim Ändern der Größe des Bildes.<pre>{errors}</pre>',
msgAjaxError: 'Bei der Aktion {operation} ist ein Fehler aufgetreten. Bitte versuche es später noch einmal!',
msgAjaxProgressError: '{operation} fehlgeschlagen',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'Datei löschen',
uploadThumb: 'Datei hochladen',
@@ -84,7 +94,8 @@
indicatorNewTitle: 'Noch nicht hochgeladen',
indicatorSuccessTitle: 'Hochgeladen',
indicatorErrorTitle: 'Upload Fehler',
- indicatorLoadingTitle: 'Hochladen ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Hochladen ...'
},
previewZoomButtonTitles: {
prev: 'Vorherige Datei anzeigen',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/el.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/el.js
index 170eba1f..a0d888e4 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/el.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/el.js
@@ -19,10 +19,13 @@
removeTitle: 'Εκκαθάριση αρχείων',
cancelLabel: 'Ακύρωση',
cancelTitle: 'Ακύρωση μεταφόρτωσης',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Μεταφόρτωση',
uploadTitle: 'Μεταφόρτωση επιλεγμένων αρχείων',
msgNo: 'Όχι',
msgNoFilesSelected: 'Δεν επιλέχθηκαν αρχεία',
+ msgPaused: 'Paused',
msgCancelled: 'Ακυρώθηκε',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Λεπτομερής Προεπισκόπηση',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Μεταφόρτωση ...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Σφάλμα Επικύρωσης',
msgLoading: 'Φόρτωση αρχείου {index} από {files} &hellip;',
msgProgress: 'Φόρτωση αρχείου {index} απο {files} - {name} - {percent}% ολοκληρώθηκε.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Σφάλμα κατά την αλλαγή μεγέθους της εικόνας. <pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Δεν μεταφορτώθηκε ακόμα',
indicatorSuccessTitle: 'Μεταφορτώθηκε',
indicatorErrorTitle: 'Σφάλμα Μεταφόρτωσης',
- indicatorLoadingTitle: 'Μεταφόρτωση ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Μεταφόρτωση ...'
},
previewZoomButtonTitles: {
prev: 'Προηγούμενο αρχείο',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/es.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/es.js
index 569e7ee5..b1c58e6f 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/es.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/es.js
@@ -19,10 +19,13 @@
removeTitle: 'Quitar archivos seleccionados',
cancelLabel: 'Cancelar',
cancelTitle: 'Abortar la subida en curso',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Subir archivo',
uploadTitle: 'Subir archivos seleccionados',
msgNo: 'No',
msgNoFilesSelected: 'No hay archivos seleccionados',
+ msgPaused: 'Paused',
msgCancelled: 'Cancelado',
msgPlaceholder: 'Seleccionar {files}...',
msgZoomModalHeading: 'Vista previa detallada',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Procesando...',
msgUploadBegin: 'Inicializando...',
msgUploadEnd: 'Hecho',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No existen datos válidos para el envío.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Error de validación',
msgLoading: 'Subiendo archivo {index} de {files} &hellip;',
msgProgress: 'Subiendo archivo {index} de {files} - {name} - {percent}% completado.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Error al cambiar el tamaño de la imagen.<pre>{errors}</pre>',
msgAjaxError: 'Algo ha ido mal con la operación {operation}. Por favor, inténtelo de nuevo mas tarde.',
msgAjaxProgressError: 'La operación {operation} ha fallado',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'Archivo borrado',
uploadThumb: 'Archivo subido',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'No subido todavía',
indicatorSuccessTitle: 'Subido',
indicatorErrorTitle: 'Error al subir',
- indicatorLoadingTitle: 'Subiendo...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Subiendo...'
},
previewZoomButtonTitles: {
prev: 'Anterior',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/et.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/et.js
index 50b15477..039980f1 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/et.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/et.js
@@ -19,10 +19,13 @@
removeTitle: 'Clear selected files',
cancelLabel: 'Tühista',
cancelTitle: 'Abort ongoing upload',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Salvesta',
uploadTitle: 'Salvesta valitud failid',
msgNo: 'No',
msgNoFilesSelected: 'No files selected',
+ msgPaused: 'Paused',
msgCancelled: 'Cancelled',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Detailed Preview',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Validation Error',
msgLoading: 'Loading file {index} of {files} &hellip;',
msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -85,7 +95,8 @@
indicatorNewTitle: 'Pole veel salvestatud',
indicatorSuccessTitle: 'Uploaded',
indicatorErrorTitle: 'Salvestamise viga',
- indicatorLoadingTitle: 'Salvestan ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Salvestan ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fa.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fa.js
index 609099c4..11d1d291 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fa.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fa.js
@@ -20,10 +20,13 @@
removeTitle: 'پاکسازی فایل‌های انتخاب شده',
cancelLabel: 'لغو',
cancelTitle: 'لغو بارگزاری جاری',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'بارگذاری',
uploadTitle: 'بارگذاری فایل‌های انتخاب شده',
msgNo: 'نه',
msgNoFilesSelected: 'هیچ فایلی انتخاب نشده است',
+ msgPaused: 'Paused',
msgCancelled: 'لغو شد',
msgPlaceholder: 'انتخاب {files}...',
msgZoomModalHeading: 'نمایش با جزییات',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'در حال پردازش...',
msgUploadBegin: 'در حال شروع...',
msgUploadEnd: 'انجام شد',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'هیچ داده معتبری برای بارگذاری موجود نیست.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'خطای اعتبار سنجی',
msgLoading: 'بارگیری فایل {index} از {files} &hellip;',
msgProgress: 'بارگیری فایل {index} از {files} - {name} - {percent}% تمام شد.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'خطا در هنگام تغییر اندازه تصویر.<pre>{errors}</pre>',
msgAjaxError: 'به نظر مشکلی در حین {operation} روی داده است. لطفا دوباره تلاش کنید!',
msgAjaxProgressError: '{operation} لغو شد',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'حذف فایل',
uploadThumb: 'بارگذاری فایل',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'آپلود نشده است',
indicatorSuccessTitle: 'آپلود شده',
indicatorErrorTitle: 'بارگذاری خطا',
- indicatorLoadingTitle: 'آپلود ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'آپلود ...'
},
previewZoomButtonTitles: {
prev: 'مشاهده فایل قبلی',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fi.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fi.js
index 19317b54..85154eec 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fi.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fi.js
@@ -19,6 +19,8 @@
removeTitle: 'Tyhj&auml;nn&auml; valitut tiedostot',
cancelLabel: 'Peruuta',
cancelTitle: 'Peruuta lataus',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Lataa',
uploadTitle: 'Lataa valitut tiedostot',
msgNoFilesSelected: '',
@@ -48,8 +50,11 @@
msgUploadThreshold: 'Käsitellään...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Ei ladattavaa dataa.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Tiedoston latausvirhe',
msgLoading: 'Ladataan tiedostoa {index} / {files} &hellip;',
msgProgress: 'Ladataan tiedostoa {index} / {files} - {name} - {percent}% valmistunut.',
@@ -57,6 +62,10 @@
msgFoldersNotAllowed: 'Raahaa ja pudota ainoastaan tiedostoja! Ohitettu {n} raahattua kansiota.',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -75,7 +84,8 @@
indicatorNewTitle: 'Ei ladattu',
indicatorSuccessTitle: 'Ladattu',
indicatorErrorTitle: 'Lataus epäonnistui',
- indicatorLoadingTitle: 'Ladataan ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Ladataan ...'
},
previewZoomButtonTitles: {
prev: 'Seuraava tiedosto',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fr.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fr.js
index 81a77042..0d9e1e97 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/fr.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/fr.js
@@ -19,10 +19,13 @@
removeTitle: 'Retirer les fichiers sélectionnés',
cancelLabel: 'Annuler',
cancelTitle: "Annuler l'envoi en cours",
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Transférer',
uploadTitle: 'Transférer les fichiers sélectionnés',
msgNo: 'Non',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Annulé',
msgPlaceholder: 'Sélectionner le(s) {files}...',
msgZoomModalHeading: 'Aperçu détaillé',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'En cours...',
msgUploadBegin: 'Initialisation...',
msgUploadEnd: 'Terminé',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Aucune donnée valide disponible pour transmission.',
- msgUploadError: 'Erreur',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Erreur',
msgValidationError: 'Erreur de validation',
msgLoading: 'Transmission du fichier {index} sur {files}&hellip;',
msgProgress: 'Transmission du fichier {index} sur {files} - {name} - {percent}%.',
@@ -68,6 +74,10 @@
msgImageResizeException: "Erreur lors du redimensionnement de l'image.<pre>{errors}</pre>",
msgAjaxError: "Une erreur s'est produite pendant l'opération de {operation}. Veuillez réessayer plus tard.",
msgAjaxProgressError: 'L\'opération "{operation}" a échoué',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'suppression du fichier',
uploadThumb: 'transfert du fichier',
@@ -85,7 +95,8 @@
indicatorNewTitle: 'Pas encore transféré',
indicatorSuccessTitle: 'Posté',
indicatorErrorTitle: 'Ajouter erreur',
- indicatorLoadingTitle: 'En cours...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'En cours...'
},
previewZoomButtonTitles: {
prev: 'Voir le fichier précédent',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/gl.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/gl.js
index a2ba90be..0b4992de 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/gl.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/gl.js
@@ -19,10 +19,13 @@
removeTitle: 'Quitar aquivos seleccionados',
cancelLabel: 'Cancelar',
cancelTitle: 'Abortar a subida en curso',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Subir arquivo',
uploadTitle: 'Subir arquivos seleccionados',
msgNo: 'Non',
msgNoFilesSelected: 'Non hay arquivos seleccionados',
+ msgPaused: 'Paused',
msgCancelled: 'Cancelado',
msgPlaceholder: 'Seleccinar {files}...',
msgZoomModalHeading: 'Vista previa detallada',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Procesando...',
msgUploadBegin: 'Inicializando...',
msgUploadEnd: 'Feito',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Non existen datos válidos para o envío.',
- msgUploadError: 'Erro',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Erro',
msgValidationError: 'Erro de validación',
msgLoading: 'Subindo arquivo {index} de {files} &hellip;',
msgProgress: 'Subindo arquivo {index} de {files} - {name} - {percent}% completado.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Erro ao cambiar o tamaño da imaxe. <pre>{errors}</pre>',
msgAjaxError: 'Algo foi mal ca operación {operation}. Por favor, inténtao de novo máis tarde.',
msgAjaxProgressError: 'A operación {operation} fallou',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'Arquivo borrado',
uploadThumb: 'Arquivo subido',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Non subido aínda',
indicatorSuccessTitle: 'Subido',
indicatorErrorTitle: 'Erro ao subir',
- indicatorLoadingTitle: 'Subindo...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Subindo...'
},
previewZoomButtonTitles: {
prev: 'Ver arquivo anterior',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/he.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/he.js
index cea7de35..49a73a13 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/he.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/he.js
@@ -20,10 +20,13 @@
removeTitle: 'נקה קבצים נבחרים',
cancelLabel: 'ביטול',
cancelTitle: 'ביטול העלאה מתמשכת',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'טעינה',
uploadTitle: 'טעינת קבצים נבחרים',
msgNo: 'לא',
msgNoFilesSelected: 'לא נבחרו קבצים',
+ msgPaused: 'Paused',
msgCancelled: 'מבוטל',
msgPlaceholder: 'בחר {files}...',
msgZoomModalHeading: 'תצוגה מקדימה מפורטת',
@@ -53,6 +56,7 @@
msgUploadThreshold: 'מעבד...',
msgUploadBegin: 'מאתחל ...',
msgUploadEnd: 'בוצע',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'אין נתונים זמינים להעלאה.',
msgValidationError: 'שגיאת אימות',
msgLoading: 'טוען קובץ {index} של {files} &hellip;',
@@ -67,6 +71,10 @@
msgImageResizeException: 'שגיאה בעת שינוי גודל התמונה.<pre>{errors}</pre>',
msgAjaxError: 'משהו השתבש עם {operation} המערכת. יש לנסות מאוחר יותר!',
msgAjaxProgressError: '{operation} נכשל',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'קובץ נמחק',
uploadThumb: 'קובץ הועלה',
@@ -83,7 +91,8 @@
indicatorNewTitle: 'עדיין לא הועלה',
indicatorSuccessTitle: 'הועלה',
indicatorErrorTitle: 'שגיאת העלאה',
- indicatorLoadingTitle: 'מעלה...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'מעלה...'
},
previewZoomButtonTitles: {
prev: 'הצגת את הקובץ הקודם',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/hu.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/hu.js
index 534815fb..de210570 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/hu.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/hu.js
@@ -19,10 +19,13 @@
removeTitle: 'Kijelölt fájlok törlése',
cancelLabel: 'Mégse',
cancelTitle: 'Feltöltés megszakítása',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Feltöltés',
uploadTitle: 'Kijelölt fájlok feltöltése',
msgNo: 'Nem',
msgNoFilesSelected: 'Nincs fájl kiválasztva',
+ msgPaused: 'Paused',
msgCancelled: 'Megszakítva',
msgPlaceholder: 'Válasz {files}...',
msgZoomModalHeading: 'Részletes Előnézet',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Folyamatban...',
msgUploadBegin: 'Inicializálás...',
msgUploadEnd: 'Kész',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Nincs érvényes adat a feltöltéshez.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Érvényesítés hiba',
msgLoading: '{index} / {files} töltése &hellip;',
msgProgress: 'Feltöltés: {index} / {files} - {name} - {percent}% kész.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Hiba történt a méretezés közben.<pre>{errors}</pre>',
msgAjaxError: 'Hiba történt a művelet közben ({operation}). Kérjük, próbálja később!',
msgAjaxProgressError: 'Hiba! ({operation})',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'fájl törlés',
uploadThumb: 'fájl feltöltés',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Nem feltöltött',
indicatorSuccessTitle: 'Feltöltött',
indicatorErrorTitle: 'Feltöltés hiba',
- indicatorLoadingTitle: 'Feltöltés ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Feltöltés ...'
},
previewZoomButtonTitles: {
prev: 'Elöző fájl megnézése',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/id.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/id.js
index cc2bab23..936e46e8 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/id.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/id.js
@@ -20,10 +20,13 @@
removeTitle: 'Hapus berkas terpilih',
cancelLabel: 'Batal',
cancelTitle: 'Batalkan proses pengunggahan',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Unggah',
uploadTitle: 'Unggah berkas terpilih',
msgNo: 'Tidak',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Dibatalkan',
msgPlaceholder: 'Pilih {files}...',
msgZoomModalHeading: 'Pratinjau terperinci',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Memproses...',
msgUploadBegin: 'Menyiapkan...',
msgUploadEnd: 'Selesai',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Tidak ada data valid yang tersedia untuk diunggah.',
- msgUploadError: 'Kesalahan',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Kesalahan',
msgValidationError: 'Kesalahan saat memvalidasi',
msgLoading: 'Memuat {index} dari {files} berkas &hellip;',
msgProgress: 'Memuat {index} dari {files} berkas - {name} - {percent}% selesai.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Kesalahan saat mengubah ukuran gambar.<pre>{errors}</pre>',
msgAjaxError: 'Terjadi kesalahan ketika melakukan operasi {operation}. Silahkan coba lagi nanti!',
msgAjaxProgressError: '{operation} gagal',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'Hapus berkas',
uploadThumb: 'Unggah berkas',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Belum diunggah',
indicatorSuccessTitle: 'Sudah diunggah',
indicatorErrorTitle: 'Kesalahan dalam mengungah',
- indicatorLoadingTitle: 'Mengunggah ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Mengunggah ...'
},
previewZoomButtonTitles: {
prev: 'Lihat berkas sebelumnya',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/it.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/it.js
index 73ee7663..fd8e5c33 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/it.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/it.js
@@ -21,10 +21,13 @@
removeTitle: 'Rimuovi i file selezionati',
cancelLabel: 'Annulla',
cancelTitle: 'Annulla i caricamenti in corso',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Carica',
uploadTitle: 'Carica i file selezionati',
msgNo: 'No',
msgNoFilesSelected: 'Nessun file selezionato',
+ msgPaused: 'Paused',
msgCancelled: 'Annullato',
msgPlaceholder: 'Seleziona {files}...',
msgZoomModalHeading: 'Anteprima dettagliata',
@@ -55,8 +58,11 @@
msgUploadThreshold: 'In lavorazione...',
msgUploadBegin: 'Inizializzazione...',
msgUploadEnd: 'Fatto',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Dati non disponibili',
- msgUploadError: 'Errore',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Errore',
msgValidationError: 'Errore di convalida',
msgLoading: 'Caricamento file {index} di {files}&hellip;',
msgProgress: 'Caricamento file {index} di {files} - {name} - {percent}% completato.',
@@ -70,6 +76,10 @@
msgImageResizeException: 'Errore durante il ridimensionamento dell\'immagine.<pre>{errors}</pre>',
msgAjaxError: 'Qualcosa non ha funzionato con l\'operazione {operation}. Per favore riprova più tardi!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'eliminazione file',
uploadThumb: 'caricamento file',
@@ -88,7 +98,8 @@
indicatorNewTitle: 'Non ancora caricato',
indicatorSuccessTitle: 'Caricati',
indicatorErrorTitle: 'Carica Errore',
- indicatorLoadingTitle: 'Caricamento ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Caricamento ...'
},
previewZoomButtonTitles: {
prev: 'Vedi il file precedente',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ja.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ja.js
index 3decd7fa..912237de 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ja.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ja.js
@@ -26,10 +26,13 @@
removeTitle: '選択したファイルを削除',
cancelLabel: 'キャンセル',
cancelTitle: 'アップロードをキャンセル',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'アップロード',
uploadTitle: '選択したファイルをアップロード',
msgNo: 'いいえ',
msgNoFilesSelected: 'ファイルが選択されていません',
+ msgPaused: 'Paused',
msgCancelled: 'キャンセル',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'プレビュー',
@@ -60,8 +63,11 @@
msgUploadThreshold: '処理中...',
msgUploadBegin: '初期化中...',
msgUploadEnd: '完了',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'アップロードに有効なデータがありません',
- msgUploadError: 'エラー',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'エラー',
msgValidationError: '検証エラー',
msgLoading: '{files}個中{index}個目のファイルを読み込み中&hellip;',
msgProgress: '{files}個中{index}個のファイルを読み込み中 - {name} - {percent}% 完了',
@@ -75,6 +81,10 @@
msgImageResizeException: '画像のリサイズ時にエラーが発生しました。<pre>{errors}</pre>',
msgAjaxError: '{operation}実行中にエラーが発生しました。時間をおいてもう一度お試しください。',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'ファイル削除',
uploadThumb: 'ファイルアップロード',
@@ -95,7 +105,8 @@
indicatorNewTitle: 'まだアップロードされていません',
indicatorSuccessTitle: 'アップロード済み',
indicatorErrorTitle: 'アップロード失敗',
- indicatorLoadingTitle: 'アップロード中...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'アップロード中...'
},
previewZoomButtonTitles: {
prev: '前のファイルを表示',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ka.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ka.js
index c6c0a230..f5c552c3 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ka.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ka.js
@@ -20,10 +20,13 @@
removeTitle: 'არჩეული ფაილების წაშლა',
cancelLabel: 'გაუქმება',
cancelTitle: 'მიმდინარე ატვირთვის გაუქმება',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'ატვირთვა',
uploadTitle: 'არჩეული ფაილების ატვირთვა',
msgNo: 'არა',
msgNoFilesSelected: 'ფაილები არ არის არჩეული',
+ msgPaused: 'Paused',
msgCancelled: 'გაუქმებულია',
msgPlaceholder: 'აირჩიეთ {files}...',
msgZoomModalHeading: 'დეტალურად ნახვა',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'მუშავდება...',
msgUploadBegin: 'ინიციალიზაცია...',
msgUploadEnd: 'დასრულებულია',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'ატვირთვისთვის დაუშვებელი მონაცემები.',
- msgUploadError: 'ატვირთვის შეცდომა',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'ატვირთვის შეცდომა',
msgValidationError: 'ვალიდაციის შეცდომა',
msgLoading: 'ატვირთვა {index} / {files} &hellip;',
msgProgress: 'ფაილის ატვირთვა დასრულებულია {index} / {files} - {name} - {percent}%.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'შეცდომა სურათის ზომის შეცვლისას.<pre>{errors}</pre>',
msgAjaxError: 'დაფიქსირდა შეცდომა ოპერაციის {operation} შესრულებისას. ცადეთ მოგვიანებით!',
msgAjaxProgressError: 'ვერ მოხერხდა ოპერაციის {operation} შესრულება',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'ფაილის წაშლა',
uploadThumb: 'ფაილის ატვირთვა',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'ჯერ არ ატვირთულა',
indicatorSuccessTitle: 'ატვირთულია',
indicatorErrorTitle: 'ატვირთვის შეცდომა',
- indicatorLoadingTitle: 'ატვირთვა ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'ატვირთვა ...'
},
previewZoomButtonTitles: {
prev: 'წინა ფაილის ნახვა',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ko.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/kr.js
index 0190dd73..0cee688e 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ko.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/kr.js
@@ -19,10 +19,13 @@
removeTitle: '선택한 파일들 지우기',
cancelLabel: '취소',
cancelTitle: '진행중인 업로드 중단',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: '업로드',
uploadTitle: '선택한 파일 업로드',
msgNo: '아니요',
msgNoFilesSelected: '선택한 파일이 없습니다',
+ msgPaused: 'Paused',
msgCancelled: '취소되었습니다',
msgPlaceholder: '{files} 선택...',
msgZoomModalHeading: '세부 정보',
@@ -53,8 +56,11 @@
msgUploadThreshold: '처리하는 중...',
msgUploadBegin: '초기화 중...',
msgUploadEnd: '완료',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: '업로드 가능한 데이터가 존재하지 않습니다.',
- msgUploadError: '오류',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: '오류',
msgValidationError: '유효성 오류',
msgLoading: '{index}/{files}번째 파일을 불러오는 중입니다. &hellip;',
msgProgress: '{index}/{files} - {name} - {percent}% 불러오기 완료.',
@@ -68,6 +74,10 @@
msgImageResizeException: '이미지 사이즈 재조정이 다음 이유로 실패했습니다.<pre>{errors}</pre>',
msgAjaxError: '{operation} 실행 도중 실패했습니다. 잠시 후 다시 시도해 주세요!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -86,7 +96,8 @@
indicatorNewTitle: '아직 업로드 되지 않았습니다',
indicatorSuccessTitle: '업로드 성공',
indicatorErrorTitle: '업로드 중 에러 발생',
- indicatorLoadingTitle: '업로드 중 ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: '업로드 중 ...'
},
previewZoomButtonTitles: {
prev: '이전 파일',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/kz.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/kz.js
index 82c34cc4..8ec28c62 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/kz.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/kz.js
@@ -20,10 +20,13 @@
removeTitle: 'Таңдалған файлдарды жою',
cancelLabel: 'Күшін жою',
cancelTitle: 'Ағымдағы жүктеуді болдырмау',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Жүктеу',
uploadTitle: 'Таңдалған файлдарды жүктеу',
msgNo: 'жоқ',
msgNoFilesSelected: 'Файл таңдалмады',
+ msgPaused: 'Paused',
msgCancelled: 'Күші жойылған',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Алдын ала толық көру',
@@ -41,8 +44,11 @@
msgUploadThreshold: 'Өңдеу...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Тексеру қатесі',
msgLoading: '{index} файлды {files} &hellip; жүктеу',
msgProgress: '{index} файлды {files} - {name} - {percent}% жүктеу аяқталды.',
@@ -56,6 +62,10 @@
msgImageResizeException: 'Суреттің мөлшерлерін өзгерткен кезде қателік пайда болды.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -74,7 +84,8 @@
indicatorNewTitle: 'Жүктелген жоқ',
indicatorSuccessTitle: 'Жүктелген',
indicatorErrorTitle: 'Жүктелу қатесі ',
- indicatorLoadingTitle: 'Жүктелу ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Жүктелу ...'
},
previewZoomButtonTitles: {
prev: 'Алдыңғы файлды қарау',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/lt.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/lt.js
index 91f36c94..f5c007a3 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/lt.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/lt.js
@@ -20,10 +20,13 @@
removeTitle: 'Pašalinti pasirinktus failus',
cancelLabel: 'Atšaukti',
cancelTitle: 'Atšaukti vykstantį įkėlimą',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Įkelti',
uploadTitle: 'Įkelti pasirinktus failus',
msgNo: 'Ne',
msgNoFilesSelected: 'Nepasirinkta jokių failų',
+ msgPaused: 'Paused',
msgCancelled: 'Atšaukta',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Detali Peržiūra',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Vykdoma...',
msgUploadBegin: 'Inicijuojama...',
msgUploadEnd: 'Baigta',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Nėra teisingų duomenų įkėlimui.',
- msgUploadError: 'Klaida',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Klaida',
msgValidationError: 'Validacijos Klaida',
msgLoading: 'Keliamas failas {index} iš {files} &hellip;',
msgProgress: 'Keliamas failas {index} iš {files} - {name} - {percent}% baigta.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Klaida keičiant paveikslėlio matmenis.<pre>{errors}</pre>',
msgAjaxError: 'Kažkas nutiko vykdant {operation} operaciją. Prašome pabandyti vėliau!',
msgAjaxProgressError: '{operation} operacija nesėkminga',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'failo trynimo',
uploadThumb: 'failo įkėlimo',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Dar neįkelta',
indicatorSuccessTitle: 'Įkelta',
indicatorErrorTitle: 'Įkėlimo Klaida',
- indicatorLoadingTitle: 'Įkeliama ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Įkeliama ...'
},
previewZoomButtonTitles: {
prev: 'Peržiūrėti ankstesnį failą',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/nl.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/nl.js
index df3f3dc4..cc462627 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/nl.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/nl.js
@@ -19,10 +19,13 @@
removeTitle: 'Verwijder geselecteerde bestanden',
cancelLabel: 'Annuleren',
cancelTitle: 'Annuleer upload',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Upload',
uploadTitle: 'Upload geselecteerde bestanden',
msgNo: 'Nee',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Geannuleerd',
msgPlaceholder: 'Selecteer {files}...',
msgZoomModalHeading: 'Gedetailleerd voorbeeld',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Verwerken...',
msgUploadBegin: 'Initialiseren...',
msgUploadEnd: 'Gedaan',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Geen geldige data beschikbaar voor upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Bevestiging fout',
msgLoading: 'Bestanden laden {index} van de {files} &hellip;',
msgProgress: 'Bestanden laden {index} van de {files} - {name} - {percent}% compleet.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Fout bij het verkleinen van de foto.<pre>{errors}</pre>',
msgAjaxError: 'Er ging iets mis met de {operation} actie. Gelieve later opnieuw te proberen!',
msgAjaxProgressError: '{operation} mislukt',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'bestand verwijderen',
uploadThumb: 'bestand uploaden',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Nog niet geupload',
indicatorSuccessTitle: 'geupload',
indicatorErrorTitle: 'fout uploaden',
- indicatorLoadingTitle: 'uploaden ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'uploaden ...'
},
previewZoomButtonTitles: {
prev: 'Toon vorig bestand',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/no.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/no.js
index 773bb1bd..f6b8ab33 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/no.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/no.js
@@ -19,10 +19,13 @@
removeTitle: 'Fjern valgte filer',
cancelLabel: 'Avbryt',
cancelTitle: 'Stopp pågående opplastninger',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Last opp',
uploadTitle: 'Last opp valgte filer',
msgNo: 'Nei',
msgNoFilesSelected: 'Ingen filer er valgt',
+ msgPaused: 'Paused',
msgCancelled: 'Avbrutt',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Detaljert visning',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Prosesserer...',
msgUploadBegin: 'Initialiserer...',
msgUploadEnd: 'Ferdig',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Ingen gyldige data tilgjengelig for opplastning.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Valideringsfeil',
msgLoading: 'Laster fil {index} av {files} &hellip;',
msgProgress: 'Laster fil {index} av {files} - {name} - {percent}% fullført.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'En feil oppstod under endring av størrelse .<pre>{errors}</pre>',
msgAjaxError: 'Noe gikk galt med {operation} operasjonen. Vennligst prøv igjen senere!',
msgAjaxProgressError: '{operation} feilet',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -85,7 +95,8 @@
indicatorNewTitle: 'Opplastning ikke fullført',
indicatorSuccessTitle: 'Opplastet',
indicatorErrorTitle: 'Opplastningsfeil',
- indicatorLoadingTitle: 'Laster opp ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Laster opp ...'
},
previewZoomButtonTitles: {
prev: 'Vis forrige fil',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pl.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pl.js
index e19a0ed2..6de299fb 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pl.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pl.js
@@ -19,10 +19,13 @@
removeTitle: 'Usuń zaznaczone pliki',
cancelLabel: 'Przerwij',
cancelTitle: 'Anuluj wysyłanie',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Wgraj',
uploadTitle: 'Wgraj zaznaczone pliki',
msgNo: 'Nie',
msgNoFilesSelected: 'Brak zaznaczonych plików',
+ msgPaused: 'Paused',
msgCancelled: 'Odwołany',
msgPlaceholder: 'Wybierz {files}...',
msgZoomModalHeading: 'Szczegółowy podgląd',
@@ -43,8 +46,11 @@
msgUploadThreshold: 'Przetwarzanie...',
msgUploadBegin: 'Rozpoczynanie...',
msgUploadEnd: 'Gotowe!',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Brak poprawnych danych do przesłania.',
- msgUploadError: 'Błąd',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Błąd',
msgValidationError: 'Błąd walidacji',
msgLoading: 'Wczytywanie pliku {index} z {files} &hellip;',
msgProgress: 'Wczytywanie pliku {index} z {files} - {name} - {percent}% zakończone.',
@@ -58,6 +64,10 @@
msgImageResizeException: 'Błąd podczas zmiany rozmiaru obrazu.<pre>{errors}</pre>',
msgAjaxError: 'Coś poczło nie tak podczas {operation}. Spróbuj ponownie!',
msgAjaxProgressError: '{operation} nie powiodło się',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'usuwanie pliku',
uploadThumb: 'przesyłanie pliku',
@@ -76,7 +86,8 @@
indicatorNewTitle: 'Jeszcze nie przesłany',
indicatorSuccessTitle: 'Dodane',
indicatorErrorTitle: 'Błąd',
- indicatorLoadingTitle: 'Przesyłanie ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Przesyłanie ...'
},
previewZoomButtonTitles: {
prev: 'Pokaż poprzedni plik',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt-BR.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt-BR.js
index 157ac84c..40c32cec 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt-BR.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt-BR.js
@@ -19,10 +19,13 @@
removeTitle: 'Remover arquivos selecionados',
cancelLabel: 'Cancelar',
cancelTitle: 'Interromper envio em andamento',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Enviar',
uploadTitle: 'Enviar arquivos selecionados',
msgNo: 'Não',
msgNoFilesSelected: 'Nenhum arquivo selecionado',
+ msgPaused: 'Paused',
msgCancelled: 'Cancelado',
msgPlaceholder: 'Selecionar {files}...',
msgZoomModalHeading: 'Pré-visualização detalhada',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Processando...',
msgUploadBegin: 'Inicializando...',
msgUploadEnd: 'Concluído',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Nenhuma informação válida para upload.',
- msgUploadError: 'Erro de Upload',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Erro de Upload',
msgValidationError: 'Erro de validação',
msgLoading: 'Enviando arquivo {index} de {files}&hellip;',
msgProgress: 'Enviando arquivo {index} de {files} - {name} - {percent}% completo.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Erro ao redimensionar a imagem.<pre>{errors}</pre>',
msgAjaxError: 'Algo deu errado com a operação {operation}. Por favor tente novamente mais tarde!',
msgAjaxProgressError: '{operation} falhou',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'Exclusão de arquivo',
uploadThumb: 'Upload de arquivos',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Ainda não enviado',
indicatorSuccessTitle: 'Enviado',
indicatorErrorTitle: 'Erro',
- indicatorLoadingTitle: 'Enviando...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Enviando...'
},
previewZoomButtonTitles: {
prev: 'Visualizar arquivo anterior',
diff --git a/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js
new file mode 100644
index 00000000..181ab198
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js
@@ -0,0 +1,111 @@
+/*!
+ * FileInput Portuguese Translations
+ *
+ * This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or
+ * any HTML markup tags in the messages must not be converted or translated.
+ *
+ * @see http://github.com/kartik-v/bootstrap-fileinput
+ *
+ * NOTE: this file must be saved in UTF-8 encoding.
+ */
+(function ($) {
+ "use strict";
+
+ $.fn.fileinputLocales['pt'] = {
+ fileSingle: 'ficheiro',
+ filePlural: 'ficheiros',
+ browseLabel: 'Procurar &hellip;',
+ removeLabel: 'Remover',
+ removeTitle: 'Remover ficheiros selecionados',
+ cancelLabel: 'Cancelar',
+ cancelTitle: 'Abortar envio',
+ pauseLabel: 'Parar',
+ pauseTitle: 'Parar envio em curso',
+ uploadLabel: 'Enviar',
+ uploadTitle: 'Enviar ficheiros selecionados',
+ msgNo: 'Não',
+ msgNoFilesSelected: 'Nenhum ficheiro selecionado',
+ msgPaused: 'Parado',
+ msgCancelled: 'Cancelado',
+ msgPlaceholder: 'Selecionar {files}...',
+ msgZoomModalHeading: 'Pré-visualização detalhada',
+ msgFileRequired: 'É necessário selecionar um ficheiro a enviar.',
+ msgSizeTooSmall: 'Ficheiro "{name}" (<b>{size} KB</b>) é demasiado pequeno, tem ser ser maior que <b>{minSize} KB</b>.',
+ msgSizeTooLarge: 'Ficheiro "{name}" (<b>{size} KB</b>) excede o tamanho máximo permido de <b>{maxSize} KB</b>.',
+ msgFilesTooLess: 'Deve selecionar pelo menos <b>{n}</b> {files} para enviar.',
+ msgFilesTooMany: 'Número máximo de ficheiros selecionados <b>({n})</b> excede o limite máximo de <b>{m}</b>.',
+ msgFileNotFound: 'Ficheiro "{name}" não encontrado.',
+ msgFileSecured: 'Restrições de segurança impedem a leitura do ficheiro "{name}".',
+ msgFileNotReadable: 'Ficheiro "{name}" não pode ser lido.',
+ msgFilePreviewAborted: 'Pré-visualização abortado para o ficheiro "{name}".',
+ msgFilePreviewError: 'Ocorreu um erro ao ler o ficheiro "{name}".',
+ msgInvalidFileName: 'Caracteres inválidos ou não suportados no nome de ficheiro "{name}".',
+ msgInvalidFileType: 'Tipo inválido para o ficheiro "{name}". Apenas ficheiros "{types}" são suportados.',
+ msgInvalidFileExtension: 'Extensão inválida para o ficheiro "{name}". Apenas ficheiros "{extensions}" são suportados.',
+ msgFileTypes: {
+ 'image': 'imagem',
+ 'html': 'HTML',
+ 'text': 'texto',
+ 'video': 'vídeo',
+ 'audio': 'audio',
+ 'flash': 'flash',
+ 'pdf': 'PDF',
+ 'object': 'objeto'
+ },
+ msgUploadAborted: 'O envio do ficheiro foi abortado',
+ msgUploadThreshold: 'A processar...',
+ msgUploadBegin: 'A inicializar...',
+ msgUploadEnd: 'Concluído',
+ msgUploadResume: 'A retomar o envio...',
+ msgUploadEmpty: 'Não existem dados válidos disponíveis para o envio.',
+ msgUploadError: 'Erro de Envio',
+ msgDeleteError: 'Erro de Eliminação',
+ msgProgressError: 'Erro',
+ msgValidationError: 'Erro de Validação',
+ msgLoading: 'A enviar ficheiro {index} de {files} &hellip;',
+ msgProgress: 'A enviar ficheiro {index} de {files} - {name} - {percent}% completo.',
+ msgSelected: '{n} {files} selecionados',
+ msgFoldersNotAllowed: 'Arrastar e largar ficheiros apenas. {n} pasta(s) ignoradas.',
+ msgImageWidthSmall: 'Largura da imagem "{name}" deve ser pelo menos {size} px.',
+ msgImageHeightSmall: 'Altura da imagem "{name}" deve ser pelo menos {size} px.',
+ msgImageWidthLarge: 'Largura da imagem "{name}" não pode exceder {size} px.',
+ msgImageHeightLarge: 'Altura da imagem "{name}" não pode exceder {size} px.',
+ msgImageResizeError: 'Nãofoi possível obter as dimensões da imagem para redimensionar.',
+ msgImageResizeException: 'Erro ao redimensionar a imagem.<pre>{errors}</pre>',
+ msgAjaxError: 'Ocorreu um erro durante a operação {operation}. Por favor tente de novo mais tarde.',
+ msgAjaxProgressError: '{operation} falhou',
+ msgDuplicateFile: 'O ficheiro "{name}" com o mesmo tamanho "{size} KB" já foi anteriormente selecionado. O ficheiro duplicado foi ignorado.',
+ msgResumableUploadRetriesExceeded: 'O envio foi abortado após <b>{max}</b> tentativas para o ficheiro <b>{file}</b>. Detalhes do erro: <pre>{error}</pre>',
+ msgPendingTime: '{time} restante',
+ msgCalculatingTime: 'a calcular o tempo restante',
+ ajaxOperations: {
+ deleteThumb: 'eliminar ficheiro',
+ uploadThumb: 'enviar ficheiro',
+ uploadBatch: 'envio de ficheiros em lote',
+ uploadExtra: 'envio de ficheiro em formulário'
+ },
+ dropZoneTitle: 'Arrastar e largar ficheiros aqui &hellip;',
+ dropZoneClickTitle: '<br>(ou clique para selecionar {files})',
+ fileActionSettings: {
+ removeTitle: 'Remover ficheiro',
+ uploadTitle: 'Enviar ficheiro',
+ uploadRetryTitle: 'Voltar a tentar o envio',
+ downloadTitle: 'Transferir ficheiro',
+ zoomTitle: 'Ver detalhes',
+ dragTitle: 'Mover / Reorganizar',
+ indicatorNewTitle: 'Ainda Não Enviado',
+ indicatorSuccessTitle: 'Enviado',
+ indicatorErrorTitle: 'Erro de Envio',
+ indicatorPausedTitle: 'Envio Parado',
+ indicatorLoadingTitle: 'A enviar ...'
+ },
+ previewZoomButtonTitles: {
+ prev: 'Ver ficheiro anterior',
+ next: 'Ver próximo ficheiro',
+ toggleheader: 'Mostrar/esconder cabeçalho',
+ fullscreen: 'Alternar entre ecrã completo',
+ borderless: 'Alternar entre modo sem bordas',
+ close: 'Fechar pré-visualização detalhada'
+ }
+ };
+})(window.jQuery);
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ro.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ro.js
index d31b85bd..b1930984 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ro.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ro.js
@@ -20,10 +20,13 @@
removeTitle: 'Curăță fișierele selectate',
cancelLabel: 'Renunță',
cancelTitle: 'Anulează încărcarea curentă',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Încarcă',
uploadTitle: 'Încarcă fișierele selectate',
msgNo: 'Nu',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Anulat',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Previzualizare detaliată',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Eroare de validare',
msgLoading: 'Se încarcă fișierul {index} din {files} &hellip;',
msgProgress: 'Se încarcă fișierul {index} din {files} - {name} - {percent}% încărcat.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Eroare la redimensionarea imaginii.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Nu a încărcat încă',
indicatorSuccessTitle: 'încărcat',
indicatorErrorTitle: 'Încărcați eroare',
- indicatorLoadingTitle: 'Se încarcă ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Se încarcă ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ru.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ru.js
index 71c5ff7a..619744bc 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/ru.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/ru.js
@@ -20,10 +20,13 @@
removeTitle: 'Очистить выбранные файлы',
cancelLabel: 'Отмена',
cancelTitle: 'Отменить текущую загрузку',
+ pauseLabel: 'Пауза',
+ pauseTitle: 'Приостановить текущую загрузку',
uploadLabel: 'Загрузить',
uploadTitle: 'Загрузить выбранные файлы',
msgNo: 'нет',
msgNoFilesSelected: '',
+ msgPaused: 'Приостановлено',
msgCancelled: 'Отменено',
msgPlaceholder: 'Выбрать {files}...',
msgZoomModalHeading: 'Подробное превью',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Обработка...',
msgUploadBegin: 'Инициализация...',
msgUploadEnd: 'Готово',
+ msgUploadResume: 'Возобновление загрузки...',
msgUploadEmpty: 'Недопустимые данные для загрузки',
msgUploadError: 'Ошибка загрузки',
+ msgDeleteError: 'Ошибка удаления',
+ msgProgressError: 'Ошибка загрузки',
msgValidationError: 'Ошибка проверки',
msgLoading: 'Загрузка файла {index} из {files} &hellip;',
msgProgress: 'Загрузка файла {index} из {files} - {name} - {percent}% завершено.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Ошибка при изменении размера изображения.<pre>{errors}</pre>',
msgAjaxError: 'Произошла ошибка при выполнении операции {operation}. Повторите попытку позже!',
msgAjaxProgressError: 'Не удалось выполнить {operation}',
+ msgDuplicateFile: 'Файл "{name}" с размером "{size} KB" уже был выбран ранее. Пропуск повторяющегося выбора.',
+ msgResumableUploadRetriesExceeded: 'Загрузка прервана после <b>{max}</b> попыток для файла <b>{file}</b>! Информация об ошибке: <pre>{error}</pre>',
+ msgPendingTime: '{time} осталось',
+ msgCalculatingTime: 'расчет оставшегося времени',
ajaxOperations: {
deleteThumb: 'удалить файл',
uploadThumb: 'загрузить файл',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Еще не загружен',
indicatorSuccessTitle: 'Загружен',
indicatorErrorTitle: 'Ошибка загрузки',
- indicatorLoadingTitle: 'Загрузка ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Загрузка ...'
},
previewZoomButtonTitles: {
prev: 'Посмотреть предыдущий файл',
@@ -98,4 +109,4 @@
close: 'Закрыть подробный предпросмотр'
}
};
-})(window.jQuery);
+})(window.jQuery); \ No newline at end of file
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sk.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sk.js
index 28d67e9a..706cb0e0 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sk.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sk.js
@@ -19,10 +19,13 @@
removeTitle: 'Vyčistiť vybraté súbory',
cancelLabel: 'Storno',
cancelTitle: 'Prerušiť nahrávanie',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Nahrať',
uploadTitle: 'Nahrať vybraté súbory',
msgNo: 'Nie',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Zrušené',
msgPlaceholder: 'Vybrať {files}...',
msgZoomModalHeading: 'Detailný náhľad',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Spracovávam...',
msgUploadBegin: 'Inicializujem...',
msgUploadEnd: 'Hotovo',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Na nahrávanie nie sú k dispozícii žiadne platné údaje.',
- msgUploadError: 'Chyba',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Chyba',
msgValidationError: 'Chyba overenia',
msgLoading: 'Nahrávanie súboru {index} z {files} &hellip;',
msgProgress: 'Nahrávanie súboru {index} z {files} - {name} - {percent}% dokončené.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Chyba pri zmene veľkosti obrázka.<pre>{errors}</pre>',
msgAjaxError: 'Pri operácii {operation} sa vyskytla chyba. Skúste to prosím neskôr!',
msgAjaxProgressError: '{operation} - neúspešné',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'odstrániť súbor',
uploadThumb: 'nahrať súbor',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'Ešte nenahral',
indicatorSuccessTitle: 'Nahraný',
indicatorErrorTitle: 'Chyba pri nahrávaní',
- indicatorLoadingTitle: 'Nahrávanie ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Nahrávanie ...'
},
previewZoomButtonTitles: {
prev: 'Zobraziť predchádzajúci súbor',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sl.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sl.js
index 490d7d61..b57d996d 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sl.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sl.js
@@ -20,10 +20,13 @@
removeTitle: 'Počisti izbrane datoteke',
cancelLabel: 'Prekliči',
cancelTitle: 'Prekliči nalaganje',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Naloži',
uploadTitle: 'Naloži izbrane datoteke',
msgNo: 'Ne',
msgNoFilesSelected: 'Nobena datoteka ni izbrana',
+ msgPaused: 'Paused',
msgCancelled: 'Preklicano',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Podroben predogled',
@@ -51,8 +54,11 @@
msgUploadThreshold: 'Procesiram...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Napaki pri validiranju',
msgLoading: 'Nalaganje datoteke {index} od {files} &hellip;',
msgProgress: 'Nalaganje datoteke {index} od {files} - {name} - {percent}% dokončano.',
@@ -66,6 +72,10 @@
msgImageResizeException: 'Napaka pri spreminjanju velikosti slike.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -84,7 +94,8 @@
indicatorNewTitle: 'Še ni naloženo',
indicatorSuccessTitle: 'Naloženo',
indicatorErrorTitle: 'Napaka pri nalaganju',
- indicatorLoadingTitle: 'Nalagam ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Nalagam ...'
},
previewZoomButtonTitles: {
prev: 'Poglej prejšno datoteko',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sv.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sv.js
index 038b1d99..90abd31d 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/sv.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/sv.js
@@ -19,10 +19,13 @@
removeTitle: 'Rensa valda filer',
cancelLabel: 'Avbryt',
cancelTitle: 'Avbryt pågående uppladdning',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Ladda upp',
uploadTitle: 'Ladda upp valda filer',
msgNo: 'Nej',
msgNoFilesSelected: 'Inga filer valda',
+ msgPaused: 'Paused',
msgCancelled: 'Avbruten',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'detaljerad förhandsgranskning',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Bearbetar...',
msgUploadBegin: 'Påbörjar...',
msgUploadEnd: 'Färdig',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Ingen giltig data tillgänglig för uppladdning.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Valideringsfel',
msgLoading: 'Laddar fil {index} av {files} &hellip;',
msgProgress: 'Laddar fil {index} av {files} - {name} - {percent}% färdig.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Fel vid storleksändring av bilden.<pre>{errors}</pre>',
msgAjaxError: 'Något gick fel med {operation} operationen. Försök igen senare!',
msgAjaxProgressError: '{operation} misslyckades',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -85,7 +95,8 @@
indicatorNewTitle: 'Inte uppladdat ännu',
indicatorSuccessTitle: 'Uppladdad',
indicatorErrorTitle: 'Uppladdningsfel',
- indicatorLoadingTitle: 'Laddar upp...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Laddar upp...'
},
previewZoomButtonTitles: {
prev: 'Visa föregående fil',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/th.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/th.js
index 7a2d0460..c00f82ea 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/th.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/th.js
@@ -19,10 +19,13 @@
removeTitle: 'ลบไฟล์ที่เลือกทิ้ง',
cancelLabel: 'ยกเลิก',
cancelTitle: 'ยกเลิกการอัพโหลด',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'อัพโหลด',
uploadTitle: 'อัพโหลดไฟล์ที่เลือก',
msgNo: 'ไม่',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'ยกเลิก',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'ตัวอย่างละเอียด',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'ข้อผิดพลาดในการตรวจสอบ',
msgLoading: 'กำลังโหลดไฟล์ {index} จาก {files} &hellip;',
msgProgress: 'กำลังโหลดไฟล์ {index} จาก {files} - {name} - {percent}%',
@@ -68,6 +74,10 @@
msgImageResizeException: 'ข้อผิดพลาดขณะปรับขนาดภาพ<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -86,7 +96,8 @@
indicatorNewTitle: 'ยังไม่ได้อัปโหลด',
indicatorSuccessTitle: 'อัพโหลด',
indicatorErrorTitle: 'อัปโหลดข้อผิดพลาด',
- indicatorLoadingTitle: 'อัพโหลด ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'อัพโหลด ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/tr.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/tr.js
index 1fe6a383..a7efa29e 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/tr.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/tr.js
@@ -19,10 +19,13 @@
removeTitle: 'Seçilen dosyaları sil',
cancelLabel: 'İptal',
cancelTitle: 'Devam eden yüklemeyi iptal et',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Yükle',
uploadTitle: 'Seçilen dosyaları yükle',
msgNo: 'Hayır',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'İptal edildi',
msgPlaceholder: 'Seçilen {files}...',
msgZoomModalHeading: 'Detaylı Önizleme',
@@ -53,8 +56,11 @@
msgUploadThreshold: 'İşlem yapılıyor...',
msgUploadBegin: 'Başlıyor...',
msgUploadEnd: 'Başarılı',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Yüklemek için geçerli veri mevcut değil.',
- msgUploadError: 'Hata',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Hata',
msgValidationError: 'Doğrulama Hatası',
msgLoading: 'Dosya yükleniyor {index} / {files} &hellip;',
msgProgress: 'Dosya yükleniyor {index} / {files} - {name} - %{percent} tamamlandı.',
@@ -68,6 +74,10 @@
msgImageResizeException: 'Görüntü boyutlandırma sırasında hata.<pre>{errors}</pre>',
msgAjaxError: '{operation} işlemi ile ilgili bir şeyler ters gitti. Lütfen daha sonra tekrar deneyiniz!',
msgAjaxProgressError: '{operation} işlemi başarısız oldu.',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'dosya silme',
uploadThumb: 'dosya yükleme',
@@ -85,7 +95,8 @@
indicatorNewTitle: 'Henüz yüklenmedi',
indicatorSuccessTitle: 'Yüklendi',
indicatorErrorTitle: 'Yükleme Hatası',
- indicatorLoadingTitle: 'Yükleniyor ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Yükleniyor ...'
},
previewZoomButtonTitles: {
prev: 'Önceki dosyayı göster',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/uk.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/uk.js
index d1b7f3a1..94928353 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/uk.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/uk.js
@@ -20,10 +20,13 @@
removeTitle: 'Видалити вибрані файли',
cancelLabel: 'Скасувати',
cancelTitle: 'Скасувати поточне відвантаження',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Відвантажити',
uploadTitle: 'Відвантажити обрані файли',
msgNo: 'Немає',
msgNoFilesSelected: '',
+ msgPaused: 'Paused',
msgCancelled: 'Cкасовано',
msgPlaceholder: 'Оберіть {files}...',
msgZoomModalHeading: 'Детальний превью',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Обробка...',
msgUploadBegin: 'Ініціалізація...',
msgUploadEnd: 'Готово',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'Немає доступних даних для відвантаження.',
- msgUploadError: 'Помилка',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Помилка',
msgValidationError: 'Помилка перевірки',
msgLoading: 'Відвантаження файла {index} із {files} &hellip;',
msgProgress: 'Відвантаження файла {index} із {files} - {name} - {percent}% завершено.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Помилка при зміні розміру зображення.<pre>{errors}</pre>',
msgAjaxError: 'Щось не так із операцією {operation}. Будь ласка, спробуйте пізніше!',
msgAjaxProgressError: 'помилка {operation}',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'видалити файл',
uploadThumb: 'відвантажити файл',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Ще не відвантажено',
indicatorSuccessTitle: 'Відвантажено',
indicatorErrorTitle: 'Помилка при відвантаженні',
- indicatorLoadingTitle: 'Завантаження ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Завантаження ...'
},
previewZoomButtonTitles: {
prev: 'Переглянути попередній файл',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/uz.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/uz.js
index c2c57168..7c43e166 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/uz.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/uz.js
@@ -20,10 +20,13 @@
removeTitle: 'Tanlangan fayllarni tozalash',
cancelLabel: 'Bekor qilish',
cancelTitle: 'Joriy yuklab olishni bekor qilish',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Yuklab olish',
uploadTitle: 'Tanlangan fayllarni yuklash',
msgNo: 'No',
msgNoFilesSelected: 'No files selected',
+ msgPaused: 'Paused',
msgCancelled: 'Cancelled',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Detailed Preview',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Processing...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Fayl yuklash xatosi',
msgLoading: '{Files} dan {index} faylini yuklash &hellip;',
msgProgress: '{Files} dan {index}{name} faylini yuklashi - {percent}% tugallandi.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Not uploaded yet',
indicatorSuccessTitle: 'Uploaded',
indicatorErrorTitle: 'Upload Error',
- indicatorLoadingTitle: 'Uploading ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Uploading ...'
},
previewZoomButtonTitles: {
prev: 'View previous file',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/vi.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/vi.js
index 7d140b5e..7a51a4b9 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/vi.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/vi.js
@@ -20,10 +20,13 @@
removeTitle: 'Bỏ tập tin đã chọn',
cancelLabel: 'Hủy',
cancelTitle: 'Hủy upload',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: 'Upload',
uploadTitle: 'Upload tập tin đã chọn',
msgNo: 'Không',
msgNoFilesSelected: 'Không tập tin nào được chọn',
+ msgPaused: 'Paused',
msgCancelled: 'Đã hủy',
msgPlaceholder: 'Select {files}...',
msgZoomModalHeading: 'Chi tiết xem trước',
@@ -54,8 +57,11 @@
msgUploadThreshold: 'Đang xử lý...',
msgUploadBegin: 'Initializing...',
msgUploadEnd: 'Done',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: 'Error',
msgValidationError: 'Lỗi xác nhận',
msgLoading: 'Đang nạp {index} tập tin trong số {files} &hellip;',
msgProgress: 'Đang nạp {index} tập tin trong số {files} - {name} - {percent}% hoàn thành.',
@@ -69,6 +75,10 @@
msgImageResizeException: 'Resize hình ảnh bị lỗi.<pre>{errors}</pre>',
msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
msgAjaxProgressError: '{operation} failed',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -87,7 +97,8 @@
indicatorNewTitle: 'Chưa được upload',
indicatorSuccessTitle: 'Đã upload',
indicatorErrorTitle: 'Upload bị lỗi',
- indicatorLoadingTitle: 'Đang upload ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: 'Đang upload ...'
},
previewZoomButtonTitles: {
prev: 'Xem tập tin phía trước',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/zh-TW.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/zh-TW.js
index 49f7710f..a07eb079 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/zh-TW.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/zh-TW.js
@@ -20,10 +20,13 @@
removeTitle: '清除選取檔案',
cancelLabel: '取消',
cancelTitle: '取消上傳中檔案',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: '上傳',
uploadTitle: '上傳選取檔案',
msgNo: '沒有',
msgNoFilesSelected: '未選擇檔案',
+ msgPaused: 'Paused',
msgCancelled: '取消',
zoomTitle: '詳細資料',
msgPlaceholder: '選擇 {files}...',
@@ -55,8 +58,11 @@
msgUploadThreshold: '處理中...',
msgUploadBegin: '正在初始化...',
msgUploadEnd: '完成',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: '無效的文件上傳.',
- msgUploadError: '上傳錯誤',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: '上傳錯誤',
msgValidationError: '驗證錯誤',
msgLoading: '載入第 {index} 個檔案,共 {files} &hellip;',
msgProgress: '載入第 {index} 個檔案,共 {files} - {name} - {percent}% 成功.',
@@ -70,6 +76,10 @@
msgImageResizeException: '錯誤而調整圖像大小。<pre>{errors}</pre>',
msgAjaxError: '{operation} 發生錯誤. 請重試!',
msgAjaxProgressError: '{operation} 失敗',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: 'file delete',
uploadThumb: 'file upload',
@@ -88,7 +98,8 @@
indicatorNewTitle: '尚未上傳',
indicatorSuccessTitle: '上傳成功',
indicatorErrorTitle: '上傳失敗',
- indicatorLoadingTitle: '上傳中 ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: '上傳中 ...'
},
previewZoomButtonTitles: {
prev: '預覽上壹個文件',
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/zh.js b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/zh.js
index 469fa380..2b000e2c 100644
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/zh.js
+++ b/kvision-modules/kvision-bootstrap-upload/src/main/resources/js/locales/bootstrap-fileinput/zh.js
@@ -20,10 +20,13 @@
removeTitle: '清除选中文件',
cancelLabel: '取消',
cancelTitle: '取消进行中的上传',
+ pauseLabel: 'Pause',
+ pauseTitle: 'Pause ongoing upload',
uploadLabel: '上传',
uploadTitle: '上传选中文件',
msgNo: '没有',
msgNoFilesSelected: '未选择文件',
+ msgPaused: 'Paused',
msgCancelled: '取消',
msgPlaceholder: '选择 {files}...',
msgZoomModalHeading: '详细预览',
@@ -54,8 +57,11 @@
msgUploadThreshold: '处理中...',
msgUploadBegin: '正在初始化...',
msgUploadEnd: '完成',
+ msgUploadResume: 'Resuming upload...',
msgUploadEmpty: '无效的文件上传.',
- msgUploadError: '上传出错',
+ msgUploadError: 'Upload Error',
+ msgDeleteError: 'Delete Error',
+ msgProgressError: '上传出错',
msgValidationError: '验证错误',
msgLoading: '加载第 {index} 文件 共 {files} &hellip;',
msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',
@@ -69,6 +75,10 @@
msgImageResizeException: '调整图像大小时发生错误。<pre>{errors}</pre>',
msgAjaxError: '{operation} 发生错误. 请重试!',
msgAjaxProgressError: '{operation} 失败',
+ msgDuplicateFile: 'File "{name}" of same size "{size} KB" has already been selected earlier. Skipping duplicate selection.',
+ msgResumableUploadRetriesExceeded: 'Upload aborted beyond <b>{max}</b> retries for file <b>{file}</b>! Error Details: <pre>{error}</pre>',
+ msgPendingTime: '{time} remaining',
+ msgCalculatingTime: 'calculating time remaining',
ajaxOperations: {
deleteThumb: '删除文件',
uploadThumb: '上传文件',
@@ -87,7 +97,8 @@
indicatorNewTitle: '没有上传',
indicatorSuccessTitle: '上传',
indicatorErrorTitle: '上传错误',
- indicatorLoadingTitle: '上传 ...'
+ indicatorPausedTitle: 'Upload Paused',
+ indicatorLoadingTitle: '上传 ...'
},
previewZoomButtonTitles: {
prev: '预览上一个文件',
diff --git a/kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt b/kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
index 13c8531b..13c8531b 100644
--- a/kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
diff --git a/kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadInputSpec.kt b/kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadInputSpec.kt
index de7a9315..de7a9315 100644
--- a/kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadInputSpec.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadInputSpec.kt
diff --git a/kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadSpec.kt b/kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadSpec.kt
index 92078153..92078153 100644
--- a/kvision-modules/kvision-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadSpec.kt
+++ b/kvision-modules/kvision-bootstrap-upload/src/test/kotlin/test/pl/treksoft/kvision/form/upload/UploadSpec.kt
diff --git a/kvision-modules/kvision-bootstrap-upload/webpack.config.d/css.js b/kvision-modules/kvision-bootstrap-upload/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-upload/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-upload/webpack.config.d/file.js b/kvision-modules/kvision-bootstrap-upload/webpack.config.d/file.js
index a5c7b5da..a5c7b5da 100644
--- a/kvision-modules/kvision-upload/webpack.config.d/file.js
+++ b/kvision-modules/kvision-bootstrap-upload/webpack.config.d/file.js
diff --git a/kvision-modules/kvision-bootstrap-upload/webpack.config.d/jquery.js b/kvision-modules/kvision-bootstrap-upload/webpack.config.d/jquery.js
new file mode 100644
index 00000000..bf5a1a20
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap-upload/webpack.config.d/jquery.js
@@ -0,0 +1,5 @@
+config.plugins.push(new webpack.ProvidePlugin({
+ $: "jquery",
+ jQuery: "jquery",
+ "window.jQuery": "jquery"
+}));
diff --git a/kvision-modules/kvision-bootstrap/build.gradle b/kvision-modules/kvision-bootstrap/build.gradle
index 6c504c17..fe519014 100644
--- a/kvision-modules/kvision-bootstrap/build.gradle
+++ b/kvision-modules/kvision-bootstrap/build.gradle
@@ -3,16 +3,10 @@ apply from: "../shared.gradle"
kotlinFrontend {
npm {
- dependency("bootstrap", "3.4.1")
- dependency("bootstrap-webpack", "0.0.6")
- dependency("font-awesome", "4.7.0")
- dependency("font-awesome-webpack-4", "1.0.0")
- dependency("awesome-bootstrap-checkbox", "0.3.7")
- dependency("bootstrap-vertical-tabs", "1.2.2")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
+ dependency("popper.js", "1.15.0")
+ dependency("bootstrap", "4.3.1")
+ dependency("awesome-bootstrap-checkbox", "1.0.1")
+ dependency("element-resize-event", "3.0.3")
}
}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrap.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrap.kt
index 01e1f3c3..78365281 100644
--- a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrap.kt
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/KVManagerBootstrap.kt
@@ -21,39 +21,41 @@
*/
package pl.treksoft.kvision
-import org.w3c.dom.asList
-import kotlin.browser.document
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.utils.isIE11
+
+internal val kVManagerBootstrapInit = KVManagerBootstrap.init()
/**
* Internal singleton object which initializes and configures KVision Bootstrap module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerBootstrap {
- private val links = document.getElementsByTagName("link")
- private val bootstrapWebpack = try {
- val bootswatch = links.asList().find { it.getAttribute("href")?.contains("bootstrap.min.css") ?: false }
- if (bootswatch != null) {
- require("bootstrap-webpack!./js/bootstrap.config.js")
- if (bootswatch.getAttribute("href")?.contains("/paper/") == true) {
- require("./css/paper.css")
+ init {
+ require("bootstrap/dist/js/bootstrap.bundle.min.js")
+ require("awesome-bootstrap-checkbox")
+ }
+
+ private val elementResizeEvent = require("element-resize-event")
+
+ @Suppress("UnsafeCastFromDynamic")
+ internal fun setResizeEvent(component: Component, callback: () -> Unit) {
+ if (!isIE11()) {
+ component.getElement()?.let {
+ elementResizeEvent(it, callback)
}
- require("./css/style.css")
- } else {
- require("bootstrap-webpack")
- require("./css/style.css")
}
- } catch (e: Throwable) {
- }
- private val fontAwesomeWebpack = try {
- require("font-awesome-webpack-4")
- } catch (e: Throwable) {
}
- private val awesomeBootstrapCheckbox = try {
- require("awesome-bootstrap-checkbox")
- } catch (e: Throwable) {
- }
- private val bootstrapVerticalTabsCss = try {
- require("bootstrap-vertical-tabs")
- } catch (e: Throwable) {
+
+ @Suppress("UnsafeCastFromDynamic")
+ internal fun clearResizeEvent(component: Component) {
+ if (!isIE11()) {
+ if (component.getElement()?.asDynamic()?.__resizeTrigger__?.contentDocument != null) {
+ component.getElement()?.let {
+ elementResizeEvent.unbind(it)
+ }
+ }
+ }
}
+
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/core/Component.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/core/Component.kt
new file mode 100644
index 00000000..c35ee9fb
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/core/Component.kt
@@ -0,0 +1,133 @@
+/*
+ * 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.core
+
+enum class BsBorder(internal val className: String) {
+ BORDER("border"),
+ BORDERTOP("border-top"),
+ BORDERBOTTOM("border-bottom"),
+ BORDERRIGHT("border-right"),
+ BORDERLEFT("border-left"),
+ BORDER_0("border-0"),
+ BORDERTOP_0("border-top-0"),
+ BORDERBOTTOM_0("border-bottom-0"),
+ BORDERRIGHT_0("border-right-0"),
+ BORDERLEFT_0("border-left-0"),
+ BORDERPRIMARY("border-primary"),
+ BORDERSECONDARY("border-secondary"),
+ BORDERSUCCESS("border-success"),
+ BORDERDANGER("border-danger"),
+ BORDERWARNING("border-warning"),
+ BORDERINFO("border-info"),
+ BORDERLIGHT("border-light"),
+ BORDERDARK("border-dark"),
+ BORDERWHITE("border-white")
+}
+
+fun Component.addBsBorder(vararg bsBorder: BsBorder) {
+ bsBorder.forEach {
+ this.addCssClass(it.className)
+ }
+}
+
+fun Component.removeBsBorder(vararg bsBorder: BsBorder) {
+ bsBorder.forEach {
+ this.removeCssClass(it.className)
+ }
+}
+
+enum class BsRounded(internal val className: String) {
+ ROUNDED("rounded"),
+ ROUNDEDTOP("rounded-top"),
+ ROUNDEDBOTTOM("rounded-bottom"),
+ ROUNDEDLEFT("rounded-left"),
+ ROUNDEDRIGHT("rounded-right"),
+ ROUNDEDCIRCLE("rounded-circle"),
+ ROUNDEDPILL("rounded-pill"),
+ ROUNDEDLG("rounded-lg"),
+ ROUNDEDSM("rounded-sm")
+}
+
+fun Component.addBsRounded(vararg bsRounded: BsRounded) {
+ bsRounded.forEach {
+ this.addCssClass(it.className)
+ }
+}
+
+fun Component.removeBsRounded(vararg bsRounded: BsRounded) {
+ bsRounded.forEach {
+ this.removeCssClass(it.className)
+ }
+}
+
+fun Component.addBsClearfix() {
+ this.addCssClass("clearfix")
+}
+
+fun Component.removeBsClearfix() {
+ this.removeCssClass("clearfix")
+}
+
+enum class BsColor(internal val className: String) {
+ PRIMARY("text-primary"),
+ SECONDARY("text-secondary"),
+ SUCCESS("text-success"),
+ DANGER("text-danger"),
+ WARNING("text-warning"),
+ INFO("text-info"),
+ LIGHT("text-light"),
+ DARK("text-dark"),
+ WHITE("text-white"),
+ BODY("text-body"),
+ MUTED("text-muted"),
+ BLACK50("text-black-50"),
+ WHITE50("text-white-50")
+}
+
+fun Component.addBsColor(bsColor: BsColor) {
+ this.addCssClass(bsColor.className)
+}
+
+fun Component.removeBsColor(bsColor: BsColor) {
+ this.removeCssClass(bsColor.className)
+}
+
+enum class BsBgColor(internal val className: String) {
+ PRIMARY("bg-primary"),
+ SECONDARY("bg-secondary"),
+ SUCCESS("bg-success"),
+ DANGER("bg-danger"),
+ WARNING("bg-warning"),
+ INFO("bg-info"),
+ LIGHT("bg-light"),
+ DARK("bg-dark"),
+ WHITE("bg-white"),
+ TRANSPARENT("bg-transparent")
+}
+
+fun Component.addBsBgColor(bsBgColor: BsBgColor) {
+ this.addCssClass(bsBgColor.className)
+}
+
+fun Component.removeBsBgColor(bsBgColor: BsBgColor) {
+ this.removeCssClass(bsBgColor.className)
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt
new file mode 100644
index 00000000..4e20de81
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.dropdown
+
+import org.w3c.dom.events.MouseEvent
+import pl.treksoft.kvision.core.Display
+import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.html.Div
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.utils.px
+
+/**
+ * Context menu component.
+ *
+ * @constructor
+ * @param element an element to bind
+ * @param fixedPosition use fixed positioning
+ * @param classes a set of CSS class names
+ */
+open class ContextMenu(
+ element: Widget? = null,
+ protected val fixedPosition: Boolean = false,
+ classes: Set<String> = setOf(), init: (ContextMenu.() -> Unit)? = null
+) : Div(classes = classes + "dropdown-menu") {
+
+ init {
+ @Suppress("LeakingThis")
+ hide()
+ @Suppress("LeakingThis")
+ display = Display.BLOCK
+ val root = element?.getRoot() ?: Root.getLastRoot()
+ if (root != null) {
+ @Suppress("LeakingThis")
+ root.addContextMenu(this)
+ } else {
+ println("At least one Root object is required to create a context menu!")
+ }
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ /**
+ * Positions and shows a context menu based on a mouse event.
+ * @param mouseEvent mouse event
+ * @return current context menu
+ */
+ open fun positionMenu(mouseEvent: MouseEvent): ContextMenu {
+ if (fixedPosition) {
+ this.top = DEFAULT_FIXED_POS_Y.px
+ this.left = DEFAULT_FIXED_POS_X.px
+ } else {
+ this.top = mouseEvent.pageY.toInt().px
+ this.left = mouseEvent.pageX.toInt().px
+ }
+ this.show()
+ return this
+ }
+
+ companion object {
+
+ const val DEFAULT_FIXED_POS_X = 5
+ const val DEFAULT_FIXED_POS_Y = 5
+
+ /**
+ * Sets context menu for the current widget.
+ * @param contextMenu a context menu
+ * @return current widget
+ */
+ fun Widget.setContextMenu(contextMenu: ContextMenu): Widget {
+ this.setEventListener<Widget> {
+ contextmenu = { e: MouseEvent ->
+ e.preventDefault()
+ contextMenu.positionMenu(e)
+ }
+ }
+ return this
+ }
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Widget.contextMenu(
+ fixedPosition: Boolean = false,
+ classes: Set<String> = setOf(), init: (ContextMenu.() -> Unit)? = null
+ ): ContextMenu {
+ val contextMenu = ContextMenu(this, fixedPosition, classes).apply { init?.invoke(this) }
+ this.setContextMenu(contextMenu)
+ return contextMenu
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
new file mode 100644
index 00000000..9862b322
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
@@ -0,0 +1,417 @@
+/*
+ * 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.dropdown
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.CssSize
+import pl.treksoft.kvision.core.ResString
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.html.Button
+import pl.treksoft.kvision.html.ButtonStyle
+import pl.treksoft.kvision.html.ButtonType
+import pl.treksoft.kvision.html.Div
+import pl.treksoft.kvision.html.Link
+import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.utils.obj
+
+/**
+ * Useful options for use in DropDown's *elements* parameter.
+ */
+enum class DD(val option: String) {
+ HEADER("DD#HEADER"),
+ DISABLED("DD#DISABLED"),
+ SEPARATOR("DD#SEPARATOR")
+}
+
+/**
+ * Dropdown directions.
+ */
+enum class Direction(internal val direction: String) {
+ DROPDOWN("dropdown"),
+ DROPUP("dropup"),
+ DROPLEFT("dropleft"),
+ DROPRIGHT("dropright")
+}
+
+/**
+ * Bootstrap dropdown component.
+ *
+ * @constructor
+ * @param text the label of the dropdown button
+ * @param elements an optional list of link elements (special options from [DD] enum class can be used as values)
+ * @param icon the icon of the dropdown button
+ * @param style the style of the dropdown button
+ * @param direction the direction of the dropdown
+ * @param disabled determines if the component is disabled on start
+ * @param forNavbar determines if the component will be used in a navbar
+ * @param forDropDown determines if the component will be used in a dropdown
+ * @param classes a set of CSS class names
+ */
+@Suppress("TooManyFunctions")
+open class DropDown(
+ text: String, elements: List<StringPair>? = null, icon: String? = null,
+ style: ButtonStyle = ButtonStyle.PRIMARY, direction: Direction = Direction.DROPDOWN, disabled: Boolean = false,
+ val forNavbar: Boolean = false, val forDropDown: Boolean = false, classes: Set<String> = setOf()
+) : SimplePanel(classes) {
+ /**
+ * Label of the dropdown button.
+ */
+ var text
+ get() = button.text
+ set(value) {
+ button.text = value
+ }
+ private var elements by refreshOnUpdate(elements) { setChildrenFromElements() }
+ /**
+ * The icon of the dropdown button.
+ */
+ var icon
+ get() = button.icon
+ set(value) {
+ button.icon = value
+ }
+ /**
+ * The style of the dropdown button.
+ */
+ var style
+ get() = button.style
+ set(value) {
+ button.style = value
+ }
+ /**
+ * The size of the dropdown button.
+ */
+ var size
+ get() = button.size
+ set(value) {
+ button.size = value
+ }
+ /**
+ * Determines if the dropdown button takes all the space horizontally.
+ */
+ var block
+ get() = button.block
+ set(value) {
+ button.block = value
+ }
+ /**
+ * Determines if the dropdown is disabled.
+ */
+ var disabled
+ get() = button.disabled
+ set(value) {
+ button.disabled = value
+ }
+ /**
+ * The image on the dropdown button.
+ */
+ var image
+ get() = button.image
+ set(value) {
+ button.image = value
+ }
+ /**
+ * The direction of the dropdown.
+ */
+ var direction by refreshOnUpdate(direction)
+ /**
+ * Width of the dropdown button.
+ */
+ override var width: CssSize?
+ get() = super.width
+ set(value) {
+ super.width = value
+ button.width = value
+ }
+
+ private val idc = "kv_dropdown_$counter"
+ internal val button: DropDownButton = DropDownButton(
+ idc, text, icon, style, disabled, forNavbar, forDropDown
+ )
+
+ fun buttonId() = button.id
+
+ internal val list: DropDownDiv = DropDownDiv(idc)
+
+ init {
+ if (forDropDown) {
+ this.style = ButtonStyle.LIGHT
+ this.direction = Direction.DROPRIGHT
+ }
+ setChildrenFromElements()
+ this.addInternal(button)
+ this.addInternal(list)
+ counter++
+ }
+
+ override fun render(): VNode {
+ return if (forNavbar) {
+ render("li", childrenVNodes())
+ } else {
+ render("div", childrenVNodes())
+ }
+ }
+
+ override fun add(child: Component): SimplePanel {
+ list.add(child)
+ return this
+ }
+
+ override fun addAll(children: List<Component>): SimplePanel {
+ list.addAll(children)
+ return this
+ }
+
+ override fun remove(child: Component): SimplePanel {
+ list.remove(child)
+ return this
+ }
+
+ override fun removeAll(): SimplePanel {
+ list.removeAll()
+ return this
+ }
+
+ override fun getChildren(): List<Component> {
+ return list.getChildren()
+ }
+
+ private fun setChildrenFromElements() {
+ list.removeAll()
+ elements?.let { elems ->
+ val c = elems.map {
+ when (it.second) {
+ DD.HEADER.option -> Header(it.first)
+ DD.SEPARATOR.option -> Separator()
+ DD.DISABLED.option -> {
+ Link(it.first, "javascript:void(0)", classes = setOf("dropdown-item", "disabled")).apply {
+ tabindex = -1
+ setAttribute("aria-disabled", "true")
+ }
+ }
+ else -> Link(it.first, it.second, classes = setOf("dropdown-item"))
+ }
+ }
+ list.addAll(c)
+ }
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ override fun afterInsert(node: VNode) {
+ this.getElementJQuery()?.on("show.bs.dropdown") { e, _ ->
+ this.dispatchEvent("showBsDropdown", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("shown.bs.dropdown") { e, _ ->
+ this.dispatchEvent("shownBsDropdown", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("hide.bs.dropdown") { e, _ ->
+ this.dispatchEvent("hideBsDropdown", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("hidden.bs.dropdown") { e, _ ->
+ this.dispatchEvent("hiddenBsDropdown", obj { detail = e })
+ }
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ if (forNavbar) cl.add("nav-item" to true)
+ cl.add(direction.direction to true)
+ return cl
+ }
+
+ /**
+ * Toggles dropdown visibility.
+ */
+ open fun toggle() {
+ this.button.getElementJQuery()?.click()
+ }
+
+ companion object {
+ internal var counter = 0
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.dropDown(
+ text: String, elements: List<StringPair>? = null, icon: String? = null,
+ style: ButtonStyle = ButtonStyle.PRIMARY, direction: Direction = Direction.DROPDOWN,
+ disabled: Boolean = false, forNavbar: Boolean = false, forDropDown: Boolean = false,
+ classes: Set<String> = setOf(), init: (DropDown.() -> Unit)? = null
+ ): DropDown {
+ val dropDown =
+ DropDown(
+ text,
+ elements,
+ icon,
+ style,
+ direction,
+ disabled,
+ forNavbar,
+ forDropDown,
+ classes
+ ).apply { init?.invoke(this) }
+ this.add(dropDown)
+ return dropDown
+ }
+
+ /**
+ * DSL builder extension function for a link in a dropdown list.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun DropDown.ddLink(
+ label: String, url: String? = null, icon: String? = null, image: ResString? = null,
+ classes: Set<String> = setOf(), init: (Link.() -> Unit)? = null
+ ): Link {
+ val link = Link(label, url, icon, image, classes + "dropdown-item").apply {
+ init?.invoke(this)
+ }
+ this.add(link)
+ return link
+ }
+
+ /**
+ * DSL builder extension function for a link in a context menu list.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun ContextMenu.cmLink(
+ label: String, url: String? = null, icon: String? = null, image: ResString? = null,
+ classes: Set<String> = setOf(), init: (Link.() -> Unit)? = null
+ ): Link {
+ val link = Link(label, url, icon, image, classes + "dropdown-item").apply {
+ init?.invoke(this)
+ }
+ this.add(link)
+ return link
+ }
+
+ /**
+ * DSL builder extension function for a disabled link in a dropdown list.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun DropDown.ddLinkDisabled(
+ label: String, icon: String? = null, image: ResString? = null,
+ classes: Set<String> = setOf(), init: (Link.() -> Unit)? = null
+ ): Link {
+ val link = Link(label, "javascript:void(0)", icon, image, classes + "dropdown-item" + "disabled").apply {
+ tabindex = -1
+ setAttribute("aria-disabled", "true")
+ init?.invoke(this)
+ }
+ this.add(link)
+ return link
+ }
+
+ /**
+ * DSL builder extension function for a disabled link in a context menu list.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun ContextMenu.cmLinkDisabled(
+ label: String, icon: String? = null, image: ResString? = null,
+ classes: Set<String> = setOf(), init: (Link.() -> Unit)? = null
+ ): Link {
+ val link = Link(label, "javascript:void(0)", icon, image, classes + "dropdown-item" + "disabled").apply {
+ tabindex = -1
+ setAttribute("aria-disabled", "true")
+ init?.invoke(this)
+ }
+ this.add(link)
+ return link
+ }
+
+ }
+}
+
+internal class DropDownButton(
+ id: String,
+ text: String,
+ icon: String? = null,
+ style: ButtonStyle = ButtonStyle.PRIMARY,
+ disabled: Boolean = false,
+ val forNavbar: Boolean = false,
+ val forDropDown: Boolean = false,
+ classes: Set<String> = setOf()
+) :
+ Button(text, icon, style, ButtonType.BUTTON, disabled, classes) {
+
+ init {
+ this.id = id
+ if (!forNavbar && !forDropDown) this.role = "button"
+ setInternalEventListener<DropDownButton> {
+ click = { e ->
+ if (parent?.parent is ContextMenu) {
+ e.asDynamic().dropDownCM = true
+ } else if (forDropDown || forNavbar) {
+ (parent as DropDown).list.getElementJQuery()?.toggle()
+ e.stopPropagation()
+ }
+ }
+ }
+ }
+
+ override fun render(): VNode {
+ val text = createLabelWithIcon(text, icon, image)
+ return if (forNavbar || forDropDown) {
+ render("a", text)
+ } else {
+ render("button", text)
+ }
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ return if (forNavbar) {
+ listOf("nav-link" to true, "dropdown-toggle" to true)
+ } else if (forDropDown) {
+ super.getSnClass() + listOf("dropdown-item" to true, "dropdown-toggle" to true)
+ } else {
+ super.getSnClass() + ("dropdown-toggle" to true)
+ }
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ val inherited = super.getSnAttrs()
+ return if (forDropDown || forNavbar) {
+ inherited.filter { it.first != "type" }
+ } else {
+ inherited
+ } + listOf(
+ "data-toggle" to "dropdown", "aria-haspopup" to "true",
+ "aria-expanded" to "false", "href" to "#"
+ )
+ }
+}
+
+internal class DropDownDiv(private val ariaId: String) : Div(
+ null, false, null, setOf("dropdown-menu")
+) {
+ override fun getSnAttrs(): List<StringPair> {
+ return super.getSnAttrs() + listOf("aria-labelledby" to ariaId)
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt
new file mode 100644
index 00000000..13e0b2e4
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.dropdown
+
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+/**
+ * Menu header component.
+ *
+ * @constructor
+ * @param content header content text
+ * @param classes a set of CSS class names
+ */
+open class Header(content: String? = null, classes: Set<String> = setOf()) :
+ Tag(TAG.H6, content, classes = classes + "dropdown-header") {
+
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun ContextMenu.header(content: String? = null, classes: Set<String> = setOf()): Header {
+ val header = Header(content, classes)
+ this.add(header)
+ return header
+ }
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun DropDown.header(content: String? = null, classes: Set<String> = setOf()): Header {
+ val header = Header(content, classes)
+ this.add(header)
+ return header
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt
new file mode 100644
index 00000000..dd2344bd
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.dropdown
+
+import pl.treksoft.kvision.html.Div
+
+/**
+ * Menu separator component.
+ *
+ * @constructor
+ * @param classes a set of CSS class names
+ */
+open class Separator(classes: Set<String> = setOf()) : Div(classes = classes + "dropdown-divider") {
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun ContextMenu.separator(classes: Set<String> = setOf()): Separator {
+ val separator = Separator(classes)
+ this.add(separator)
+ return separator
+ }
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun DropDown.separator(classes: Set<String> = setOf()): Separator {
+ val separator = Separator(classes)
+ this.add(separator)
+ return separator
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Alert.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Alert.kt
new file mode 100644
index 00000000..4c5b222e
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Alert.kt
@@ -0,0 +1,121 @@
+/*
+ * 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.modal
+
+import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.html.Align
+import pl.treksoft.kvision.html.ButtonStyle
+import pl.treksoft.kvision.html.Button
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+import pl.treksoft.kvision.utils.ENTER_KEY
+
+/**
+ * Alert window based on Bootstrap modal.
+ *
+ * @constructor
+ * @param caption window title
+ * @param text window content text.
+ * @param rich determines if [text] can contain HTML code
+ * @param align text align
+ * @param size modal window size
+ * @param animation determines if animations are used
+ * @param callback a function called after closing window with OK button
+ */
+open class Alert(
+ caption: String? = null, text: String? = null, rich: Boolean = false,
+ align: Align? = null, size: ModalSize? = null, animation: Boolean = true,
+ private val callback: (() -> Unit)? = null
+) : Modal(caption, true, size, animation) {
+
+ /**
+ * Window content text.
+ */
+ var text
+ get() = contentTag.content
+ set(value) {
+ contentTag.content = value
+ }
+ /**
+ * Determines if [text] can contain HTML code.
+ */
+ var rich
+ get() = contentTag.rich
+ set(value) {
+ contentTag.rich = value
+ }
+ /**
+ * Text align.
+ */
+ var align
+ get() = contentTag.align
+ set(value) {
+ contentTag.align = value
+ }
+
+ private val contentTag = Tag(TAG.DIV, text, rich, align)
+
+ init {
+ body.add(contentTag)
+ val okButton = Button("OK", "fas fa-check", ButtonStyle.PRIMARY)
+ okButton.setEventListener {
+ click = {
+ hide()
+ }
+ }
+ this.addButton(okButton)
+ this.setEventListener {
+ keydown = { e ->
+ if (e.keyCode == ENTER_KEY) {
+ hide()
+ }
+ }
+ }
+ }
+
+ override fun hide(): Widget {
+ super.hide()
+ this.callback?.invoke()
+ return this
+ }
+
+ companion object {
+ /**
+ * Helper function for opening Alert window.
+ * @param caption window title
+ * @param text window content text.
+ * @param rich determines if [text] can contain HTML code
+ * @param align text align
+ * @param size modal window size
+ * @param animation determines if animations are used
+ * @param callback a function called after closing window with OK button
+ */
+ @Suppress("LongParameterList")
+ fun show(
+ caption: String? = null, text: String? = null, rich: Boolean = false,
+ align: Align? = null, size: ModalSize? = null, animation: Boolean = true,
+ callback: (() -> Unit)? = null
+ ) {
+ Alert(caption, text, rich, align, size, animation, callback).show()
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/CloseIcon.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/CloseIcon.kt
new file mode 100644
index 00000000..5f0440a6
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/CloseIcon.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.modal
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.KVManager
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.core.Widget
+
+/**
+ * Helper class for close icon component.
+ */
+open class CloseIcon : Widget(setOf()) {
+
+ override fun render(): VNode {
+ return render("button", arrayOf(KVManager.virtualize("<span aria-hidden='true'>&times;</span>")))
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("close" to true)
+ return cl
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ return super.getSnAttrs() + listOf("type" to "button", "aria-label" to "Close")
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Confirm.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Confirm.kt
new file mode 100644
index 00000000..058ca7bc
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Confirm.kt
@@ -0,0 +1,176 @@
+/*
+ * 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.modal
+
+import pl.treksoft.kvision.html.Align
+import pl.treksoft.kvision.html.Button
+import pl.treksoft.kvision.html.ButtonStyle
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+/**
+ * Confirm window based on Bootstrap modal.
+ *
+ * @constructor
+ * @param caption window title
+ * @param text window content text.
+ * @param rich determines if [text] can contain HTML code
+ * @param align text align
+ * @param size modal window size
+ * @param animation determines if animations are used
+ * @param cancelVisible determines if Cancel button is visible
+ * @param yesTitle yes button text
+ * @param noTitle no button text
+ * @param cancelTitle cancel button text
+ * @param noCallback a function called after closing window with No button
+ * @param yesCallback a function called after closing window with Yes button
+ */
+open class Confirm(
+ caption: String? = null, text: String? = null, rich: Boolean = false,
+ align: Align? = null, size: ModalSize? = null, animation: Boolean = true,
+ cancelVisible: Boolean = false, yesTitle: String = "Yes", noTitle: String = "No", cancelTitle: String = "Cancel",
+ private val noCallback: (() -> Unit)? = null,
+ private val yesCallback: (() -> Unit)? = null
+) : Modal(caption, false, size, animation, false) {
+ /**
+ * Window content text.
+ */
+ var text
+ get() = contentTag.content
+ set(value) {
+ contentTag.content = value
+ }
+ /**
+ * Determines if [text] can contain HTML code.
+ */
+ var rich
+ get() = contentTag.rich
+ set(value) {
+ contentTag.rich = value
+ }
+ /**
+ * Text align.
+ */
+ var align
+ get() = contentTag.align
+ set(value) {
+ contentTag.align = value
+ }
+ /**
+ * Determines if Cancel button is visible.
+ */
+ var cancelVisible by refreshOnUpdate(cancelVisible) { refreshCancelButton() }
+
+ /**
+ * Yes button text.
+ */
+ var yesTitle
+ get() = yesButton.text
+ set(value) {
+ yesButton.text = value
+ }
+
+ /**
+ * No button text.
+ */
+ var noTitle
+ get() = noButton.text
+ set(value) {
+ noButton.text = value
+ }
+
+ /**
+ * Cancel button text.
+ */
+ var cancelTitle
+ get() = cancelButton.text
+ set(value) {
+ cancelButton.text = value
+ }
+
+ private val contentTag = Tag(TAG.DIV, text, rich, align)
+ private val cancelButton = Button(cancelTitle, "fas fa-times")
+ private val noButton = Button(noTitle, "fas fa-ban")
+ private val yesButton = Button(yesTitle, "fas fa-check", ButtonStyle.PRIMARY)
+
+ init {
+ body.add(contentTag)
+ cancelButton.setEventListener {
+ click = {
+ hide()
+ }
+ }
+ this.addButton(cancelButton)
+ noButton.setEventListener {
+ click = {
+ hide()
+ noCallback?.invoke()
+ }
+ }
+ this.addButton(noButton)
+ yesButton.setEventListener {
+ click = {
+ hide()
+ yesCallback?.invoke()
+ }
+ }
+ this.addButton(yesButton)
+ refreshCancelButton()
+ }
+
+ private fun refreshCancelButton() {
+ if (cancelVisible) {
+ cancelButton.show()
+ closeIcon.show()
+ } else {
+ cancelButton.hide()
+ closeIcon.hide()
+ }
+ }
+
+ companion object {
+ /**
+ * Helper function for opening Confirm window.
+ * @param caption window title
+ * @param text window content text.
+ * @param rich determines if [text] can contain HTML code
+ * @param align text align
+ * @param size modal window size
+ * @param animation determines if animations are used
+ * @param cancelVisible determines if Cancel button is visible
+ * @param noCallback a function called after closing window with No button
+ * @param yesCallback a function called after closing window with Yes button
+ */
+ @Suppress("LongParameterList")
+ fun show(
+ caption: String? = null, text: String? = null, rich: Boolean = false,
+ align: Align? = null, size: ModalSize? = null, animation: Boolean = true,
+ cancelVisible: Boolean = false, yesTitle: String = "Yes", noTitle: String = "No",
+ cancelTitle: String = "Cancel", noCallback: (() -> Unit)? = null, yesCallback: (() -> Unit)? = null
+ ) {
+ Confirm(
+ caption, text, rich, align, size, animation, cancelVisible, yesTitle, noTitle, cancelTitle,
+ noCallback, yesCallback
+ ).show()
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt
new file mode 100644
index 00000000..08fc7aa8
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt
@@ -0,0 +1,292 @@
+/*
+ * 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.modal
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.html.Button
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.panel.Root.Companion.addModal
+import pl.treksoft.kvision.panel.Root.Companion.removeModal
+import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.utils.obj
+
+/**
+ * Modal window sizes.
+ */
+enum class ModalSize(val className: String) {
+ XLARGE("modal-xl"),
+ LARGE("modal-lg"),
+ SMALL("modal-sm")
+}
+
+/**
+ * Configurable modal window based on Bootstrap modal.
+ *
+ * @constructor
+ * @param caption window title
+ * @param closeButton determines if Close button is visible
+ * @param size modal window size
+ * @param animation determines if animations are used
+ * @param escape determines if dialog can be closed with Esc key
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+@Suppress("TooManyFunctions")
+open class Modal(
+ caption: String? = null, closeButton: Boolean = true,
+ size: ModalSize? = null, animation: Boolean = true, private val escape: Boolean = true,
+ classes: Set<String> = setOf(), init: (Modal.() -> Unit)? = null
+) : SimplePanel(classes) {
+
+ override var parent: Container? = Root.getFirstRoot()
+
+ /**
+ * Window caption text.
+ */
+ var caption
+ get() = captionTag.content
+ set(value) {
+ captionTag.content = value
+ checkHeaderVisibility()
+ }
+ /**
+ * Determines if Close button is visible.
+ */
+ var closeButton
+ get() = closeIcon.visible
+ set(value) {
+ closeIcon.visible = value
+ checkHeaderVisibility()
+ }
+ /**
+ * Window size.
+ */
+ var size
+ get() = dialog.size
+ set(value) {
+ dialog.size = value
+ }
+ /**
+ * Determines if animations are used.
+ */
+ var animation by refreshOnUpdate(animation)
+
+ private val dialog = ModalDialog(size)
+ private val header = SimplePanel(setOf("modal-header"))
+ /**
+ * @suppress
+ * Internal property.
+ */
+ protected val closeIcon = CloseIcon()
+ private val captionTag = Tag(TAG.H5, caption, classes = setOf("modal-title"))
+ /**
+ * @suppress
+ * Internal property.
+ */
+ protected val body = SimplePanel(setOf("modal-body"))
+ private val footer = SimplePanel(setOf("modal-footer"))
+
+ init {
+ this.hide()
+ this.role = "dialog"
+ this.tabindex = -1
+ this.addInternal(dialog)
+ val content = SimplePanel(setOf("modal-content"))
+ dialog.role = "document"
+ dialog.add(content)
+ closeIcon.visible = closeButton
+ closeIcon.setEventListener {
+ click = {
+ hide()
+ }
+ }
+ header.add(captionTag)
+ header.add(closeIcon)
+ checkHeaderVisibility()
+ content.add(header)
+ content.add(body)
+ content.add(footer)
+ @Suppress("LeakingThis")
+ addModal(this)
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ private fun checkHeaderVisibility() {
+ if (!closeButton && caption == null) {
+ header.hide()
+ } else {
+ header.show()
+ }
+ }
+
+ override fun add(child: Component): SimplePanel {
+ body.add(child)
+ return this
+ }
+
+ override fun addAll(children: List<Component>): SimplePanel {
+ body.addAll(children)
+ return this
+ }
+
+ override fun remove(child: Component): SimplePanel {
+ body.remove(child)
+ return this
+ }
+
+ override fun removeAll(): SimplePanel {
+ body.removeAll()
+ return this
+ }
+
+ override fun getChildren(): List<Component> {
+ return body.getChildren()
+ }
+
+ /**
+ * Adds given button to the bottom section of dialog window.
+ * @param button a [Button] component
+ * @return this modal
+ */
+ open fun addButton(button: Button): Modal {
+ footer.add(button)
+ return this
+ }
+
+ /**
+ * Removes given button from the bottom section of dialog window.
+ * @param button a [Button] component
+ * @return this modal
+ */
+ open fun removeButton(button: Button): Modal {
+ footer.remove(button)
+ return this
+ }
+
+ /**
+ * Removes all buttons from the bottom section of dialog window.
+ * @return this modal
+ */
+ open fun removeAllButtons(): Modal {
+ footer.removeAll()
+ return this
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("modal" to true)
+ if (animation) {
+ cl.add("fade" to true)
+ }
+ return cl
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ override fun afterInsert(node: VNode) {
+ getElementJQueryD()?.modal(obj {
+ keyboard = escape
+ backdrop = if (escape) "true" else "static"
+ })
+ this.getElementJQuery()?.on("show.bs.modal") { e, _ ->
+ this.dispatchEvent("showBsModal", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("shown.bs.modal") { e, _ ->
+ this.dispatchEvent("shownBsModal", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("hide.bs.modal") { e, _ ->
+ this.dispatchEvent("hideBsModal", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("hidden.bs.modal") { e, _ ->
+ this.visible = false
+ hide()
+ this.dispatchEvent("hiddenBsModal", obj { detail = e })
+ }
+ }
+
+ override fun hide(): Widget {
+ if (visible) hideInternal()
+ return super.hide()
+ }
+
+ /**
+ * Toggle modal window visibility.
+ */
+ open fun toggle() {
+ if (visible)
+ hide()
+ else
+ show()
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ private fun showInternal() {
+ getElementJQueryD()?.modal("show")
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ private fun hideInternal() {
+ getElementJQueryD()?.modal("hide")
+ }
+
+ override fun clearParent(): Widget {
+ this.parent = null
+ return this
+ }
+
+ override fun getRoot(): Root? {
+ return this.parent?.getRoot()
+ }
+
+ override fun dispose() {
+ removeModal(this)
+ }
+}
+
+/**
+ * Internal helper class for modal content.
+ *
+ * @constructor
+ * @param size modal window size
+ */
+internal class ModalDialog(size: ModalSize?) : SimplePanel(setOf("modal-dialog")) {
+
+ /**
+ * Modal window size.
+ */
+ var size by refreshOnUpdate(size)
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ size?.let {
+ cl.add(it.className to true)
+ }
+ return cl
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Nav.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Nav.kt
new file mode 100644
index 00000000..e0da480d
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Nav.kt
@@ -0,0 +1,110 @@
+/*
+ * 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.navbar
+
+import pl.treksoft.kvision.core.ResString
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.html.Div
+import pl.treksoft.kvision.html.Link
+
+/**
+ * The Bootstrap Nav container.
+ *
+ * @constructor
+ * @param rightAlign determines if the nav is aligned to the right
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class Nav(rightAlign: Boolean = false, classes: Set<String> = setOf(), init: (Nav.() -> Unit)? = null) :
+ Div(classes = classes) {
+
+ /**
+ * Determines if the nav is aligned to the right.
+ */
+ var rightAlign by refreshOnUpdate(rightAlign)
+
+ init {
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("navbar-nav" to true)
+ if (rightAlign) {
+ cl.add("ml-auto" to true)
+ }
+ return cl
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Navbar.nav(
+ rightAlign: Boolean = false, classes: Set<String> = setOf(), init: (Nav.() -> Unit)? = null
+ ): Nav {
+ val nav = Nav(rightAlign, classes).apply { init?.invoke(this) }
+ this.add(nav)
+ return nav
+ }
+
+
+ /**
+ * DSL builder extension function for a link in a nav list.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Nav.navLink(
+ label: String, url: String? = null, icon: String? = null, image: ResString? = null,
+ classes: Set<String> = setOf(), init: (Link.() -> Unit)? = null
+ ): Link {
+ val link = Link(label, url, icon, image, classes + "nav-item" + "nav-link").apply {
+ init?.invoke(this)
+ }
+ this.add(link)
+ return link
+ }
+
+ /**
+ * DSL builder extension function for a disabled link in a nav list.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Nav.navLinkDisabled(
+ label: String, icon: String? = null, image: ResString? = null,
+ classes: Set<String> = setOf(), init: (Link.() -> Unit)? = null
+ ): Link {
+ val link =
+ Link(label, "javascript:void(0)", icon, image, classes + "nav-item" + "nav-link" + "disabled").apply {
+ tabindex = -1
+ setAttribute("aria-disabled", "true")
+ init?.invoke(this)
+ }
+ this.add(link)
+ return link
+ }
+
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/NavForm.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/NavForm.kt
new file mode 100644
index 00000000..45454cc8
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/NavForm.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.navbar
+
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+/**
+ * The Bootstrap Nav form container.
+ *
+ * @constructor
+ * @param rightAlign determines if the nav form is aligned to the right
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class NavForm(rightAlign: Boolean = false, classes: Set<String> = setOf(), init: (NavForm.() -> Unit)? = null) :
+ Tag(TAG.FORM, classes = classes) {
+
+ /**
+ * Determines if the nav form is aligned to the right.
+ */
+ var rightAlign by refreshOnUpdate(rightAlign)
+
+ init {
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("form-inline" to true)
+ if (rightAlign) {
+ cl.add("ml-auto" to true)
+ }
+ return cl
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Navbar.navForm(
+ rightAlign: Boolean = false, classes: Set<String> = setOf(), init: (NavForm.() -> Unit)? = null
+ ): NavForm {
+ val navForm = NavForm(rightAlign, classes).apply { init?.invoke(this) }
+ this.add(navForm)
+ return navForm
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Navbar.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Navbar.kt
new file mode 100644
index 00000000..34a9dbe2
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/navbar/Navbar.kt
@@ -0,0 +1,229 @@
+/*
+ * 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.navbar
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.core.BsBgColor
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.html.Link
+import pl.treksoft.kvision.html.Span
+import pl.treksoft.kvision.html.Span.Companion.span
+import pl.treksoft.kvision.panel.SimplePanel
+
+/**
+ * Navbar types.
+ */
+enum class NavbarType(internal val navbarType: String) {
+ FIXEDTOP("fixed-top"),
+ FIXEDBOTTOM("fixed-bottom"),
+ STICKYTOP("sticky-top")
+}
+
+/**
+ * Navbar colors.
+ */
+enum class NavbarColor(internal val navbarColor: String) {
+ LIGHT("navbar-light"),
+ DARK("navbar-dark")
+}
+
+/**
+ * Navbar responsive behavior.
+ */
+enum class NavbarExpand(internal val navbarExpand: String) {
+ ALWAYS("navbar-expand"),
+ XL("navbar-expand-xl"),
+ LG("navbar-expand-lg"),
+ MD("navbar-expand-md"),
+ SM("navbar-expand-sm"),
+}
+
+/**
+ * The Bootstrap Navbar container.
+ *
+ * @constructor
+ * @param label the navbar label
+ * @param type the navbar type
+ * @param expand the navbar responsive behavior
+ * @param nColor the navbar color
+ * @param bgColor the navbar background color
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class Navbar(
+ label: String? = null,
+ type: NavbarType? = null,
+ expand: NavbarExpand? = NavbarExpand.LG,
+ nColor: NavbarColor = NavbarColor.LIGHT,
+ bgColor: BsBgColor = BsBgColor.LIGHT,
+ classes: Set<String> = setOf(), init: (Navbar.() -> Unit)? = null
+) : SimplePanel(classes) {
+
+ /**
+ * The navbar header label.
+ */
+ var label
+ get() = if (brandLink.visible) brandLink.label else null
+ set(value) {
+ if (value != null) {
+ brandLink.label = value
+ brandLink.show()
+ } else {
+ brandLink.hide()
+ }
+ }
+
+ /**
+ * The navbar type.
+ */
+ var type by refreshOnUpdate(type)
+ /**
+ * The navbar responsive behavior.
+ */
+ var expand by refreshOnUpdate(expand)
+ /**
+ * The navbar color.
+ */
+ var nColor by refreshOnUpdate(nColor)
+ /**
+ * The navbar background color.
+ */
+ var bgColor by refreshOnUpdate(bgColor)
+
+ private val idc = "kv_navbar_$counter"
+
+ private val brandLink = Link(label ?: "", "#", classes = setOf("navbar-brand"))
+ internal val container = SimplePanel(setOf("collapse", "navbar-collapse")) {
+ id = idc
+ }
+
+ init {
+ addInternal(brandLink)
+ addInternal(NavbarButton(idc))
+ addInternal(container)
+ if (label == null) brandLink.hide()
+ counter++
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ override fun render(): VNode {
+ return render("nav", childrenVNodes())
+ }
+
+ override fun add(child: Component): Navbar {
+ container.add(child)
+ return this
+ }
+
+ override fun addAll(children: List<Component>): Navbar {
+ container.addAll(children)
+ return this
+ }
+
+ override fun remove(child: Component): Navbar {
+ container.remove(child)
+ return this
+ }
+
+ override fun removeAll(): Navbar {
+ container.removeAll()
+ return this
+ }
+
+ override fun getChildren(): List<Component> {
+ return container.getChildren()
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("navbar" to true)
+ type?.let {
+ cl.add(it.navbarType to true)
+ }
+ expand?.let {
+ cl.add(it.navbarExpand to true)
+ }
+ cl.add(nColor.navbarColor to true)
+ cl.add(bgColor.className to true)
+ return cl
+ }
+
+ companion object {
+ internal var counter = 0
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.navbar(
+ label: String? = null,
+ type: NavbarType? = null,
+ expand: NavbarExpand? = NavbarExpand.LG,
+ nColor: NavbarColor = NavbarColor.LIGHT,
+ bgColor: BsBgColor = BsBgColor.LIGHT,
+ classes: Set<String> = setOf(), init: (Navbar.() -> Unit)? = null
+ ): Navbar {
+ val navbar = Navbar(label, type, expand, nColor, bgColor, classes, init)
+ this.add(navbar)
+ return navbar
+ }
+
+ fun Navbar.navText(label: String, classes: Set<String> = setOf()): Span {
+ val text = Span(label, classes = classes + "navbar-text")
+ this.add(text)
+ return text
+ }
+ }
+}
+
+/**
+ * @suppress
+ * Internal component.
+ * The Bootstrap Navbar header button.
+ */
+internal class NavbarButton(private val idc: String, private val toggle: String = "Toggle navigation") :
+ SimplePanel(setOf("navbar-toggler")) {
+
+ init {
+ span(classes = setOf("navbar-toggler-icon"))
+ }
+
+ override fun render(): VNode {
+ return render("button", childrenVNodes())
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ return super.getSnAttrs() + listOf(
+ "type" to "button",
+ "data-toggle" to "collapse",
+ "data-target" to "#$idc",
+ "aria-controls" to idc,
+ "aria-expanded" to "false",
+ "aria-label" to toggle
+ )
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt
new file mode 100644
index 00000000..2ff6fa19
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/ResponsiveGridPanel.kt
@@ -0,0 +1,185 @@
+/*
+ * 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.panel
+
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.WidgetWrapper
+import pl.treksoft.kvision.html.Align
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+/**
+ * Bootstrap grid sizes.
+ */
+enum class GridSize(internal val size: String) {
+ SM("sm"),
+ MD("md"),
+ LG("lg"),
+ XL("xs")
+}
+
+internal const val MAX_COLUMNS = 12
+
+internal data class WidgetParam(val widget: Component, val size: Int, val offset: Int)
+
+/**
+ * The container with support for Bootstrap responsive grid layout.
+ *
+ * @constructor
+ * @param gridSize grid size
+ * @param rows number of rows
+ * @param cols number of columns
+ * @param align text align of grid cells
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class ResponsiveGridPanel(
+ private val gridSize: GridSize = GridSize.MD,
+ private var rows: Int = 0, private var cols: Int = 0, align: Align? = null,
+ classes: Set<String> = setOf(), init: (ResponsiveGridPanel.() -> Unit)? = null
+) : SimplePanel(classes + "container-fluid") {
+
+ /**
+ * Text align of grid cells.
+ */
+ var align by refreshOnUpdate(align) { refreshRowContainers() }
+
+ internal val map = mutableMapOf<Int, MutableMap<Int, WidgetParam>>()
+ private var auto: Boolean = true
+
+ init {
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ /**
+ * Adds child component to the grid.
+ * @param child child component
+ * @param col column number
+ * @param row row number
+ * @param size cell size (colspan)
+ * @param offset cell offset
+ * @return this container
+ */
+ open fun add(child: Component, col: Int, row: Int, size: Int = 0, offset: Int = 0): ResponsiveGridPanel {
+ val cRow = maxOf(row, 1)
+ val cCol = maxOf(col, 1)
+ if (cRow > rows) rows = cRow
+ if (cCol > cols) cols = cCol
+ map.getOrPut(cRow) { mutableMapOf() }[cCol] = WidgetParam(child, size, offset)
+ if (size > 0 || offset > 0) auto = false
+ refreshRowContainers()
+ return this
+ }
+
+ override fun add(child: Component): ResponsiveGridPanel {
+ return this.add(child, this.cols, 0)
+ }
+
+ override fun addAll(children: List<Component>): ResponsiveGridPanel {
+ children.forEach { this.add(it) }
+ return this
+ }
+
+ @Suppress("NestedBlockDepth")
+ override fun remove(child: Component): ResponsiveGridPanel {
+ map.values.forEach { row ->
+ row.filterValues { it.widget == child }
+ .forEach { (i, _) -> row.remove(i) }
+ }
+ refreshRowContainers()
+ return this
+ }
+
+ /**
+ * Removes child component at given location (column, row).
+ * @param col column number
+ * @param row row number
+ * @return this container
+ */
+ open fun removeAt(col: Int, row: Int): ResponsiveGridPanel {
+ map[row]?.remove(col)
+ refreshRowContainers()
+ return this
+ }
+
+ @Suppress("ComplexMethod", "NestedBlockDepth")
+ private fun refreshRowContainers() {
+ singleRender {
+ clearRowContainers()
+ val num = MAX_COLUMNS / cols
+ for (i in 1..rows) {
+ val rowContainer = SimplePanel(setOf("row"))
+ val row = map[i]
+ if (row != null) {
+ (1..cols).map { row[it] }.forEach { wp ->
+ if (auto) {
+ val widget = wp?.widget?.let {
+ WidgetWrapper(it, setOf("col-" + gridSize.size + "-" + num))
+ } ?: Tag(TAG.DIV, classes = setOf("col-" + gridSize.size + "-" + num))
+ align?.let {
+ widget.addCssClass(it.className)
+ }
+ rowContainer.add(widget)
+ } else {
+ if (wp != null) {
+ val s = if (wp.size > 0) wp.size else num
+ val widget = WidgetWrapper(wp.widget, setOf("col-" + gridSize.size + "-" + s))
+ if (wp.offset > 0) {
+ widget.addCssClass("offset-" + gridSize.size + "-" + wp.offset)
+ }
+ align?.let {
+ widget.addCssClass(it.className)
+ }
+ rowContainer.add(widget)
+ }
+ }
+ }
+ }
+ addInternal(rowContainer)
+ }
+ }
+ }
+
+ private fun clearRowContainers() {
+ children.forEach { it.dispose() }
+ removeAll()
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.responsiveGridPanel(
+ gridSize: GridSize = GridSize.MD,
+ rows: Int = 0, cols: Int = 0, align: Align? = null,
+ classes: Set<String> = setOf(), init: (ResponsiveGridPanel.() -> Unit)? = null
+ ): ResponsiveGridPanel {
+ val responsiveGridPanel = ResponsiveGridPanel(gridSize, rows, cols, align, classes, init)
+ this.add(responsiveGridPanel)
+ return responsiveGridPanel
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
new file mode 100644
index 00000000..2009e4fc
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/panel/TabPanel.kt
@@ -0,0 +1,273 @@
+/*
+ * 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.panel
+
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.ResString
+import pl.treksoft.kvision.core.WidgetWrapper
+import pl.treksoft.kvision.html.Icon
+import pl.treksoft.kvision.html.Link.Companion.link
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+import pl.treksoft.kvision.routing.routing
+import pl.treksoft.kvision.utils.obj
+import pl.treksoft.kvision.html.Icon.Companion.icon as cicon
+
+/**
+ * Tab position.
+ */
+enum class TabPosition {
+ TOP,
+ LEFT,
+ RIGHT
+}
+
+/**
+ * Left or right tab size.
+ */
+enum class SideTabSize {
+ SIZE_1,
+ SIZE_2,
+ SIZE_3,
+ SIZE_4,
+ SIZE_5,
+ SIZE_6
+}
+
+/**
+ * The container rendering it's children as tabs.
+ *
+ * It supports activating children by a JavaScript route.
+ *
+ * @constructor
+ * @param tabPosition tab position
+ * @param sideTabSize side tab size
+ * @param scrollableTabs determines if tabs are scrollable (default: false)
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class TabPanel(
+ private val tabPosition: TabPosition = TabPosition.TOP,
+ private val sideTabSize: SideTabSize = SideTabSize.SIZE_3,
+ scrollableTabs: Boolean = false,
+ classes: Set<String> = setOf(),
+ init: (TabPanel.() -> Unit)? = null
+) : SimplePanel(classes) {
+
+ /**
+ * The index of active (visible) tab.
+ */
+ var activeIndex
+ get() = content.activeIndex
+ set(value) {
+ if (content.activeIndex != value) {
+ content.activeIndex = value
+ }
+ nav.getChildren().forEach {
+ (it as Tag).getChildren().firstOrNull()?.removeCssClass("active")
+ }
+ if (content.activeIndex in nav.getChildren().indices) {
+ (nav.getChildren()[content.activeIndex] as Tag).getChildren().firstOrNull()?.addCssClass("active")
+ }
+ }
+ private val navClasses = when (tabPosition) {
+ TabPosition.TOP -> if (scrollableTabs) setOf("nav", "nav-tabs", "tabs-top") else setOf("nav", "nav-tabs")
+ TabPosition.LEFT -> setOf("nav", "nav-tabs", "tabs-left", "flex-column")
+ TabPosition.RIGHT -> setOf("nav", "nav-tabs", "tabs-right", "flex-column")
+ }
+ private var nav = Tag(TAG.UL, classes = navClasses)
+ private var content = StackPanel(false)
+
+ internal val childrenMap = mutableMapOf<Int, Component>()
+
+ init {
+ when (tabPosition) {
+ TabPosition.TOP -> {
+ this.addInternal(nav)
+ this.addInternal(content)
+ }
+ TabPosition.LEFT -> {
+ this.addSurroundingCssClass("container-fluid")
+ this.addCssClass("row")
+ val sizes = calculateSideClasses()
+ this.addInternal(WidgetWrapper(nav, setOf(sizes.first, "pl-0", "pr-0")))
+ this.addInternal(WidgetWrapper(content, setOf(sizes.second, "pl-0", "pr-0")))
+ }
+ TabPosition.RIGHT -> {
+ this.addSurroundingCssClass("container-fluid")
+ this.addCssClass("row")
+ val sizes = calculateSideClasses()
+ this.addInternal(WidgetWrapper(content, setOf(sizes.second, "pl-0", "pr-0")))
+ this.addInternal(WidgetWrapper(nav, setOf(sizes.first, "pl-0", "pr-0")))
+ }
+ }
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ private fun calculateSideClasses(): Pair<String, String> {
+ return when (sideTabSize) {
+ SideTabSize.SIZE_1 -> Pair("col-sm-1", "col-sm-11")
+ SideTabSize.SIZE_2 -> Pair("col-sm-2", "col-sm-10")
+ SideTabSize.SIZE_3 -> Pair("col-sm-3", "col-sm-9")
+ SideTabSize.SIZE_4 -> Pair("col-sm-4", "col-sm-8")
+ SideTabSize.SIZE_5 -> Pair("col-sm-5", "col-sm-7")
+ SideTabSize.SIZE_6 -> Pair("col-sm-6", "col-sm-6")
+ }
+ }
+
+ /**
+ * Adds new tab and optionally bounds it's activation to a given route.
+ * @param title title of the tab
+ * @param panel child component
+ * @param icon icon of the tab
+ * @param image image of the tab
+ * @param closable determines if this tab is closable
+ * @param route JavaScript route to activate given child
+ * @return current container
+ */
+ open fun addTab(
+ title: String, panel: Component, icon: String? = null,
+ image: ResString? = null, closable: Boolean = false, route: String? = null
+ ): TabPanel {
+ val currentIndex = counter++
+ childrenMap[currentIndex] = panel
+ val tag = Tag(TAG.LI, classes = setOf("nav-item")) {
+ link(title, "#", icon, image, classes = setOf("nav-link")) {
+ if (closable) {
+ cicon("fas fa-times") {
+ addCssClass("kv-tab-close")
+ setEventListener<Icon> {
+ click = { e ->
+ val actIndex = this@TabPanel.content.getChildren().indexOf(childrenMap[currentIndex])
+ e.asDynamic().data = actIndex
+ @Suppress("UnsafeCastFromDynamic")
+ if (this@TabPanel.dispatchEvent(
+ "tabClosing",
+ obj { detail = e; cancelable = true }) != false
+ ) {
+ this@TabPanel.removeTab(actIndex)
+ this@TabPanel.dispatchEvent("tabClosed", obj { detail = e })
+ }
+ e.stopPropagation()
+ }
+ }
+ }
+ }
+ }
+ setEventListener {
+ click = { e ->
+ activeIndex = this@TabPanel.content.getChildren().indexOf(childrenMap[currentIndex])
+ e.preventDefault()
+ if (route != null) {
+ routing.navigate(route)
+ }
+ }
+ }
+ }
+ nav.add(tag)
+ if (nav.getChildren().size == 1) {
+ tag.getChildren().firstOrNull()?.addCssClass("active")
+ activeIndex = 0
+ }
+ content.add(panel)
+ if (route != null) {
+ routing.on(
+ route,
+ { _ -> activeIndex = this@TabPanel.content.getChildren().indexOf(childrenMap[currentIndex]) })
+ .resolve()
+ }
+ return this
+ }
+
+ /**
+ * Removes tab at given index.
+ */
+ open fun removeTab(index: Int): TabPanel {
+ nav.remove(nav.getChildren()[index])
+ childrenMap.filter { it.value == content.getChildren()[index] }.keys.firstOrNull()?.let {
+ childrenMap.remove(it)
+ }
+ content.remove(content.getChildren()[index])
+ activeIndex = content.activeIndex
+ return this
+ }
+
+ override fun add(child: Component): TabPanel {
+ return addTab("", child)
+ }
+
+ override fun addAll(children: List<Component>): TabPanel {
+ children.forEach { add(it) }
+ return this
+ }
+
+ override fun remove(child: Component): TabPanel {
+ val index = content.getChildren().indexOf(child)
+ return removeTab(index)
+ }
+
+ /**
+ * Returns child component by tab index.
+ * @param index tab index
+ */
+ open fun getChildComponent(index: Int): Component? {
+ return content.getChildren()[index]
+ }
+
+ /**
+ * Returns tab header component by tab index.
+ * @param index tab index
+ */
+ open fun getNavComponent(index: Int): Tag? {
+ return nav.getChildren()[index] as? Tag
+ }
+
+ override fun removeAll(): TabPanel {
+ content.removeAll()
+ nav.removeAll()
+ childrenMap.clear()
+ refresh()
+ return this
+ }
+
+ companion object {
+ internal var counter = 0
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.tabPanel(
+ tabPosition: TabPosition = TabPosition.TOP,
+ sideTabSize: SideTabSize = SideTabSize.SIZE_3,
+ scrollableTabs: Boolean = false,
+ classes: Set<String> = setOf(),
+ init: (TabPanel.() -> Unit)? = null
+ ): TabPanel {
+ val tabPanel = TabPanel(tabPosition, sideTabSize, scrollableTabs, classes, init)
+ this.add(tabPanel)
+ return tabPanel
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressBar.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressBar.kt
new file mode 100644
index 00000000..4d0f4b93
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressBar.kt
@@ -0,0 +1,162 @@
+/*
+ * 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.progress
+
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.html.Align
+import pl.treksoft.kvision.panel.SimplePanel
+
+/**
+ * The Bootstrap progress bar.
+ *
+ * @constructor
+ * @param progress the current progress
+ * @param min the minimal progress
+ * @param max the maximal progress
+ * @param style the style of the progress bar
+ * @param striped determines if the progress bar is striped
+ * @param animated determines if the progress bar is animated
+ * @param content element text
+ * @param rich determines if content can contain HTML code
+ * @param align content align
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class ProgressBar(
+ progress: Int, min: Int = DEFAULT_MIN, max: Int = DEFAULT_MAX, style: ProgressBarStyle? = null,
+ striped: Boolean = false, animated: Boolean = false, content: String? = null,
+ rich: Boolean = false, align: Align? = null,
+ classes: Set<String> = setOf(), init: (ProgressBar.() -> Unit)? = null
+) :
+ SimplePanel(classes + "progress") {
+
+ /**
+ * The current progress.
+ */
+ var progress
+ get() = indicator.progress
+ set(value) {
+ indicator.progress = value
+ }
+ /**
+ * The minimal progress.
+ */
+ var min
+ get() = indicator.min
+ set(value) {
+ indicator.min = value
+ }
+ /**
+ * The maximal progress.
+ */
+ var max
+ get() = indicator.max
+ set(value) {
+ indicator.max = value
+ }
+ /**
+ * The style of the progress bar.
+ */
+ var style
+ get() = indicator.style
+ set(value) {
+ indicator.style = value
+ }
+ /**
+ * Determines if the progress bar is striped.
+ */
+ var striped
+ get() = indicator.striped
+ set(value) {
+ indicator.striped = value
+ }
+ /**
+ * Determines if the progress bar is animated.
+ */
+ var animated
+ get() = indicator.animated
+ set(value) {
+ indicator.animated = value
+ }
+ /**
+ * Text content of the progress bar.
+ */
+ var content
+ get() = indicator.content
+ set(value) {
+ indicator.content = value
+ }
+ /**
+ * Determines if [content] can contain HTML code.
+ */
+ var rich
+ get() = indicator.rich
+ set(value) {
+ indicator.rich = value
+ }
+ /**
+ * Text align of the progress bar.
+ */
+ var align
+ get() = indicator.align
+ set(value) {
+ indicator.align = value
+ }
+
+ internal val indicator = ProgressIndicator(progress, min, max, style, striped, animated, content, rich, align)
+
+ init {
+ addInternal(indicator)
+
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.progressBar(
+ progress: Int, min: Int = DEFAULT_MIN, max: Int = DEFAULT_MAX, style: ProgressBarStyle? = null,
+ striped: Boolean = false, animated: Boolean = false,
+ content: String? = null, rich: Boolean = false, align: Align? = null,
+ classes: Set<String> = setOf(), init: (ProgressBar.() -> Unit)? = null
+ ): ProgressBar {
+ val progressBar = ProgressBar(
+ progress,
+ min,
+ max,
+ style,
+ striped,
+ animated,
+ content,
+ rich,
+ align,
+ classes
+ ).apply { init?.invoke(this) }
+ this.add(progressBar)
+ return progressBar
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressIndicator.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressIndicator.kt
new file mode 100644
index 00000000..256d15d7
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/progress/ProgressIndicator.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.progress
+
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.html.Align
+import pl.treksoft.kvision.html.Div
+import pl.treksoft.kvision.utils.perc
+
+/**
+ * Progress bar styles.
+ */
+enum class ProgressBarStyle(internal val className: String) {
+ SUCCESS("progress-bar-success"),
+ INFO("progress-bar-info"),
+ WARNING("progress-bar-warning"),
+ DANGER("progress-bar-danger")
+}
+
+internal const val DEFAULT_MIN = 0
+internal const val DEFAULT_MAX = 100
+
+
+/**
+ * The Bootstrap progress bar indicator.
+ *
+ * @constructor
+ * @param progress the current progress
+ * @param min the minimal progress
+ * @param max the maximal progress
+ * @param style the style of the progress bar indicator
+ * @param striped determines if the progress bar indicator is striped
+ * @param animated determines if the progress bar indicator is animated
+ * @param content element text
+ * @param rich determines if [content] can contain HTML code
+ * @param align content align
+ * @param classes a set of CSS class names
+ */
+internal class ProgressIndicator(
+ progress: Int, min: Int = DEFAULT_MIN, max: Int = DEFAULT_MAX, style: ProgressBarStyle? = null,
+ striped: Boolean = false, animated: Boolean = false,
+ content: String? = null, rich: Boolean = false, align: Align? = null,
+ classes: Set<String> = setOf()
+) :
+ Div(content, rich, align, classes) {
+
+ /**
+ * The current progress.
+ */
+ var progress by refreshOnUpdate(progress) { refreshWidth() }
+ /**
+ * The minimal progress.
+ */
+ var min by refreshOnUpdate(min) { refreshWidth() }
+ /**
+ * The maximal progress.
+ */
+ var max by refreshOnUpdate(max) { refreshWidth() }
+ /**
+ * The style of the progress indicator.
+ */
+ var style by refreshOnUpdate(style)
+ /**
+ * Determines if the progress indicator is striped.
+ */
+ var striped by refreshOnUpdate(striped)
+ /**
+ * Determines if the progress indicator is animated.
+ */
+ var animated by refreshOnUpdate(animated)
+
+ init {
+ role = "progressbar"
+ refreshWidth()
+ }
+
+ private fun refreshWidth() {
+ val value = (if (max - min > 0) (progress - min) * DEFAULT_MAX.toFloat() / (max - min) else 0f).toInt()
+ val percent = if (value < 0) 0 else if (value > DEFAULT_MAX) DEFAULT_MAX else value
+ width = percent.perc
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("progress-bar" to true)
+ style?.let {
+ cl.add(it.className to true)
+ }
+ if (striped || animated) {
+ cl.add("progress-bar-striped" to true)
+ }
+ if (animated) {
+ cl.add("active" to true)
+ }
+ return cl
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ val sn = super.getSnAttrs().toMutableList()
+ sn.add("aria-valuenow" to "$progress")
+ sn.add("aria-valuemin" to "$min")
+ sn.add("aria-valuemax" to "$max")
+ return sn
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/ButtonGroup.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/ButtonGroup.kt
new file mode 100644
index 00000000..2aef9e63
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/ButtonGroup.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.toolbar
+
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.utils.px
+
+/**
+ * Button group sizes.
+ */
+enum class ButtonGroupSize(internal val className: String) {
+ LARGE("btn-group-lg"),
+ SMALL("btn-group-sm")
+}
+
+/**
+ * The Bootstrap button group.
+ *
+ * @constructor
+ * @param size button group size
+ * @param vertical determines if button group is aligned vertically
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class ButtonGroup(
+ size: ButtonGroupSize? = null, vertical: Boolean = false,
+ classes: Set<String> = setOf(), init: (ButtonGroup.() -> Unit)? = null
+) : SimplePanel(classes) {
+
+ /**
+ * Button group size.
+ */
+ var size by refreshOnUpdate(size)
+ /**
+ * Vertical alignment.
+ */
+ var vertical by refreshOnUpdate(vertical)
+
+ init {
+ role = "group"
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ if (vertical) {
+ cl.add("btn-group-vertical" to true)
+ } else {
+ cl.add("btn-group" to true)
+ }
+ size?.let {
+ cl.add(it.className to true)
+ }
+ return cl
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.buttonGroup(
+ size: ButtonGroupSize? = null, vertical: Boolean = false,
+ classes: Set<String> = setOf(), init: (ButtonGroup.() -> Unit)? = null
+ ): ButtonGroup {
+ val group = ButtonGroup(size, vertical, classes).apply { init?.invoke(this) }
+ this.add(group)
+ return group
+ }
+ /**
+ * DSL builder extension function for toolbar.
+ *
+ * It creates button groups with size and vertical parameters of the toolbar.
+ */
+ fun Toolbar.buttonGroup(
+ classes: Set<String> = setOf(), init: (ButtonGroup.() -> Unit)? = null
+ ): ButtonGroup {
+ val group = ButtonGroup(this.size, this.vertical, classes).apply {
+ marginRight = this@buttonGroup.spacing.px
+ init?.invoke(this)
+ }
+ this.add(group)
+ return group
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/Toolbar.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/Toolbar.kt
new file mode 100644
index 00000000..13ed8972
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/toolbar/Toolbar.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.toolbar
+
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.panel.SimplePanel
+
+/**
+ * The Bootstrap toolbar.
+ *
+ * @constructor
+ * @param size button groups size
+ * @param spacing the spacing between button groups
+ * @param vertical determines if button groups are aligned vertically
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class Toolbar(
+ val size: ButtonGroupSize? = null, val spacing: Int = 5, val vertical: Boolean = false,
+ classes: Set<String> = setOf(), init: (Toolbar.() -> Unit)? = null
+) : SimplePanel(classes + "btn-toolbar") {
+
+ init {
+ role = "toolbar"
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.toolbar(
+ size: ButtonGroupSize? = null, spacing: Int = 2, vertical: Boolean = false,
+ classes: Set<String> = setOf(), init: (Toolbar.() -> Unit)? = null
+ ): Toolbar {
+ val toolbar = Toolbar(size, spacing, vertical, classes).apply { init?.invoke(this) }
+ this.add(toolbar)
+ return toolbar
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt
new file mode 100644
index 00000000..a3ceaf61
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.window
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.KVManager
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.core.Widget
+
+/**
+ * Helper class for maximize icon component.
+ */
+open class MaximizeIcon : Widget(setOf()) {
+
+ override fun render(): VNode {
+ return render("button", arrayOf(KVManager.virtualize("<span aria-hidden='true'>&#x1f5d6;</span>")))
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("close" to true)
+ return cl
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ return super.getSnAttrs() + listOf("type" to "button", "aria-label" to "Maximize")
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt
new file mode 100644
index 00000000..c8034d09
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.window
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.KVManager
+import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.core.Widget
+
+/**
+ * Helper class for minimize icon component.
+ */
+open class MinimizeIcon : Widget(setOf()) {
+
+ override fun render(): VNode {
+ return render("button", arrayOf(KVManager.virtualize("<span aria-hidden='true'>&#x1f5d5;</span>")))
+ }
+
+ override fun getSnClass(): List<StringBoolPair> {
+ val cl = super.getSnClass().toMutableList()
+ cl.add("close" to true)
+ return cl
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ return super.getSnAttrs() + listOf("type" to "button", "aria-label" to "Minimize")
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/Window.kt b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/Window.kt
new file mode 100644
index 00000000..83473858
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/main/kotlin/pl/treksoft/kvision/window/Window.kt
@@ -0,0 +1,449 @@
+/*
+ * 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.window
+
+import com.github.snabbdom.VNode
+import org.w3c.dom.events.Event
+import org.w3c.dom.events.MouseEvent
+import pl.treksoft.kvision.KVManager
+import pl.treksoft.kvision.KVManagerBootstrap
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.CssSize
+import pl.treksoft.kvision.core.Overflow
+import pl.treksoft.kvision.core.Position
+import pl.treksoft.kvision.core.Resize
+import pl.treksoft.kvision.core.UNIT
+import pl.treksoft.kvision.html.Icon
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+import pl.treksoft.kvision.modal.CloseIcon
+import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.utils.obj
+import pl.treksoft.kvision.utils.px
+
+internal const val DEFAULT_Z_INDEX = 900
+internal const val WINDOW_HEADER_HEIGHT = 40
+internal const val WINDOW_CONTENT_MARGIN_BOTTOM = 11
+
+/**
+ * Floating window container.
+ *
+ * @constructor
+ * @param caption window title
+ * @param contentWidth window content width
+ * @param contentHeight window content height
+ * @param isResizable determines if the window is resizable
+ * @param isDraggable determines if the window is draggable
+ * @param closeButton determines if Close button is visible
+ * @param maximizeButton determines if Maximize button is visible
+ * @param minimizeButton determines if Minimize button is visible
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+@Suppress("TooManyFunctions")
+open class Window(
+ caption: String? = null,
+ contentWidth: CssSize? = CssSize(0, UNIT.auto),
+ contentHeight: CssSize? = CssSize(0, UNIT.auto),
+ isResizable: Boolean = true,
+ isDraggable: Boolean = true,
+ closeButton: Boolean = false,
+ maximizeButton: Boolean = false,
+ minimizeButton: Boolean = false,
+ icon: String? = null,
+ classes: Set<String> = setOf(),
+ init: (Window.() -> Unit)? = null
+) :
+ SimplePanel(classes + setOf("modal-content", "kv-window")) {
+
+ /**
+ * Window caption text.
+ */
+ var caption
+ get() = captionTag.content
+ set(value) {
+ captionTag.content = value
+ checkHeaderVisibility()
+ }
+ /**
+ * Window content width.
+ */
+ var contentWidth
+ get() = width
+ set(value) {
+ width = value
+ }
+ /**
+ * Window content height.
+ */
+ var contentHeight
+ get() = content.height
+ set(value) {
+ content.height = value
+ }
+ /**
+ * Window content height.
+ */
+ var contentOverflow
+ get() = content.overflow
+ set(value) {
+ content.overflow = value
+ }
+ /**
+ * Determines if the window is resizable.
+ */
+ var isResizable by refreshOnUpdate(isResizable) { checkIsResizable() }
+ /**
+ * Determines if the window is draggable.
+ */
+ var isDraggable by refreshOnUpdate(isDraggable) { checkIsDraggable(); checkHeaderVisibility() }
+ /**
+ * Determines if Close button is visible.
+ */
+ var closeButton
+ get() = closeIcon.visible
+ set(value) {
+ closeIcon.visible = value
+ checkHeaderVisibility()
+ }
+ /**
+ * Determines if Maximize button is visible.
+ */
+ var maximizeButton
+ get() = maximizeIcon.visible
+ set(value) {
+ maximizeIcon.visible = value
+ checkHeaderVisibility()
+ }
+ /**
+ * Determines if Maximize button is visible.
+ */
+ var minimizeButton
+ get() = minimizeIcon.visible
+ set(value) {
+ minimizeIcon.visible = value
+ checkHeaderVisibility()
+ }
+ /**
+ * Window icon.
+ */
+ var icon
+ get() = if (windowIcon.icon == "") null else windowIcon.icon
+ set(value) {
+ windowIcon.icon = value ?: ""
+ windowIcon.visible = (value != null && value != "")
+ }
+
+ private val header = SimplePanel(setOf("modal-header"))
+
+ /**
+ * @suppress
+ * Internal property.
+ */
+ protected val content = SimplePanel().apply {
+ this.height = contentHeight
+ this.overflow = Overflow.AUTO
+ }
+ private val closeIcon = CloseIcon()
+ private val maximizeIcon = MaximizeIcon()
+ private val minimizeIcon = MinimizeIcon()
+ private val captionTag = Tag(TAG.H5, caption, classes = setOf("modal-title"))
+ private val iconsContainer = SimplePanel(setOf("kv-window-icons-container"))
+ private val windowIcon = Icon(icon ?: "").apply {
+ addCssClass("window-icon")
+ visible = (icon != null && icon != "")
+ }
+
+ private var isResizeEvent = false
+
+ init {
+ id = "kv_window_$counter"
+ @Suppress("LeakingThis")
+ position = Position.ABSOLUTE
+ @Suppress("LeakingThis")
+ overflow = Overflow.HIDDEN
+ @Suppress("LeakingThis")
+ width = contentWidth
+ @Suppress("LeakingThis")
+ zIndex = ++zIndexCounter
+ header.add(captionTag)
+ captionTag.add(windowIcon)
+ header.add(iconsContainer)
+ minimizeIcon.visible = minimizeButton
+ minimizeIcon.setEventListener {
+ click = { _ ->
+ @Suppress("UnsafeCastFromDynamic")
+ if (this@Window.dispatchEvent("minimizeWindow", obj {}) != false) {
+ toggleMinimize()
+ }
+ }
+ mousedown = { e ->
+ e.stopPropagation()
+ }
+ }
+ iconsContainer.add(minimizeIcon)
+ maximizeIcon.visible = maximizeButton
+ maximizeIcon.setEventListener {
+ click = { _ ->
+ @Suppress("UnsafeCastFromDynamic")
+ if (this@Window.dispatchEvent("maximizeWindow", obj {}) != false) {
+ toggleMaximize()
+ }
+ }
+ mousedown = { e ->
+ e.stopPropagation()
+ }
+ }
+ iconsContainer.add(maximizeIcon)
+ closeIcon.visible = closeButton
+ closeIcon.setEventListener {
+ click = { _ ->
+ @Suppress("UnsafeCastFromDynamic")
+ if (this@Window.dispatchEvent("closeWindow", obj {}) != false) {
+ close()
+ }
+ }
+ mousedown = { e ->
+ e.stopPropagation()
+ }
+ }
+ iconsContainer.add(closeIcon)
+ checkHeaderVisibility()
+ addInternal(header)
+ addInternal(content)
+ checkIsDraggable()
+ if (isResizable) {
+ @Suppress("LeakingThis")
+ resize = Resize.BOTH
+ content.marginBottom = WINDOW_CONTENT_MARGIN_BOTTOM.px
+ }
+ @Suppress("LeakingThis")
+ setEventListener<Window> {
+ click = {
+ toFront()
+ focus()
+ }
+ }
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ counter++
+ }
+
+ private fun checkHeaderVisibility() {
+ @Suppress("ComplexCondition")
+ if (!closeButton && !maximizeButton && !minimizeButton && caption == null && !isDraggable) {
+ header.hide()
+ } else {
+ header.show()
+ }
+ }
+
+ private fun checkIsDraggable() {
+ var isDrag: Boolean
+ if (isDraggable) {
+ header.setEventListener<SimplePanel> {
+ mousedown = { e ->
+ if (e.button.toInt() == 0) {
+ isDrag = true
+ val dragStartX = this@Window.getElementJQuery()?.position()?.left?.toInt() ?: 0
+ val dragStartY = this@Window.getElementJQuery()?.position()?.top?.toInt() ?: 0
+ val dragMouseX = e.pageX
+ val dragMouseY = e.pageY
+ val moveCallback = { me: Event ->
+ if (isDrag) {
+ this@Window.left = (dragStartX + (me as MouseEvent).pageX - dragMouseX).toInt().px
+ this@Window.top = (dragStartY + (me).pageY - dragMouseY).toInt().px
+ }
+ }
+ kotlin.browser.window.addEventListener("mousemove", moveCallback)
+ var upCallback: ((Event) -> Unit)? = null
+ upCallback = {
+ isDrag = false
+ kotlin.browser.window.removeEventListener("mousemove", moveCallback)
+ kotlin.browser.window.removeEventListener("mouseup", upCallback)
+ }
+ kotlin.browser.window.addEventListener("mouseup", upCallback)
+ }
+ }
+ }
+ } else {
+ isDrag = false
+ header.removeEventListeners()
+ }
+ }
+
+ private fun checkIsResizable() {
+ checkResizablEventHandler()
+ if (isResizable) {
+ resize = Resize.BOTH
+ val intHeight = (getElementJQuery()?.height()?.toInt() ?: 0)
+ content.height = (intHeight - WINDOW_HEADER_HEIGHT - WINDOW_CONTENT_MARGIN_BOTTOM).px
+ content.marginBottom = WINDOW_CONTENT_MARGIN_BOTTOM.px
+ } else {
+ resize = Resize.NONE
+ val intHeight = (getElementJQuery()?.height()?.toInt() ?: 0)
+ content.height = (intHeight - WINDOW_HEADER_HEIGHT).px
+ content.marginBottom = 0.px
+ }
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ private fun checkResizablEventHandler() {
+ if (isResizable) {
+ if (!isResizeEvent) {
+ isResizeEvent = true
+ KVManagerBootstrap.setResizeEvent(this) {
+ val eid = getElementJQuery()?.attr("id")
+ if (isResizable && eid == id) {
+ val outerWidth = (getElementJQuery()?.outerWidth()?.toInt() ?: 0)
+ val outerHeight = (getElementJQuery()?.outerHeight()?.toInt() ?: 0)
+ val intWidth = (getElementJQuery()?.width()?.toInt() ?: 0)
+ val intHeight = (getElementJQuery()?.height()?.toInt() ?: 0)
+ content.width = intWidth.px
+ content.height = (intHeight - WINDOW_HEADER_HEIGHT - WINDOW_CONTENT_MARGIN_BOTTOM).px
+ width = outerWidth.px
+ height = outerHeight.px
+ this.dispatchEvent("resizeWindow", obj {
+ detail = obj {
+ this.width = outerWidth
+ this.height = outerHeight
+ }
+ })
+ }
+ }
+ }
+ } else if (isResizeEvent) {
+ KVManagerBootstrap.clearResizeEvent(this)
+ isResizeEvent = false
+ }
+ }
+
+ override fun add(child: Component): SimplePanel {
+ content.add(child)
+ return this
+ }
+
+ override fun addAll(children: List<Component>): SimplePanel {
+ content.addAll(children)
+ return this
+ }
+
+ override fun remove(child: Component): SimplePanel {
+ content.remove(child)
+ return this
+ }
+
+ override fun removeAll(): SimplePanel {
+ content.removeAll()
+ return this
+ }
+
+ override fun getChildren(): List<Component> {
+ return content.getChildren()
+ }
+
+ override fun afterCreate(node: VNode) {
+ checkResizablEventHandler()
+ }
+
+ override fun afterDestroy() {
+ if (isResizeEvent) {
+ KVManagerBootstrap.clearResizeEvent(this)
+ isResizeEvent = false
+ }
+ }
+
+ /**
+ * Moves the current window to the front.
+ */
+ open fun toFront() {
+ if ((zIndex ?: 0) < zIndexCounter) zIndex = ++zIndexCounter
+ }
+
+ /**
+ * Makes the current window focused.
+ */
+ open fun focus() {
+ getElementJQuery()?.focus()
+ }
+
+ /**
+ * Close the window.
+ */
+ open fun close() {
+ hide()
+ }
+
+ /**
+ * Maximize or restore the window size.
+ */
+ open fun toggleMaximize() {
+ }
+
+ /**
+ * Minimize or restore the window size.
+ */
+ open fun toggleMinimize() {
+ }
+
+ companion object {
+ internal var counter = 0
+ internal var zIndexCounter = DEFAULT_Z_INDEX
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.window(
+ caption: String? = null,
+ contentWidth: CssSize? = CssSize(0, UNIT.auto),
+ contentHeight: CssSize? = CssSize(0, UNIT.auto),
+ isResizable: Boolean = true,
+ isDraggable: Boolean = true,
+ closeButton: Boolean = false,
+ maximizeButton: Boolean = false,
+ minimizeButton: Boolean = false,
+ icon: String? = null,
+ classes: Set<String> = setOf(),
+ init: (Window.() -> Unit)? = null
+ ): Window {
+ val window =
+ Window(
+ caption,
+ contentWidth,
+ contentHeight,
+ isResizable,
+ isDraggable,
+ closeButton,
+ maximizeButton,
+ minimizeButton,
+ icon,
+ classes,
+ init
+ )
+ this.add(window)
+ return window
+ }
+ }
+}
diff --git a/kvision-modules/kvision-bootstrap/src/main/resources/css/paper.css b/kvision-modules/kvision-bootstrap/src/main/resources/css/paper.css
deleted file mode 100644
index 1c783608..00000000
--- a/kvision-modules/kvision-bootstrap/src/main/resources/css/paper.css
+++ /dev/null
@@ -1,16 +0,0 @@
-body {
- font-size: 14px;
- line-height: 1.42857143;
-}
-
-.kv-radio-checkbox {
- padding-left: 20px !important;
-}
-
-.radio label, .checkbox label {
- white-space: nowrap;
-}
-
-.modal-title {
- font-size: 18px;
-}
diff --git a/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css b/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css
deleted file mode 100644
index 475a0b85..00000000
--- a/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css
+++ /dev/null
@@ -1,226 +0,0 @@
-.splitpanel-vertical {
- display: flex;
- flex-direction: row;
- overflow: auto;
-}
-
-.splitpanel-vertical > *:first-child {
- max-width: calc(100% - 9px);
-}
-
-.splitpanel-vertical > * {
- flex: 0 0 auto;
- overflow: auto;
-}
-
-.splitpanel-vertical > *:last-child {
- flex: 1 1 auto;
- overflow: auto;
-}
-
-.splitpanel-horizontal {
- display: flex;
- flex-direction: column;
- overflow: auto;
-}
-
-.splitpanel-horizontal > *:first-child {
- max-height: calc(100% - 9px);
-}
-
-.splitpanel-horizontal > * {
- flex: 0 0 auto;
- overflow: auto;
-}
-
-.splitpanel-horizontal > *:last-child {
- flex: 1 1 auto;
- overflow: auto;
-}
-
-
-.splitter-vertical {
- flex: 0 0 auto;
- width: 9px;
- background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAhCAQAAABOpSL+AAAAIklEQVR4AWMwbb/PdR+JZDD9f1/oPhI5sgVGBSruc9xHIgGdSQqqQJGkRgAAAABJRU5ErkJggg==') center center no-repeat #cecece;
- cursor: col-resize;
-}
-
-.splitter-horizontal {
- flex: 0 0 auto;
- height: 9px;
- background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAICAQAAADdTl4aAAAAIElEQVQoz2MwrTD9TxFsZ7jPcV+IIsjFQAUw6hFqegQA+xzRHT2p7pEAAAAASUVORK5CYII=') center center no-repeat #cecece;
- cursor: row-resize;
-}
-
-.trix-control {
- overflow-y: auto;
-}
-
-trix-toolbar .trix-button-group {
- margin-bottom: 3px;
-}
-
-.form-inline .form-group {
- margin-right:6px;
-}
-
-.form-inline .checkbox, .form-inline .radio {
- margin-right:6px;
-}
-
-.form-inline .form-group .form-control, .navbar-form .form-group .form-control {
- margin-left:6px;
-}
-
-.form-horizontal .checkbox, .form-horizontal .radio {
- padding-left: 25px;
-}
-
-.form-inline .form-group trix-editor.form-control {
- margin-left: 0px;
- width: 100%;
-}
-
-.form-inline .form-group, .form-inline .control-label {
- vertical-align: top;
-}
-
-.bootstrap-touchspin .input-group-btn-vertical> .input-sm {
- padding: 7px 10px;
- height: 6px;
-}
-
-.bootstrap-touchspin .input-group-btn-vertical> .input-lg {
- height: 24px;
-}
-
-.kv-spinner-btn-none .input-group-btn-vertical {
- display: none;
-}
-
-.kv-spinner-btn-none .form-control {
- border-radius: 4px !important;
-}
-
-.kv-spinner-btn-vertical .form-control {
- border-radius: 4px 0px 0px 4px !important;
-}
-
-.kv-radiogroup .radio {
- margin-top: -5px;
-}
-
-.kv-radiogroup-inline label {
- margin-right: 10px;
-}
-
-.kv-radio-checkbox {
- padding-left: 7px;
-}
-
-.kv-window {
- border-radius: 0px;
-}
-
-.kv-window .modal-header {
- height: 40px;
- padding: 10px 15px 5px 15px;
-}
-
-.kv-window .modal-header button.close {
- width: 21px;
-}
-
-.kv-window .modal-header .modal-title {
- white-space: nowrap;
-}
-
-.kv-window .modal-header .window-icon {
- display: inline-block;
- margin-right: 6px;
-}
-
-ul.dropdown-menu li a {
- cursor: pointer;
-}
-
-.col-nopadding {
- padding-left: 0;
- padding-right: 0;
-}
-
-.kv-preview-thumb .btn, .kv-zoom-actions .btn, .file-zoom-dialog .floating-buttons .btn {
- padding: 5px 8px;
-}
-
-.file-drop-zone.clickable:hover {
- border: 1px dashed #999;
-}
-
-.file-drop-zone.clickable:focus {
- border: 1px solid #5acde2;
-}
-
-ul.tabs-top {
- overflow-x: auto;
- overflow-y: hidden;
- display: flex;
-}
-
-ul.tabs-top > li {
- float:none;
- flex-shrink: 0;
-}
-
-.kv-tab-close {
- margin-left: 10px;
- color: #000;
- text-shadow: 0 1px 0 #fff;
- filter: alpha(opacity=20);
- opacity: 0.2;
-}
-
-.kv-tab-close:hover, .kv-tab-close:focus {
- cursor: pointer;
- filter: alpha(opacity=50);
- opacity: 0.5;
-}
-
-select.form-control, .tabulator-row .tabulator-cell.tabulator-editing select {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background: transparent none no-repeat;
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAKCAYAAABblxXYAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wUKFyIn4IjqJgAAAENJREFUKM/l0LERACEQQlGsiTa2px1aokGugNNAx8wfMy8AeLoBALYjaTqoKkga2+gKPgF/2Q7JkEx359oftu+C7/UBCUIcVQz0PvcAAAAASUVORK5CYII=');
- background-position: right center;
- cursor: pointer;
-}
-
-select.form-control:hover {
- background-color: #e6e6e6;
-}
-
-select.form-control option {
- background-color: white;
-}
-
-select.input-sm {
- line-height: inherit;
-}
-
-.tabulator-row .tabulator-cell.tabulator-editing input, .tabulator-row .tabulator-cell.tabulator-editing select {
- border: 1px solid #ccc;
- border-radius: 4px;
-}
-
-.tabulator-row .tabulator-cell.tabulator-editing input:focus, .tabulator-row .tabulator-cell.tabulator-editing select:focus {
- border-color: #66afe9;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);
-}
-
-.tabulator-row .tabulator-cell.tabulator-editing {
- border-right: 1px solid #1d68cd !important;
- padding: 2px !important;
-}
diff --git a/kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.js b/kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.js
deleted file mode 100644
index 906942d1..00000000
--- a/kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.js
+++ /dev/null
@@ -1,64 +0,0 @@
-module.exports = {
-
- // Default for the style loading
- styleLoader: 'style-loader!css-loader!less-loader',
-
- scripts: {
- 'transition': true,
- 'alert': true,
- 'button': true,
- 'carousel': true,
- 'collapse': true,
- 'dropdown': true,
- 'modal': true,
- 'tooltip': true,
- 'popover': true,
- 'scrollspy': true,
- 'tab': true,
- 'affix': true
- },
- styles: {
- "mixins": false,
-
- "normalize": false,
- "print": false,
-
- "scaffolding": false,
- "type": false,
- "code": false,
- "grid": false,
- "tables": false,
- "forms": false,
- "buttons": false,
-
- "component-animations": false,
- "glyphicons": false,
- "dropdowns": false,
- "button-groups": false,
- "input-groups": false,
- "navs": false,
- "navbar": false,
- "breadcrumbs": false,
- "pagination": false,
- "pager": false,
- "labels": false,
- "badges": false,
- "jumbotron": false,
- "thumbnails": false,
- "alerts": false,
- "progress-bars": false,
- "media": false,
- "list-group": false,
- "panels": false,
- "wells": false,
- "close": false,
-
- "modals": false,
- "tooltip": false,
- "popovers": false,
- "carousel": false,
-
- "utilities": false,
- "responsive-utilities": false
- }
-};
diff --git a/kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.less b/kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.less
deleted file mode 100644
index e69de29b..00000000
--- a/kvision-modules/kvision-bootstrap/src/main/resources/js/bootstrap.config.less
+++ /dev/null
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
index 1ad97acc..fc3d5242 100644
--- a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt
@@ -70,8 +70,8 @@ interface DomSpec : TestSpec {
fun assertEqualsHtml(expected: String?, actual: String?, message: String?) {
if (expected != null && actual != null) {
- val exp = jQuery(expected)
- val act = jQuery(actual)
+ val exp = jQuery(expected.replace("position: ;","position: absolute;"))
+ val act = jQuery(actual.replace("position: ;","position: absolute;"))
val result = exp[0]?.isEqualNode(act[0])
if (result == true) {
assertTrue(result == true, message)
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/ContextMenuSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/ContextMenuSpec.kt
new file mode 100644
index 00000000..b467f1ff
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/ContextMenuSpec.kt
@@ -0,0 +1,76 @@
+/*
+ * 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 test.pl.treksoft.kvision.dropdown
+
+import pl.treksoft.kvision.dropdown.ContextMenu
+import pl.treksoft.kvision.dropdown.ContextMenu.Companion.setContextMenu
+import pl.treksoft.kvision.html.Link.Companion.link
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.utils.obj
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class ContextMenuSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val m = ContextMenu {
+ link("a", "b")
+ link("c", "d")
+ }
+ root.setContextMenu(m)
+ m.show()
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"dropdown-menu\" style=\"display: block;\"><a href=\"b\">a</a><a href=\"d\">c</a></div>",
+ element?.innerHTML,
+ "Should render correct context menu"
+ )
+ }
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ @Test
+ fun positionMenu() {
+ run {
+ val root = Root("test", fixed = true)
+ val m = ContextMenu {
+ link("a", "b")
+ link("c", "d")
+ }
+ root.setContextMenu(m)
+ m.positionMenu(obj {
+ pageX = 40
+ pageY = 50
+ })
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"dropdown-menu\" style=\"display: block; top: 50px; left: 40px;\"><a href=\"b\">a</a><a href=\"d\">c</a></div>",
+ element?.innerHTML,
+ "Should place context menu in the correct position"
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt
index af35fa51..f75331f3 100644
--- a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt
@@ -22,6 +22,7 @@
package test.pl.treksoft.kvision.dropdown
import pl.treksoft.kvision.dropdown.DD
+import pl.treksoft.kvision.dropdown.Direction
import pl.treksoft.kvision.dropdown.DropDown
import pl.treksoft.kvision.panel.Root
import test.pl.treksoft.kvision.DomSpec
@@ -37,11 +38,11 @@ class DropDownSpec : DomSpec {
val root = Root("test", fixed = true)
val dd = DropDown("Dropdown", listOf("abc" to "#!/x", "def" to "#!/y"), "flag")
root.add(dd)
- dd.toggle()
+ dd.list.getElementJQueryD()?.dropdown("toggle")
val element = document.getElementById("test")
val id = dd.buttonId()
assertEqualsHtml(
- "<div class=\"dropdown open\"><button class=\"dropdown btn btn-default\" id=\"$id\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" role=\"button\" href=\"#\"><span class=\"glyphicon glyphicon-flag\"></span> Dropdown</button><ul class=\"dropdown-menu\" aria-labelledby=\"$id\" aria-expanded=\"true\"><li><a href=\"#!/x\">abc</a></li><li><a href=\"#!/y\">def</a></li></ul></div>",
+ "<div class=\"dropdown show\"><button class=\"btn btn-primary dropdown-toggle\" id=\"$id\" role=\"button\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" href=\"#\"><i class=\"flag\"></i> Dropdown</button><div class=\"dropdown-menu show\" aria-labelledby=\"$id\" x-placement=\"bottom-start\" aria-expanded=\"true\" style=\"position: ;\"><a class=\"dropdown-item\" href=\"#!/x\">abc</a><a class=\"dropdown-item\" href=\"#!/y\">def</a></div></div>",
element?.innerHTML,
"Should render correct drop down"
)
@@ -52,13 +53,13 @@ class DropDownSpec : DomSpec {
fun renderDropUp() {
run {
val root = Root("test", fixed = true)
- val dd = DropDown("Dropdown", listOf("abc" to "#!/x", "def" to "#!/y"), "flag").apply { dropup = true }
+ val dd = DropDown("Dropdown", listOf("abc" to "#!/x", "def" to "#!/y"), "flag").apply { direction = Direction.DROPUP }
root.add(dd)
- dd.toggle()
+ dd.list.getElementJQueryD()?.dropdown("toggle")
val element = document.getElementById("test")
val id = dd.buttonId()
assertEqualsHtml(
- "<div class=\"dropup open\"><button class=\"dropdown btn btn-default\" id=\"$id\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" role=\"button\" href=\"#\"><span class=\"glyphicon glyphicon-flag\"></span> Dropdown</button><ul class=\"dropdown-menu\" aria-labelledby=\"$id\" aria-expanded=\"true\"><li><a href=\"#!/x\">abc</a></li><li><a href=\"#!/y\">def</a></li></ul></div>",
+ "<div class=\"dropup show\"><button class=\"btn btn-primary dropdown-toggle\" id=\"$id\" role=\"button\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" href=\"#\"><i class=\"flag\"></i> Dropdown</button><div class=\"dropdown-menu show\" aria-labelledby=\"$id\" x-placement=\"top-start\" aria-expanded=\"true\" style=\"position: ;\"><a class=\"dropdown-item\" href=\"#!/x\">abc</a><a class=\"dropdown-item\" href=\"#!/y\">def</a></div></div>",
element?.innerHTML,
"Should render correct drop down"
)
@@ -71,11 +72,11 @@ class DropDownSpec : DomSpec {
val root = Root("test", fixed = true)
val dd = DropDown("Dropdown", listOf("abc" to DD.HEADER.option), "flag")
root.add(dd)
- dd.toggle()
+ dd.list.getElementJQueryD()?.dropdown("toggle")
val element = document.getElementById("test")
val id = dd.buttonId()
assertEqualsHtml(
- "<div class=\"dropdown open\"><button class=\"dropdown btn btn-default\" id=\"$id\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" role=\"button\" href=\"#\"><span class=\"glyphicon glyphicon-flag\"></span> Dropdown</button><ul class=\"dropdown-menu\" aria-labelledby=\"$id\" aria-expanded=\"true\"><li class=\"dropdown-header\">abc</li></ul></div>",
+ "<div class=\"dropdown show\"><button class=\"btn btn-primary dropdown-toggle\" id=\"$id\" role=\"button\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" href=\"#\"><i class=\"flag\"></i> Dropdown</button><div class=\"dropdown-menu show\" aria-labelledby=\"$id\" x-placement=\"bottom-start\" aria-expanded=\"true\" style=\"position: ;\"><h6 class=\"dropdown-header\">abc</h6></div></div>",
element?.innerHTML,
"Should render correct drop down"
)
@@ -88,11 +89,11 @@ class DropDownSpec : DomSpec {
val root = Root("test", fixed = true)
val dd = DropDown("Dropdown", listOf("abc" to DD.SEPARATOR.option), "flag")
root.add(dd)
- dd.toggle()
+ dd.list.getElementJQueryD()?.dropdown("toggle")
val element = document.getElementById("test")
val id = dd.buttonId()
assertEqualsHtml(
- "<div class=\"dropdown open\"><button class=\"dropdown btn btn-default\" id=\"$id\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" role=\"button\" href=\"#\"><span class=\"glyphicon glyphicon-flag\"></span> Dropdown</button><ul class=\"dropdown-menu\" aria-labelledby=\"$id\" aria-expanded=\"true\"><li class=\"divider\" role=\"separator\"></li></ul></div>",
+ "<div class=\"dropdown show\"><button class=\"btn btn-primary dropdown-toggle\" id=\"$id\" role=\"button\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" href=\"#\"><i class=\"flag\"></i> Dropdown</button><div class=\"dropdown-menu show\" aria-labelledby=\"$id\" x-placement=\"bottom-start\" aria-expanded=\"true\" style=\"position: ;\"><div class=\"dropdown-divider\"></div></div></div>",
element?.innerHTML,
"Should render correct drop down"
)
@@ -105,11 +106,11 @@ class DropDownSpec : DomSpec {
val root = Root("test", fixed = true)
val dd = DropDown("Dropdown", listOf("abc" to DD.DISABLED.option), "flag")
root.add(dd)
- dd.toggle()
+ dd.list.getElementJQueryD()?.dropdown("toggle")
val element = document.getElementById("test")
val id = dd.buttonId()
assertEqualsHtml(
- "<div class=\"dropdown open\"><button class=\"dropdown btn btn-default\" id=\"$id\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" role=\"button\" href=\"#\"><span class=\"glyphicon glyphicon-flag\"></span> Dropdown</button><ul class=\"dropdown-menu\" aria-labelledby=\"$id\" aria-expanded=\"true\"><li class=\"disabled\"><a>abc</a></li></ul></div>",
+ "<div class=\"dropdown show\"><button class=\"btn btn-primary dropdown-toggle\" id=\"$id\" role=\"button\" type=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" href=\"#\"><i class=\"flag\"></i> Dropdown</button><div class=\"dropdown-menu show\" aria-labelledby=\"$id\" x-placement=\"bottom-start\" aria-expanded=\"true\" style=\"position: ;\"><a class=\"dropdown-item disabled\" tabindex=\"-1\" aria-disabled=\"true\" href=\"javascript:void(0)\">abc</a></div></div>",
element?.innerHTML,
"Should render correct drop down"
)
@@ -122,10 +123,10 @@ class DropDownSpec : DomSpec {
val root = Root("test", fixed = true)
val dd = DropDown("Dropdown", listOf("abc" to "#!/x", "def" to "#!/y"), "flag")
root.add(dd)
- val visible = dd.getElementJQuery()?.hasClass("open") ?: false
+ val visible = dd.getElementJQuery()?.hasClass("show") ?: false
assertTrue("Dropdown menu is not visible before toggle") { !visible }
- dd.toggle()
- val visible2 = dd.getElementJQuery()?.hasClass("open") ?: false
+ dd.list.getElementJQueryD()?.dropdown("toggle")
+ val visible2 = dd.getElementJQuery()?.hasClass("show") ?: false
assertTrue("Dropdown menu is visible after toggle") { visible2 }
}
}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/HeaderSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/HeaderSpec.kt
new file mode 100644
index 00000000..25ca7a7d
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/HeaderSpec.kt
@@ -0,0 +1,46 @@
+/*
+ * 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 test.pl.treksoft.kvision.dropdown
+
+import pl.treksoft.kvision.dropdown.Header
+import pl.treksoft.kvision.panel.Root
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class HeaderSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val h = Header("Test")
+ root.add(h)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<h6 class=\"dropdown-header\">Test</h6>",
+ element?.innerHTML,
+ "Should render correct drop down header"
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/SeparatorSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/SeparatorSpec.kt
new file mode 100644
index 00000000..36c22a74
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/dropdown/SeparatorSpec.kt
@@ -0,0 +1,46 @@
+/*
+ * 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 test.pl.treksoft.kvision.dropdown
+
+import pl.treksoft.kvision.dropdown.Separator
+import pl.treksoft.kvision.panel.Root
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class SeparatorSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val s = Separator()
+ root.add(s)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"dropdown-divider\"></div>",
+ element?.innerHTML,
+ "Should render correct drop down separator"
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/modal/AlertSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/modal/AlertSpec.kt
index c3d17de9..48a8b5a0 100644
--- a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/modal/AlertSpec.kt
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/modal/AlertSpec.kt
@@ -37,22 +37,22 @@ class AlertSpec : DomSpec {
fun render() {
run {
Root("test", fixed = true)
- Alert.show("Alert caption", "Alert content")
- val alert = document.getElementById("test")?.let { jQuery(it).find(".modal")[0] }
+ Alert.show("Alert caption", "Alert content", animation = false)
+ val alert = document.getElementById("test")?.let { jQuery(it).parent().parent().find(".modal")[0] }
assertNotNull(alert, "Should show alert window")
- val title = document.getElementById("test")?.let { jQuery(it).find(".modal-title").html() }
+ val title = document.getElementById("test")?.let { jQuery(it).parent().parent().find(".modal-title").html() }
assertEquals("Alert caption", title, "Should render alert window with correct caption")
- val body = document.getElementById("test")?.let { jQuery(it).find(".modal-body").html() }
+ val body = document.getElementById("test")?.let { jQuery(it).parent().parent().find(".modal-body").html() }
assertEquals("<div>Alert content</div>", body, "Should render alert window with correct content")
- val footer = document.getElementById("test")?.let { jQuery(it).find(".modal-footer").html() }
+ val footer = document.getElementById("test")?.let { jQuery(it).parent().parent().find(".modal-footer").html() }
assertEqualsHtml(
- "<button class=\"btn btn-primary\" type=\"button\"><span class=\"glyphicon glyphicon-ok\"></span> OK</button>",
+ "<button class=\"btn btn-primary\" type=\"button\"><i class=\"fas fa-check\"></i> OK</button>",
footer,
"Should render alert window with correct footer"
)
- val button = document.getElementById("test")?.let { jQuery(it).find(".modal-footer").find("button") }
+ val button = document.getElementById("test")?.let { jQuery(it).parent().parent().find(".modal-footer").find("button") }
button?.click()
- val alert2 = document.getElementById("test")?.let { jQuery(it).find(".modal")[0] }
+ val alert2 = document.getElementById("test")?.let { jQuery(it).parent().parent().find(".modal")[0] }
assertNull(alert2, "Should hide alert window after clicking OK")
}
}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavFormSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavFormSpec.kt
new file mode 100644
index 00000000..8eb7bd5b
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavFormSpec.kt
@@ -0,0 +1,54 @@
+/*
+ * 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 test.pl.treksoft.kvision.navbar
+
+import pl.treksoft.kvision.navbar.NavForm
+import pl.treksoft.kvision.panel.Root
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class NavFormSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val navf = NavForm()
+ root.add(navf)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<form class=\"form-inline\"></form>",
+ element?.innerHTML,
+ "Should render correct nav form"
+ )
+ navf.rightAlign = true
+ assertEqualsHtml(
+ "<form class=\"form-inline ml-auto\"></form>",
+ element?.innerHTML,
+ "Should render correct right aligned nav form"
+ )
+
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavSpec.kt
new file mode 100644
index 00000000..2e52557f
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavSpec.kt
@@ -0,0 +1,54 @@
+/*
+ * 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 test.pl.treksoft.kvision.navbar
+
+import pl.treksoft.kvision.navbar.Nav
+import pl.treksoft.kvision.panel.Root
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class NavSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val nav = Nav()
+ root.add(nav)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"navbar-nav\"></div>",
+ element?.innerHTML,
+ "Should render correct nav"
+ )
+ nav.rightAlign = true
+ assertEqualsHtml(
+ "<div class=\"navbar-nav ml-auto\"></div>",
+ element?.innerHTML,
+ "Should render correct right aligned nav"
+ )
+
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavbarSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavbarSpec.kt
new file mode 100644
index 00000000..1658e63c
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/navbar/NavbarSpec.kt
@@ -0,0 +1,71 @@
+/*
+ * 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 test.pl.treksoft.kvision.navbar
+
+import pl.treksoft.kvision.html.Link.Companion.link
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag.Companion.tag
+import pl.treksoft.kvision.navbar.Nav
+import pl.treksoft.kvision.navbar.Navbar
+import pl.treksoft.kvision.navbar.NavbarColor
+import pl.treksoft.kvision.navbar.NavbarType
+import pl.treksoft.kvision.panel.Root
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class NavbarSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val navbar = Navbar("TEST", NavbarType.FIXEDTOP)
+ root.add(navbar)
+ val element = document.getElementById("test")
+ val id = navbar.container.id
+ assertEqualsHtml(
+ "<nav class=\"navbar fixed-top navbar-expand-lg navbar-light bg-light\"><a class=\"navbar-brand\" href=\"#\">TEST</a><button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#$id\" aria-controls=\"$id\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"$id\"></div></nav>",
+ element?.innerHTML,
+ "Should render correct navbar"
+ )
+ navbar.nColor = NavbarColor.DARK
+ assertEqualsHtml(
+ "<nav class=\"navbar fixed-top navbar-expand-lg bg-light navbar-dark\"><a class=\"navbar-brand\" href=\"#\">TEST</a><button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#$id\" aria-controls=\"$id\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"$id\"></div></nav>",
+ element?.innerHTML,
+ "Should render correct dark navbar"
+ )
+ navbar.add(Nav {
+ tag(TAG.LI) {
+ link("Test", "#!/test")
+ }
+ })
+ assertEqualsHtml(
+ "<nav class=\"navbar fixed-top navbar-expand-lg bg-light navbar-dark\"><a class=\"navbar-brand\" href=\"#\">TEST</a><button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#$id\" aria-controls=\"$id\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"$id\"><div class=\"navbar-nav\"><li><a href=\"#!/test\">Test</a></li></div></div></nav>",
+ element?.innerHTML,
+ "Should render correct navbar with nav link"
+ )
+
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/ResponsiveGridPanelSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/ResponsiveGridPanelSpec.kt
new file mode 100644
index 00000000..1ebac202
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/ResponsiveGridPanelSpec.kt
@@ -0,0 +1,50 @@
+/*
+ * 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 test.pl.treksoft.kvision.panel
+
+import pl.treksoft.kvision.html.Span
+import pl.treksoft.kvision.panel.ResponsiveGridPanel
+import pl.treksoft.kvision.panel.Root
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class ResponsiveGridPanelSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val rgPanel = ResponsiveGridPanel()
+ root.add(rgPanel)
+ rgPanel.add(Span("abc"), 1, 1)
+ rgPanel.add(Span("def"), 2, 2)
+ rgPanel.add(Span("ghi"), 3, 3)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"container-fluid\"><div class=\"row\"><div class=\"col-md-4\"><span>abc</span></div><div class=\"col-md-4\"></div><div class=\"col-md-4\"></div></div><div class=\"row\"><div class=\"col-md-4\"></div><div class=\"col-md-4\"><span>def</span></div><div class=\"col-md-4\"></div></div><div class=\"row\"><div class=\"col-md-4\"></div><div class=\"col-md-4\"></div><div class=\"col-md-4\"><span>ghi</span></div></div></div>",
+ element?.innerHTML,
+ "Should render correct responsive grid panel"
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt
new file mode 100644
index 00000000..7a76cde9
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/panel/TabPanelSpec.kt
@@ -0,0 +1,117 @@
+/*
+ * 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 test.pl.treksoft.kvision.panel
+
+import pl.treksoft.jquery.jQuery
+import pl.treksoft.kvision.html.Span
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.panel.TabPanel
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class TabPanelSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val tabs = TabPanel()
+ root.add(tabs)
+ val label1 = Span("abc")
+ val label2 = Span("def")
+ tabs.addTab("ABC", label1)
+ tabs.addTab("DEF", label2)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div><ul class=\"nav nav-tabs\"><li class=\"nav-item\"><a class=\"nav-link active\" href=\"#\">ABC</a></li><li class=\"nav-item\"><a class=\"nav-link\" href=\"#\">DEF</a></li></ul><div><span>abc</span></div></div>",
+ element?.innerHTML,
+ "Should render correct tabs"
+ )
+ }
+ }
+
+ @Test
+ fun setActiveIndex() {
+ run {
+ val root = Root("test", fixed = true)
+ val tabs = TabPanel()
+ root.add(tabs)
+ val label1 = Span("abc")
+ val label2 = Span("def")
+ tabs.addTab("ABC", label1)
+ tabs.addTab("DEF", label2)
+ tabs.activeIndex = 1
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div><ul class=\"nav nav-tabs\"><li class=\"nav-item\"><a class=\"nav-link\" href=\"#\">ABC</a></li><li class=\"nav-item\"><a class=\"nav-link active\" href=\"#\">DEF</a></li></ul><div><span>def</span></div></div>",
+ element?.innerHTML,
+ "Should change selected tab"
+ )
+ }
+ }
+
+ @Test
+ fun removeTab() {
+ run {
+ val root = Root("test", fixed = true)
+ val tabs = TabPanel()
+ root.add(tabs)
+ val label1 = Span("abc")
+ val label2 = Span("def")
+ tabs.addTab("ABC", label1)
+ tabs.addTab("DEF", label2)
+ tabs.activeIndex = 1
+ tabs.removeTab(1)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div><ul class=\"nav nav-tabs\"><li class=\"nav-item\"><a class=\"nav-link active\" href=\"#\">ABC</a></li></ul><div><span>abc</span></div></div>",
+ element?.innerHTML,
+ "Should remove tab"
+ )
+ }
+ }
+
+
+ @Test
+ fun tabClick() {
+ run {
+ val root = Root("test", fixed = true)
+ val tabs = TabPanel()
+ root.add(tabs)
+ val label1 = Span("abc")
+ val label2 = Span("def")
+ tabs.addTab("ABC", label1)
+ tabs.addTab("DEF", label2)
+ tabs.removeTab(0)
+ val label3 = Span("ghi")
+ tabs.addTab("GHI", label3)
+ jQuery("#test a")[1]?.click()
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div><ul class=\"nav nav-tabs\"><li class=\"nav-item\"><a class=\"nav-link\" href=\"#\">DEF</a></li><li class=\"nav-item\"><a class=\"nav-link active\" href=\"#\">GHI</a></li></ul><div><span>ghi</span></div></div>",
+ element?.innerHTML,
+ "Should select correct tab by clicking"
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressBarSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressBarSpec.kt
new file mode 100644
index 00000000..2f044987
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressBarSpec.kt
@@ -0,0 +1,56 @@
+/*
+ * 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 test.pl.treksoft.kvision.progress
+
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.progress.ProgressBar
+import pl.treksoft.kvision.progress.ProgressBarStyle
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class ProgressBarSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val progressBar =
+ ProgressBar(50, style = ProgressBarStyle.SUCCESS, striped = true, content = "Processing ...")
+ root.add(progressBar)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"progress\"><div class=\"progress-bar progress-bar-success progress-bar-striped\" role=\"progressbar\" aria-valuenow=\"50\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 50%;\">Processing ...</div></div>",
+ element?.innerHTML,
+ "Should render correct progress bar"
+ )
+ progressBar.max = 200
+ assertEqualsHtml(
+ "<div class=\"progress\"><div class=\"progress-bar progress-bar-success progress-bar-striped\" role=\"progressbar\" aria-valuenow=\"50\" aria-valuemin=\"0\" aria-valuemax=\"200\" style=\"width: 25%;\">Processing ...</div></div>",
+ element?.innerHTML,
+ "Should render correct progress bar after max value change"
+ )
+
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressIndicatorSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressIndicatorSpec.kt
new file mode 100644
index 00000000..4aa14230
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/progress/ProgressIndicatorSpec.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 test.pl.treksoft.kvision.progress
+
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.progress.ProgressBarStyle
+import pl.treksoft.kvision.progress.ProgressIndicator
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class ProgressIndicatorSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val ind = ProgressIndicator(50, style = ProgressBarStyle.SUCCESS, striped = true)
+ root.add(ind)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"progress-bar progress-bar-success progress-bar-striped\" role=\"progressbar\" aria-valuenow=\"50\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 50%;\"></div>",
+ element?.innerHTML,
+ "Should render correct progress bar indicator"
+ )
+ ind.max = 200
+ assertEqualsHtml(
+ "<div class=\"progress-bar progress-bar-success progress-bar-striped\" role=\"progressbar\" aria-valuenow=\"50\" aria-valuemin=\"0\" aria-valuemax=\"200\" style=\"width: 25%;\"></div>",
+ element?.innerHTML,
+ "Should render correct progress bar indicator after max value change"
+ )
+
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ButtonGroupSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ButtonGroupSpec.kt
new file mode 100644
index 00000000..b3ddbe40
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ButtonGroupSpec.kt
@@ -0,0 +1,56 @@
+/*
+ * 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 test.pl.treksoft.kvision.toolbar
+
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.toolbar.ButtonGroup
+import pl.treksoft.kvision.toolbar.ButtonGroupSize
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class ButtonGroupSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val group = ButtonGroup()
+ root.add(group)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"btn-group\" role=\"group\"></div>",
+ element?.innerHTML,
+ "Should render correct button group"
+ )
+ group.size = ButtonGroupSize.LARGE
+ group.vertical = true
+ assertEqualsHtml(
+ "<div class=\"btn-group-lg btn-group-vertical\" role=\"group\"></div>",
+ element?.innerHTML,
+ "Should render correct button group with large and vertical buttons"
+ )
+
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ToolbarSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ToolbarSpec.kt
new file mode 100644
index 00000000..d41ef05e
--- /dev/null
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/toolbar/ToolbarSpec.kt
@@ -0,0 +1,47 @@
+/*
+ * 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 test.pl.treksoft.kvision.toolbar
+
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.toolbar.Toolbar
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+
+class ToolbarSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test", fixed = true)
+ val toolbar = Toolbar()
+ root.add(toolbar)
+ val element = document.getElementById("test")
+ assertEqualsHtml(
+ "<div class=\"btn-toolbar\" role=\"toolbar\"></div>",
+ element?.innerHTML,
+ "Should render correct toolbar"
+ )
+ }
+ }
+
+}
diff --git a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/window/WindowSpec.kt b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/window/WindowSpec.kt
index c79b9d32..a65ff7c3 100644
--- a/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/window/WindowSpec.kt
+++ b/kvision-modules/kvision-bootstrap/src/test/kotlin/test/pl/treksoft/kvision/window/WindowSpec.kt
@@ -35,18 +35,13 @@ class WindowSpec : DomSpec {
val root = Root("test", fixed = true)
val window = Window("Window title", isResizable = false)
root.add(window)
+ window.show()
val id = window.id
val element = document.getElementById("test")
assertEqualsHtml(
- "<div class=\"modal-content kv-window\" id=\"$id\" style=\"width: auto; position: absolute; z-index: 901; overflow: hidden;\"><div class=\"modal-header\"><h4 class=\"modal-title\">Window title</h4></div><div style=\"height: auto; overflow: auto;\"></div></div>",
+ "<div class=\"modal-content kv-window\" id=\"$id\" style=\"width: auto; position: absolute; z-index: 901; overflow: hidden;\"><div class=\"modal-header\"><h5 class=\"modal-title\">Window title</h5><div class=\"kv-window-icons-container\"></div></div><div style=\"height: auto; overflow: auto;\"></div></div>",
element?.innerHTML,
- "Should render floating window without resizable handler"
- )
- window.isResizable = true
- assertEqualsHtml(
- "<div class=\"modal-content kv-window\" id=\"$id\" style=\"width: auto; position: absolute; z-index: 901; overflow: hidden; resize: both;\"><div class=\"modal-header\"><h4 class=\"modal-title\">Window title</h4></div><div style=\"height: auto; overflow: auto; margin-bottom: 11px;\"></div><object style=\"position: absolute; top: 0; left: 0; height: 100%; width: 100%; pointer-events: none; z-index: -1; opacity: 0;\" class=\"resize-sensor\" tabindex=\"-1\" type=\"text/html\" data=\"about:blank\"></object></div>",
- element?.innerHTML,
- "Should render floating window with resizable handler"
+ "Should render floating window"
)
}
}
diff --git a/kvision-modules/kvision-chart/build.gradle b/kvision-modules/kvision-chart/build.gradle
index d90de6ce..6733a4ab 100644
--- a/kvision-modules/kvision-chart/build.gradle
+++ b/kvision-modules/kvision-chart/build.gradle
@@ -4,10 +4,6 @@ kotlinFrontend {
npm {
dependency("chart.js", "2.7.3")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
}
}
diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt
index 73a0f2b9..b572d896 100644
--- a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt
+++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt
@@ -26,13 +26,11 @@ internal val kVManagerChartInit = KVManagerChart.init()
/**
* Internal singleton object which initializes and configures KVision Chart module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerChart {
- fun init() {}
- private val chart = try {
+ init {
require("chart.js/dist/Chart.bundle.min.js")
- } catch (e: Throwable) {
}
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-chart/webpack.config.d/css.js b/kvision-modules/kvision-chart/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-chart/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-cordova/webpack.config.d/css.js b/kvision-modules/kvision-cordova/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-cordova/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-datacontainer/build.gradle b/kvision-modules/kvision-datacontainer/build.gradle
index a10a048f..6779c309 100644
--- a/kvision-modules/kvision-datacontainer/build.gradle
+++ b/kvision-modules/kvision-datacontainer/build.gradle
@@ -1,12 +1 @@
apply from: "../shared.gradle"
-
-kotlinFrontend {
-
- npm {
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-datacontainer/webpack.config.d/css.js b/kvision-modules/kvision-datacontainer/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-datacontainer/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-datetime/build.gradle b/kvision-modules/kvision-datetime/build.gradle
deleted file mode 100644
index bbd4bb79..00000000
--- a/kvision-modules/kvision-datetime/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-apply from: "../shared.gradle"
-
-kotlinFrontend {
-
- npm {
- dependency("bootstrap-datetime-picker", "2.4.4")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt b/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt
deleted file mode 100644
index 4cc71c8b..00000000
--- a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/KVManagerDatetime.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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
-
-internal val kVManagerDatetimeInit = KVManagerDatetime.init()
-
-/**
- * Internal singleton object which initializes and configures KVision datetime module.
- */
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
-internal object KVManagerDatetime {
- fun init() {}
-
- private val bootstrapDateTimePickerCss = try {
- require("bootstrap-datetime-picker/css/bootstrap-datetimepicker.min.css")
- } catch (e: Throwable) {
- }
- private val bootstrapDateTimePicker = try {
- require("bootstrap-datetime-picker/js/bootstrap-datetimepicker.min.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ar.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.az.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bg.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bn.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ca.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.cs.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.da.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.de.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ee.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.el.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.es.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fi.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fr.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.he.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hr.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hu.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hy.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.id.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.is.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.it.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ja.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ko.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lt.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lv.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nl.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.no.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pl.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ro.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ru.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sk.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sl.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sv.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.th.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.tr.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ua.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.uk.js")
- require("./js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh.js")
- } catch (e: Throwable) {
- }
-
-}
diff --git a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt b/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
deleted file mode 100644
index a375ef35..00000000
--- a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * 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.form.time
-
-import com.github.snabbdom.VNode
-import pl.treksoft.kvision.core.Container
-import pl.treksoft.kvision.core.StringBoolPair
-import pl.treksoft.kvision.core.StringPair
-import pl.treksoft.kvision.core.Widget
-import pl.treksoft.kvision.form.FormInput
-import pl.treksoft.kvision.form.InputSize
-import pl.treksoft.kvision.i18n.I18n
-import pl.treksoft.kvision.types.toDateF
-import pl.treksoft.kvision.types.toStringF
-import pl.treksoft.kvision.utils.obj
-import kotlin.js.Date
-
-internal const val DEFAULT_MINUTE_STEP = 5
-internal const val MAX_VIEW = 4
-
-/**
- * Basic date/time chooser component.
- *
- * @constructor
- * @param value date/time input value
- * @param format date/time format (default YYYY-MM-DD HH:mm)
- * @param classes a set of CSS class names
- */
-@Suppress("TooManyFunctions")
-open class DateTimeInput(
- value: Date? = null, format: String = "YYYY-MM-DD HH:mm",
- classes: Set<String> = setOf()
-) : Widget(classes + "form-control"), FormInput {
-
- private var initialized = false
-
- init {
- this.setInternalEventListener<DateTimeInput> {
- change = {
- self.changeValue()
- }
- }
- }
-
- /**
- * Date/time input value.
- */
- var value by refreshOnUpdate(value) { refreshState() }
- /**
- * Date/time format.
- */
- var format by refreshOnUpdate(format) { refreshDatePicker() }
- /**
- * The placeholder for the date/time input.
- */
- var placeholder: String? by refreshOnUpdate()
- /**
- * The name attribute of the generated HTML input element.
- */
- override var name: String? by refreshOnUpdate()
- /**
- * Determines if the field is disabled.
- */
- override var disabled by refreshOnUpdate(false) { refresh(); checkDisabled() }
- /**
- * Determines if the text input is automatically focused.
- */
- var autofocus: Boolean? by refreshOnUpdate()
- /**
- * Determines if the date/time input is read-only.
- */
- var readonly: Boolean? by refreshOnUpdate()
- /**
- * The size of the input.
- */
- override var size: InputSize? by refreshOnUpdate()
- /**
- * Day of the week start. 0 (Sunday) to 6 (Saturday).
- */
- var weekStart by refreshOnUpdate(0) { refreshDatePicker() }
- /**
- * Days of the week that should be disabled. Multiple values should be comma separated.
- */
- var daysOfWeekDisabled by refreshOnUpdate(arrayOf<Int>()) { refreshDatePicker() }
- /**
- * Determines if *Clear* button should be visible.
- */
- var clearBtn by refreshOnUpdate(true) { refreshDatePicker() }
- /**
- * Determines if *Today* button should be visible.
- */
- var todayBtn by refreshOnUpdate(false) { refreshDatePicker() }
- /**
- * Determines if the current day should be highlighted.
- */
- var todayHighlight by refreshOnUpdate(false) { refreshDatePicker() }
- /**
- * The increment used to build the hour view.
- */
- var minuteStep by refreshOnUpdate(DEFAULT_MINUTE_STEP) { refreshDatePicker() }
- /**
- * Determines if meridian views are visible in day and hour views.
- */
- var showMeridian by refreshOnUpdate(false) { refreshDatePicker() }
-
- override fun render(): VNode {
- return render("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 translate(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 "disabled")
- value?.let {
- sn.add("value" to it.toStringF(format))
- }
- }
- return sn
- }
-
- private fun checkDisabled() {
- if (disabled) {
- if (initialized) {
- getElementJQueryD()?.datetimepicker("remove")
- initialized = false
- }
- } else {
- if (!initialized) {
- this.initDateTimePicker()
- this.initEventHandlers()
- this.refreshState()
- initialized = true
- }
- }
- }
-
- @Suppress("UnsafeCastFromDynamic")
- protected open fun refreshState() {
- value?.let {
- getElementJQueryD()?.datetimepicker("update", it)
- } ?: run {
- getElementJQueryD()?.`val`(null)
- 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 date/time chooser popup.
- */
- open fun showPopup() {
- if (initialized) getElementJQueryD()?.datetimepicker("show")
- }
-
- /**
- * Hides date/time chooser popup.
- */
- open fun hidePopup() {
- if (initialized) getElementJQueryD()?.datetimepicker("hide")
- }
-
- @Suppress("UnsafeCastFromDynamic")
- override fun afterInsert(node: VNode) {
- if (!this.disabled) {
- this.initDateTimePicker()
- this.initEventHandlers()
- this.refreshState()
- initialized = true
- }
- }
-
- override fun afterDestroy() {
- if (initialized) {
- getElementJQueryD()?.datetimepicker("remove")
- initialized = false
- }
- }
-
- 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
- val language = I18n.language
- 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
- this.language = language
- })
- }
-
- private fun initEventHandlers() {
- this.getElementJQuery()?.on("changeDate") { e, _ ->
- @Suppress("UnsafeCastFromDynamic")
- this.dispatchEvent("change", obj { detail = e })
- }
- this.getElementJQuery()?.on("show") { e, _ ->
- @Suppress("UnsafeCastFromDynamic")
- this.dispatchEvent("showBsDateTime", obj { detail = e })
- }
- this.getElementJQuery()?.on("hide") { e, _ ->
- @Suppress("UnsafeCastFromDynamic")
- this.dispatchEvent("hideBsDateTime", obj { detail = e })
- }
- }
-
- /**
- * Get value of date/time input control as String
- * @return value as a String
- */
- fun getValueAsString(): String? {
- return value?.toStringF(format)
- }
-
- /**
- * Makes the input element focused.
- */
- override fun focus() {
- getElementJQuery()?.focus()
- }
-
- /**
- * Makes the input element blur.
- */
- override fun blur() {
- getElementJQuery()?.blur()
- }
-
- 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")
- }
-
- /**
- * DSL builder extension function.
- *
- * It takes the same parameters as the constructor of the built component.
- */
- fun Container.dateTimeInput(
- value: Date? = null, format: String = "YYYY-MM-DD HH:mm", classes: Set<String> = setOf(),
- init: (DateTimeInput.() -> Unit)? = null
- ): DateTimeInput {
- val dateTimeInput = DateTimeInput(value, format, classes).apply { init?.invoke(this) }
- this.add(dateTimeInput)
- return dateTimeInput
- }
- }
-}
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ar.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ar.js
deleted file mode 100644
index a43b4739..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ar.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
-* Arabic translation for bootstrap-datetimepicker
-* Ala' Mohammad <amohammad@birzeit.ecu>
-*/
-;(function($){
- $.fn.datetimepicker.dates['ar'] = {
- days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
- daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
- daysMin: ["أح", "إث", "ث", "أر", "خ", "ج", "س", "أح"],
- months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
- monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
- today: "هذا اليوم",
- clear: "x",
- suffix: [],
- meridiem: [],
- rtl: true
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.az.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.az.js
deleted file mode 100644
index c840d6f0..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.az.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Azerbaijani translation for bootstrap-datetimepicker
- * Konstantin Kaluzhnikov <k.kaluzhnikov@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['az'] = {
- days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə", "Bazar"],
- daysShort: ["B", "Be", "Ça", "Ç", "Ca", "C", "Ş", "B"],
- daysMin: ["B", "Be", "Ça", "Ç", "Ca", "C", "Ş", "B"],
- months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"],
- monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"],
- today: "Bugün",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bg.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bg.js
deleted file mode 100644
index 3bc7e273..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bg.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Bulgarian translation for bootstrap-datetimepicker
- * Apostol Apostolov <apostol.s.apostolov@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['bg'] = {
- days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"],
- daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб", "Нед"],
- daysMin: ["Н", "П", "В", "С", "Ч", "П", "С", "Н"],
- months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"],
- monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"],
- today: "днес",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bn.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bn.js
deleted file mode 100644
index b46bd54f..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.bn.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Bangla(Bangladesh) translation for bootstrap-datetimepicker
- * Mahbub Rabbani <mahbub [dot] rucse [at] gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['bn'] = {
- days: ["রবিবার", "সোমবার", "মঙ্গলবার", "বুধবার", "বৃহষ্পতিবার", "শুক্রবার", "শনিবার", "রবিবার"],
- daysShort: ["রবি", "সোম", "মঙ্গল", "বুধ", " বৃহঃ", "শুক্র", "শনি", "রবি"],
- daysMin: ["রবি", "সোম", "মঙ্গ", "বুধ", "বৃহ", "শুক্র", "শনি", "রবি"],
- months: ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'অগাস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর' ],
- monthsShort: ['জানু', 'ফেব্রু', 'মার্চ', 'এপ্রি', 'মে', 'জুন', 'জুলা', 'অগা', 'সেপ্টে', 'অক্টো', 'নভে', 'ডিসে' ],
- today: "আজ",
- clear: "x",
- suffix: [],
- meridiem: ['পূর্বাহ্ণ', 'অপরাহ্ন']
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ca.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ca.js
deleted file mode 100644
index d3137a2d..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ca.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Catalan translation for bootstrap-datetimepicker
- * J. Garcia <jogaco.en@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['ca'] = {
- days: ["Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte", "Diumenge"],
- daysShort: ["Diu", "Dil", "Dmt", "Dmc", "Dij", "Div", "Dis", "Diu"],
- daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds", "dg"],
- months: ["Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"],
- monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"],
- today: "Avui",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.cs.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.cs.js
deleted file mode 100644
index 318cd5cf..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.cs.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Czech translation for bootstrap-datetimepicker
- * Matěj Koubík <matej@koubik.name>
- * Fixes by Michal Remiš <michal.remis@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['cs'] = {
- days: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"],
- daysShort: ["Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob", "Ned"],
- daysMin: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So", "Ne"],
- months: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"],
- monthsShort: ["Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čnc", "Srp", "Zář", "Říj", "Lis", "Pro"],
- today: "Dnes",
- suffix: [],
- clear: "x",
- meridiem: [],
- weekStart: 1,
- format: "dd.mm.yyyy"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.da.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.da.js
deleted file mode 100644
index 30d9a34a..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.da.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Danish translation for bootstrap-datetimepicker
- * Christian Pedersen <http://github.com/chripede>
- */
-;(function($){
- $.fn.datetimepicker.dates['da'] = {
- days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"],
- daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"],
- daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"],
- months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
- today: "I Dag",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.de.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.de.js
deleted file mode 100644
index 52a19060..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.de.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * German translation for bootstrap-datetimepicker
- * Sam Zurcher <sam@orelias.ch>
- */
-;(function($){
- $.fn.datetimepicker.dates['de'] = {
- days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"],
- daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"],
- daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
- months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
- monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
- today: "Heute",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1,
- format: "dd.mm.yyyy"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ee.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ee.js
deleted file mode 100644
index 882378f3..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ee.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Estonian translation for bootstrap-datetimepicker
- * Rene Korss <http://rene.korss.ee>
- */
-;(function($){
- $.fn.datetimepicker.dates['ee'] = {
- days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev", "Pühapäev"],
- daysShort: ["P", "E", "T", "K", "N", "R", "L", "P"],
- daysMin: ["P", "E", "T", "K", "N", "R", "L", "P"],
- months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"],
- monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"],
- today: "Täna",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1,
- format: "dd.mm.yyyy hh:ii"
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.el.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.el.js
deleted file mode 100644
index cbbdc9a7..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.el.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
-* Greek translation for bootstrap-datetimepicker
-*/
-;(function($){
- $.fn.datetimepicker.dates['el'] = {
- days: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο", "Κυριακή"],
- daysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", "Κυρ"],
- daysMin: ["Κυ", "Δε", "Τρ", "Τε", "Πε", "Πα", "Σα", "Κυ"],
- months: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"],
- monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"],
- today: "Σήμερα",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.es.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.es.js
deleted file mode 100644
index bbf3c207..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.es.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Spanish translation for bootstrap-datetimepicker
- * Bruno Bonamin <bruno.bonamin@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['es'] = {
- days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"],
- daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"],
- daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"],
- months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
- monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
- today: "Hoy",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fi.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fi.js
deleted file mode 100644
index 95eb4a8d..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fi.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Finnish translation for bootstrap-datetimepicker
- * Jaakko Salonen <https://github.com/jsalonen>
- */
-;(function($){
- $.fn.datetimepicker.dates['fi'] = {
- days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"],
- daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"],
- daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"],
- months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
- monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"],
- today: "tänään",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fr.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fr.js
deleted file mode 100644
index f9194cbd..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.fr.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * French translation for bootstrap-datetimepicker
- * Nico Mollet <nico.mollet@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['fr'] = {
- days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"],
- daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"],
- daysMin: ["D", "L", "Ma", "Me", "J", "V", "S", "D"],
- months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
- monthsShort: ["Jan", "Fev", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"],
- today: "Aujourd'hui",
- suffix: [],
- clear: "x",
- meridiem: ["am", "pm"],
- weekStart: 1,
- format: "dd/mm/yyyy hh:ii"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.he.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.he.js
deleted file mode 100644
index 1060a4a7..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.he.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Hebrew translation for bootstrap-datetimepicker
- * Sagie Maoz <sagie@maoz.info>
- */
-;(function($){
- $.fn.datetimepicker.dates['he'] = {
- days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"],
- daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
- daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
- months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
- monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"],
- today: "היום",
- clear: "x",
- suffix: [],
- meridiem: [],
- rtl: true
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hr.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hr.js
deleted file mode 100644
index f85540fa..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hr.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * Croatian localisation
- */
-;(function($){
- $.fn.datetimepicker.dates['hr'] = {
- days: ["Nedjelja", "Ponedjelja", "Utorak", "Srijeda", "Četrtak", "Petak", "Subota", "Nedjelja"],
- daysShort: ["Ned", "Pon", "Uto", "Srr", "Čet", "Pet", "Sub", "Ned"],
- daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su", "Ne"],
- months: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"],
- monthsShort: ["Sije", "Velj", "Ožu", "Tra", "Svi", "Lip", "Jul", "Kol", "Ruj", "Lis", "Stu", "Pro"],
- today: "Danas",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hu.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hu.js
deleted file mode 100644
index 5de9fe9e..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hu.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Hungarian translation for bootstrap-datetimepicker
- * darevish <http://github.com/darevish>
- */
-;(function($){
- $.fn.datetimepicker.dates['hu'] = {
- days: ["Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap"],
- daysShort: ["Vas", "Hét", "Ked", "Sze", "Csü", "Pén", "Szo", "Vas"],
- daysMin: ["V", "H", "K", "Sze", "Cs", "P", "Szo", "V"],
- months: ["Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"],
- monthsShort: ["Jan", "Feb", "Már", "Ápr", "Máj", "Jún", "Júl", "Aug", "Sze", "Okt", "Nov", "Dec"],
- today: "Ma",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hy.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hy.js
deleted file mode 100644
index cedee4db..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.hy.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Armenian translation for bootstrap-datepicker
- * Hayk Chamyan <hamshen@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['hy'] = {
- days: ["Կիրակի", "Երկուշաբթի", "Երեքշաբթի", "Չորեքշաբթի", "Հինգշաբթի", "Ուրբաթ", "Շաբաթ", "Կիրակի"],
- daysShort: ["Կիր", "Երկ", "Երք", "Չոր", "Հնգ", "Ուր", "Շաբ", "Կիր"],
- daysMin: ["Կի", "Եկ", "Եք", "Չո", "Հի", "Ու", "Շա", "Կի"],
- months: ["Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր"],
- monthsShort: ["Հնվ", "Փետ", "Մար", "Ապր", "Մայ", "Հուն", "Հուլ", "Օգս", "Սեպ", "Հոկ", "Նոյ", "Դեկ"],
- today: "Այսօր",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.id.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.id.js
deleted file mode 100644
index feef4a3b..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.id.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Bahasa translation for bootstrap-datetimepicker
- * Azwar Akbar <azwar.akbar@gmail.com>
- * Addtional by Yulian Sutopo <yuliansutopo@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['id'] = {
- days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"],
- daysShort: ["Mng", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mng"],
- daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"],
- months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"],
- today: "Hari Ini",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1,
- format: "dd/mm/yyyy hh:ii:ss"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.is.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.is.js
deleted file mode 100644
index 9944c6d7..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.is.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Icelandic translation for bootstrap-datetimepicker
- * Hinrik Örn Sigurðsson <hinrik.sig@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['is'] = {
- days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur", "Sunnudagur"],
- daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau", "Sun"],
- daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La", "Su"],
- months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ágú", "Sep", "Okt", "Nóv", "Des"],
- today: "Í Dag",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.it.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.it.js
deleted file mode 100644
index c00a0499..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.it.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Italian translation for bootstrap-datetimepicker
- * Enrico Rubboli <rubboli@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['it'] = {
- days: ["Domenica", "Lunedi", "Martedi", "Mercoledi", "Giovedi", "Venerdi", "Sabato", "Domenica"],
- daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"],
- daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"],
- months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
- monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
- today: "Oggi",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1,
- format: "dd/mm/yyyy hh:ii:ss"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ja.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ja.js
deleted file mode 100644
index 3a2d3b9b..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ja.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Japanese translation for bootstrap-datetimepicker
- * Norio Suzuki <https://github.com/suzuki/>
- */
-;(function($){
- $.fn.datetimepicker.dates['ja'] = {
- days: ["日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜", "日曜"],
- daysShort: ["日", "月", "火", "水", "木", "金", "土", "日"],
- daysMin: ["日", "月", "火", "水", "木", "金", "土", "日"],
- months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
- monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
- today: "今日",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ka.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ka.js
deleted file mode 100644
index d4595eff..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ka.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Georgian translation for bootstrap-datetimepicker
- * Zura Jijavadze <mailzura@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['ka'] = {
- days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი", "კვირა"],
- daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ", "კვი"],
- daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა", "კვ"],
- months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომბერი", "ნოემბერი", "დეკემბერი"],
- monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"],
- today: "დღეს",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ko.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ko.js
deleted file mode 100644
index adeb6cb6..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ko.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Korean translation for bootstrap-datetimepicker
- * Gu Youn <http://github.com/guyoun>
- * Baekjoon Choi <http://github.com/Baekjoon>
- */
-;(function($){
- $.fn.datetimepicker.dates['ko'] = {
- days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"],
- daysShort: ["일", "월", "화", "수", "목", "금", "토", "일"],
- daysMin: ["일", "월", "화", "수", "목", "금", "토", "일"],
- months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
- monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
- suffix: [],
- meridiem: ["오전", "오후"],
- today: "오늘",
- clear: "x"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lt.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lt.js
deleted file mode 100644
index 917243c4..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lt.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Lithuanian translation for bootstrap-datetimepicker
- * Šarūnas Gliebus <ssharunas@yahoo.co.uk>
- */
-
-;(function($){
- $.fn.datetimepicker.dates['lt'] = {
- days: ["Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis", "Sekmadienis"],
- daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Š", "S"],
- daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Št", "Sk"],
- months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis"],
- monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"],
- today: "Šiandien",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lv.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lv.js
deleted file mode 100644
index f9b3c774..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.lv.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Latvian translation for bootstrap-datetimepicker
- * Artis Avotins <artis@apit.lv>
- */
-
-;(function($){
- $.fn.datetimepicker.dates['lv'] = {
- days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena", "Svētdiena"],
- daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S", "Sv"],
- daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "St", "Sv"],
- months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec."],
- today: "Šodien",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ms.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ms.js
deleted file mode 100644
index 26a2cc0e..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ms.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Malay translation for bootstrap-datetimepicker
- * Ateman Faiz <noorulfaiz@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['ms'] = {
- days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu", "Ahad"],
- daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab", "Aha"],
- daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa", "Ah"],
- months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"],
- today: "Hari Ini",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nb.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nb.js
deleted file mode 100644
index a2fd01a6..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nb.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Norwegian (bokmål) translation for bootstrap-datetimepicker
- * Fredrik Sundmyhr <http://github.com/fsundmyhr>
- */
-;(function($){
- $.fn.datetimepicker.dates['nb'] = {
- days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"],
- daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"],
- daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"],
- months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"],
- today: "I Dag",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nl.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nl.js
deleted file mode 100644
index a28fa031..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.nl.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Dutch translation for bootstrap-datetimepicker
- * Reinier Goltstein <mrgoltstein@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['nl'] = {
- days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"],
- daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"],
- daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"],
- months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"],
- monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
- today: "Vandaag",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.no.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.no.js
deleted file mode 100644
index 36e33a0b..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.no.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Norwegian translation for bootstrap-datetimepicker
- * Rune Warhuus <rune@dinkdonkd.no>
- */
-;(function($){
- $.fn.datetimepicker.dates['no'] = {
- days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"],
- daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"],
- daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"],
- months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"],
- today: "I Dag",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pl.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pl.js
deleted file mode 100644
index 12fc7422..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pl.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Polish translation for bootstrap-datetimepicker
- * Robert <rtpm@gazeta.pl>
- */
-;(function($){
-$.fn.datetimepicker.dates['pl'] = {
- days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota", "Niedziela"],
- daysShort: ["Nie", "Pn", "Wt", "Śr", "Czw", "Pt", "So", "Nie"],
- daysMin: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So", "N"],
- months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
- monthsShort: ["Sty", "Lu", "Mar", "Kw", "Maj", "Cze", "Lip", "Sie", "Wrz", "Pa", "Lis", "Gru"],
- today: "Dzisiaj",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1
-};
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt-BR.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt-BR.js
deleted file mode 100644
index 1d307416..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt-BR.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Brazilian translation for bootstrap-datetimepicker
- * Cauan Cabral <cauan@radig.com.br>
- */
-;(function($){
- $.fn.datetimepicker.dates['pt-BR'] = {
- format: 'dd/mm/yyyy',
- days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"],
- daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"],
- daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"],
- months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
- monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
- today: "Hoje",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt.js
deleted file mode 100644
index 166034ef..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.pt.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Portuguese translation for bootstrap-datetimepicker
- * Original code: Cauan Cabral <cauan@radig.com.br>
- * Tiago Melo <tiago.blackcode@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['pt'] = {
- days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"],
- daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"],
- daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"],
- months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
- monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
- suffix: [],
- meridiem: [],
- today: "Hoje",
- clear: "x"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ro.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ro.js
deleted file mode 100644
index a7569c6f..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ro.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Romanian translation for bootstrap-datetimepicker
- * Cristian Vasile <cristi.mie@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['ro'] = {
- days: ["Duminică", "Luni", "Marţi", "Miercuri", "Joi", "Vineri", "Sâmbătă", "Duminică"],
- daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"],
- daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ", "Du"],
- months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"],
- monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"],
- today: "Astăzi",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs-latin.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs-latin.js
deleted file mode 100644
index 57c819f9..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs-latin.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Serbian latin translation for bootstrap-datetimepicker
- * Bojan Milosavlević <milboj@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['rs'] = {
- days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota", "Nedelja"],
- daysShort: ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub", "Ned"],
- daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su", "N"],
- months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
- today: "Danas",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs.js
deleted file mode 100644
index 3e9db3e6..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.rs.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Serbian cyrillic translation for bootstrap-datetimepicker
- * Bojan Milosavlević <milboj@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['rs'] = {
- days: ["Недеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота", "Недеља"],
- daysShort: ["Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб", "Нед"],
- daysMin: ["Н", "По", "У", "Ср", "Ч", "Пе", "Су", "Н"],
- months: ["Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"],
- monthsShort: ["Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец"],
- today: "Данас",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ru.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ru.js
deleted file mode 100644
index 20caf251..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ru.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Russian translation for bootstrap-datetimepicker
- * Victor Taranenko <darwin@snowdale.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['ru'] = {
- days: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"],
- daysShort: ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Вск"],
- daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"],
- months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
- monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"],
- today: "Сегодня",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sk.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sk.js
deleted file mode 100644
index acf1495a..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sk.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Slovak translation for bootstrap-datetimepicker
- * Marek Lichtner <marek@licht.sk>
- * Fixes by Michal Remiš <michal.remis@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates["sk"] = {
- days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota", "Nedeľa"],
- daysShort: ["Ned", "Pon", "Uto", "Str", "Štv", "Pia", "Sob", "Ned"],
- daysMin: ["Ne", "Po", "Ut", "St", "Št", "Pi", "So", "Ne"],
- months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"],
- today: "Dnes",
- clear: "x",
- suffix: [],
- meridiem: [],
- weekStart: 1,
- format: "dd.mm.yyyy"
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sl.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sl.js
deleted file mode 100644
index a7e58bdf..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sl.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Slovene translation for bootstrap-datetimepicker
- * Gregor Rudolf <gregor.rudolf@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['sl'] = {
- days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota", "Nedelja"],
- daysShort: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob", "Ned"],
- daysMin: ["Ne", "Po", "To", "Sr", "Če", "Pe", "So", "Ne"],
- months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
- today: "Danes",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sv.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sv.js
deleted file mode 100644
index 050125ad..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sv.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Swedish translation for bootstrap-datetimepicker
- * Patrik Ragnarsson <patrik@starkast.net>
- */
-;(function($){
- $.fn.datetimepicker.dates['sv'] = {
- days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"],
- daysShort: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör", "Sön"],
- daysMin: ["Sö", "Må", "Ti", "On", "To", "Fr", "Lö", "Sö"],
- months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"],
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
- today: "I Dag",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sw.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sw.js
deleted file mode 100644
index 8cdb4df2..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.sw.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Swahili translation for bootstrap-datetimepicker
- * Edwin Mugendi <https://github.com/edwinmugendi>
- * Source: http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=xnfaqyzcku
- */
-;(function($){
- $.fn.datetimepicker.dates['sw'] = {
- days: ["Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi", "Jumapili"],
- daysShort: ["J2", "J3", "J4", "J5", "Alh", "Ij", "J1", "J2"],
- daysMin: ["2", "3", "4", "5", "A", "I", "1", "2"],
- months: ["Januari", "Februari", "Machi", "Aprili", "Mei", "Juni", "Julai", "Agosti", "Septemba", "Oktoba", "Novemba", "Desemba"],
- monthsShort: ["Jan", "Feb", "Mac", "Apr", "Mei", "Jun", "Jul", "Ago", "Sep", "Okt", "Nov", "Des"],
- today: "Leo",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.th.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.th.js
deleted file mode 100644
index 8adc129a..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.th.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Thai translation for bootstrap-datetimepicker
- * Suchau Jiraprapot <seroz24@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['th'] = {
- days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุกร์", "เสาร์", "อาทิตย์"],
- daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"],
- daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"],
- months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"],
- monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."],
- today: "วันนี้",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.tr.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.tr.js
deleted file mode 100644
index 0130c94c..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.tr.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Turkish translation for bootstrap-datetimepicker
- * Serkan Algur <kaisercrazy_2@hotmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['tr'] = {
- days: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi", "Pazar"],
- daysShort: ["Pz", "Pzt", "Sal", "Çrş", "Prş", "Cu", "Cts", "Pz"],
- daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct", "Pz"],
- months: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"],
- monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"],
- today: "Bugün",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery));
-
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ua.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ua.js
deleted file mode 100644
index 1687a1dc..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.ua.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * Ukrainian translation for bootstrap-datepicker
- * Igor Polynets
- */
-;(function($){
- $.fn.datetimepicker.dates['ua'] = {
- days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четверг", "П'ятниця", "Субота", "Неділя"],
- daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"],
- daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"],
- months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"],
- monthsShort: ["Січ", "Лют", "Бер", "Квт", "Трв", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Грд"],
- today: "Сьогодні",
- clear: "x",
- weekStart: 1
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.uk.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.uk.js
deleted file mode 100644
index 4b3a9e0a..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.uk.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Ukrainian translation for bootstrap-datetimepicker
- * Andrey Vityuk <andrey [dot] vityuk [at] gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['uk'] = {
- days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота", "Неділя"],
- daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"],
- daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"],
- months: ["Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"],
- monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"],
- today: "Сьогодні",
- clear: "x",
- suffix: [],
- meridiem: []
- };
-}(jQuery)); \ No newline at end of file
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh-TW.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh-TW.js
deleted file mode 100644
index f84ba548..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh-TW.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Traditional Chinese translation for bootstrap-datetimepicker
- * Rung-Sheng Jang <daniel@i-trend.co.cc>
- */
-;(function($){
- $.fn.datetimepicker.dates['zh-TW'] = {
- days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
- daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
- daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
- months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
- monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
- today: "今天",
- clear: "x",
- suffix: [],
- meridiem: ["上午", "下午"]
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh.js b/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh.js
deleted file mode 100644
index 66ac5a01..00000000
--- a/kvision-modules/kvision-datetime/src/main/resources/js/locales/bootstrap-datetime-picker/bootstrap-datetimepicker.zh.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Simplified Chinese translation for bootstrap-datetimepicker
- * Yuan Cheung <advanimal@gmail.com>
- */
-;(function($){
- $.fn.datetimepicker.dates['zh'] = {
- days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
- daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
- daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
- months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
- monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
- today: "今天",
- clear: "x",
- suffix: [],
- meridiem: ["上午", "下午"]
- };
-}(jQuery));
diff --git a/kvision-modules/kvision-dialog/build.gradle b/kvision-modules/kvision-dialog/build.gradle
deleted file mode 100644
index 292a228f..00000000
--- a/kvision-modules/kvision-dialog/build.gradle
+++ /dev/null
@@ -1,16 +0,0 @@
-apply from: "../shared.gradle"
-
-dependencies {
- compile "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion"
-}
-
-kotlinFrontend {
-
- npm {
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-fontawesome/build.gradle b/kvision-modules/kvision-fontawesome/build.gradle
new file mode 100644
index 00000000..82dd1894
--- /dev/null
+++ b/kvision-modules/kvision-fontawesome/build.gradle
@@ -0,0 +1,9 @@
+apply from: "../shared.gradle"
+
+kotlinFrontend {
+
+ npm {
+ dependency("@fortawesome/fontawesome-free", "5.11.2")
+ }
+
+}
diff --git a/kvision-modules/kvision-fontawesome/package.json.d/project.info b/kvision-modules/kvision-fontawesome/package.json.d/project.info
new file mode 100644
index 00000000..0801ee7b
--- /dev/null
+++ b/kvision-modules/kvision-fontawesome/package.json.d/project.info
@@ -0,0 +1,3 @@
+{
+ "description": "KVision Font Awesome module"
+}
diff --git a/kvision-modules/kvision-fontawesome/src/main/kotlin/pl/treksoft/kvision/KVManagerFontAwesome.kt b/kvision-modules/kvision-fontawesome/src/main/kotlin/pl/treksoft/kvision/KVManagerFontAwesome.kt
new file mode 100644
index 00000000..f816fb0e
--- /dev/null
+++ b/kvision-modules/kvision-fontawesome/src/main/kotlin/pl/treksoft/kvision/KVManagerFontAwesome.kt
@@ -0,0 +1,35 @@
+/*
+ * 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
+
+internal val kVManagerFontAwesomeInit = KVManagerFontAwesome.init()
+
+/**
+ * Internal singleton object which initializes and configures KVision Font Awesome module.
+ */
+internal object KVManagerFontAwesome {
+ init {
+ require("@fortawesome/fontawesome-free/css/all.min.css")
+ }
+
+ internal fun init() {}
+}
diff --git a/kvision-modules/kvision-fontawesome/webpack.config.d/bootstrap.js b/kvision-modules/kvision-fontawesome/webpack.config.d/bootstrap.js
new file mode 100644
index 00000000..32a7c4d0
--- /dev/null
+++ b/kvision-modules/kvision-fontawesome/webpack.config.d/bootstrap.js
@@ -0,0 +1,4 @@
+config.module.rules.push({test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'});
+config.module.rules.push({test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'});
+config.module.rules.push({test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'});
+config.module.rules.push({test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'});
diff --git a/kvision-modules/kvision-fontawesome/webpack.config.d/css.js b/kvision-modules/kvision-fontawesome/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-fontawesome/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-fontawesome/webpack.config.d/jquery.js b/kvision-modules/kvision-fontawesome/webpack.config.d/jquery.js
new file mode 100644
index 00000000..bf5a1a20
--- /dev/null
+++ b/kvision-modules/kvision-fontawesome/webpack.config.d/jquery.js
@@ -0,0 +1,5 @@
+config.plugins.push(new webpack.ProvidePlugin({
+ $: "jquery",
+ jQuery: "jquery",
+ "window.jQuery": "jquery"
+}));
diff --git a/kvision-modules/kvision-handlebars/build.gradle b/kvision-modules/kvision-handlebars/build.gradle
index a971427e..3864067c 100644
--- a/kvision-modules/kvision-handlebars/build.gradle
+++ b/kvision-modules/kvision-handlebars/build.gradle
@@ -3,12 +3,8 @@ apply from: "../shared.gradle"
kotlinFrontend {
npm {
- dependency("handlebars", "4.1.0")
+ dependency("handlebars", "4.3.1")
dependency("handlebars-loader", "1.7.1")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
}
}
diff --git a/kvision-modules/kvision-handlebars/src/main/kotlin/pl/treksoft/kvision/KVManagerHandlebars.kt b/kvision-modules/kvision-handlebars/src/main/kotlin/pl/treksoft/kvision/KVManagerHandlebars.kt
index b2e52bf7..3bc021bc 100644
--- a/kvision-modules/kvision-handlebars/src/main/kotlin/pl/treksoft/kvision/KVManagerHandlebars.kt
+++ b/kvision-modules/kvision-handlebars/src/main/kotlin/pl/treksoft/kvision/KVManagerHandlebars.kt
@@ -26,13 +26,11 @@ internal val kVManagerHandlebarsInit = KVManagerHandlebars.init()
/**
* Internal singleton object which initializes and configures KVision handlebars module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerHandlebars {
- fun init() {}
- private val handlebars = try {
+ init {
require("handlebars/dist/handlebars.runtime.min.js")
- } catch (e: Throwable) {
}
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-i18n/build.gradle b/kvision-modules/kvision-i18n/build.gradle
index 72870169..a2b6d3f8 100644
--- a/kvision-modules/kvision-i18n/build.gradle
+++ b/kvision-modules/kvision-i18n/build.gradle
@@ -4,10 +4,6 @@ kotlinFrontend {
npm {
dependency("jed", "1.1.1")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
}
}
diff --git a/kvision-modules/kvision-i18n/src/main/kotlin/pl/treksoft/kvision/KVManagerI18n.kt b/kvision-modules/kvision-i18n/src/main/kotlin/pl/treksoft/kvision/KVManagerI18n.kt
index 9e24327b..51f24fa4 100644
--- a/kvision-modules/kvision-i18n/src/main/kotlin/pl/treksoft/kvision/KVManagerI18n.kt
+++ b/kvision-modules/kvision-i18n/src/main/kotlin/pl/treksoft/kvision/KVManagerI18n.kt
@@ -26,13 +26,11 @@ internal val kVManagerI18nInit = KVManagerI18n.init()
/**
* Internal singleton object which initializes and configures KVision i18n module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerI18n {
- fun init() {}
- private val jed = try {
+ init {
require("jed")
- } catch (e: Throwable) {
}
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-i18n/webpack.config.d/css.js b/kvision-modules/kvision-i18n/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-i18n/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-moment/src/main/kotlin/pl/treksoft/kvision/KVManagerMoment.kt b/kvision-modules/kvision-moment/src/main/kotlin/pl/treksoft/kvision/KVManagerMoment.kt
index 330d818d..fe11288b 100644
--- a/kvision-modules/kvision-moment/src/main/kotlin/pl/treksoft/kvision/KVManagerMoment.kt
+++ b/kvision-modules/kvision-moment/src/main/kotlin/pl/treksoft/kvision/KVManagerMoment.kt
@@ -27,11 +27,11 @@ internal val kVManagerMomentInit = KVManagerMoment.init()
/**
* Internal singleton object which initializes and configures KVision Moment module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerMoment {
- fun init() {}
- private val moment = try {
+ init {
require("moment/min/moment-with-locales.js")
- } catch (e: Throwable) {}
+ }
+
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-pace/build.gradle b/kvision-modules/kvision-pace/build.gradle
index 238f9efa..d577df20 100644
--- a/kvision-modules/kvision-pace/build.gradle
+++ b/kvision-modules/kvision-pace/build.gradle
@@ -4,10 +4,6 @@ kotlinFrontend {
npm {
dependency("pace-progressbar", "1.0.8")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
}
} \ No newline at end of file
diff --git a/kvision-modules/kvision-pace/src/main/kotlin/pl/treksoft/kvision/KVManagerPace.kt b/kvision-modules/kvision-pace/src/main/kotlin/pl/treksoft/kvision/KVManagerPace.kt
index 9678d1fa..1a57f871 100644
--- a/kvision-modules/kvision-pace/src/main/kotlin/pl/treksoft/kvision/KVManagerPace.kt
+++ b/kvision-modules/kvision-pace/src/main/kotlin/pl/treksoft/kvision/KVManagerPace.kt
@@ -27,13 +27,11 @@ internal val kVManagerPaceInit = KVManagerPace.init()
/**
* Internal singleton object which initializes and configures KVision Moment module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerPace {
- fun init() {
- }
- private val pace = try {
+ init {
require("pace-progressbar").default
- } catch (e: Throwable) {
}
+
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-redux-kotlin/build.gradle b/kvision-modules/kvision-redux-kotlin/build.gradle
index 78bfda21..0b00ddd8 100644
--- a/kvision-modules/kvision-redux-kotlin/build.gradle
+++ b/kvision-modules/kvision-redux-kotlin/build.gradle
@@ -4,14 +4,3 @@ dependencies {
compile ("org.reduxkotlin:redux-kotlin-js:$reduxKotlinVersion")
compile ("org.reduxkotlin:redux-kotlin-thunk-js:$reduxKotlinThunkVersion")
}
-
-kotlinFrontend {
-
- npm {
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-redux-kotlin/webpack.config.d/css.js b/kvision-modules/kvision-redux-kotlin/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-redux-kotlin/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-redux/build.gradle b/kvision-modules/kvision-redux/build.gradle
index 3394095f..7acecd2f 100644
--- a/kvision-modules/kvision-redux/build.gradle
+++ b/kvision-modules/kvision-redux/build.gradle
@@ -9,13 +9,9 @@ dependencies {
kotlinFrontend {
npm {
- dependency("redux", "4.0.0")
+ dependency("redux", "4.0.4")
dependency("redux-thunk", "2.3.0")
- dependency("core-js", "3.0.0")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
+ dependency("core-js", "3.2.1")
}
}
diff --git a/kvision-modules/kvision-redux/src/main/kotlin/pl/treksoft/kvision/KVManagerRedux.kt b/kvision-modules/kvision-redux/src/main/kotlin/pl/treksoft/kvision/KVManagerRedux.kt
index 346f623d..d86f3a67 100644
--- a/kvision-modules/kvision-redux/src/main/kotlin/pl/treksoft/kvision/KVManagerRedux.kt
+++ b/kvision-modules/kvision-redux/src/main/kotlin/pl/treksoft/kvision/KVManagerRedux.kt
@@ -33,18 +33,10 @@ internal val kVManagerReduxInit = KVManagerRedux.init()
/**
* Internal singleton object which initializes and configures KVision Redux module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerRedux {
- fun init() {}
- private val redux = try {
- require("redux/dist/redux.min.js")
- } catch (e: Throwable) {
- }
- internal val reduxThunk = try {
- require("redux-thunk/dist/redux-thunk.min.js").default
- } catch (e: Throwable) {
- }
+ private val redux = require("redux/dist/redux.min.js")
+ internal val reduxThunk = require("redux-thunk/dist/redux-thunk.min.js").default
@Suppress("UnsafeCastFromDynamic")
internal fun <S, A, R> createStore(
@@ -72,4 +64,6 @@ internal object KVManagerRedux {
}
return composeEnhancers(function1, function2)
}
+
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-redux/webpack.config.d/css.js b/kvision-modules/kvision-redux/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-redux/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/Profile.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/Profile.kt
index d5745afe..47026f7f 100644
--- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/Profile.kt
+++ b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/Profile.kt
@@ -22,7 +22,6 @@
package pl.treksoft.kvision.remote
import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
/**
* A user profile.
@@ -38,7 +37,6 @@ actual data class Profile(
val remembered: Boolean = false,
val clientName: String? = null
) {
- @Transient
var username: String?
get() = attributes["username"]
set(value) {
@@ -48,7 +46,6 @@ actual data class Profile(
attributes.remove("username")
}
}
- @Transient
var firstName: String?
get() = attributes["first_name"]
set(value) {
@@ -58,7 +55,6 @@ actual data class Profile(
attributes.remove("first_name")
}
}
- @Transient
var familyName: String?
get() = attributes["family_name"]
set(value) {
@@ -68,7 +64,6 @@ actual data class Profile(
attributes.remove("family_name")
}
}
- @Transient
var displayName: String?
get() = attributes["display_name"]
set(value) {
@@ -78,7 +73,6 @@ actual data class Profile(
attributes.remove("display_name")
}
}
- @Transient
var email: String?
get() = attributes["email"]
set(value) {
@@ -88,7 +82,6 @@ actual data class Profile(
attributes.remove("email")
}
}
- @Transient
var pictureUrl: String?
get() = attributes["picture_url"]
set(value) {
@@ -98,7 +91,6 @@ actual data class Profile(
attributes.remove("picture_url")
}
}
- @Transient
var profileUrl: String?
get() = attributes["profile_url"]
set(value) {
diff --git a/kvision-modules/kvision-richtext/build.gradle b/kvision-modules/kvision-richtext/build.gradle
index fde9ff17..489113a7 100644
--- a/kvision-modules/kvision-richtext/build.gradle
+++ b/kvision-modules/kvision-richtext/build.gradle
@@ -3,11 +3,7 @@ apply from: "../shared.gradle"
kotlinFrontend {
npm {
- dependency("trix", "1.1.0")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
+ dependency("trix", "1.2.0")
}
}
diff --git a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt
index c7cd444c..b1b624eb 100644
--- a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt
+++ b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt
@@ -30,15 +30,10 @@ internal val kVManagerRichTextInit = KVManagerRichText.init()
/**
* Internal singleton object which initializes and configures KVision RichText module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerRichText {
- fun init() {}
- private val trixCss = try {
+ init {
require("trix/dist/trix.css")
- } catch (e: Throwable) {
- }
- private val trix = try {
val trix = require("trix")
window.asDynamic().Trix = trix
trix.config.languages = obj {}
@@ -59,6 +54,7 @@ internal object KVManagerRichText {
orig()
}
require("./js/locales/trix/trix.pl.js")
- } catch (e: Throwable) {
}
+
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
index 22126797..04a02279 100644
--- a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
+++ b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
@@ -55,7 +55,7 @@ open class RichText(
@Suppress("LeakingThis")
input.eventTarget = this
this.addInternal(input)
- this.addInternal(validationInfo)
+ this.addInternal(invalidFeedback)
}
companion object {
diff --git a/kvision-modules/kvision-richtext/webpack.config.d/jquery.js b/kvision-modules/kvision-richtext/webpack.config.d/jquery.js
new file mode 100644
index 00000000..bf5a1a20
--- /dev/null
+++ b/kvision-modules/kvision-richtext/webpack.config.d/jquery.js
@@ -0,0 +1,5 @@
+config.plugins.push(new webpack.ProvidePlugin({
+ $: "jquery",
+ jQuery: "jquery",
+ "window.jQuery": "jquery"
+}));
diff --git a/kvision-modules/kvision-select/build.gradle b/kvision-modules/kvision-select/build.gradle
deleted file mode 100644
index 7525f037..00000000
--- a/kvision-modules/kvision-select/build.gradle
+++ /dev/null
@@ -1,14 +0,0 @@
-apply from: "../shared.gradle"
-
-kotlinFrontend {
-
- npm {
- dependency("bootstrap-select", "1.12.4")
- dependency("ajax-bootstrap-select", "1.4.3")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-spinner/build.gradle b/kvision-modules/kvision-spinner/build.gradle
deleted file mode 100644
index 4569b8bc..00000000
--- a/kvision-modules/kvision-spinner/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-apply from: "../shared.gradle"
-
-kotlinFrontend {
-
- npm {
- dependency("bootstrap-touchspin", "4.2.5")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-tabulator-remote/webpack.config.d/css.js b/kvision-modules/kvision-tabulator-remote/webpack.config.d/css.js
new file mode 100644
index 00000000..5d710d35
--- /dev/null
+++ b/kvision-modules/kvision-tabulator-remote/webpack.config.d/css.js
@@ -0,0 +1,2 @@
+config.module.rules.push({ test: /\.css$/, loader: "style-loader!css-loader" });
+
diff --git a/kvision-modules/kvision-tabulator/build.gradle b/kvision-modules/kvision-tabulator/build.gradle
index 19da0553..0712c1e6 100644
--- a/kvision-modules/kvision-tabulator/build.gradle
+++ b/kvision-modules/kvision-tabulator/build.gradle
@@ -8,10 +8,6 @@ kotlinFrontend {
npm {
dependency("tabulator-tables", "4.4.1")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
}
}
diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/KVManagerTabulator.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/KVManagerTabulator.kt
index ebd1b9f7..96c084e0 100644
--- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/KVManagerTabulator.kt
+++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/KVManagerTabulator.kt
@@ -26,22 +26,18 @@ internal val kVManagerTabulatorInit = KVManagerTabulator.init()
/**
* Internal singleton object which initializes and configures KVision Tabulator module.
*/
-@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
internal object KVManagerTabulator {
- fun init() {}
- private val tabulatorCss = try {
- require("tabulator-tables/dist/css/bootstrap/tabulator_bootstrap.min.css")
- } catch (e: Throwable) {
+ init {
+ require("tabulator-tables/dist/css/bootstrap/tabulator_bootstrap4.min.css")
}
- private val tabulator = try {
- require("tabulator-tables/dist/js/tabulator.min.js")
- } catch (e: Throwable) {
- }
+ private val tabulator = require("tabulator-tables/dist/js/tabulator.min.js")
@Suppress("UnsafeCastFromDynamic")
fun getConstructor(): Any {
return tabulator
}
+
+ internal fun init() {}
}
diff --git a/kvision-modules/kvision-upload/build.gradle b/kvision-modules/kvision-upload/build.gradle
deleted file mode 100644
index 2ac20c32..00000000
--- a/kvision-modules/kvision-upload/build.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-apply from: "../shared.gradle"
-
-dependencies {
- compile "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion"
-}
-
-kotlinFrontend {
-
- npm {
- dependency("bootstrap-fileinput", "4.5.2")
- devDependency("karma", "3.1.4")
- devDependency("karma-chrome-launcher", "2.2.0")
- devDependency("karma-webpack", "3.0.5")
- devDependency("qunit", "2.8.0")
- }
-
-}
diff --git a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js b/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js
deleted file mode 100644
index 419b1761..00000000
--- a/kvision-modules/kvision-upload/src/main/resources/js/locales/bootstrap-fileinput/pt.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/*!
- * FileInput Portuguese Translations
- *
- * This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or
- * any HTML markup tags in the messages must not be converted or translated.
- *
- * @see http://github.com/kartik-v/bootstrap-fileinput
- *
- * NOTE: this file must be saved in UTF-8 encoding.
- */
-(function ($) {
- "use strict";
-
- $.fn.fileinputLocales['pt'] = {
- fileSingle: 'ficheiro',
- filePlural: 'ficheiros',
- browseLabel: 'Procurar &hellip;',
- removeLabel: 'Remover',
- removeTitle: 'Remover ficheiros seleccionados',
- cancelLabel: 'Cancelar',
- cancelTitle: 'Abortar carregamento ',
- uploadLabel: 'Carregar',
- uploadTitle: 'Carregar ficheiros seleccionados',
- msgNo: 'Não',
- msgNoFilesSelected: '',
- msgCancelled: 'Cancelado',
- msgPlaceholder: 'Select {files}...',
- msgZoomModalHeading: 'Pré-visualização detalhada',
- msgFileRequired: 'You must select a file to upload.',
- msgSizeTooSmall: 'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',
- msgSizeTooLarge: 'Ficheiro "{name}" (<b>{size} KB</b>) excede o tamanho máximo permido de <b>{maxSize} KB</b>.',
- msgFilesTooLess: 'Deve seleccionar pelo menos <b>{n}</b> {files} para fazer upload.',
- msgFilesTooMany: 'Número máximo de ficheiros seleccionados <b>({n})</b> excede o limite máximo de <b>{m}</b>.',
- msgFileNotFound: 'Ficheiro "{name}" não encontrado!',
- msgFileSecured: 'Restrições de segurança preventem a leitura do ficheiro "{name}".',
- msgFileNotReadable: 'Ficheiro "{name}" não pode ser lido.',
- msgFilePreviewAborted: 'Pré-visualização abortado para o ficheiro "{name}".',
- msgFilePreviewError: 'Ocorreu um erro ao ler o ficheiro "{name}".',
- msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
- msgInvalidFileType: 'Tipo inválido para o ficheiro "{name}". Apenas ficheiros "{types}" são suportados.',
- msgInvalidFileExtension: 'Extensão inválida para o ficheiro "{name}". Apenas ficheiros "{extensions}" são suportados.',
- msgFileTypes: {
- 'image': 'image',
- 'html': 'HTML',
- 'text': 'text',
- 'video': 'video',
- 'audio': 'audio',
- 'flash': 'flash',
- 'pdf': 'PDF',
- 'object': 'object'
- },
- msgUploadAborted: 'O upload do arquivo foi abortada',
- msgUploadThreshold: 'Processing...',
- msgUploadBegin: 'Initializing...',
- msgUploadEnd: 'Done',
- msgUploadEmpty: 'No valid data available for upload.',
- msgUploadError: 'Error',
- msgValidationError: 'Erro de validação',
- msgLoading: 'A carregar ficheiro {index} de {files} &hellip;',
- msgProgress: 'A carregar ficheiro {index} de {files} - {name} - {percent}% completo.',
- msgSelected: '{n} {files} seleccionados',
- msgFoldersNotAllowed: 'Arrastar e largar ficheiros apenas! {n} pasta(s) ignoradas.',
- msgImageWidthSmall: 'Largura do arquivo de imagem "{name}" deve ser pelo menos {size} px.',
- msgImageHeightSmall: 'Altura do arquivo de imagem "{name}" deve ser pelo menos {size} px.',
- msgImageWidthLarge: 'Largura do arquivo de imagem "{name}" não pode exceder {size} px.',
- msgImageHeightLarge: 'Altura do arquivo de imagem "{name}" não pode exceder {size} px.',
- msgImageResizeError: 'Could not get the image dimensions to resize.',
- msgImageResizeException: 'Erro ao redimensionar a imagem.<pre>{errors}</pre>',
- msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
- msgAjaxProgressError: '{operation} failed',
- ajaxOperations: {
- deleteThumb: 'file delete',
- uploadThumb: 'file upload',
- uploadBatch: 'batch file upload',
- uploadExtra: 'form data upload'
- },
- dropZoneTitle: 'Arrastar e largar ficheiros aqui &hellip;',
- dropZoneClickTitle: '<br>(or click to select {files})',
- fileActionSettings: {
- removeTitle: 'Remover arquivo',
- uploadTitle: 'Carregar arquivo',
- uploadRetryTitle: 'Retry upload',
- downloadTitle: 'Download file',
- zoomTitle: 'Ver detalhes',
- dragTitle: 'Move / Rearrange',
- indicatorNewTitle: 'Ainda não carregou',
- indicatorSuccessTitle: 'Carregado',
- indicatorErrorTitle: 'Carregar Erro',
- indicatorLoadingTitle: 'A carregar ...'
- },
- previewZoomButtonTitles: {
- prev: 'View previous file',
- next: 'View next file',
- toggleheader: 'Toggle header',
- fullscreen: 'Toggle full screen',
- borderless: 'Toggle borderless mode',
- close: 'Close detailed preview'
- }
- };
-})(window.jQuery); \ No newline at end of file
diff --git a/kvision-modules/shared.gradle b/kvision-modules/shared.gradle
index 2b45f630..640d8478 100644
--- a/kvision-modules/shared.gradle
+++ b/kvision-modules/shared.gradle
@@ -4,6 +4,13 @@ apply plugin: 'kotlinx-serialization'
kotlinFrontend {
+ npm {
+ devDependency("karma", "4.3.0")
+ devDependency("karma-chrome-launcher", "3.1.0")
+ devDependency("karma-webpack", "4.0.2")
+ devDependency("qunit", "2.9.2")
+ }
+
webpackBundle {
bundleName = "main"
contentPath = file('src/main/web')